diff --git a/.env.sample b/.env.sample index e180f1e512..289d0cd4be 100644 --- a/.env.sample +++ b/.env.sample @@ -4,3 +4,10 @@ MAINNET_RPC=https://mango.rpcpool.com DEVNET_RPC=https://mango.devnet.rpcpool.com DEFAULT_GOVERNANCE_PROGRAM_ID=GTesTBiEWE32WHXXE2S4XbZvA5CrEc4xs6ZgRe895dP + +NEXT_PUBLIC_JUPTER_SWAP_API_ENDPOINT=https://quote-api.jup.ag/v6 +NEXT_PUBLIC_API_ENDPOINT=https://api.realms.today/graphql +NEXT_PUBLIC_DISCORD_APPLICATION_CLIENT_ID=1042836142560645130 +NEXT_PUBLIC_DISCORD_MATCHDAY_CLIENT_ID=1044361939322683442 +NEXT_PUBLIC_HELIUS_MAINNET_RPC= +NEXT_PUBLIC_HELIUS_DEVNET_RPC= diff --git a/.eslintrc.json b/.eslintrc.json index 9f13623016..118a722b56 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,9 +1,10 @@ { "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint"], + "plugins": ["@typescript-eslint", "unused-imports"], "extends": [ "eslint:recommended", "plugin:react/recommended", + "plugin:react-hooks/recommended", "plugin:@typescript-eslint/recommended", // Uncomment the following lines to enable eslint-config-prettier // Is not enabled right now to avoid issues with the Next.js repo @@ -21,16 +22,24 @@ } }, "rules": { + "react-hooks/exhaustive-deps": [ + "warn", + { + "additionalHooks": "(useAsync|useAsyncCallback|useAsyncAbortable)" + } + ], "react/react-in-jsx-scope": 0, "react/display-name": 0, "react/prop-types": 0, + "unused-imports/no-unused-imports": "error", + //"@typescript-eslint/no-unnecessary-condition": "error", "@typescript-eslint/explicit-function-return-type": 0, "@typescript-eslint/explicit-module-boundary-types": 0, "@typescript-eslint/explicit-member-accessibility": 0, "@typescript-eslint/indent": 0, "@typescript-eslint/member-delimiter-style": 0, "@typescript-eslint/ban-ts-comment": 0, - "@typescript-eslint/no-non-null-assertion": 0, + "@typescript-eslint/no-non-null-assertion": 0, // days are numbered "@typescript-eslint/no-explicit-any": 0, "@typescript-eslint/no-var-requires": 0, "@typescript-eslint/no-use-before-define": 0, diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 9a24410b84..0000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: 2 -updates: - - package-ecosystem: 'npm' - directory: '/' - schedule: - interval: 'daily' - allow: - - dependency-type: 'direct' - commit-message: - prefix: 'npm' - open-pull-requests-limit: 0 diff --git a/.github/workflows/ci-main-tests.yml b/.github/workflows/ci-main-tests.yml new file mode 100644 index 0000000000..2f471a90a3 --- /dev/null +++ b/.github/workflows/ci-main-tests.yml @@ -0,0 +1,94 @@ +name: 'Main branch CI' + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + sast: + name: Static Security Tests + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialise CodeQL + uses: github/codeql-action/init@v2 + with: + languages: 'javascript' + + - name: Run CodeQL + uses: github/codeql-action/analyze@v2 + + sca: + name: Dependency Scan + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Report all vulnerabilities GitHub security tab + - name: Report on all vulnerabilities + uses: aquasecurity/trivy-action@master + with: + scan-type: 'fs' + ignore-unfixed: true + hide-progress: true + format: 'sarif' + output: 'trivy-results.sarif' + + # Fail the job on critical vulnerabiliies with fix available + - name: Fail on critical vulnerabilities + uses: aquasecurity/trivy-action@master + with: + scan-type: 'fs' + ignore-unfixed: true + hide-progress: true + format: 'table' + severity: 'CRITICAL' + exit-code: '1' + + - name: Upload scan results + uses: github/codeql-action/upload-sarif@v3 + if: always() + with: + sarif_file: 'trivy-results.sarif' + + test: + name: Run Tests + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: yarn + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: '**/node_modules' + key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} + + - name: Install dependencies + run: yarn ci + + - name: Run tests + run: yarn test-all + + pass: + name: All tests pass + needs: ['sast', 'sca', 'test'] + runs-on: ubuntu-latest + steps: + - run: echo ok diff --git a/.github/workflows/codeql-scan.yml b/.github/workflows/codeql-scan.yml deleted file mode 100644 index b3a6b68fdf..0000000000 --- a/.github/workflows/codeql-scan.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: 'CodeQL Scan' - -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - analyze: - name: CodeQL Analysis - runs-on: ubuntu-latest - if: (github.actor != 'dependabot[bot]') # Skip PRs created by dependabot to avoid permission issues - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: ['javascript'] - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Initialise CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - - - name: Run CodeQL - uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/depbot.yml b/.github/workflows/depbot.yml deleted file mode 100644 index 2be00451b2..0000000000 --- a/.github/workflows/depbot.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Dependabot Auto-merger - -on: pull_request_target - -permissions: - pull-requests: write - contents: write - -jobs: - dependabot: - runs-on: ubuntu-latest - # Only run on bot PRs - if: ${{ github.actor == 'dependabot[bot]' }} - steps: - # Fails if no metadata - - name: Dependabot metadata - id: dependabot-metadata - uses: dependabot/fetch-metadata@v1.3.0 - with: - github-token: '${{ secrets.GITHUB_TOKEN }}' - # Approves PRs - - name: Approve PR - run: gh pr review --approve "$PR_URL" - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # Auto-merge patch and minor updates if all checks pass - - name: Auto-merge Dependabot PRs - if: ${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }} - run: gh pr merge --auto --squash "$PR_URL" - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml deleted file mode 100644 index 24873048e9..0000000000 --- a/.github/workflows/deploy-docs.yml +++ /dev/null @@ -1,39 +0,0 @@ -on: - push: - branches: [main] - paths: [docs/**] - -jobs: - deploy: - name: Deploy Docs to GitHub Pages - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: lts/* - cache: yarn - - # temporary hack so that root postcss config doesn't - # interfere with the build process for the docs - - name: Remove root postcss config - run: rm postcss.config.js - - - name: Build docs - working-directory: docs - run: | - yarn install --frozen-lockfile - yarn build - - - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - # Build output to publish to the `gh-pages` branch: - publish_dir: ./docs/build - # Assign commit authorship to the official GH-Actions bot for deploys to `gh-pages` branch: - # https://github.com/actions/checkout/issues/13#issuecomment-724415212 - # The GH actions bot is used by default if you didn't specify the two fields. - # You can swap them out with your own user credentials. - user_name: github-actions[bot] - user_email: 41898282+github-actions[bot]@users.noreply.github.com diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml deleted file mode 100644 index ab46c7107f..0000000000 --- a/.github/workflows/pull-request.yml +++ /dev/null @@ -1,16 +0,0 @@ -on: - pull_request: - types: [opened, synchronize] - -jobs: - test: - name: yarn test-all - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: lts/* - cache: yarn - - run: yarn install - - run: yarn test-all diff --git a/.gitignore b/.gitignore index 223bf7fbcb..55713a92f9 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,9 @@ yarn-debug.log* yarn-error.log* # local env files +.env .env.local +.env.development .env.development.local .env.test.local .env.production.local @@ -41,3 +43,5 @@ yarn-error.log* # Sentry .sentryclirc + +.vscode/settings.json \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit index 586bf3373c..6700f51282 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,2 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" - -yarn lint-staged && yarn type-check && yarn lint diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..0a47c855eb --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +lts/iron \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index b2095be81e..00fbdb1856 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,4 @@ { "semi": false, "singleQuote": true -} +} \ No newline at end of file diff --git a/.vscode/deploy.txt b/.vscode/deploy.txt new file mode 100644 index 0000000000..7949afce22 --- /dev/null +++ b/.vscode/deploy.txt @@ -0,0 +1 @@ +Please deploy \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index fb5c775ae7..0000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "typescript.tsdk": "node_modules/typescript/lib", - "cSpell.words": ["Addin", "blockworks", "lamports", "solana", "VERCEL"], - "editor.formatOnSave": true -} diff --git a/.yarnrc b/.yarnrc new file mode 100644 index 0000000000..b16a8dd6e3 --- /dev/null +++ b/.yarnrc @@ -0,0 +1,2 @@ +--add.exact true +ignore-scripts true diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 0000000000..1e5671cea1 --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1 @@ +enableScripts: false diff --git a/0.png b/0.png new file mode 100644 index 0000000000..2d27c6ad8e Binary files /dev/null and b/0.png differ diff --git a/@types/types.ts b/@types/types.ts index e09141d5af..519b525fb9 100644 --- a/@types/types.ts +++ b/@types/types.ts @@ -1,13 +1,8 @@ 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 | null - effectiveMint: PublicKey -} +export type GovernanceRole = 'council' | 'community'; \ No newline at end of file diff --git a/DriftStakeVoterPlugin/DriftVoterClient.ts b/DriftStakeVoterPlugin/DriftVoterClient.ts new file mode 100644 index 0000000000..6a83a5c5f3 --- /dev/null +++ b/DriftStakeVoterPlugin/DriftVoterClient.ts @@ -0,0 +1,259 @@ +import { BN, Program, Provider } from '@coral-xyz/anchor' +import { Client } from '@solana/governance-program-library' +import { + getTokenOwnerRecordAddress, + SYSTEM_PROGRAM_ID, +} from '@solana/spl-governance' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { DriftStakeVoter, IDL } from './idl/driftStakeVoter' +import { IDL as DriftIDL } from './idl/drift' +import { + getInsuranceFundStakeAccountPublicKey, + getInsuranceFundVaultPublicKey, + getSpotMarketPublicKey, + unstakeSharesToAmountWithOpenRequest, +} from './driftSdk' +import { fetchTokenAccountByPubkey } from '@hooks/queries/tokenAccount' +import { DRIFT_STAKE_VOTER_PLUGIN } from './constants' +import { fetchRealmByPubkey } from '@hooks/queries/realm' +import queryClient from '@hooks/queries/queryClient' + +export class DriftVoterClient extends Client { + readonly requiresInputVoterWeight = true + + async _fetchRegistrar(realm: PublicKey, mint: PublicKey) { + const { registrar: registrarPk } = this.getRegistrarPDA(realm, mint) + const registrar = await queryClient.fetchQuery( + ['Drift', 'Plugin Registrar', registrarPk], + () => this.program.account.registrar.fetch(registrarPk) + ) + return registrar + } + + constructor( + public program: Program, + public devnet: boolean + ) { + super(program, devnet) + } + + async calculateMaxVoterWeight( + _realm: PublicKey, + _mint: PublicKey + ): Promise { + console.log( + 'drift voter client was just asked to calculate max voter weight' + ) + const { result: realm } = await fetchRealmByPubkey( + this.program.provider.connection, + _realm + ) + console.log('drift voter client realm', realm) + return realm?.account.config?.communityMintMaxVoteWeightSource.value ?? null // TODO this code should not actually be called because this is not a max voter weight plugin + } + + async calculateVoterWeight( + voter: PublicKey, + realm: PublicKey, + mint: PublicKey, + inputVoterWeight: BN + ): Promise { + const registrar = await this._fetchRegistrar(realm, mint) + const spotMarketIndex = registrar.spotMarketIndex // could just hardcode spotmarket pk + const driftProgramId = registrar.driftProgramId // likewise + const drift = new Program(DriftIDL, driftProgramId, this.program.provider) + const spotMarketPk = await getSpotMarketPublicKey( + driftProgramId, + spotMarketIndex + ) + const insuranceFundVaultPk = await getInsuranceFundVaultPublicKey( + driftProgramId, + spotMarketIndex + ) + const insuranceFundStakePk = await getInsuranceFundStakeAccountPublicKey( + driftProgramId, + voter, + spotMarketIndex + ) + + const insuranceFundStake = await queryClient.fetchQuery({ + queryKey: ['Insurance Fund Stake', insuranceFundStakePk.toString()], + queryFn: async () => + drift.account.insuranceFundStake.fetchNullable(insuranceFundStakePk), + }) + + if (insuranceFundStake === null) { + console.log('drift voter client', 'no insurance fund stake account found') + return inputVoterWeight + } + + const spotMarket = await queryClient.fetchQuery({ + queryKey: ['Drift Spot Market', spotMarketPk.toString()], + queryFn: async () => drift.account.spotMarket.fetchNullable(spotMarketPk), + }) + + if (spotMarket === null) { + console.log('Drift spot market not found: ' + spotMarketPk.toString()) + return inputVoterWeight + } + + const insuranceFundVault = await fetchTokenAccountByPubkey( + this.program.provider.connection, + insuranceFundVaultPk + ) + if (insuranceFundVault.result === undefined) { + console.log( + 'Insurance fund vault not found: ' + insuranceFundVaultPk.toString() + ) + return inputVoterWeight + } + + const nShares = insuranceFundStake.ifShares + const withdrawRequestShares = insuranceFundStake.lastWithdrawRequestShares + const withdrawRequestAmount = insuranceFundStake.lastWithdrawRequestValue + const totalIfShares = spotMarket.insuranceFund.totalShares + const insuranceFundVaultBalance = insuranceFundVault.result?.amount + + const amount = unstakeSharesToAmountWithOpenRequest( + nShares, + withdrawRequestShares, + withdrawRequestAmount, + totalIfShares, + insuranceFundVaultBalance + ) + + return amount.add(inputVoterWeight) + } + + async updateVoterWeightRecord( + voter: PublicKey, + realm: PublicKey, + mint: PublicKey + //action?: VoterWeightAction | undefined, + //inputRecordCallback?: (() => Promise) | undefined + ): Promise<{ + pre: TransactionInstruction[] + post?: TransactionInstruction[] | undefined + }> { + const connection = this.program.provider.connection + const { result: realmAccount } = await fetchRealmByPubkey(connection, realm) + if (!realmAccount) throw new Error('Realm not found') + const tokenOwnerRecordPk = await getTokenOwnerRecordAddress( + realmAccount?.owner, + realm, + mint, + voter + ) + const { voterWeightPk } = await this.getVoterWeightRecordPDA( + realm, + mint, + voter + ) + const { registrar: registrarPk } = this.getRegistrarPDA(realm, mint) + const registrar = await this._fetchRegistrar(realm, mint) + const spotMarketIndex = registrar.spotMarketIndex // could just hardcode spotmarket pk + const driftProgramId = registrar.driftProgramId // likewise + const drift = new Program(DriftIDL, driftProgramId, this.program.provider) + + //const drift = new Program(DriftIDL, driftProgramId, this.program.provider) + const spotMarketPk = await getSpotMarketPublicKey( + driftProgramId, + spotMarketIndex + ) + const insuranceFundVaultPk = await getInsuranceFundVaultPublicKey( + driftProgramId, + spotMarketIndex + ) + const insuranceFundStakePk = await getInsuranceFundStakeAccountPublicKey( + driftProgramId, + voter, + spotMarketIndex + ) + + const spotMarket = await queryClient.fetchQuery({ + queryKey: ['Drift Spot Market', spotMarketPk.toString()], + queryFn: async () => drift.account.spotMarket.fetchNullable(spotMarketPk), + }) + const spotMarketPkOrNull = spotMarket === null ? null : spotMarketPk + + const insuranceFundVault = await fetchTokenAccountByPubkey( + this.program.provider.connection, + insuranceFundVaultPk + ) + const insuranceFundVaultPkOrNull = + insuranceFundVault.found === false ? null : insuranceFundVaultPk + + let insuranceFundStake: + | Awaited> + | undefined + try { + insuranceFundStake = await drift.account.insuranceFundStake.fetch( + insuranceFundStakePk + ) + } catch (e) { + console.log('drift voter client', 'no insurance fund stake account found') + insuranceFundStake = undefined + } + const stakePkOrNull = + insuranceFundStake === undefined ? null : insuranceFundStakePk + + const ix = await this.program.methods + .updateVoterWeightRecord() + .accountsStrict({ + voterWeightRecord: voterWeightPk, + registrar: registrarPk, + driftProgram: driftProgramId, + spotMarket: spotMarketPkOrNull, + insuranceFundStake: stakePkOrNull, + insuranceFundVault: insuranceFundVaultPkOrNull, + tokenOwnerRecord: tokenOwnerRecordPk, + }) + .instruction() + + return { pre: [ix] } + } + + // NO-OP + async createMaxVoterWeightRecord(): Promise { + return null + } + + // NO-OP + async updateMaxVoterWeightRecord(): Promise { + return null + } + + static async connect( + provider: Provider, + programId = new PublicKey(DRIFT_STAKE_VOTER_PLUGIN), + devnet = false + ): Promise { + return new DriftVoterClient( + new Program(IDL, programId, provider), + devnet + ) + } + + async createVoterWeightRecord( + voter: PublicKey, + realm: PublicKey, + mint: PublicKey + ): Promise { + const { voterWeightPk } = await this.getVoterWeightRecordPDA( + realm, + mint, + voter + ) + const { registrar } = this.getRegistrarPDA(realm, mint) + + return this.program.methods + .createVoterWeightRecord(voter) + .accounts({ + voterWeightRecord: voterWeightPk, + registrar, + payer: voter, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .instruction() + } +} diff --git a/DriftStakeVoterPlugin/components/DriftDeposit.tsx b/DriftStakeVoterPlugin/components/DriftDeposit.tsx new file mode 100644 index 0000000000..a17d82ec0e --- /dev/null +++ b/DriftStakeVoterPlugin/components/DriftDeposit.tsx @@ -0,0 +1,57 @@ +import { BigNumber } from 'bignumber.js' +import { useRealmQuery } from '@hooks/queries/realm' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import useUserGovTokenAccountQuery from '@hooks/useUserGovTokenAccount' +import { DepositTokensButton } from '@components/DepositTokensButton' +import Button from '@components/Button' +import { DRIFT_GOVERNANCE_TICKER } from 'DriftStakeVoterPlugin/constants' + +/** Contextual deposit, shows only if relevant */ +export const DriftDeposit = ({ role }: { role: 'community' | 'council' }) => { + const realm = useRealmQuery().data?.result + const mint = + role === 'community' + ? realm?.account.communityMint + : realm?.account.config.councilMint + + const mintInfo = useMintInfoByPubkeyQuery(mint).data?.result + const userAta = useUserGovTokenAccountQuery(role).data?.result + + const depositAmount = userAta?.amount + ? new BigNumber(userAta.amount.toString()) + : new BigNumber(0) + + return !depositAmount.isGreaterThan(0) ? null : ( + <> +
+ You have{' '} + {mintInfo + ? depositAmount.shiftedBy(-mintInfo.decimals).toFormat() + : depositAmount.toFormat()}{' '} + more {DRIFT_GOVERNANCE_TICKER} in your wallet. You can stake it with + Drift or deposit it into Realms to increase your voting power. +
+
+ + +
+ + ) +} diff --git a/DriftStakeVoterPlugin/components/DriftVotingPower.tsx b/DriftStakeVoterPlugin/components/DriftVotingPower.tsx new file mode 100644 index 0000000000..96509cd95a --- /dev/null +++ b/DriftStakeVoterPlugin/components/DriftVotingPower.tsx @@ -0,0 +1,145 @@ +import classNames from 'classnames' + +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import { useRealmQuery } from '@hooks/queries/realm' +import { BigNumber } from 'bignumber.js' +import clsx from 'clsx' +import { useMemo } from 'react' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import { useJoinRealm } from '@hooks/useJoinRealm' +import { Transaction } from '@solana/web3.js' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useConnection } from '@solana/wallet-adapter-react' +import Button from '@components/Button' +import { sendTransaction } from '@utils/send' +import { DriftDeposit } from './DriftDeposit' +import { BN } from '@coral-xyz/anchor' + +interface Props { + className?: string + role: 'community' | 'council' +} + +export default function DriftVotingPower({ role, className }: Props) { + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const { connection } = useConnection() + const realm = useRealmQuery().data?.result + const { + userNeedsTokenOwnerRecord, + userNeedsVoterWeightRecords, + handleRegister, + } = useJoinRealm() + const mintInfo = useMintInfoByPubkeyQuery(realm?.account.communityMint).data + ?.result + + const { totalCalculatedVoterWeight, isReady } = useRealmVoterWeightPlugins( + role + ) + + const vanillaValue = totalCalculatedVoterWeight?.initialValue + const stakedValue = totalCalculatedVoterWeight?.value?.sub( + vanillaValue ?? new BN(0) + ) + + const formattedTotal = useMemo( + () => + mintInfo && totalCalculatedVoterWeight?.value + ? new BigNumber(totalCalculatedVoterWeight?.value.toString()) + .shiftedBy(-mintInfo.decimals) + .toFormat(2) + : undefined, + [mintInfo, totalCalculatedVoterWeight?.value] + ) + + const formattedStaked = useMemo( + () => + mintInfo && stakedValue + ? new BigNumber(stakedValue.toString()) + .shiftedBy(-mintInfo.decimals) + .toFormat(2) + : undefined, + [mintInfo, stakedValue] + ) + + const formattedVanilla = useMemo( + () => + mintInfo && vanillaValue + ? new BigNumber(vanillaValue.toString()) + .shiftedBy(-mintInfo.decimals) + .toFormat(2) + : undefined, + [mintInfo, vanillaValue] + ) + + // There are two buttons available on this UI: + // The Deposit button - available if you have tokens to deposit + // The Join button - available if you have already deposited tokens (you have a Token Owner Record) + // but you may not have all your Voter Weight Records yet. + // This latter case may occur if the DAO changes its configuration and new Voter Weight Records are required. + // For example if a new plugin is added. + const showJoinButton = + userNeedsTokenOwnerRecord || userNeedsVoterWeightRecords + + const join = async () => { + const instructions = await handleRegister() + const transaction = new Transaction() + transaction.add(...instructions) + + await sendTransaction({ + transaction: transaction, + wallet: wallet!, + connection, + signers: [], + sendingMessage: `Registering`, + successMessage: `Registered`, + }) + } + + if (!isReady || formattedTotal === undefined) { + return ( +
+ ) + } + + return ( +
+
+
+
+
Votes
+
+ {formattedTotal ?? 0} +
+ {formattedStaked && + stakedValue?.gtn(0) && + formattedVanilla && + vanillaValue?.gtn(0) && ( + <> +
+ {formattedStaked} from Drift insurance staking +
+
+ {formattedVanilla} from Realms deposit +
+ + )} +
+
+
+ {connected && showJoinButton && ( + + )} + +
+
+
+ ) +} diff --git a/DriftStakeVoterPlugin/constants.ts b/DriftStakeVoterPlugin/constants.ts new file mode 100644 index 0000000000..4a48c341f5 --- /dev/null +++ b/DriftStakeVoterPlugin/constants.ts @@ -0,0 +1,8 @@ +export const DRIFT_STAKE_VOTER_PLUGIN = + 'dVoTE1AJqkZVoE1mPbWcqYPmEEvAUBksHY2NiM2UJQe' + +export const DRIFT_PROGRAM_ID = 'dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH' + +//export const DRIFT_GOVERNANCE_PROGRAM_ID = 'dgov7NC8iaumWw3k8TkmLDybvZBCmd1qwxgLAGAsWxf' + +export const DRIFT_GOVERNANCE_TICKER = 'DRFT' diff --git a/DriftStakeVoterPlugin/driftSdk.ts b/DriftStakeVoterPlugin/driftSdk.ts new file mode 100644 index 0000000000..7341b55590 --- /dev/null +++ b/DriftStakeVoterPlugin/driftSdk.ts @@ -0,0 +1,78 @@ +import { PublicKey } from '@solana/web3.js' +import * as anchor from '@coral-xyz/anchor' +import { BN } from '@coral-xyz/anchor' + +export async function getSpotMarketPublicKey( + programId: PublicKey, + marketIndex: number +): Promise { + return ( + await PublicKey.findProgramAddress( + [ + Buffer.from(anchor.utils.bytes.utf8.encode('spot_market')), + new anchor.BN(marketIndex).toArrayLike(Buffer, 'le', 2), + ], + programId + ) + )[0] +} + +export async function getInsuranceFundVaultPublicKey( + programId: PublicKey, + marketIndex: number +): Promise { + return ( + await PublicKey.findProgramAddress( + [ + Buffer.from(anchor.utils.bytes.utf8.encode('insurance_fund_vault')), + new anchor.BN(marketIndex).toArrayLike(Buffer, 'le', 2), + ], + programId + ) + )[0] +} + +export function getInsuranceFundStakeAccountPublicKey( + programId: PublicKey, + authority: PublicKey, + marketIndex: number +): PublicKey { + return PublicKey.findProgramAddressSync( + [ + Buffer.from(anchor.utils.bytes.utf8.encode('insurance_fund_stake')), + authority.toBuffer(), + new anchor.BN(marketIndex).toArrayLike(Buffer, 'le', 2), + ], + programId + )[0] +} + +const ZERO = new BN(0) +export function unstakeSharesToAmountWithOpenRequest( + nShares: BN, + withdrawRequestShares: BN, + withdrawRequestAmount: BN, + totalIfShares: BN, + insuranceFundVaultBalance: BN +): BN { + let stakedAmount: BN + if (totalIfShares.gt(ZERO)) { + stakedAmount = BN.max( + ZERO, + nShares + .sub(withdrawRequestShares) + .mul(insuranceFundVaultBalance) + .div(totalIfShares) + ) + } else { + stakedAmount = ZERO + } + + const withdrawAmount = BN.min( + withdrawRequestAmount, + withdrawRequestShares.mul(insuranceFundVaultBalance).div(totalIfShares) + ) + const amount = withdrawAmount.add(stakedAmount) + + return amount +} diff --git a/DriftStakeVoterPlugin/idl/drift.ts b/DriftStakeVoterPlugin/idl/drift.ts new file mode 100644 index 0000000000..541e857a0c --- /dev/null +++ b/DriftStakeVoterPlugin/idl/drift.ts @@ -0,0 +1,25907 @@ +export type Drift = { + "version": "2.92.0", + "name": "drift", + "instructions": [ + { + "name": "initializeUser", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "initializeUserStats", + "accounts": [ + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "initializeReferrerName", + "accounts": [ + { + "name": "referrerName", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "deposit", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "amount", + "type": "u64" + }, + { + "name": "reduceOnly", + "type": "bool" + } + ] + }, + { + "name": "withdraw", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "amount", + "type": "u64" + }, + { + "name": "reduceOnly", + "type": "bool" + } + ] + }, + { + "name": "transferDeposit", + "accounts": [ + { + "name": "fromUser", + "isMut": true, + "isSigner": false + }, + { + "name": "toUser", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "placePerpOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + } + ] + }, + { + "name": "cancelOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "orderId", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "cancelOrderByUserId", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "userOrderId", + "type": "u8" + } + ] + }, + { + "name": "cancelOrders", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "marketType", + "type": { + "option": { + "defined": "MarketType" + } + } + }, + { + "name": "marketIndex", + "type": { + "option": "u16" + } + }, + { + "name": "direction", + "type": { + "option": { + "defined": "PositionDirection" + } + } + } + ] + }, + { + "name": "cancelOrdersByIds", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "orderIds", + "type": { + "vec": "u32" + } + } + ] + }, + { + "name": "modifyOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "orderId", + "type": { + "option": "u32" + } + }, + { + "name": "modifyOrderParams", + "type": { + "defined": "ModifyOrderParams" + } + } + ] + }, + { + "name": "modifyOrderByUserId", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "userOrderId", + "type": "u8" + }, + { + "name": "modifyOrderParams", + "type": { + "defined": "ModifyOrderParams" + } + } + ] + }, + { + "name": "placeAndTakePerpOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + }, + { + "name": "makerOrderId", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "placeAndMakePerpOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "taker", + "isMut": true, + "isSigner": false + }, + { + "name": "takerStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + }, + { + "name": "takerOrderId", + "type": "u32" + } + ] + }, + { + "name": "placeSpotOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + } + ] + }, + { + "name": "placeAndTakeSpotOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + }, + { + "name": "fulfillmentType", + "type": { + "option": { + "defined": "SpotFulfillmentType" + } + } + }, + { + "name": "makerOrderId", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "placeAndMakeSpotOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "taker", + "isMut": true, + "isSigner": false + }, + { + "name": "takerStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + }, + { + "name": "takerOrderId", + "type": "u32" + }, + { + "name": "fulfillmentType", + "type": { + "option": { + "defined": "SpotFulfillmentType" + } + } + } + ] + }, + { + "name": "placeOrders", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "vec": { + "defined": "OrderParams" + } + } + } + ] + }, + { + "name": "beginSwap", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "outSpotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "inSpotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "outTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "inTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "instructions", + "isMut": false, + "isSigner": false, + "docs": [ + "Instructions Sysvar for instruction introspection" + ] + } + ], + "args": [ + { + "name": "inMarketIndex", + "type": "u16" + }, + { + "name": "outMarketIndex", + "type": "u16" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "endSwap", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "outSpotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "inSpotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "outTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "inTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "instructions", + "isMut": false, + "isSigner": false, + "docs": [ + "Instructions Sysvar for instruction introspection" + ] + } + ], + "args": [ + { + "name": "inMarketIndex", + "type": "u16" + }, + { + "name": "outMarketIndex", + "type": "u16" + }, + { + "name": "limitPrice", + "type": { + "option": "u64" + } + }, + { + "name": "reduceOnly", + "type": { + "option": { + "defined": "SwapReduceOnly" + } + } + } + ] + }, + { + "name": "addPerpLpShares", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "nShares", + "type": "u64" + }, + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "removePerpLpShares", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "sharesToBurn", + "type": "u64" + }, + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "removePerpLpSharesInExpiringMarket", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "sharesToBurn", + "type": "u64" + }, + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "updateUserName", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "updateUserCustomMarginRatio", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "marginRatio", + "type": "u32" + } + ] + }, + { + "name": "updateUserMarginTradingEnabled", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "marginTradingEnabled", + "type": "bool" + } + ] + }, + { + "name": "updateUserDelegate", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "delegate", + "type": "publicKey" + } + ] + }, + { + "name": "updateUserReduceOnly", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "reduceOnly", + "type": "bool" + } + ] + }, + { + "name": "updateUserAdvancedLp", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "advancedLp", + "type": "bool" + } + ] + }, + { + "name": "deleteUser", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [] + }, + { + "name": "reclaimRent", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "fillPerpOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "fillerStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "orderId", + "type": { + "option": "u32" + } + }, + { + "name": "makerOrderId", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "revertFill", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "fillerStats", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "fillSpotOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "fillerStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "orderId", + "type": { + "option": "u32" + } + }, + { + "name": "fulfillmentType", + "type": { + "option": { + "defined": "SpotFulfillmentType" + } + } + }, + { + "name": "makerOrderId", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "triggerOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "orderId", + "type": "u32" + } + ] + }, + { + "name": "forceCancelOrders", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateUserIdle", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateUserOpenOrdersCount", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "adminDisableUpdatePerpBidAskTwap", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "disable", + "type": "bool" + } + ] + }, + { + "name": "settlePnl", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "settleMultiplePnls", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndexes", + "type": { + "vec": "u16" + } + }, + { + "name": "mode", + "type": { + "defined": "SettlePnlMode" + } + } + ] + }, + { + "name": "settleFundingPayment", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "settleLp", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "settleExpiredMarket", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "liquidatePerp", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "liquidatorMaxBaseAssetAmount", + "type": "u64" + }, + { + "name": "limitPrice", + "type": { + "option": "u64" + } + } + ] + }, + { + "name": "liquidatePerpWithFill", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "liquidateSpot", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "assetMarketIndex", + "type": "u16" + }, + { + "name": "liabilityMarketIndex", + "type": "u16" + }, + { + "name": "liquidatorMaxLiabilityTransfer", + "type": "u128" + }, + { + "name": "limitPrice", + "type": { + "option": "u64" + } + } + ] + }, + { + "name": "liquidateBorrowForPerpPnl", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "spotMarketIndex", + "type": "u16" + }, + { + "name": "liquidatorMaxLiabilityTransfer", + "type": "u128" + }, + { + "name": "limitPrice", + "type": { + "option": "u64" + } + } + ] + }, + { + "name": "liquidatePerpPnlForDeposit", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "spotMarketIndex", + "type": "u16" + }, + { + "name": "liquidatorMaxPnlTransfer", + "type": "u128" + }, + { + "name": "limitPrice", + "type": { + "option": "u64" + } + } + ] + }, + { + "name": "setUserStatusToBeingLiquidated", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "resolvePerpPnlDeficit", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "spotMarketIndex", + "type": "u16" + }, + { + "name": "perpMarketIndex", + "type": "u16" + } + ] + }, + { + "name": "resolvePerpBankruptcy", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "quoteSpotMarketIndex", + "type": "u16" + }, + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "resolveSpotBankruptcy", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "settleRevenueToInsuranceFund", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "spotMarketIndex", + "type": "u16" + } + ] + }, + { + "name": "updateFundingRate", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "updatePrelaunchOracle", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "oracle", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updatePerpBidAskTwap", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "keeperStats", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [] + }, + { + "name": "updateSpotMarketCumulativeInterest", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateAmms", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "marketIndexes", + "type": { + "array": [ + "u16", + 5 + ] + } + } + ] + }, + { + "name": "updateSpotMarketExpiry", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "expiryTs", + "type": "i64" + } + ] + }, + { + "name": "updateUserQuoteAssetInsuranceStake", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateUserGovTokenInsuranceStake", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "initializeInsuranceFundStake", + "accounts": [ + { + "name": "spotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "addInsuranceFundStake", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "requestRemoveInsuranceFundStake", + "accounts": [ + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "cancelRequestRemoveInsuranceFundStake", + "accounts": [ + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "removeInsuranceFundStake", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "transferProtocolIfShares", + "accounts": [ + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "transferConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "shares", + "type": "u128" + } + ] + }, + { + "name": "updatePythPullOracle", + "accounts": [ + { + "name": "keeper", + "isMut": true, + "isSigner": true + }, + { + "name": "pythSolanaReceiver", + "isMut": false, + "isSigner": false + }, + { + "name": "encodedVaa", + "isMut": false, + "isSigner": false + }, + { + "name": "priceFeed", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feedId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "params", + "type": "bytes" + } + ] + }, + { + "name": "postPythPullOracleUpdateAtomic", + "accounts": [ + { + "name": "keeper", + "isMut": true, + "isSigner": true + }, + { + "name": "pythSolanaReceiver", + "isMut": false, + "isSigner": false + }, + { + "name": "guardianSet", + "isMut": false, + "isSigner": false + }, + { + "name": "priceFeed", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feedId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "params", + "type": "bytes" + } + ] + }, + { + "name": "postMultiPythPullOracleUpdatesAtomic", + "accounts": [ + { + "name": "keeper", + "isMut": true, + "isSigner": true + }, + { + "name": "pythSolanaReceiver", + "isMut": false, + "isSigner": false + }, + { + "name": "guardianSet", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "params", + "type": "bytes" + } + ] + }, + { + "name": "initialize", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "quoteAssetMint", + "isMut": false, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "initializeSpotMarket", + "accounts": [ + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketMint", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "optimalUtilization", + "type": "u32" + }, + { + "name": "optimalBorrowRate", + "type": "u32" + }, + { + "name": "maxBorrowRate", + "type": "u32" + }, + { + "name": "oracleSource", + "type": { + "defined": "OracleSource" + } + }, + { + "name": "initialAssetWeight", + "type": "u32" + }, + { + "name": "maintenanceAssetWeight", + "type": "u32" + }, + { + "name": "initialLiabilityWeight", + "type": "u32" + }, + { + "name": "maintenanceLiabilityWeight", + "type": "u32" + }, + { + "name": "imfFactor", + "type": "u32" + }, + { + "name": "liquidatorFee", + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "type": "u32" + }, + { + "name": "activeStatus", + "type": "bool" + }, + { + "name": "assetTier", + "type": { + "defined": "AssetTier" + } + }, + { + "name": "scaleInitialAssetWeightStart", + "type": "u64" + }, + { + "name": "withdrawGuardThreshold", + "type": "u64" + }, + { + "name": "orderTickSize", + "type": "u64" + }, + { + "name": "orderStepSize", + "type": "u64" + }, + { + "name": "ifTotalFactor", + "type": "u32" + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "deleteInitializedSpotMarket", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "initializeSerumFulfillmentConfig", + "accounts": [ + { + "name": "baseSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "quoteSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "serumProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "serumMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "serumOpenOrders", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "serumFulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "updateSerumFulfillmentConfigStatus", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "serumFulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + } + ], + "args": [ + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + } + ] + }, + { + "name": "initializeOpenbookV2FulfillmentConfig", + "accounts": [ + { + "name": "baseSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "quoteSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "openbookV2Program", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookV2Market", + "isMut": false, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookV2FulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "openbookV2FulfillmentConfigStatus", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookV2FulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + } + ], + "args": [ + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + } + ] + }, + { + "name": "initializePhoenixFulfillmentConfig", + "accounts": [ + { + "name": "baseSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "quoteSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "phoenixProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "phoenixMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "phoenixFulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "phoenixFulfillmentConfigStatus", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "phoenixFulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + } + ], + "args": [ + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + } + ] + }, + { + "name": "updateSerumVault", + "accounts": [ + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "srmVault", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "initializePerpMarket", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "ammBaseAssetReserve", + "type": "u128" + }, + { + "name": "ammQuoteAssetReserve", + "type": "u128" + }, + { + "name": "ammPeriodicity", + "type": "i64" + }, + { + "name": "ammPegMultiplier", + "type": "u128" + }, + { + "name": "oracleSource", + "type": { + "defined": "OracleSource" + } + }, + { + "name": "contractTier", + "type": { + "defined": "ContractTier" + } + }, + { + "name": "marginRatioInitial", + "type": "u32" + }, + { + "name": "marginRatioMaintenance", + "type": "u32" + }, + { + "name": "liquidatorFee", + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "type": "u32" + }, + { + "name": "imfFactor", + "type": "u32" + }, + { + "name": "activeStatus", + "type": "bool" + }, + { + "name": "baseSpread", + "type": "u32" + }, + { + "name": "maxSpread", + "type": "u32" + }, + { + "name": "maxOpenInterest", + "type": "u128" + }, + { + "name": "maxRevenueWithdrawPerPeriod", + "type": "u64" + }, + { + "name": "quoteMaxInsurance", + "type": "u64" + }, + { + "name": "orderStepSize", + "type": "u64" + }, + { + "name": "orderTickSize", + "type": "u64" + }, + { + "name": "minOrderSize", + "type": "u64" + }, + { + "name": "concentrationCoefScale", + "type": "u128" + }, + { + "name": "curveUpdateIntensity", + "type": "u8" + }, + { + "name": "ammJitIntensity", + "type": "u8" + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "initializePredictionMarket", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "deleteInitializedPerpMarket", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "moveAmmPrice", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "baseAssetReserve", + "type": "u128" + }, + { + "name": "quoteAssetReserve", + "type": "u128" + }, + { + "name": "sqrtK", + "type": "u128" + } + ] + }, + { + "name": "recenterPerpMarketAmm", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "pegMultiplier", + "type": "u128" + }, + { + "name": "sqrtK", + "type": "u128" + } + ] + }, + { + "name": "updatePerpMarketAmmSummaryStats", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "UpdatePerpMarketSummaryStatsParams" + } + } + ] + }, + { + "name": "updatePerpMarketExpiry", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "expiryTs", + "type": "i64" + } + ] + }, + { + "name": "settleExpiredMarketPoolsToRevenuePool", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "depositIntoPerpMarketFeePool", + "accounts": [ + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "sourceVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "quoteSpotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "depositIntoSpotMarketVault", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "sourceVault", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "depositIntoSpotMarketRevenuePool", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": true, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "repegAmmCurve", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "newPegCandidate", + "type": "u128" + } + ] + }, + { + "name": "updatePerpMarketAmmOracleTwap", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + } + ], + "args": [] + }, + { + "name": "resetPerpMarketAmmOracleTwap", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + } + ], + "args": [] + }, + { + "name": "updateK", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "sqrtK", + "type": "u128" + } + ] + }, + { + "name": "updatePerpMarketMarginRatio", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marginRatioInitial", + "type": "u32" + }, + { + "name": "marginRatioMaintenance", + "type": "u32" + } + ] + }, + { + "name": "updatePerpMarketFundingPeriod", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "fundingPeriod", + "type": "i64" + } + ] + }, + { + "name": "updatePerpMarketMaxImbalances", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "unrealizedMaxImbalance", + "type": "u64" + }, + { + "name": "maxRevenueWithdrawPerPeriod", + "type": "u64" + }, + { + "name": "quoteMaxInsurance", + "type": "u64" + } + ] + }, + { + "name": "updatePerpMarketLiquidationFee", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "liquidatorFee", + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "type": "u32" + } + ] + }, + { + "name": "updateInsuranceFundUnstakingPeriod", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "insuranceFundUnstakingPeriod", + "type": "i64" + } + ] + }, + { + "name": "updateSpotMarketLiquidationFee", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "liquidatorFee", + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "type": "u32" + } + ] + }, + { + "name": "updateWithdrawGuardThreshold", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "withdrawGuardThreshold", + "type": "u64" + } + ] + }, + { + "name": "updateSpotMarketIfFactor", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "spotMarketIndex", + "type": "u16" + }, + { + "name": "userIfFactor", + "type": "u32" + }, + { + "name": "totalIfFactor", + "type": "u32" + } + ] + }, + { + "name": "updateSpotMarketRevenueSettlePeriod", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "revenueSettlePeriod", + "type": "i64" + } + ] + }, + { + "name": "updateSpotMarketStatus", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "status", + "type": { + "defined": "MarketStatus" + } + } + ] + }, + { + "name": "updateSpotMarketPausedOperations", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "pausedOperations", + "type": "u8" + } + ] + }, + { + "name": "updateSpotMarketAssetTier", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "assetTier", + "type": { + "defined": "AssetTier" + } + } + ] + }, + { + "name": "updateSpotMarketMarginWeights", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "initialAssetWeight", + "type": "u32" + }, + { + "name": "maintenanceAssetWeight", + "type": "u32" + }, + { + "name": "initialLiabilityWeight", + "type": "u32" + }, + { + "name": "maintenanceLiabilityWeight", + "type": "u32" + }, + { + "name": "imfFactor", + "type": "u32" + } + ] + }, + { + "name": "updateSpotMarketBorrowRate", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "optimalUtilization", + "type": "u32" + }, + { + "name": "optimalBorrowRate", + "type": "u32" + }, + { + "name": "maxBorrowRate", + "type": "u32" + }, + { + "name": "minBorrowRate", + "type": { + "option": "u8" + } + } + ] + }, + { + "name": "updateSpotMarketMaxTokenDeposits", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxTokenDeposits", + "type": "u64" + } + ] + }, + { + "name": "updateSpotMarketMaxTokenBorrows", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxTokenBorrowsFraction", + "type": "u16" + } + ] + }, + { + "name": "updateSpotMarketScaleInitialAssetWeightStart", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "scaleInitialAssetWeightStart", + "type": "u64" + } + ] + }, + { + "name": "updateSpotMarketOracle", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "oracle", + "type": "publicKey" + }, + { + "name": "oracleSource", + "type": { + "defined": "OracleSource" + } + } + ] + }, + { + "name": "updateSpotMarketStepSizeAndTickSize", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "stepSize", + "type": "u64" + }, + { + "name": "tickSize", + "type": "u64" + } + ] + }, + { + "name": "updateSpotMarketMinOrderSize", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "orderSize", + "type": "u64" + } + ] + }, + { + "name": "updateSpotMarketOrdersEnabled", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "ordersEnabled", + "type": "bool" + } + ] + }, + { + "name": "updateSpotMarketIfPausedOperations", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "pausedOperations", + "type": "u8" + } + ] + }, + { + "name": "updateSpotMarketName", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "updatePerpMarketStatus", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "status", + "type": { + "defined": "MarketStatus" + } + } + ] + }, + { + "name": "updatePerpMarketPausedOperations", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "pausedOperations", + "type": "u8" + } + ] + }, + { + "name": "updatePerpMarketContractTier", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "contractTier", + "type": { + "defined": "ContractTier" + } + } + ] + }, + { + "name": "updatePerpMarketImfFactor", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "imfFactor", + "type": "u32" + }, + { + "name": "unrealizedPnlImfFactor", + "type": "u32" + } + ] + }, + { + "name": "updatePerpMarketUnrealizedAssetWeight", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "unrealizedInitialAssetWeight", + "type": "u32" + }, + { + "name": "unrealizedMaintenanceAssetWeight", + "type": "u32" + } + ] + }, + { + "name": "updatePerpMarketConcentrationCoef", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "concentrationScale", + "type": "u128" + } + ] + }, + { + "name": "updatePerpMarketCurveUpdateIntensity", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "curveUpdateIntensity", + "type": "u8" + } + ] + }, + { + "name": "updatePerpMarketTargetBaseAssetAmountPerLp", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "targetBaseAssetAmountPerLp", + "type": "i32" + } + ] + }, + { + "name": "updatePerpMarketPerLpBase", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "perLpBase", + "type": "i8" + } + ] + }, + { + "name": "updateLpCooldownTime", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "lpCooldownTime", + "type": "u64" + } + ] + }, + { + "name": "updatePerpFeeStructure", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feeStructure", + "type": { + "defined": "FeeStructure" + } + } + ] + }, + { + "name": "updateSpotFeeStructure", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feeStructure", + "type": { + "defined": "FeeStructure" + } + } + ] + }, + { + "name": "updateInitialPctToLiquidate", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "initialPctToLiquidate", + "type": "u16" + } + ] + }, + { + "name": "updateLiquidationDuration", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "liquidationDuration", + "type": "u8" + } + ] + }, + { + "name": "updateLiquidationMarginBufferRatio", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "liquidationMarginBufferRatio", + "type": "u32" + } + ] + }, + { + "name": "updateOracleGuardRails", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "oracleGuardRails", + "type": { + "defined": "OracleGuardRails" + } + } + ] + }, + { + "name": "updateStateSettlementDuration", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "settlementDuration", + "type": "u16" + } + ] + }, + { + "name": "updateStateMaxNumberOfSubAccounts", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxNumberOfSubAccounts", + "type": "u16" + } + ] + }, + { + "name": "updateStateMaxInitializeUserFee", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxInitializeUserFee", + "type": "u16" + } + ] + }, + { + "name": "updatePerpMarketOracle", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "oracle", + "type": "publicKey" + }, + { + "name": "oracleSource", + "type": { + "defined": "OracleSource" + } + } + ] + }, + { + "name": "updatePerpMarketBaseSpread", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "baseSpread", + "type": "u32" + } + ] + }, + { + "name": "updateAmmJitIntensity", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "ammJitIntensity", + "type": "u8" + } + ] + }, + { + "name": "updatePerpMarketMaxSpread", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxSpread", + "type": "u32" + } + ] + }, + { + "name": "updatePerpMarketStepSizeAndTickSize", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "stepSize", + "type": "u64" + }, + { + "name": "tickSize", + "type": "u64" + } + ] + }, + { + "name": "updatePerpMarketName", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "updatePerpMarketMinOrderSize", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "orderSize", + "type": "u64" + } + ] + }, + { + "name": "updatePerpMarketMaxSlippageRatio", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxSlippageRatio", + "type": "u16" + } + ] + }, + { + "name": "updatePerpMarketMaxFillReserveFraction", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxFillReserveFraction", + "type": "u16" + } + ] + }, + { + "name": "updatePerpMarketMaxOpenInterest", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxOpenInterest", + "type": "u128" + } + ] + }, + { + "name": "updatePerpMarketNumberOfUsers", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "numberOfUsers", + "type": { + "option": "u32" + } + }, + { + "name": "numberOfUsersWithBase", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "updatePerpMarketFeeAdjustment", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feeAdjustment", + "type": "i16" + } + ] + }, + { + "name": "updateSpotMarketFeeAdjustment", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feeAdjustment", + "type": "i16" + } + ] + }, + { + "name": "updatePerpMarketFuel", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "fuelBoostTaker", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostMaker", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostPosition", + "type": { + "option": "u8" + } + } + ] + }, + { + "name": "updateSpotMarketFuel", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "fuelBoostDeposits", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostBorrows", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostTaker", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostMaker", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostInsurance", + "type": { + "option": "u8" + } + } + ] + }, + { + "name": "initUserFuel", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "fuelBoostDeposits", + "type": { + "option": "u32" + } + }, + { + "name": "fuelBoostBorrows", + "type": { + "option": "u32" + } + }, + { + "name": "fuelBoostTaker", + "type": { + "option": "u32" + } + }, + { + "name": "fuelBoostMaker", + "type": { + "option": "u32" + } + }, + { + "name": "fuelBoostInsurance", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "updateAdmin", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "admin", + "type": "publicKey" + } + ] + }, + { + "name": "updateWhitelistMint", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "whitelistMint", + "type": "publicKey" + } + ] + }, + { + "name": "updateDiscountMint", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "discountMint", + "type": "publicKey" + } + ] + }, + { + "name": "updateExchangeStatus", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "exchangeStatus", + "type": "u8" + } + ] + }, + { + "name": "updatePerpAuctionDuration", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "minPerpAuctionDuration", + "type": "u8" + } + ] + }, + { + "name": "updateSpotAuctionDuration", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "defaultSpotAuctionDuration", + "type": "u8" + } + ] + }, + { + "name": "initializeProtocolIfSharesTransferConfig", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "protocolIfSharesTransferConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateProtocolIfSharesTransferConfig", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "protocolIfSharesTransferConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "whitelistedSigners", + "type": { + "option": { + "array": [ + "publicKey", + 4 + ] + } + } + }, + { + "name": "maxTransferPerEpoch", + "type": { + "option": "u128" + } + } + ] + }, + { + "name": "initializePrelaunchOracle", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "prelaunchOracle", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "PrelaunchOracleParams" + } + } + ] + }, + { + "name": "updatePrelaunchOracleParams", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "prelaunchOracle", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "PrelaunchOracleParams" + } + } + ] + }, + { + "name": "deletePrelaunchOracle", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "prelaunchOracle", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "perpMarketIndex", + "type": "u16" + } + ] + }, + { + "name": "initializePythPullOracle", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "pythSolanaReceiver", + "isMut": false, + "isSigner": false + }, + { + "name": "priceFeed", + "isMut": true, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "feedId", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + } + ], + "accounts": [ + { + "name": "OpenbookV2FulfillmentConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "type": "publicKey" + }, + { + "name": "openbookV2ProgramId", + "type": "publicKey" + }, + { + "name": "openbookV2Market", + "type": "publicKey" + }, + { + "name": "openbookV2MarketAuthority", + "type": "publicKey" + }, + { + "name": "openbookV2EventHeap", + "type": "publicKey" + }, + { + "name": "openbookV2Bids", + "type": "publicKey" + }, + { + "name": "openbookV2Asks", + "type": "publicKey" + }, + { + "name": "openbookV2BaseVault", + "type": "publicKey" + }, + { + "name": "openbookV2QuoteVault", + "type": "publicKey" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "fulfillmentType", + "type": { + "defined": "SpotFulfillmentType" + } + }, + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 4 + ] + } + } + ] + } + }, + { + "name": "PhoenixV1FulfillmentConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "type": "publicKey" + }, + { + "name": "phoenixProgramId", + "type": "publicKey" + }, + { + "name": "phoenixLogAuthority", + "type": "publicKey" + }, + { + "name": "phoenixMarket", + "type": "publicKey" + }, + { + "name": "phoenixBaseVault", + "type": "publicKey" + }, + { + "name": "phoenixQuoteVault", + "type": "publicKey" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "fulfillmentType", + "type": { + "defined": "SpotFulfillmentType" + } + }, + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 4 + ] + } + } + ] + } + }, + { + "name": "SerumV3FulfillmentConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "type": "publicKey" + }, + { + "name": "serumProgramId", + "type": "publicKey" + }, + { + "name": "serumMarket", + "type": "publicKey" + }, + { + "name": "serumRequestQueue", + "type": "publicKey" + }, + { + "name": "serumEventQueue", + "type": "publicKey" + }, + { + "name": "serumBids", + "type": "publicKey" + }, + { + "name": "serumAsks", + "type": "publicKey" + }, + { + "name": "serumBaseVault", + "type": "publicKey" + }, + { + "name": "serumQuoteVault", + "type": "publicKey" + }, + { + "name": "serumOpenOrders", + "type": "publicKey" + }, + { + "name": "serumSignerNonce", + "type": "u64" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "fulfillmentType", + "type": { + "defined": "SpotFulfillmentType" + } + }, + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 4 + ] + } + } + ] + } + }, + { + "name": "insuranceFundStake", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "publicKey" + }, + { + "name": "ifShares", + "type": "u128" + }, + { + "name": "lastWithdrawRequestShares", + "type": "u128" + }, + { + "name": "ifBase", + "type": "u128" + }, + { + "name": "lastValidTs", + "type": "i64" + }, + { + "name": "lastWithdrawRequestValue", + "type": "u64" + }, + { + "name": "lastWithdrawRequestTs", + "type": "i64" + }, + { + "name": "costBasis", + "type": "i64" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 14 + ] + } + } + ] + } + }, + { + "name": "ProtocolIfSharesTransferConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "whitelistedSigners", + "type": { + "array": [ + "publicKey", + 4 + ] + } + }, + { + "name": "maxTransferPerEpoch", + "type": "u128" + }, + { + "name": "currentEpochTransfer", + "type": "u128" + }, + { + "name": "nextEpochTs", + "type": "i64" + }, + { + "name": "padding", + "type": { + "array": [ + "u128", + 8 + ] + } + } + ] + } + }, + { + "name": "PrelaunchOracle", + "type": { + "kind": "struct", + "fields": [ + { + "name": "price", + "type": "i64" + }, + { + "name": "maxPrice", + "type": "i64" + }, + { + "name": "confidence", + "type": "u64" + }, + { + "name": "lastUpdateSlot", + "type": "u64" + }, + { + "name": "ammLastUpdateSlot", + "type": "u64" + }, + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 70 + ] + } + } + ] + } + }, + { + "name": "PerpMarket", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "docs": [ + "The perp market's address. It is a pda of the market index" + ], + "type": "publicKey" + }, + { + "name": "amm", + "docs": [ + "The automated market maker" + ], + "type": { + "defined": "AMM" + } + }, + { + "name": "pnlPool", + "docs": [ + "The market's pnl pool. When users settle negative pnl, the balance increases.", + "When users settle positive pnl, the balance decreases. Can not go negative." + ], + "type": { + "defined": "PoolBalance" + } + }, + { + "name": "name", + "docs": [ + "Encoded display name for the perp market e.g. SOL-PERP" + ], + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "insuranceClaim", + "docs": [ + "The perp market's claim on the insurance fund" + ], + "type": { + "defined": "InsuranceClaim" + } + }, + { + "name": "unrealizedPnlMaxImbalance", + "docs": [ + "The max pnl imbalance before positive pnl asset weight is discounted", + "pnl imbalance is the difference between long and short pnl. When it's greater than 0,", + "the amm has negative pnl and the initial asset weight for positive pnl is discounted", + "precision = QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "expiryTs", + "docs": [ + "The ts when the market will be expired. Only set if market is in reduce only mode" + ], + "type": "i64" + }, + { + "name": "expiryPrice", + "docs": [ + "The price at which positions will be settled. Only set if market is expired", + "precision = PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "nextFillRecordId", + "docs": [ + "Every trade has a fill record id. This is the next id to be used" + ], + "type": "u64" + }, + { + "name": "nextFundingRateRecordId", + "docs": [ + "Every funding rate update has a record id. This is the next id to be used" + ], + "type": "u64" + }, + { + "name": "nextCurveRecordId", + "docs": [ + "Every amm k updated has a record id. This is the next id to be used" + ], + "type": "u64" + }, + { + "name": "imfFactor", + "docs": [ + "The initial margin fraction factor. Used to increase margin ratio for large positions", + "precision: MARGIN_PRECISION" + ], + "type": "u32" + }, + { + "name": "unrealizedPnlImfFactor", + "docs": [ + "The imf factor for unrealized pnl. Used to discount asset weight for large positive pnl", + "precision: MARGIN_PRECISION" + ], + "type": "u32" + }, + { + "name": "liquidatorFee", + "docs": [ + "The fee the liquidator is paid for taking over perp position", + "precision: LIQUIDATOR_FEE_PRECISION" + ], + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "docs": [ + "The fee the insurance fund receives from liquidation", + "precision: LIQUIDATOR_FEE_PRECISION" + ], + "type": "u32" + }, + { + "name": "marginRatioInitial", + "docs": [ + "The margin ratio which determines how much collateral is required to open a position", + "e.g. margin ratio of .1 means a user must have $100 of total collateral to open a $1000 position", + "precision: MARGIN_PRECISION" + ], + "type": "u32" + }, + { + "name": "marginRatioMaintenance", + "docs": [ + "The margin ratio which determines when a user will be liquidated", + "e.g. margin ratio of .05 means a user must have $50 of total collateral to maintain a $1000 position", + "else they will be liquidated", + "precision: MARGIN_PRECISION" + ], + "type": "u32" + }, + { + "name": "unrealizedPnlInitialAssetWeight", + "docs": [ + "The initial asset weight for positive pnl. Negative pnl always has an asset weight of 1", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "unrealizedPnlMaintenanceAssetWeight", + "docs": [ + "The maintenance asset weight for positive pnl. Negative pnl always has an asset weight of 1", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "numberOfUsersWithBase", + "docs": [ + "number of users in a position (base)" + ], + "type": "u32" + }, + { + "name": "numberOfUsers", + "docs": [ + "number of users in a position (pnl) or pnl (quote)" + ], + "type": "u32" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "status", + "docs": [ + "Whether a market is active, reduce only, expired, etc", + "Affects whether users can open/close positions" + ], + "type": { + "defined": "MarketStatus" + } + }, + { + "name": "contractType", + "docs": [ + "Currently only Perpetual markets are supported" + ], + "type": { + "defined": "ContractType" + } + }, + { + "name": "contractTier", + "docs": [ + "The contract tier determines how much insurance a market can receive, with more speculative markets receiving less insurance", + "It also influences the order perp markets can be liquidated, with less speculative markets being liquidated first" + ], + "type": { + "defined": "ContractTier" + } + }, + { + "name": "pausedOperations", + "type": "u8" + }, + { + "name": "quoteSpotMarketIndex", + "docs": [ + "The spot market that pnl is settled in" + ], + "type": "u16" + }, + { + "name": "feeAdjustment", + "docs": [ + "Between -100 and 100, represents what % to increase/decrease the fee by", + "E.g. if this is -50 and the fee is 5bps, the new fee will be 2.5bps", + "if this is 50 and the fee is 5bps, the new fee will be 7.5bps" + ], + "type": "i16" + }, + { + "name": "fuelBoostPosition", + "docs": [ + "fuel multiplier for perp funding", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostTaker", + "docs": [ + "fuel multiplier for perp taker", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostMaker", + "docs": [ + "fuel multiplier for perp maker", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 43 + ] + } + } + ] + } + }, + { + "name": "spotMarket", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "docs": [ + "The address of the spot market. It is a pda of the market index" + ], + "type": "publicKey" + }, + { + "name": "oracle", + "docs": [ + "The oracle used to price the markets deposits/borrows" + ], + "type": "publicKey" + }, + { + "name": "mint", + "docs": [ + "The token mint of the market" + ], + "type": "publicKey" + }, + { + "name": "vault", + "docs": [ + "The vault used to store the market's deposits", + "The amount in the vault should be equal to or greater than deposits - borrows" + ], + "type": "publicKey" + }, + { + "name": "name", + "docs": [ + "The encoded display name for the market e.g. SOL" + ], + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "historicalOracleData", + "type": { + "defined": "HistoricalOracleData" + } + }, + { + "name": "historicalIndexData", + "type": { + "defined": "HistoricalIndexData" + } + }, + { + "name": "revenuePool", + "docs": [ + "Revenue the protocol has collected in this markets token", + "e.g. for SOL-PERP, funds can be settled in usdc and will flow into the USDC revenue pool" + ], + "type": { + "defined": "PoolBalance" + } + }, + { + "name": "spotFeePool", + "docs": [ + "The fees collected from swaps between this market and the quote market", + "Is settled to the quote markets revenue pool" + ], + "type": { + "defined": "PoolBalance" + } + }, + { + "name": "insuranceFund", + "docs": [ + "Details on the insurance fund covering bankruptcies in this markets token", + "Covers bankruptcies for borrows with this markets token and perps settling in this markets token" + ], + "type": { + "defined": "InsuranceFund" + } + }, + { + "name": "totalSpotFee", + "docs": [ + "The total spot fees collected for this market", + "precision: QUOTE_PRECISION" + ], + "type": "u128" + }, + { + "name": "depositBalance", + "docs": [ + "The sum of the scaled balances for deposits across users and pool balances", + "To convert to the deposit token amount, multiply by the cumulative deposit interest", + "precision: SPOT_BALANCE_PRECISION" + ], + "type": "u128" + }, + { + "name": "borrowBalance", + "docs": [ + "The sum of the scaled balances for borrows across users and pool balances", + "To convert to the borrow token amount, multiply by the cumulative borrow interest", + "precision: SPOT_BALANCE_PRECISION" + ], + "type": "u128" + }, + { + "name": "cumulativeDepositInterest", + "docs": [ + "The cumulative interest earned by depositors", + "Used to calculate the deposit token amount from the deposit balance", + "precision: SPOT_CUMULATIVE_INTEREST_PRECISION" + ], + "type": "u128" + }, + { + "name": "cumulativeBorrowInterest", + "docs": [ + "The cumulative interest earned by borrowers", + "Used to calculate the borrow token amount from the borrow balance", + "precision: SPOT_CUMULATIVE_INTEREST_PRECISION" + ], + "type": "u128" + }, + { + "name": "totalSocialLoss", + "docs": [ + "The total socialized loss from borrows, in the mint's token", + "precision: token mint precision" + ], + "type": "u128" + }, + { + "name": "totalQuoteSocialLoss", + "docs": [ + "The total socialized loss from borrows, in the quote market's token", + "preicision: QUOTE_PRECISION" + ], + "type": "u128" + }, + { + "name": "withdrawGuardThreshold", + "docs": [ + "no withdraw limits/guards when deposits below this threshold", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "maxTokenDeposits", + "docs": [ + "The max amount of token deposits in this market", + "0 if there is no limit", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "depositTokenTwap", + "docs": [ + "24hr average of deposit token amount", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "borrowTokenTwap", + "docs": [ + "24hr average of borrow token amount", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "utilizationTwap", + "docs": [ + "24hr average of utilization", + "which is borrow amount over token amount", + "precision: SPOT_UTILIZATION_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastInterestTs", + "docs": [ + "Last time the cumulative deposit and borrow interest was updated" + ], + "type": "u64" + }, + { + "name": "lastTwapTs", + "docs": [ + "Last time the deposit/borrow/utilization averages were updated" + ], + "type": "u64" + }, + { + "name": "expiryTs", + "docs": [ + "The time the market is set to expire. Only set if market is in reduce only mode" + ], + "type": "i64" + }, + { + "name": "orderStepSize", + "docs": [ + "Spot orders must be a multiple of the step size", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "orderTickSize", + "docs": [ + "Spot orders must be a multiple of the tick size", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "minOrderSize", + "docs": [ + "The minimum order size", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "maxPositionSize", + "docs": [ + "The maximum spot position size", + "if the limit is 0, there is no limit", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "nextFillRecordId", + "docs": [ + "Every spot trade has a fill record id. This is the next id to use" + ], + "type": "u64" + }, + { + "name": "nextDepositRecordId", + "docs": [ + "Every deposit has a deposit record id. This is the next id to use" + ], + "type": "u64" + }, + { + "name": "initialAssetWeight", + "docs": [ + "The initial asset weight used to calculate a deposits contribution to a users initial total collateral", + "e.g. if the asset weight is .8, $100 of deposits contributes $80 to the users initial total collateral", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "maintenanceAssetWeight", + "docs": [ + "The maintenance asset weight used to calculate a deposits contribution to a users maintenance total collateral", + "e.g. if the asset weight is .9, $100 of deposits contributes $90 to the users maintenance total collateral", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "initialLiabilityWeight", + "docs": [ + "The initial liability weight used to calculate a borrows contribution to a users initial margin requirement", + "e.g. if the liability weight is .9, $100 of borrows contributes $90 to the users initial margin requirement", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "maintenanceLiabilityWeight", + "docs": [ + "The maintenance liability weight used to calculate a borrows contribution to a users maintenance margin requirement", + "e.g. if the liability weight is .8, $100 of borrows contributes $80 to the users maintenance margin requirement", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "imfFactor", + "docs": [ + "The initial margin fraction factor. Used to increase liability weight/decrease asset weight for large positions", + "precision: MARGIN_PRECISION" + ], + "type": "u32" + }, + { + "name": "liquidatorFee", + "docs": [ + "The fee the liquidator is paid for taking over borrow/deposit", + "precision: LIQUIDATOR_FEE_PRECISION" + ], + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "docs": [ + "The fee the insurance fund receives from liquidation", + "precision: LIQUIDATOR_FEE_PRECISION" + ], + "type": "u32" + }, + { + "name": "optimalUtilization", + "docs": [ + "The optimal utilization rate for this market.", + "Used to determine the markets borrow rate", + "precision: SPOT_UTILIZATION_PRECISION" + ], + "type": "u32" + }, + { + "name": "optimalBorrowRate", + "docs": [ + "The borrow rate for this market when the market has optimal utilization", + "precision: SPOT_RATE_PRECISION" + ], + "type": "u32" + }, + { + "name": "maxBorrowRate", + "docs": [ + "The borrow rate for this market when the market has 1000 utilization", + "precision: SPOT_RATE_PRECISION" + ], + "type": "u32" + }, + { + "name": "decimals", + "docs": [ + "The market's token mint's decimals. To from decimals to a precision, 10^decimals" + ], + "type": "u32" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "ordersEnabled", + "docs": [ + "Whether or not spot trading is enabled" + ], + "type": "bool" + }, + { + "name": "oracleSource", + "type": { + "defined": "OracleSource" + } + }, + { + "name": "status", + "type": { + "defined": "MarketStatus" + } + }, + { + "name": "assetTier", + "docs": [ + "The asset tier affects how a deposit can be used as collateral and the priority for a borrow being liquidated" + ], + "type": { + "defined": "AssetTier" + } + }, + { + "name": "pausedOperations", + "type": "u8" + }, + { + "name": "ifPausedOperations", + "type": "u8" + }, + { + "name": "feeAdjustment", + "type": "i16" + }, + { + "name": "maxTokenBorrowsFraction", + "docs": [ + "What fraction of max_token_deposits", + "disabled when 0, 1 => 1/10000 => .01% of max_token_deposits", + "precision: X/10000" + ], + "type": "u16" + }, + { + "name": "flashLoanAmount", + "docs": [ + "For swaps, the amount of token loaned out in the begin_swap ix", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "flashLoanInitialTokenAmount", + "docs": [ + "For swaps, the amount in the users token account in the begin_swap ix", + "Used to calculate how much of the token left the system in end_swap ix", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "totalSwapFee", + "docs": [ + "The total fees received from swaps", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "scaleInitialAssetWeightStart", + "docs": [ + "When to begin scaling down the initial asset weight", + "disabled when 0", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "minBorrowRate", + "docs": [ + "The min borrow rate for this market when the market regardless of utilization", + "1 => 1/200 => .5%", + "precision: X/200" + ], + "type": "u8" + }, + { + "name": "fuelBoostDeposits", + "docs": [ + "fuel multiplier for spot deposits", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostBorrows", + "docs": [ + "fuel multiplier for spot borrows", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostTaker", + "docs": [ + "fuel multiplier for spot taker", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostMaker", + "docs": [ + "fuel multiplier for spot maker", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostInsurance", + "docs": [ + "fuel multiplier for spot insurance stake", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "tokenProgram", + "type": "u8" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 41 + ] + } + } + ] + } + }, + { + "name": "State", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "publicKey" + }, + { + "name": "whitelistMint", + "type": "publicKey" + }, + { + "name": "discountMint", + "type": "publicKey" + }, + { + "name": "signer", + "type": "publicKey" + }, + { + "name": "srmVault", + "type": "publicKey" + }, + { + "name": "perpFeeStructure", + "type": { + "defined": "FeeStructure" + } + }, + { + "name": "spotFeeStructure", + "type": { + "defined": "FeeStructure" + } + }, + { + "name": "oracleGuardRails", + "type": { + "defined": "OracleGuardRails" + } + }, + { + "name": "numberOfAuthorities", + "type": "u64" + }, + { + "name": "numberOfSubAccounts", + "type": "u64" + }, + { + "name": "lpCooldownTime", + "type": "u64" + }, + { + "name": "liquidationMarginBufferRatio", + "type": "u32" + }, + { + "name": "settlementDuration", + "type": "u16" + }, + { + "name": "numberOfMarkets", + "type": "u16" + }, + { + "name": "numberOfSpotMarkets", + "type": "u16" + }, + { + "name": "signerNonce", + "type": "u8" + }, + { + "name": "minPerpAuctionDuration", + "type": "u8" + }, + { + "name": "defaultMarketOrderTimeInForce", + "type": "u8" + }, + { + "name": "defaultSpotAuctionDuration", + "type": "u8" + }, + { + "name": "exchangeStatus", + "type": "u8" + }, + { + "name": "liquidationDuration", + "type": "u8" + }, + { + "name": "initialPctToLiquidate", + "type": "u16" + }, + { + "name": "maxNumberOfSubAccounts", + "type": "u16" + }, + { + "name": "maxInitializeUserFee", + "type": "u16" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 10 + ] + } + } + ] + } + }, + { + "name": "User", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "docs": [ + "The owner/authority of the account" + ], + "type": "publicKey" + }, + { + "name": "delegate", + "docs": [ + "An addresses that can control the account on the authority's behalf. Has limited power, cant withdraw" + ], + "type": "publicKey" + }, + { + "name": "name", + "docs": [ + "Encoded display name e.g. \"toly\"" + ], + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "spotPositions", + "docs": [ + "The user's spot positions" + ], + "type": { + "array": [ + { + "defined": "SpotPosition" + }, + 8 + ] + } + }, + { + "name": "perpPositions", + "docs": [ + "The user's perp positions" + ], + "type": { + "array": [ + { + "defined": "PerpPosition" + }, + 8 + ] + } + }, + { + "name": "orders", + "docs": [ + "The user's orders" + ], + "type": { + "array": [ + { + "defined": "Order" + }, + 32 + ] + } + }, + { + "name": "lastAddPerpLpSharesTs", + "docs": [ + "The last time the user added perp lp positions" + ], + "type": "i64" + }, + { + "name": "totalDeposits", + "docs": [ + "The total values of deposits the user has made", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalWithdraws", + "docs": [ + "The total values of withdrawals the user has made", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalSocialLoss", + "docs": [ + "The total socialized loss the users has incurred upon the protocol", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "settledPerpPnl", + "docs": [ + "Fees (taker fees, maker rebate, referrer reward, filler reward) and pnl for perps", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "cumulativeSpotFees", + "docs": [ + "Fees (taker fees, maker rebate, filler reward) for spot", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "cumulativePerpFunding", + "docs": [ + "Cumulative funding paid/received for perps", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "liquidationMarginFreed", + "docs": [ + "The amount of margin freed during liquidation. Used to force the liquidation to occur over a period of time", + "Defaults to zero when not being liquidated", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastActiveSlot", + "docs": [ + "The last slot a user was active. Used to determine if a user is idle" + ], + "type": "u64" + }, + { + "name": "nextOrderId", + "docs": [ + "Every user order has an order id. This is the next order id to be used" + ], + "type": "u32" + }, + { + "name": "maxMarginRatio", + "docs": [ + "Custom max initial margin ratio for the user" + ], + "type": "u32" + }, + { + "name": "nextLiquidationId", + "docs": [ + "The next liquidation id to be used for user" + ], + "type": "u16" + }, + { + "name": "subAccountId", + "docs": [ + "The sub account id for this user" + ], + "type": "u16" + }, + { + "name": "status", + "docs": [ + "Whether the user is active, being liquidated or bankrupt" + ], + "type": "u8" + }, + { + "name": "isMarginTradingEnabled", + "docs": [ + "Whether the user has enabled margin trading" + ], + "type": "bool" + }, + { + "name": "idle", + "docs": [ + "User is idle if they haven't interacted with the protocol in 1 week and they have no orders, perp positions or borrows", + "Off-chain keeper bots can ignore users that are idle" + ], + "type": "bool" + }, + { + "name": "openOrders", + "docs": [ + "number of open orders" + ], + "type": "u8" + }, + { + "name": "hasOpenOrder", + "docs": [ + "Whether or not user has open order" + ], + "type": "bool" + }, + { + "name": "openAuctions", + "docs": [ + "number of open orders with auction" + ], + "type": "u8" + }, + { + "name": "hasOpenAuction", + "docs": [ + "Whether or not user has open order with auction" + ], + "type": "bool" + }, + { + "name": "padding1", + "type": { + "array": [ + "u8", + 5 + ] + } + }, + { + "name": "lastFuelBonusUpdateTs", + "type": "u32" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 12 + ] + } + } + ] + } + }, + { + "name": "UserStats", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "docs": [ + "The authority for all of a users sub accounts" + ], + "type": "publicKey" + }, + { + "name": "referrer", + "docs": [ + "The address that referred this user" + ], + "type": "publicKey" + }, + { + "name": "fees", + "docs": [ + "Stats on the fees paid by the user" + ], + "type": { + "defined": "UserFees" + } + }, + { + "name": "nextEpochTs", + "docs": [ + "The timestamp of the next epoch", + "Epoch is used to limit referrer rewards earned in single epoch" + ], + "type": "i64" + }, + { + "name": "makerVolume30d", + "docs": [ + "Rolling 30day maker volume for user", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "takerVolume30d", + "docs": [ + "Rolling 30day taker volume for user", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "fillerVolume30d", + "docs": [ + "Rolling 30day filler volume for user", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastMakerVolume30dTs", + "docs": [ + "last time the maker volume was updated" + ], + "type": "i64" + }, + { + "name": "lastTakerVolume30dTs", + "docs": [ + "last time the taker volume was updated" + ], + "type": "i64" + }, + { + "name": "lastFillerVolume30dTs", + "docs": [ + "last time the filler volume was updated" + ], + "type": "i64" + }, + { + "name": "ifStakedQuoteAssetAmount", + "docs": [ + "The amount of tokens staked in the quote spot markets if" + ], + "type": "u64" + }, + { + "name": "numberOfSubAccounts", + "docs": [ + "The current number of sub accounts" + ], + "type": "u16" + }, + { + "name": "numberOfSubAccountsCreated", + "docs": [ + "The number of sub accounts created. Can be greater than the number of sub accounts if user", + "has deleted sub accounts" + ], + "type": "u16" + }, + { + "name": "isReferrer", + "docs": [ + "Whether the user is a referrer. Sub account 0 can not be deleted if user is a referrer" + ], + "type": "bool" + }, + { + "name": "disableUpdatePerpBidAskTwap", + "type": "bool" + }, + { + "name": "padding1", + "type": { + "array": [ + "u8", + 2 + ] + } + }, + { + "name": "fuelInsurance", + "docs": [ + "accumulated fuel for token amounts of insurance" + ], + "type": "u32" + }, + { + "name": "fuelDeposits", + "docs": [ + "accumulated fuel for notional of deposits" + ], + "type": "u32" + }, + { + "name": "fuelBorrows", + "docs": [ + "accumulate fuel bonus for notional of borrows" + ], + "type": "u32" + }, + { + "name": "fuelPositions", + "docs": [ + "accumulated fuel for perp open interest" + ], + "type": "u32" + }, + { + "name": "fuelTaker", + "docs": [ + "accumulate fuel bonus for taker volume" + ], + "type": "u32" + }, + { + "name": "fuelMaker", + "docs": [ + "accumulate fuel bonus for maker volume" + ], + "type": "u32" + }, + { + "name": "ifStakedGovTokenAmount", + "docs": [ + "The amount of tokens staked in the governance spot markets if" + ], + "type": "u64" + }, + { + "name": "lastFuelIfBonusUpdateTs", + "docs": [ + "last unix ts user stats data was used to update if fuel (u32 to save space)" + ], + "type": "u32" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 12 + ] + } + } + ] + } + }, + { + "name": "ReferrerName", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "publicKey" + }, + { + "name": "user", + "type": "publicKey" + }, + { + "name": "userStats", + "type": "publicKey" + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + } + } + ], + "types": [ + { + "name": "UpdatePerpMarketSummaryStatsParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "quoteAssetAmountWithUnsettledLp", + "type": { + "option": "i64" + } + }, + { + "name": "netUnsettledFundingPnl", + "type": { + "option": "i64" + } + }, + { + "name": "updateAmmSummaryStats", + "type": { + "option": "bool" + } + } + ] + } + }, + { + "name": "LiquidatePerpRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "oraclePrice", + "type": "i64" + }, + { + "name": "baseAssetAmount", + "type": "i64" + }, + { + "name": "quoteAssetAmount", + "type": "i64" + }, + { + "name": "lpShares", + "docs": [ + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u64" + }, + { + "name": "fillRecordId", + "type": "u64" + }, + { + "name": "userOrderId", + "type": "u32" + }, + { + "name": "liquidatorOrderId", + "type": "u32" + }, + { + "name": "liquidatorFee", + "docs": [ + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "ifFee", + "docs": [ + "precision: QUOTE_PRECISION" + ], + "type": "u64" + } + ] + } + }, + { + "name": "LiquidateSpotRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "assetMarketIndex", + "type": "u16" + }, + { + "name": "assetPrice", + "type": "i64" + }, + { + "name": "assetTransfer", + "type": "u128" + }, + { + "name": "liabilityMarketIndex", + "type": "u16" + }, + { + "name": "liabilityPrice", + "type": "i64" + }, + { + "name": "liabilityTransfer", + "docs": [ + "precision: token mint precision" + ], + "type": "u128" + }, + { + "name": "ifFee", + "docs": [ + "precision: token mint precision" + ], + "type": "u64" + } + ] + } + }, + { + "name": "LiquidateBorrowForPerpPnlRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "marketOraclePrice", + "type": "i64" + }, + { + "name": "pnlTransfer", + "type": "u128" + }, + { + "name": "liabilityMarketIndex", + "type": "u16" + }, + { + "name": "liabilityPrice", + "type": "i64" + }, + { + "name": "liabilityTransfer", + "type": "u128" + } + ] + } + }, + { + "name": "LiquidatePerpPnlForDepositRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "marketOraclePrice", + "type": "i64" + }, + { + "name": "pnlTransfer", + "type": "u128" + }, + { + "name": "assetMarketIndex", + "type": "u16" + }, + { + "name": "assetPrice", + "type": "i64" + }, + { + "name": "assetTransfer", + "type": "u128" + } + ] + } + }, + { + "name": "PerpBankruptcyRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "pnl", + "type": "i128" + }, + { + "name": "ifPayment", + "type": "u128" + }, + { + "name": "clawbackUser", + "type": { + "option": "publicKey" + } + }, + { + "name": "clawbackUserPayment", + "type": { + "option": "u128" + } + }, + { + "name": "cumulativeFundingRateDelta", + "type": "i128" + } + ] + } + }, + { + "name": "SpotBankruptcyRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "borrowAmount", + "type": "u128" + }, + { + "name": "ifPayment", + "type": "u128" + }, + { + "name": "cumulativeDepositInterestDelta", + "type": "u128" + } + ] + } + }, + { + "name": "MarketIdentifier", + "type": { + "kind": "struct", + "fields": [ + { + "name": "marketType", + "type": { + "defined": "MarketType" + } + }, + { + "name": "marketIndex", + "type": "u16" + } + ] + } + }, + { + "name": "HistoricalOracleData", + "type": { + "kind": "struct", + "fields": [ + { + "name": "lastOraclePrice", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastOracleConf", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastOracleDelay", + "docs": [ + "number of slots since last update" + ], + "type": "i64" + }, + { + "name": "lastOraclePriceTwap", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastOraclePriceTwap5min", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastOraclePriceTwapTs", + "docs": [ + "unix_timestamp of last snapshot" + ], + "type": "i64" + } + ] + } + }, + { + "name": "HistoricalIndexData", + "type": { + "kind": "struct", + "fields": [ + { + "name": "lastIndexBidPrice", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastIndexAskPrice", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastIndexPriceTwap", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastIndexPriceTwap5min", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastIndexPriceTwapTs", + "docs": [ + "unix_timestamp of last snapshot" + ], + "type": "i64" + } + ] + } + }, + { + "name": "PrelaunchOracleParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "price", + "type": { + "option": "i64" + } + }, + { + "name": "maxPrice", + "type": { + "option": "i64" + } + } + ] + } + }, + { + "name": "OrderParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "orderType", + "type": { + "defined": "OrderType" + } + }, + { + "name": "marketType", + "type": { + "defined": "MarketType" + } + }, + { + "name": "direction", + "type": { + "defined": "PositionDirection" + } + }, + { + "name": "userOrderId", + "type": "u8" + }, + { + "name": "baseAssetAmount", + "type": "u64" + }, + { + "name": "price", + "type": "u64" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "reduceOnly", + "type": "bool" + }, + { + "name": "postOnly", + "type": { + "defined": "PostOnlyParam" + } + }, + { + "name": "immediateOrCancel", + "type": "bool" + }, + { + "name": "maxTs", + "type": { + "option": "i64" + } + }, + { + "name": "triggerPrice", + "type": { + "option": "u64" + } + }, + { + "name": "triggerCondition", + "type": { + "defined": "OrderTriggerCondition" + } + }, + { + "name": "oraclePriceOffset", + "type": { + "option": "i32" + } + }, + { + "name": "auctionDuration", + "type": { + "option": "u8" + } + }, + { + "name": "auctionStartPrice", + "type": { + "option": "i64" + } + }, + { + "name": "auctionEndPrice", + "type": { + "option": "i64" + } + } + ] + } + }, + { + "name": "ModifyOrderParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "direction", + "type": { + "option": { + "defined": "PositionDirection" + } + } + }, + { + "name": "baseAssetAmount", + "type": { + "option": "u64" + } + }, + { + "name": "price", + "type": { + "option": "u64" + } + }, + { + "name": "reduceOnly", + "type": { + "option": "bool" + } + }, + { + "name": "postOnly", + "type": { + "option": { + "defined": "PostOnlyParam" + } + } + }, + { + "name": "immediateOrCancel", + "type": { + "option": "bool" + } + }, + { + "name": "maxTs", + "type": { + "option": "i64" + } + }, + { + "name": "triggerPrice", + "type": { + "option": "u64" + } + }, + { + "name": "triggerCondition", + "type": { + "option": { + "defined": "OrderTriggerCondition" + } + } + }, + { + "name": "oraclePriceOffset", + "type": { + "option": "i32" + } + }, + { + "name": "auctionDuration", + "type": { + "option": "u8" + } + }, + { + "name": "auctionStartPrice", + "type": { + "option": "i64" + } + }, + { + "name": "auctionEndPrice", + "type": { + "option": "i64" + } + }, + { + "name": "policy", + "type": { + "option": { + "defined": "ModifyOrderPolicy" + } + } + } + ] + } + }, + { + "name": "InsuranceClaim", + "type": { + "kind": "struct", + "fields": [ + { + "name": "revenueWithdrawSinceLastSettle", + "docs": [ + "The amount of revenue last settled", + "Positive if funds left the perp market,", + "negative if funds were pulled into the perp market", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "maxRevenueWithdrawPerPeriod", + "docs": [ + "The max amount of revenue that can be withdrawn per period", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "quoteMaxInsurance", + "docs": [ + "The max amount of insurance that perp market can use to resolve bankruptcy and pnl deficits", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "quoteSettledInsurance", + "docs": [ + "The amount of insurance that has been used to resolve bankruptcy and pnl deficits", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastRevenueWithdrawTs", + "docs": [ + "The last time revenue was settled in/out of market" + ], + "type": "i64" + } + ] + } + }, + { + "name": "PoolBalance", + "type": { + "kind": "struct", + "fields": [ + { + "name": "scaledBalance", + "docs": [ + "To get the pool's token amount, you must multiply the scaled balance by the market's cumulative", + "deposit interest", + "precision: SPOT_BALANCE_PRECISION" + ], + "type": "u128" + }, + { + "name": "marketIndex", + "docs": [ + "The spot market the pool is for" + ], + "type": "u16" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 6 + ] + } + } + ] + } + }, + { + "name": "AMM", + "type": { + "kind": "struct", + "fields": [ + { + "name": "oracle", + "docs": [ + "oracle price data public key" + ], + "type": "publicKey" + }, + { + "name": "historicalOracleData", + "docs": [ + "stores historically witnessed oracle data" + ], + "type": { + "defined": "HistoricalOracleData" + } + }, + { + "name": "baseAssetAmountPerLp", + "docs": [ + "accumulated base asset amount since inception per lp share", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "quoteAssetAmountPerLp", + "docs": [ + "accumulated quote asset amount since inception per lp share", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "feePool", + "docs": [ + "partition of fees from perp market trading moved from pnl settlements" + ], + "type": { + "defined": "PoolBalance" + } + }, + { + "name": "baseAssetReserve", + "docs": [ + "`x` reserves for constant product mm formula (x * y = k)", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "quoteAssetReserve", + "docs": [ + "`y` reserves for constant product mm formula (x * y = k)", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "concentrationCoef", + "docs": [ + "determines how close the min/max base asset reserve sit vs base reserves", + "allow for decreasing slippage without increasing liquidity and v.v.", + "precision: PERCENTAGE_PRECISION" + ], + "type": "u128" + }, + { + "name": "minBaseAssetReserve", + "docs": [ + "minimum base_asset_reserve allowed before AMM is unavailable", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "maxBaseAssetReserve", + "docs": [ + "maximum base_asset_reserve allowed before AMM is unavailable", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "sqrtK", + "docs": [ + "`sqrt(k)` in constant product mm formula (x * y = k). stored to avoid drift caused by integer math issues", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "pegMultiplier", + "docs": [ + "normalizing numerical factor for y, its use offers lowest slippage in cp-curve when market is balanced", + "precision: PEG_PRECISION" + ], + "type": "u128" + }, + { + "name": "terminalQuoteAssetReserve", + "docs": [ + "y when market is balanced. stored to save computation", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "baseAssetAmountLong", + "docs": [ + "always non-negative. tracks number of total longs in market (regardless of counterparty)", + "precision: BASE_PRECISION" + ], + "type": "i128" + }, + { + "name": "baseAssetAmountShort", + "docs": [ + "always non-positive. tracks number of total shorts in market (regardless of counterparty)", + "precision: BASE_PRECISION" + ], + "type": "i128" + }, + { + "name": "baseAssetAmountWithAmm", + "docs": [ + "tracks net position (longs-shorts) in market with AMM as counterparty", + "precision: BASE_PRECISION" + ], + "type": "i128" + }, + { + "name": "baseAssetAmountWithUnsettledLp", + "docs": [ + "tracks net position (longs-shorts) in market with LPs as counterparty", + "precision: BASE_PRECISION" + ], + "type": "i128" + }, + { + "name": "maxOpenInterest", + "docs": [ + "max allowed open interest, blocks trades that breach this value", + "precision: BASE_PRECISION" + ], + "type": "u128" + }, + { + "name": "quoteAssetAmount", + "docs": [ + "sum of all user's perp quote_asset_amount in market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "quoteEntryAmountLong", + "docs": [ + "sum of all long user's quote_entry_amount in market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "quoteEntryAmountShort", + "docs": [ + "sum of all short user's quote_entry_amount in market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "quoteBreakEvenAmountLong", + "docs": [ + "sum of all long user's quote_break_even_amount in market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "quoteBreakEvenAmountShort", + "docs": [ + "sum of all short user's quote_break_even_amount in market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "userLpShares", + "docs": [ + "total user lp shares of sqrt_k (protocol owned liquidity = sqrt_k - last_funding_rate)", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "lastFundingRate", + "docs": [ + "last funding rate in this perp market (unit is quote per base)", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastFundingRateLong", + "docs": [ + "last funding rate for longs in this perp market (unit is quote per base)", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastFundingRateShort", + "docs": [ + "last funding rate for shorts in this perp market (unit is quote per base)", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "last24hAvgFundingRate", + "docs": [ + "estimate of last 24h of funding rate perp market (unit is quote per base)", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "totalFee", + "docs": [ + "total fees collected by this perp market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "totalMmFee", + "docs": [ + "total fees collected by the vAMM's bid/ask spread", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "totalExchangeFee", + "docs": [ + "total fees collected by exchange fee schedule", + "precision: QUOTE_PRECISION" + ], + "type": "u128" + }, + { + "name": "totalFeeMinusDistributions", + "docs": [ + "total fees minus any recognized upnl and pool withdraws", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "totalFeeWithdrawn", + "docs": [ + "sum of all fees from fee pool withdrawn to revenue pool", + "precision: QUOTE_PRECISION" + ], + "type": "u128" + }, + { + "name": "totalLiquidationFee", + "docs": [ + "all fees collected by market for liquidations", + "precision: QUOTE_PRECISION" + ], + "type": "u128" + }, + { + "name": "cumulativeFundingRateLong", + "docs": [ + "accumulated funding rate for longs since inception in market" + ], + "type": "i128" + }, + { + "name": "cumulativeFundingRateShort", + "docs": [ + "accumulated funding rate for shorts since inception in market" + ], + "type": "i128" + }, + { + "name": "totalSocialLoss", + "docs": [ + "accumulated social loss paid by users since inception in market" + ], + "type": "u128" + }, + { + "name": "askBaseAssetReserve", + "docs": [ + "transformed base_asset_reserve for users going long", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "askQuoteAssetReserve", + "docs": [ + "transformed quote_asset_reserve for users going long", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "bidBaseAssetReserve", + "docs": [ + "transformed base_asset_reserve for users going short", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "bidQuoteAssetReserve", + "docs": [ + "transformed quote_asset_reserve for users going short", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "lastOracleNormalisedPrice", + "docs": [ + "the last seen oracle price partially shrunk toward the amm reserve price", + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastOracleReservePriceSpreadPct", + "docs": [ + "the gap between the oracle price and the reserve price = y * peg_multiplier / x" + ], + "type": "i64" + }, + { + "name": "lastBidPriceTwap", + "docs": [ + "average estimate of bid price over funding_period", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastAskPriceTwap", + "docs": [ + "average estimate of ask price over funding_period", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastMarkPriceTwap", + "docs": [ + "average estimate of (bid+ask)/2 price over funding_period", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastMarkPriceTwap5min", + "docs": [ + "average estimate of (bid+ask)/2 price over FIVE_MINUTES" + ], + "type": "u64" + }, + { + "name": "lastUpdateSlot", + "docs": [ + "the last blockchain slot the amm was updated" + ], + "type": "u64" + }, + { + "name": "lastOracleConfPct", + "docs": [ + "the pct size of the oracle confidence interval", + "precision: PERCENTAGE_PRECISION" + ], + "type": "u64" + }, + { + "name": "netRevenueSinceLastFunding", + "docs": [ + "the total_fee_minus_distribution change since the last funding update", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastFundingRateTs", + "docs": [ + "the last funding rate update unix_timestamp" + ], + "type": "i64" + }, + { + "name": "fundingPeriod", + "docs": [ + "the peridocity of the funding rate updates" + ], + "type": "i64" + }, + { + "name": "orderStepSize", + "docs": [ + "the base step size (increment) of orders", + "precision: BASE_PRECISION" + ], + "type": "u64" + }, + { + "name": "orderTickSize", + "docs": [ + "the price tick size of orders", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "minOrderSize", + "docs": [ + "the minimum base size of an order", + "precision: BASE_PRECISION" + ], + "type": "u64" + }, + { + "name": "maxPositionSize", + "docs": [ + "the max base size a single user can have", + "precision: BASE_PRECISION" + ], + "type": "u64" + }, + { + "name": "volume24h", + "docs": [ + "estimated total of volume in market", + "QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "longIntensityVolume", + "docs": [ + "the volume intensity of long fills against AMM" + ], + "type": "u64" + }, + { + "name": "shortIntensityVolume", + "docs": [ + "the volume intensity of short fills against AMM" + ], + "type": "u64" + }, + { + "name": "lastTradeTs", + "docs": [ + "the blockchain unix timestamp at the time of the last trade" + ], + "type": "i64" + }, + { + "name": "markStd", + "docs": [ + "estimate of standard deviation of the fill (mark) prices", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "oracleStd", + "docs": [ + "estimate of standard deviation of the oracle price at each update", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastMarkPriceTwapTs", + "docs": [ + "the last unix_timestamp the mark twap was updated" + ], + "type": "i64" + }, + { + "name": "baseSpread", + "docs": [ + "the minimum spread the AMM can quote. also used as step size for some spread logic increases." + ], + "type": "u32" + }, + { + "name": "maxSpread", + "docs": [ + "the maximum spread the AMM can quote" + ], + "type": "u32" + }, + { + "name": "longSpread", + "docs": [ + "the spread for asks vs the reserve price" + ], + "type": "u32" + }, + { + "name": "shortSpread", + "docs": [ + "the spread for bids vs the reserve price" + ], + "type": "u32" + }, + { + "name": "longIntensityCount", + "docs": [ + "the count intensity of long fills against AMM" + ], + "type": "u32" + }, + { + "name": "shortIntensityCount", + "docs": [ + "the count intensity of short fills against AMM" + ], + "type": "u32" + }, + { + "name": "maxFillReserveFraction", + "docs": [ + "the fraction of total available liquidity a single fill on the AMM can consume" + ], + "type": "u16" + }, + { + "name": "maxSlippageRatio", + "docs": [ + "the maximum slippage a single fill on the AMM can push" + ], + "type": "u16" + }, + { + "name": "curveUpdateIntensity", + "docs": [ + "the update intensity of AMM formulaic updates (adjusting k). 0-100" + ], + "type": "u8" + }, + { + "name": "ammJitIntensity", + "docs": [ + "the jit intensity of AMM. larger intensity means larger participation in jit. 0 means no jit participation.", + "(0, 100] is intensity for protocol-owned AMM. (100, 200] is intensity for user LP-owned AMM." + ], + "type": "u8" + }, + { + "name": "oracleSource", + "docs": [ + "the oracle provider information. used to decode/scale the oracle public key" + ], + "type": { + "defined": "OracleSource" + } + }, + { + "name": "lastOracleValid", + "docs": [ + "tracks whether the oracle was considered valid at the last AMM update" + ], + "type": "bool" + }, + { + "name": "targetBaseAssetAmountPerLp", + "docs": [ + "the target value for `base_asset_amount_per_lp`, used during AMM JIT with LP split", + "precision: BASE_PRECISION" + ], + "type": "i32" + }, + { + "name": "perLpBase", + "docs": [ + "expo for unit of per_lp, base 10 (if per_lp_base=X, then per_lp unit is 10^X)" + ], + "type": "i8" + }, + { + "name": "padding1", + "type": "u8" + }, + { + "name": "padding2", + "type": "u16" + }, + { + "name": "totalFeeEarnedPerLp", + "type": "u64" + }, + { + "name": "netUnsettledFundingPnl", + "type": "i64" + }, + { + "name": "quoteAssetAmountWithUnsettledLp", + "type": "i64" + }, + { + "name": "referencePriceOffset", + "type": "i32" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 12 + ] + } + } + ] + } + }, + { + "name": "InsuranceFund", + "type": { + "kind": "struct", + "fields": [ + { + "name": "vault", + "type": "publicKey" + }, + { + "name": "totalShares", + "type": "u128" + }, + { + "name": "userShares", + "type": "u128" + }, + { + "name": "sharesBase", + "type": "u128" + }, + { + "name": "unstakingPeriod", + "type": "i64" + }, + { + "name": "lastRevenueSettleTs", + "type": "i64" + }, + { + "name": "revenueSettlePeriod", + "type": "i64" + }, + { + "name": "totalFactor", + "type": "u32" + }, + { + "name": "userFactor", + "type": "u32" + } + ] + } + }, + { + "name": "OracleGuardRails", + "type": { + "kind": "struct", + "fields": [ + { + "name": "priceDivergence", + "type": { + "defined": "PriceDivergenceGuardRails" + } + }, + { + "name": "validity", + "type": { + "defined": "ValidityGuardRails" + } + } + ] + } + }, + { + "name": "PriceDivergenceGuardRails", + "type": { + "kind": "struct", + "fields": [ + { + "name": "markOraclePercentDivergence", + "type": "u64" + }, + { + "name": "oracleTwap5minPercentDivergence", + "type": "u64" + } + ] + } + }, + { + "name": "ValidityGuardRails", + "type": { + "kind": "struct", + "fields": [ + { + "name": "slotsBeforeStaleForAmm", + "type": "i64" + }, + { + "name": "slotsBeforeStaleForMargin", + "type": "i64" + }, + { + "name": "confidenceIntervalMaxSize", + "type": "u64" + }, + { + "name": "tooVolatileRatio", + "type": "i64" + } + ] + } + }, + { + "name": "FeeStructure", + "type": { + "kind": "struct", + "fields": [ + { + "name": "feeTiers", + "type": { + "array": [ + { + "defined": "FeeTier" + }, + 10 + ] + } + }, + { + "name": "fillerRewardStructure", + "type": { + "defined": "OrderFillerRewardStructure" + } + }, + { + "name": "referrerRewardEpochUpperBound", + "type": "u64" + }, + { + "name": "flatFillerFee", + "type": "u64" + } + ] + } + }, + { + "name": "FeeTier", + "type": { + "kind": "struct", + "fields": [ + { + "name": "feeNumerator", + "type": "u32" + }, + { + "name": "feeDenominator", + "type": "u32" + }, + { + "name": "makerRebateNumerator", + "type": "u32" + }, + { + "name": "makerRebateDenominator", + "type": "u32" + }, + { + "name": "referrerRewardNumerator", + "type": "u32" + }, + { + "name": "referrerRewardDenominator", + "type": "u32" + }, + { + "name": "refereeFeeNumerator", + "type": "u32" + }, + { + "name": "refereeFeeDenominator", + "type": "u32" + } + ] + } + }, + { + "name": "OrderFillerRewardStructure", + "type": { + "kind": "struct", + "fields": [ + { + "name": "rewardNumerator", + "type": "u32" + }, + { + "name": "rewardDenominator", + "type": "u32" + }, + { + "name": "timeBasedRewardLowerBound", + "type": "u128" + } + ] + } + }, + { + "name": "UserFees", + "type": { + "kind": "struct", + "fields": [ + { + "name": "totalFeePaid", + "docs": [ + "Total taker fee paid", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalFeeRebate", + "docs": [ + "Total maker fee rebate", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalTokenDiscount", + "docs": [ + "Total discount from holding token", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalRefereeDiscount", + "docs": [ + "Total discount from being referred", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalReferrerReward", + "docs": [ + "Total reward to referrer", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "currentEpochReferrerReward", + "docs": [ + "Total reward to referrer this epoch", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + } + ] + } + }, + { + "name": "SpotPosition", + "type": { + "kind": "struct", + "fields": [ + { + "name": "scaledBalance", + "docs": [ + "The scaled balance of the position. To get the token amount, multiply by the cumulative deposit/borrow", + "interest of corresponding market.", + "precision: SPOT_BALANCE_PRECISION" + ], + "type": "u64" + }, + { + "name": "openBids", + "docs": [ + "How many spot bids the user has open", + "precision: token mint precision" + ], + "type": "i64" + }, + { + "name": "openAsks", + "docs": [ + "How many spot asks the user has open", + "precision: token mint precision" + ], + "type": "i64" + }, + { + "name": "cumulativeDeposits", + "docs": [ + "The cumulative deposits/borrows a user has made into a market", + "precision: token mint precision" + ], + "type": "i64" + }, + { + "name": "marketIndex", + "docs": [ + "The market index of the corresponding spot market" + ], + "type": "u16" + }, + { + "name": "balanceType", + "docs": [ + "Whether the position is deposit or borrow" + ], + "type": { + "defined": "SpotBalanceType" + } + }, + { + "name": "openOrders", + "docs": [ + "Number of open orders" + ], + "type": "u8" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 4 + ] + } + } + ] + } + }, + { + "name": "PerpPosition", + "type": { + "kind": "struct", + "fields": [ + { + "name": "lastCumulativeFundingRate", + "docs": [ + "The perp market's last cumulative funding rate. Used to calculate the funding payment owed to user", + "precision: FUNDING_RATE_PRECISION" + ], + "type": "i64" + }, + { + "name": "baseAssetAmount", + "docs": [ + "the size of the users perp position", + "precision: BASE_PRECISION" + ], + "type": "i64" + }, + { + "name": "quoteAssetAmount", + "docs": [ + "Used to calculate the users pnl. Upon entry, is equal to base_asset_amount * avg entry price - fees", + "Updated when the user open/closes position or settles pnl. Includes fees/funding", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "quoteBreakEvenAmount", + "docs": [ + "The amount of quote the user would need to exit their position at to break even", + "Updated when the user open/closes position or settles pnl. Includes fees/funding", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "quoteEntryAmount", + "docs": [ + "The amount quote the user entered the position with. Equal to base asset amount * avg entry price", + "Updated when the user open/closes position. Excludes fees/funding", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "openBids", + "docs": [ + "The amount of open bids the user has in this perp market", + "precision: BASE_PRECISION" + ], + "type": "i64" + }, + { + "name": "openAsks", + "docs": [ + "The amount of open asks the user has in this perp market", + "precision: BASE_PRECISION" + ], + "type": "i64" + }, + { + "name": "settledPnl", + "docs": [ + "The amount of pnl settled in this market since opening the position", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lpShares", + "docs": [ + "The number of lp (liquidity provider) shares the user has in this perp market", + "LP shares allow users to provide liquidity via the AMM", + "precision: BASE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastBaseAssetAmountPerLp", + "docs": [ + "The last base asset amount per lp the amm had", + "Used to settle the users lp position", + "precision: BASE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastQuoteAssetAmountPerLp", + "docs": [ + "The last quote asset amount per lp the amm had", + "Used to settle the users lp position", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "remainderBaseAssetAmount", + "docs": [ + "Settling LP position can lead to a small amount of base asset being left over smaller than step size", + "This records that remainder so it can be settled later on", + "precision: BASE_PRECISION" + ], + "type": "i32" + }, + { + "name": "marketIndex", + "docs": [ + "The market index for the perp market" + ], + "type": "u16" + }, + { + "name": "openOrders", + "docs": [ + "The number of open orders" + ], + "type": "u8" + }, + { + "name": "perLpBase", + "type": "i8" + } + ] + } + }, + { + "name": "Order", + "type": { + "kind": "struct", + "fields": [ + { + "name": "slot", + "docs": [ + "The slot the order was placed" + ], + "type": "u64" + }, + { + "name": "price", + "docs": [ + "The limit price for the order (can be 0 for market orders)", + "For orders with an auction, this price isn't used until the auction is complete", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "baseAssetAmount", + "docs": [ + "The size of the order", + "precision for perps: BASE_PRECISION", + "precision for spot: token mint precision" + ], + "type": "u64" + }, + { + "name": "baseAssetAmountFilled", + "docs": [ + "The amount of the order filled", + "precision for perps: BASE_PRECISION", + "precision for spot: token mint precision" + ], + "type": "u64" + }, + { + "name": "quoteAssetAmountFilled", + "docs": [ + "The amount of quote filled for the order", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "triggerPrice", + "docs": [ + "At what price the order will be triggered. Only relevant for trigger orders", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "auctionStartPrice", + "docs": [ + "The start price for the auction. Only relevant for market/oracle orders", + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "auctionEndPrice", + "docs": [ + "The end price for the auction. Only relevant for market/oracle orders", + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "maxTs", + "docs": [ + "The time when the order will expire" + ], + "type": "i64" + }, + { + "name": "oraclePriceOffset", + "docs": [ + "If set, the order limit price is the oracle price + this offset", + "precision: PRICE_PRECISION" + ], + "type": "i32" + }, + { + "name": "orderId", + "docs": [ + "The id for the order. Each users has their own order id space" + ], + "type": "u32" + }, + { + "name": "marketIndex", + "docs": [ + "The perp/spot market index" + ], + "type": "u16" + }, + { + "name": "status", + "docs": [ + "Whether the order is open or unused" + ], + "type": { + "defined": "OrderStatus" + } + }, + { + "name": "orderType", + "docs": [ + "The type of order" + ], + "type": { + "defined": "OrderType" + } + }, + { + "name": "marketType", + "docs": [ + "Whether market is spot or perp" + ], + "type": { + "defined": "MarketType" + } + }, + { + "name": "userOrderId", + "docs": [ + "User generated order id. Can make it easier to place/cancel orders" + ], + "type": "u8" + }, + { + "name": "existingPositionDirection", + "docs": [ + "What the users position was when the order was placed" + ], + "type": { + "defined": "PositionDirection" + } + }, + { + "name": "direction", + "docs": [ + "Whether the user is going long or short. LONG = bid, SHORT = ask" + ], + "type": { + "defined": "PositionDirection" + } + }, + { + "name": "reduceOnly", + "docs": [ + "Whether the order is allowed to only reduce position size" + ], + "type": "bool" + }, + { + "name": "postOnly", + "docs": [ + "Whether the order must be a maker" + ], + "type": "bool" + }, + { + "name": "immediateOrCancel", + "docs": [ + "Whether the order must be canceled the same slot it is placed" + ], + "type": "bool" + }, + { + "name": "triggerCondition", + "docs": [ + "Whether the order is triggered above or below the trigger price. Only relevant for trigger orders" + ], + "type": { + "defined": "OrderTriggerCondition" + } + }, + { + "name": "auctionDuration", + "docs": [ + "How many slots the auction lasts" + ], + "type": "u8" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 3 + ] + } + } + ] + } + }, + { + "name": "SwapDirection", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Add" + }, + { + "name": "Remove" + } + ] + } + }, + { + "name": "ModifyOrderId", + "type": { + "kind": "enum", + "variants": [ + { + "name": "UserOrderId", + "fields": [ + "u8" + ] + }, + { + "name": "OrderId", + "fields": [ + "u32" + ] + } + ] + } + }, + { + "name": "PositionDirection", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Long" + }, + { + "name": "Short" + } + ] + } + }, + { + "name": "SpotFulfillmentType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "SerumV3" + }, + { + "name": "Match" + }, + { + "name": "PhoenixV1" + }, + { + "name": "OpenbookV2" + } + ] + } + }, + { + "name": "SwapReduceOnly", + "type": { + "kind": "enum", + "variants": [ + { + "name": "In" + }, + { + "name": "Out" + } + ] + } + }, + { + "name": "TwapPeriod", + "type": { + "kind": "enum", + "variants": [ + { + "name": "FundingPeriod" + }, + { + "name": "FiveMin" + } + ] + } + }, + { + "name": "LiquidationMultiplierType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Discount" + }, + { + "name": "Premium" + } + ] + } + }, + { + "name": "MarginRequirementType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Initial" + }, + { + "name": "Fill" + }, + { + "name": "Maintenance" + } + ] + } + }, + { + "name": "OracleValidity", + "type": { + "kind": "enum", + "variants": [ + { + "name": "NonPositive" + }, + { + "name": "TooVolatile" + }, + { + "name": "TooUncertain" + }, + { + "name": "StaleForMargin" + }, + { + "name": "InsufficientDataPoints" + }, + { + "name": "StaleForAMM" + }, + { + "name": "Valid" + } + ] + } + }, + { + "name": "DriftAction", + "type": { + "kind": "enum", + "variants": [ + { + "name": "UpdateFunding" + }, + { + "name": "SettlePnl" + }, + { + "name": "TriggerOrder" + }, + { + "name": "FillOrderMatch" + }, + { + "name": "FillOrderAmm" + }, + { + "name": "Liquidate" + }, + { + "name": "MarginCalc" + }, + { + "name": "UpdateTwap" + }, + { + "name": "UpdateAMMCurve" + }, + { + "name": "OracleOrderPrice" + } + ] + } + }, + { + "name": "PositionUpdateType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Open" + }, + { + "name": "Increase" + }, + { + "name": "Reduce" + }, + { + "name": "Close" + }, + { + "name": "Flip" + } + ] + } + }, + { + "name": "DepositExplanation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "None" + }, + { + "name": "Transfer" + }, + { + "name": "Borrow" + }, + { + "name": "RepayBorrow" + } + ] + } + }, + { + "name": "DepositDirection", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Deposit" + }, + { + "name": "Withdraw" + } + ] + } + }, + { + "name": "OrderAction", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Place" + }, + { + "name": "Cancel" + }, + { + "name": "Fill" + }, + { + "name": "Trigger" + }, + { + "name": "Expire" + } + ] + } + }, + { + "name": "OrderActionExplanation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "None" + }, + { + "name": "InsufficientFreeCollateral" + }, + { + "name": "OraclePriceBreachedLimitPrice" + }, + { + "name": "MarketOrderFilledToLimitPrice" + }, + { + "name": "OrderExpired" + }, + { + "name": "Liquidation" + }, + { + "name": "OrderFilledWithAMM" + }, + { + "name": "OrderFilledWithAMMJit" + }, + { + "name": "OrderFilledWithMatch" + }, + { + "name": "OrderFilledWithMatchJit" + }, + { + "name": "MarketExpired" + }, + { + "name": "RiskingIncreasingOrder" + }, + { + "name": "ReduceOnlyOrderIncreasedPosition" + }, + { + "name": "OrderFillWithSerum" + }, + { + "name": "NoBorrowLiquidity" + }, + { + "name": "OrderFillWithPhoenix" + }, + { + "name": "OrderFilledWithAMMJitLPSplit" + }, + { + "name": "OrderFilledWithLPJit" + }, + { + "name": "DeriskLp" + }, + { + "name": "OrderFilledWithOpenbookV2" + } + ] + } + }, + { + "name": "LPAction", + "type": { + "kind": "enum", + "variants": [ + { + "name": "AddLiquidity" + }, + { + "name": "RemoveLiquidity" + }, + { + "name": "SettleLiquidity" + }, + { + "name": "RemoveLiquidityDerisk" + } + ] + } + }, + { + "name": "LiquidationType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "LiquidatePerp" + }, + { + "name": "LiquidateSpot" + }, + { + "name": "LiquidateBorrowForPerpPnl" + }, + { + "name": "LiquidatePerpPnlForDeposit" + }, + { + "name": "PerpBankruptcy" + }, + { + "name": "SpotBankruptcy" + } + ] + } + }, + { + "name": "SettlePnlExplanation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "None" + }, + { + "name": "ExpiredPosition" + } + ] + } + }, + { + "name": "StakeAction", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Stake" + }, + { + "name": "UnstakeRequest" + }, + { + "name": "UnstakeCancelRequest" + }, + { + "name": "Unstake" + }, + { + "name": "UnstakeTransfer" + }, + { + "name": "StakeTransfer" + } + ] + } + }, + { + "name": "FillMode", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Fill" + }, + { + "name": "PlaceAndMake" + }, + { + "name": "PlaceAndTake" + }, + { + "name": "Liquidation" + } + ] + } + }, + { + "name": "PerpFulfillmentMethod", + "type": { + "kind": "enum", + "variants": [ + { + "name": "AMM", + "fields": [ + { + "option": "u64" + } + ] + }, + { + "name": "Match", + "fields": [ + "publicKey", + "u16" + ] + } + ] + } + }, + { + "name": "SpotFulfillmentMethod", + "type": { + "kind": "enum", + "variants": [ + { + "name": "ExternalMarket" + }, + { + "name": "Match", + "fields": [ + "publicKey", + "u16" + ] + } + ] + } + }, + { + "name": "MarginCalculationMode", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Standard", + "fields": [ + { + "name": "trackOpenOrdersFraction", + "type": "bool" + } + ] + }, + { + "name": "Liquidation", + "fields": [ + { + "name": "marketToTrackMarginRequirement", + "type": { + "option": { + "defined": "MarketIdentifier" + } + } + } + ] + } + ] + } + }, + { + "name": "OracleSource", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Pyth" + }, + { + "name": "Switchboard" + }, + { + "name": "QuoteAsset" + }, + { + "name": "Pyth1K" + }, + { + "name": "Pyth1M" + }, + { + "name": "PythStableCoin" + }, + { + "name": "Prelaunch" + }, + { + "name": "PythPull" + }, + { + "name": "Pyth1KPull" + }, + { + "name": "Pyth1MPull" + }, + { + "name": "PythStableCoinPull" + }, + { + "name": "SwitchboardOnDemand" + } + ] + } + }, + { + "name": "PostOnlyParam", + "type": { + "kind": "enum", + "variants": [ + { + "name": "None" + }, + { + "name": "MustPostOnly" + }, + { + "name": "TryPostOnly" + }, + { + "name": "Slide" + } + ] + } + }, + { + "name": "ModifyOrderPolicy", + "type": { + "kind": "enum", + "variants": [ + { + "name": "TryModify" + }, + { + "name": "MustModify" + } + ] + } + }, + { + "name": "PerpOperation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "UpdateFunding" + }, + { + "name": "AmmFill" + }, + { + "name": "Fill" + }, + { + "name": "SettlePnl" + }, + { + "name": "SettlePnlWithPosition" + }, + { + "name": "Liquidation" + } + ] + } + }, + { + "name": "SpotOperation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "UpdateCumulativeInterest" + }, + { + "name": "Fill" + }, + { + "name": "Deposit" + }, + { + "name": "Withdraw" + }, + { + "name": "Liquidation" + } + ] + } + }, + { + "name": "InsuranceFundOperation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Init" + }, + { + "name": "Add" + }, + { + "name": "RequestRemove" + }, + { + "name": "Remove" + } + ] + } + }, + { + "name": "MarketStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Initialized" + }, + { + "name": "Active" + }, + { + "name": "FundingPaused" + }, + { + "name": "AmmPaused" + }, + { + "name": "FillPaused" + }, + { + "name": "WithdrawPaused" + }, + { + "name": "ReduceOnly" + }, + { + "name": "Settlement" + }, + { + "name": "Delisted" + } + ] + } + }, + { + "name": "ContractType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Perpetual" + }, + { + "name": "Future" + }, + { + "name": "Prediction" + } + ] + } + }, + { + "name": "ContractTier", + "type": { + "kind": "enum", + "variants": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "Speculative" + }, + { + "name": "HighlySpeculative" + }, + { + "name": "Isolated" + } + ] + } + }, + { + "name": "AMMLiquiditySplit", + "type": { + "kind": "enum", + "variants": [ + { + "name": "ProtocolOwned" + }, + { + "name": "LPOwned" + }, + { + "name": "Shared" + } + ] + } + }, + { + "name": "SettlePnlMode", + "type": { + "kind": "enum", + "variants": [ + { + "name": "MustSettle" + }, + { + "name": "TrySettle" + } + ] + } + }, + { + "name": "SpotBalanceType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Deposit" + }, + { + "name": "Borrow" + } + ] + } + }, + { + "name": "SpotFulfillmentConfigStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Enabled" + }, + { + "name": "Disabled" + } + ] + } + }, + { + "name": "AssetTier", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Collateral" + }, + { + "name": "Protected" + }, + { + "name": "Cross" + }, + { + "name": "Isolated" + }, + { + "name": "Unlisted" + } + ] + } + }, + { + "name": "ExchangeStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "DepositPaused" + }, + { + "name": "WithdrawPaused" + }, + { + "name": "AmmPaused" + }, + { + "name": "FillPaused" + }, + { + "name": "LiqPaused" + }, + { + "name": "FundingPaused" + }, + { + "name": "SettlePnlPaused" + } + ] + } + }, + { + "name": "UserStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "BeingLiquidated" + }, + { + "name": "Bankrupt" + }, + { + "name": "ReduceOnly" + }, + { + "name": "AdvancedLp" + } + ] + } + }, + { + "name": "AssetType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Base" + }, + { + "name": "Quote" + } + ] + } + }, + { + "name": "OrderStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Init" + }, + { + "name": "Open" + }, + { + "name": "Filled" + }, + { + "name": "Canceled" + } + ] + } + }, + { + "name": "OrderType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Market" + }, + { + "name": "Limit" + }, + { + "name": "TriggerMarket" + }, + { + "name": "TriggerLimit" + }, + { + "name": "Oracle" + } + ] + } + }, + { + "name": "OrderTriggerCondition", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Above" + }, + { + "name": "Below" + }, + { + "name": "TriggeredAbove" + }, + { + "name": "TriggeredBelow" + } + ] + } + }, + { + "name": "MarketType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Spot" + }, + { + "name": "Perp" + } + ] + } + } + ], + "events": [ + { + "name": "NewUserRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "userAuthority", + "type": "publicKey", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "subAccountId", + "type": "u16", + "index": false + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + }, + "index": false + }, + { + "name": "referrer", + "type": "publicKey", + "index": false + } + ] + }, + { + "name": "DepositRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "userAuthority", + "type": "publicKey", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "direction", + "type": { + "defined": "DepositDirection" + }, + "index": false + }, + { + "name": "depositRecordId", + "type": "u64", + "index": false + }, + { + "name": "amount", + "type": "u64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "oraclePrice", + "type": "i64", + "index": false + }, + { + "name": "marketDepositBalance", + "type": "u128", + "index": false + }, + { + "name": "marketWithdrawBalance", + "type": "u128", + "index": false + }, + { + "name": "marketCumulativeDepositInterest", + "type": "u128", + "index": false + }, + { + "name": "marketCumulativeBorrowInterest", + "type": "u128", + "index": false + }, + { + "name": "totalDepositsAfter", + "type": "u64", + "index": false + }, + { + "name": "totalWithdrawsAfter", + "type": "u64", + "index": false + }, + { + "name": "explanation", + "type": { + "defined": "DepositExplanation" + }, + "index": false + }, + { + "name": "transferUser", + "type": { + "option": "publicKey" + }, + "index": false + } + ] + }, + { + "name": "SpotInterestRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "depositBalance", + "type": "u128", + "index": false + }, + { + "name": "cumulativeDepositInterest", + "type": "u128", + "index": false + }, + { + "name": "borrowBalance", + "type": "u128", + "index": false + }, + { + "name": "cumulativeBorrowInterest", + "type": "u128", + "index": false + }, + { + "name": "optimalUtilization", + "type": "u32", + "index": false + }, + { + "name": "optimalBorrowRate", + "type": "u32", + "index": false + }, + { + "name": "maxBorrowRate", + "type": "u32", + "index": false + } + ] + }, + { + "name": "FundingPaymentRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "userAuthority", + "type": "publicKey", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "fundingPayment", + "type": "i64", + "index": false + }, + { + "name": "baseAssetAmount", + "type": "i64", + "index": false + }, + { + "name": "userLastCumulativeFunding", + "type": "i64", + "index": false + }, + { + "name": "ammCumulativeFundingLong", + "type": "i128", + "index": false + }, + { + "name": "ammCumulativeFundingShort", + "type": "i128", + "index": false + } + ] + }, + { + "name": "FundingRateRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "recordId", + "type": "u64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "fundingRate", + "type": "i64", + "index": false + }, + { + "name": "fundingRateLong", + "type": "i128", + "index": false + }, + { + "name": "fundingRateShort", + "type": "i128", + "index": false + }, + { + "name": "cumulativeFundingRateLong", + "type": "i128", + "index": false + }, + { + "name": "cumulativeFundingRateShort", + "type": "i128", + "index": false + }, + { + "name": "oraclePriceTwap", + "type": "i64", + "index": false + }, + { + "name": "markPriceTwap", + "type": "u64", + "index": false + }, + { + "name": "periodRevenue", + "type": "i64", + "index": false + }, + { + "name": "baseAssetAmountWithAmm", + "type": "i128", + "index": false + }, + { + "name": "baseAssetAmountWithUnsettledLp", + "type": "i128", + "index": false + } + ] + }, + { + "name": "CurveRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "recordId", + "type": "u64", + "index": false + }, + { + "name": "pegMultiplierBefore", + "type": "u128", + "index": false + }, + { + "name": "baseAssetReserveBefore", + "type": "u128", + "index": false + }, + { + "name": "quoteAssetReserveBefore", + "type": "u128", + "index": false + }, + { + "name": "sqrtKBefore", + "type": "u128", + "index": false + }, + { + "name": "pegMultiplierAfter", + "type": "u128", + "index": false + }, + { + "name": "baseAssetReserveAfter", + "type": "u128", + "index": false + }, + { + "name": "quoteAssetReserveAfter", + "type": "u128", + "index": false + }, + { + "name": "sqrtKAfter", + "type": "u128", + "index": false + }, + { + "name": "baseAssetAmountLong", + "type": "u128", + "index": false + }, + { + "name": "baseAssetAmountShort", + "type": "u128", + "index": false + }, + { + "name": "baseAssetAmountWithAmm", + "type": "i128", + "index": false + }, + { + "name": "totalFee", + "type": "i128", + "index": false + }, + { + "name": "totalFeeMinusDistributions", + "type": "i128", + "index": false + }, + { + "name": "adjustmentCost", + "type": "i128", + "index": false + }, + { + "name": "oraclePrice", + "type": "i64", + "index": false + }, + { + "name": "fillRecord", + "type": "u128", + "index": false + }, + { + "name": "numberOfUsers", + "type": "u32", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + } + ] + }, + { + "name": "OrderRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "order", + "type": { + "defined": "Order" + }, + "index": false + } + ] + }, + { + "name": "OrderActionRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "action", + "type": { + "defined": "OrderAction" + }, + "index": false + }, + { + "name": "actionExplanation", + "type": { + "defined": "OrderActionExplanation" + }, + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "marketType", + "type": { + "defined": "MarketType" + }, + "index": false + }, + { + "name": "filler", + "type": { + "option": "publicKey" + }, + "index": false + }, + { + "name": "fillerReward", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "fillRecordId", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "baseAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "quoteAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "takerFee", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "makerFee", + "type": { + "option": "i64" + }, + "index": false + }, + { + "name": "referrerReward", + "type": { + "option": "u32" + }, + "index": false + }, + { + "name": "quoteAssetAmountSurplus", + "type": { + "option": "i64" + }, + "index": false + }, + { + "name": "spotFulfillmentMethodFee", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "taker", + "type": { + "option": "publicKey" + }, + "index": false + }, + { + "name": "takerOrderId", + "type": { + "option": "u32" + }, + "index": false + }, + { + "name": "takerOrderDirection", + "type": { + "option": { + "defined": "PositionDirection" + } + }, + "index": false + }, + { + "name": "takerOrderBaseAssetAmount", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "takerOrderCumulativeBaseAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "takerOrderCumulativeQuoteAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "maker", + "type": { + "option": "publicKey" + }, + "index": false + }, + { + "name": "makerOrderId", + "type": { + "option": "u32" + }, + "index": false + }, + { + "name": "makerOrderDirection", + "type": { + "option": { + "defined": "PositionDirection" + } + }, + "index": false + }, + { + "name": "makerOrderBaseAssetAmount", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "makerOrderCumulativeBaseAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "makerOrderCumulativeQuoteAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "oraclePrice", + "type": "i64", + "index": false + } + ] + }, + { + "name": "LPRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "action", + "type": { + "defined": "LPAction" + }, + "index": false + }, + { + "name": "nShares", + "type": "u64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "deltaBaseAssetAmount", + "type": "i64", + "index": false + }, + { + "name": "deltaQuoteAssetAmount", + "type": "i64", + "index": false + }, + { + "name": "pnl", + "type": "i64", + "index": false + } + ] + }, + { + "name": "LiquidationRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "liquidationType", + "type": { + "defined": "LiquidationType" + }, + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "liquidator", + "type": "publicKey", + "index": false + }, + { + "name": "marginRequirement", + "type": "u128", + "index": false + }, + { + "name": "totalCollateral", + "type": "i128", + "index": false + }, + { + "name": "marginFreed", + "type": "u64", + "index": false + }, + { + "name": "liquidationId", + "type": "u16", + "index": false + }, + { + "name": "bankrupt", + "type": "bool", + "index": false + }, + { + "name": "canceledOrderIds", + "type": { + "vec": "u32" + }, + "index": false + }, + { + "name": "liquidatePerp", + "type": { + "defined": "LiquidatePerpRecord" + }, + "index": false + }, + { + "name": "liquidateSpot", + "type": { + "defined": "LiquidateSpotRecord" + }, + "index": false + }, + { + "name": "liquidateBorrowForPerpPnl", + "type": { + "defined": "LiquidateBorrowForPerpPnlRecord" + }, + "index": false + }, + { + "name": "liquidatePerpPnlForDeposit", + "type": { + "defined": "LiquidatePerpPnlForDepositRecord" + }, + "index": false + }, + { + "name": "perpBankruptcy", + "type": { + "defined": "PerpBankruptcyRecord" + }, + "index": false + }, + { + "name": "spotBankruptcy", + "type": { + "defined": "SpotBankruptcyRecord" + }, + "index": false + } + ] + }, + { + "name": "SettlePnlRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "pnl", + "type": "i128", + "index": false + }, + { + "name": "baseAssetAmount", + "type": "i64", + "index": false + }, + { + "name": "quoteAssetAmountAfter", + "type": "i64", + "index": false + }, + { + "name": "quoteEntryAmount", + "type": "i64", + "index": false + }, + { + "name": "settlePrice", + "type": "i64", + "index": false + }, + { + "name": "explanation", + "type": { + "defined": "SettlePnlExplanation" + }, + "index": false + } + ] + }, + { + "name": "InsuranceFundRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "spotMarketIndex", + "type": "u16", + "index": false + }, + { + "name": "perpMarketIndex", + "type": "u16", + "index": false + }, + { + "name": "userIfFactor", + "type": "u32", + "index": false + }, + { + "name": "totalIfFactor", + "type": "u32", + "index": false + }, + { + "name": "vaultAmountBefore", + "type": "u64", + "index": false + }, + { + "name": "insuranceVaultAmountBefore", + "type": "u64", + "index": false + }, + { + "name": "totalIfSharesBefore", + "type": "u128", + "index": false + }, + { + "name": "totalIfSharesAfter", + "type": "u128", + "index": false + }, + { + "name": "amount", + "type": "i64", + "index": false + } + ] + }, + { + "name": "InsuranceFundStakeRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "userAuthority", + "type": "publicKey", + "index": false + }, + { + "name": "action", + "type": { + "defined": "StakeAction" + }, + "index": false + }, + { + "name": "amount", + "type": "u64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "insuranceVaultAmountBefore", + "type": "u64", + "index": false + }, + { + "name": "ifSharesBefore", + "type": "u128", + "index": false + }, + { + "name": "userIfSharesBefore", + "type": "u128", + "index": false + }, + { + "name": "totalIfSharesBefore", + "type": "u128", + "index": false + }, + { + "name": "ifSharesAfter", + "type": "u128", + "index": false + }, + { + "name": "userIfSharesAfter", + "type": "u128", + "index": false + }, + { + "name": "totalIfSharesAfter", + "type": "u128", + "index": false + } + ] + }, + { + "name": "SwapRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "amountOut", + "type": "u64", + "index": false + }, + { + "name": "amountIn", + "type": "u64", + "index": false + }, + { + "name": "outMarketIndex", + "type": "u16", + "index": false + }, + { + "name": "inMarketIndex", + "type": "u16", + "index": false + }, + { + "name": "outOraclePrice", + "type": "i64", + "index": false + }, + { + "name": "inOraclePrice", + "type": "i64", + "index": false + }, + { + "name": "fee", + "type": "u64", + "index": false + } + ] + }, + { + "name": "SpotMarketVaultDepositRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "depositBalance", + "type": "u128", + "index": false + }, + { + "name": "cumulativeDepositInterestBefore", + "type": "u128", + "index": false + }, + { + "name": "cumulativeDepositInterestAfter", + "type": "u128", + "index": false + }, + { + "name": "depositTokenAmountBefore", + "type": "u64", + "index": false + }, + { + "name": "amount", + "type": "u64", + "index": false + } + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "InvalidSpotMarketAuthority", + "msg": "Invalid Spot Market Authority" + }, + { + "code": 6001, + "name": "InvalidInsuranceFundAuthority", + "msg": "Clearing house not insurance fund authority" + }, + { + "code": 6002, + "name": "InsufficientDeposit", + "msg": "Insufficient deposit" + }, + { + "code": 6003, + "name": "InsufficientCollateral", + "msg": "Insufficient collateral" + }, + { + "code": 6004, + "name": "SufficientCollateral", + "msg": "Sufficient collateral" + }, + { + "code": 6005, + "name": "MaxNumberOfPositions", + "msg": "Max number of positions taken" + }, + { + "code": 6006, + "name": "AdminControlsPricesDisabled", + "msg": "Admin Controls Prices Disabled" + }, + { + "code": 6007, + "name": "MarketDelisted", + "msg": "Market Delisted" + }, + { + "code": 6008, + "name": "MarketIndexAlreadyInitialized", + "msg": "Market Index Already Initialized" + }, + { + "code": 6009, + "name": "UserAccountAndUserPositionsAccountMismatch", + "msg": "User Account And User Positions Account Mismatch" + }, + { + "code": 6010, + "name": "UserHasNoPositionInMarket", + "msg": "User Has No Position In Market" + }, + { + "code": 6011, + "name": "InvalidInitialPeg", + "msg": "Invalid Initial Peg" + }, + { + "code": 6012, + "name": "InvalidRepegRedundant", + "msg": "AMM repeg already configured with amt given" + }, + { + "code": 6013, + "name": "InvalidRepegDirection", + "msg": "AMM repeg incorrect repeg direction" + }, + { + "code": 6014, + "name": "InvalidRepegProfitability", + "msg": "AMM repeg out of bounds pnl" + }, + { + "code": 6015, + "name": "SlippageOutsideLimit", + "msg": "Slippage Outside Limit Price" + }, + { + "code": 6016, + "name": "OrderSizeTooSmall", + "msg": "Order Size Too Small" + }, + { + "code": 6017, + "name": "InvalidUpdateK", + "msg": "Price change too large when updating K" + }, + { + "code": 6018, + "name": "AdminWithdrawTooLarge", + "msg": "Admin tried to withdraw amount larger than fees collected" + }, + { + "code": 6019, + "name": "MathError", + "msg": "Math Error" + }, + { + "code": 6020, + "name": "BnConversionError", + "msg": "Conversion to u128/u64 failed with an overflow or underflow" + }, + { + "code": 6021, + "name": "ClockUnavailable", + "msg": "Clock unavailable" + }, + { + "code": 6022, + "name": "UnableToLoadOracle", + "msg": "Unable To Load Oracles" + }, + { + "code": 6023, + "name": "PriceBandsBreached", + "msg": "Price Bands Breached" + }, + { + "code": 6024, + "name": "ExchangePaused", + "msg": "Exchange is paused" + }, + { + "code": 6025, + "name": "InvalidWhitelistToken", + "msg": "Invalid whitelist token" + }, + { + "code": 6026, + "name": "WhitelistTokenNotFound", + "msg": "Whitelist token not found" + }, + { + "code": 6027, + "name": "InvalidDiscountToken", + "msg": "Invalid discount token" + }, + { + "code": 6028, + "name": "DiscountTokenNotFound", + "msg": "Discount token not found" + }, + { + "code": 6029, + "name": "ReferrerNotFound", + "msg": "Referrer not found" + }, + { + "code": 6030, + "name": "ReferrerStatsNotFound", + "msg": "ReferrerNotFound" + }, + { + "code": 6031, + "name": "ReferrerMustBeWritable", + "msg": "ReferrerMustBeWritable" + }, + { + "code": 6032, + "name": "ReferrerStatsMustBeWritable", + "msg": "ReferrerMustBeWritable" + }, + { + "code": 6033, + "name": "ReferrerAndReferrerStatsAuthorityUnequal", + "msg": "ReferrerAndReferrerStatsAuthorityUnequal" + }, + { + "code": 6034, + "name": "InvalidReferrer", + "msg": "InvalidReferrer" + }, + { + "code": 6035, + "name": "InvalidOracle", + "msg": "InvalidOracle" + }, + { + "code": 6036, + "name": "OracleNotFound", + "msg": "OracleNotFound" + }, + { + "code": 6037, + "name": "LiquidationsBlockedByOracle", + "msg": "Liquidations Blocked By Oracle" + }, + { + "code": 6038, + "name": "MaxDeposit", + "msg": "Can not deposit more than max deposit" + }, + { + "code": 6039, + "name": "CantDeleteUserWithCollateral", + "msg": "Can not delete user that still has collateral" + }, + { + "code": 6040, + "name": "InvalidFundingProfitability", + "msg": "AMM funding out of bounds pnl" + }, + { + "code": 6041, + "name": "CastingFailure", + "msg": "Casting Failure" + }, + { + "code": 6042, + "name": "InvalidOrder", + "msg": "InvalidOrder" + }, + { + "code": 6043, + "name": "InvalidOrderMaxTs", + "msg": "InvalidOrderMaxTs" + }, + { + "code": 6044, + "name": "InvalidOrderMarketType", + "msg": "InvalidOrderMarketType" + }, + { + "code": 6045, + "name": "InvalidOrderForInitialMarginReq", + "msg": "InvalidOrderForInitialMarginReq" + }, + { + "code": 6046, + "name": "InvalidOrderNotRiskReducing", + "msg": "InvalidOrderNotRiskReducing" + }, + { + "code": 6047, + "name": "InvalidOrderSizeTooSmall", + "msg": "InvalidOrderSizeTooSmall" + }, + { + "code": 6048, + "name": "InvalidOrderNotStepSizeMultiple", + "msg": "InvalidOrderNotStepSizeMultiple" + }, + { + "code": 6049, + "name": "InvalidOrderBaseQuoteAsset", + "msg": "InvalidOrderBaseQuoteAsset" + }, + { + "code": 6050, + "name": "InvalidOrderIOC", + "msg": "InvalidOrderIOC" + }, + { + "code": 6051, + "name": "InvalidOrderPostOnly", + "msg": "InvalidOrderPostOnly" + }, + { + "code": 6052, + "name": "InvalidOrderIOCPostOnly", + "msg": "InvalidOrderIOCPostOnly" + }, + { + "code": 6053, + "name": "InvalidOrderTrigger", + "msg": "InvalidOrderTrigger" + }, + { + "code": 6054, + "name": "InvalidOrderAuction", + "msg": "InvalidOrderAuction" + }, + { + "code": 6055, + "name": "InvalidOrderOracleOffset", + "msg": "InvalidOrderOracleOffset" + }, + { + "code": 6056, + "name": "InvalidOrderMinOrderSize", + "msg": "InvalidOrderMinOrderSize" + }, + { + "code": 6057, + "name": "PlacePostOnlyLimitFailure", + "msg": "Failed to Place Post-Only Limit Order" + }, + { + "code": 6058, + "name": "UserHasNoOrder", + "msg": "User has no order" + }, + { + "code": 6059, + "name": "OrderAmountTooSmall", + "msg": "Order Amount Too Small" + }, + { + "code": 6060, + "name": "MaxNumberOfOrders", + "msg": "Max number of orders taken" + }, + { + "code": 6061, + "name": "OrderDoesNotExist", + "msg": "Order does not exist" + }, + { + "code": 6062, + "name": "OrderNotOpen", + "msg": "Order not open" + }, + { + "code": 6063, + "name": "FillOrderDidNotUpdateState", + "msg": "FillOrderDidNotUpdateState" + }, + { + "code": 6064, + "name": "ReduceOnlyOrderIncreasedRisk", + "msg": "Reduce only order increased risk" + }, + { + "code": 6065, + "name": "UnableToLoadAccountLoader", + "msg": "Unable to load AccountLoader" + }, + { + "code": 6066, + "name": "TradeSizeTooLarge", + "msg": "Trade Size Too Large" + }, + { + "code": 6067, + "name": "UserCantReferThemselves", + "msg": "User cant refer themselves" + }, + { + "code": 6068, + "name": "DidNotReceiveExpectedReferrer", + "msg": "Did not receive expected referrer" + }, + { + "code": 6069, + "name": "CouldNotDeserializeReferrer", + "msg": "Could not deserialize referrer" + }, + { + "code": 6070, + "name": "CouldNotDeserializeReferrerStats", + "msg": "Could not deserialize referrer stats" + }, + { + "code": 6071, + "name": "UserOrderIdAlreadyInUse", + "msg": "User Order Id Already In Use" + }, + { + "code": 6072, + "name": "NoPositionsLiquidatable", + "msg": "No positions liquidatable" + }, + { + "code": 6073, + "name": "InvalidMarginRatio", + "msg": "Invalid Margin Ratio" + }, + { + "code": 6074, + "name": "CantCancelPostOnlyOrder", + "msg": "Cant Cancel Post Only Order" + }, + { + "code": 6075, + "name": "InvalidOracleOffset", + "msg": "InvalidOracleOffset" + }, + { + "code": 6076, + "name": "CantExpireOrders", + "msg": "CantExpireOrders" + }, + { + "code": 6077, + "name": "CouldNotLoadMarketData", + "msg": "CouldNotLoadMarketData" + }, + { + "code": 6078, + "name": "PerpMarketNotFound", + "msg": "PerpMarketNotFound" + }, + { + "code": 6079, + "name": "InvalidMarketAccount", + "msg": "InvalidMarketAccount" + }, + { + "code": 6080, + "name": "UnableToLoadPerpMarketAccount", + "msg": "UnableToLoadMarketAccount" + }, + { + "code": 6081, + "name": "MarketWrongMutability", + "msg": "MarketWrongMutability" + }, + { + "code": 6082, + "name": "UnableToCastUnixTime", + "msg": "UnableToCastUnixTime" + }, + { + "code": 6083, + "name": "CouldNotFindSpotPosition", + "msg": "CouldNotFindSpotPosition" + }, + { + "code": 6084, + "name": "NoSpotPositionAvailable", + "msg": "NoSpotPositionAvailable" + }, + { + "code": 6085, + "name": "InvalidSpotMarketInitialization", + "msg": "InvalidSpotMarketInitialization" + }, + { + "code": 6086, + "name": "CouldNotLoadSpotMarketData", + "msg": "CouldNotLoadSpotMarketData" + }, + { + "code": 6087, + "name": "SpotMarketNotFound", + "msg": "SpotMarketNotFound" + }, + { + "code": 6088, + "name": "InvalidSpotMarketAccount", + "msg": "InvalidSpotMarketAccount" + }, + { + "code": 6089, + "name": "UnableToLoadSpotMarketAccount", + "msg": "UnableToLoadSpotMarketAccount" + }, + { + "code": 6090, + "name": "SpotMarketWrongMutability", + "msg": "SpotMarketWrongMutability" + }, + { + "code": 6091, + "name": "SpotMarketInterestNotUpToDate", + "msg": "SpotInterestNotUpToDate" + }, + { + "code": 6092, + "name": "SpotMarketInsufficientDeposits", + "msg": "SpotMarketInsufficientDeposits" + }, + { + "code": 6093, + "name": "UserMustSettleTheirOwnPositiveUnsettledPNL", + "msg": "UserMustSettleTheirOwnPositiveUnsettledPNL" + }, + { + "code": 6094, + "name": "CantUpdatePoolBalanceType", + "msg": "CantUpdatePoolBalanceType" + }, + { + "code": 6095, + "name": "InsufficientCollateralForSettlingPNL", + "msg": "InsufficientCollateralForSettlingPNL" + }, + { + "code": 6096, + "name": "AMMNotUpdatedInSameSlot", + "msg": "AMMNotUpdatedInSameSlot" + }, + { + "code": 6097, + "name": "AuctionNotComplete", + "msg": "AuctionNotComplete" + }, + { + "code": 6098, + "name": "MakerNotFound", + "msg": "MakerNotFound" + }, + { + "code": 6099, + "name": "MakerStatsNotFound", + "msg": "MakerNotFound" + }, + { + "code": 6100, + "name": "MakerMustBeWritable", + "msg": "MakerMustBeWritable" + }, + { + "code": 6101, + "name": "MakerStatsMustBeWritable", + "msg": "MakerMustBeWritable" + }, + { + "code": 6102, + "name": "MakerOrderNotFound", + "msg": "MakerOrderNotFound" + }, + { + "code": 6103, + "name": "CouldNotDeserializeMaker", + "msg": "CouldNotDeserializeMaker" + }, + { + "code": 6104, + "name": "CouldNotDeserializeMakerStats", + "msg": "CouldNotDeserializeMaker" + }, + { + "code": 6105, + "name": "AuctionPriceDoesNotSatisfyMaker", + "msg": "AuctionPriceDoesNotSatisfyMaker" + }, + { + "code": 6106, + "name": "MakerCantFulfillOwnOrder", + "msg": "MakerCantFulfillOwnOrder" + }, + { + "code": 6107, + "name": "MakerOrderMustBePostOnly", + "msg": "MakerOrderMustBePostOnly" + }, + { + "code": 6108, + "name": "CantMatchTwoPostOnlys", + "msg": "CantMatchTwoPostOnlys" + }, + { + "code": 6109, + "name": "OrderBreachesOraclePriceLimits", + "msg": "OrderBreachesOraclePriceLimits" + }, + { + "code": 6110, + "name": "OrderMustBeTriggeredFirst", + "msg": "OrderMustBeTriggeredFirst" + }, + { + "code": 6111, + "name": "OrderNotTriggerable", + "msg": "OrderNotTriggerable" + }, + { + "code": 6112, + "name": "OrderDidNotSatisfyTriggerCondition", + "msg": "OrderDidNotSatisfyTriggerCondition" + }, + { + "code": 6113, + "name": "PositionAlreadyBeingLiquidated", + "msg": "PositionAlreadyBeingLiquidated" + }, + { + "code": 6114, + "name": "PositionDoesntHaveOpenPositionOrOrders", + "msg": "PositionDoesntHaveOpenPositionOrOrders" + }, + { + "code": 6115, + "name": "AllOrdersAreAlreadyLiquidations", + "msg": "AllOrdersAreAlreadyLiquidations" + }, + { + "code": 6116, + "name": "CantCancelLiquidationOrder", + "msg": "CantCancelLiquidationOrder" + }, + { + "code": 6117, + "name": "UserIsBeingLiquidated", + "msg": "UserIsBeingLiquidated" + }, + { + "code": 6118, + "name": "LiquidationsOngoing", + "msg": "LiquidationsOngoing" + }, + { + "code": 6119, + "name": "WrongSpotBalanceType", + "msg": "WrongSpotBalanceType" + }, + { + "code": 6120, + "name": "UserCantLiquidateThemself", + "msg": "UserCantLiquidateThemself" + }, + { + "code": 6121, + "name": "InvalidPerpPositionToLiquidate", + "msg": "InvalidPerpPositionToLiquidate" + }, + { + "code": 6122, + "name": "InvalidBaseAssetAmountForLiquidatePerp", + "msg": "InvalidBaseAssetAmountForLiquidatePerp" + }, + { + "code": 6123, + "name": "InvalidPositionLastFundingRate", + "msg": "InvalidPositionLastFundingRate" + }, + { + "code": 6124, + "name": "InvalidPositionDelta", + "msg": "InvalidPositionDelta" + }, + { + "code": 6125, + "name": "UserBankrupt", + "msg": "UserBankrupt" + }, + { + "code": 6126, + "name": "UserNotBankrupt", + "msg": "UserNotBankrupt" + }, + { + "code": 6127, + "name": "UserHasInvalidBorrow", + "msg": "UserHasInvalidBorrow" + }, + { + "code": 6128, + "name": "DailyWithdrawLimit", + "msg": "DailyWithdrawLimit" + }, + { + "code": 6129, + "name": "DefaultError", + "msg": "DefaultError" + }, + { + "code": 6130, + "name": "InsufficientLPTokens", + "msg": "Insufficient LP tokens" + }, + { + "code": 6131, + "name": "CantLPWithPerpPosition", + "msg": "Cant LP with a market position" + }, + { + "code": 6132, + "name": "UnableToBurnLPTokens", + "msg": "Unable to burn LP tokens" + }, + { + "code": 6133, + "name": "TryingToRemoveLiquidityTooFast", + "msg": "Trying to remove liqudity too fast after adding it" + }, + { + "code": 6134, + "name": "InvalidSpotMarketVault", + "msg": "Invalid Spot Market Vault" + }, + { + "code": 6135, + "name": "InvalidSpotMarketState", + "msg": "Invalid Spot Market State" + }, + { + "code": 6136, + "name": "InvalidSerumProgram", + "msg": "InvalidSerumProgram" + }, + { + "code": 6137, + "name": "InvalidSerumMarket", + "msg": "InvalidSerumMarket" + }, + { + "code": 6138, + "name": "InvalidSerumBids", + "msg": "InvalidSerumBids" + }, + { + "code": 6139, + "name": "InvalidSerumAsks", + "msg": "InvalidSerumAsks" + }, + { + "code": 6140, + "name": "InvalidSerumOpenOrders", + "msg": "InvalidSerumOpenOrders" + }, + { + "code": 6141, + "name": "FailedSerumCPI", + "msg": "FailedSerumCPI" + }, + { + "code": 6142, + "name": "FailedToFillOnExternalMarket", + "msg": "FailedToFillOnExternalMarket" + }, + { + "code": 6143, + "name": "InvalidFulfillmentConfig", + "msg": "InvalidFulfillmentConfig" + }, + { + "code": 6144, + "name": "InvalidFeeStructure", + "msg": "InvalidFeeStructure" + }, + { + "code": 6145, + "name": "InsufficientIFShares", + "msg": "Insufficient IF shares" + }, + { + "code": 6146, + "name": "MarketActionPaused", + "msg": "the Market has paused this action" + }, + { + "code": 6147, + "name": "MarketPlaceOrderPaused", + "msg": "the Market status doesnt allow placing orders" + }, + { + "code": 6148, + "name": "MarketFillOrderPaused", + "msg": "the Market status doesnt allow filling orders" + }, + { + "code": 6149, + "name": "MarketWithdrawPaused", + "msg": "the Market status doesnt allow withdraws" + }, + { + "code": 6150, + "name": "ProtectedAssetTierViolation", + "msg": "Action violates the Protected Asset Tier rules" + }, + { + "code": 6151, + "name": "IsolatedAssetTierViolation", + "msg": "Action violates the Isolated Asset Tier rules" + }, + { + "code": 6152, + "name": "UserCantBeDeleted", + "msg": "User Cant Be Deleted" + }, + { + "code": 6153, + "name": "ReduceOnlyWithdrawIncreasedRisk", + "msg": "Reduce Only Withdraw Increased Risk" + }, + { + "code": 6154, + "name": "MaxOpenInterest", + "msg": "Max Open Interest" + }, + { + "code": 6155, + "name": "CantResolvePerpBankruptcy", + "msg": "Cant Resolve Perp Bankruptcy" + }, + { + "code": 6156, + "name": "LiquidationDoesntSatisfyLimitPrice", + "msg": "Liquidation Doesnt Satisfy Limit Price" + }, + { + "code": 6157, + "name": "MarginTradingDisabled", + "msg": "Margin Trading Disabled" + }, + { + "code": 6158, + "name": "InvalidMarketStatusToSettlePnl", + "msg": "Invalid Market Status to Settle Perp Pnl" + }, + { + "code": 6159, + "name": "PerpMarketNotInSettlement", + "msg": "PerpMarketNotInSettlement" + }, + { + "code": 6160, + "name": "PerpMarketNotInReduceOnly", + "msg": "PerpMarketNotInReduceOnly" + }, + { + "code": 6161, + "name": "PerpMarketSettlementBufferNotReached", + "msg": "PerpMarketSettlementBufferNotReached" + }, + { + "code": 6162, + "name": "PerpMarketSettlementUserHasOpenOrders", + "msg": "PerpMarketSettlementUserHasOpenOrders" + }, + { + "code": 6163, + "name": "PerpMarketSettlementUserHasActiveLP", + "msg": "PerpMarketSettlementUserHasActiveLP" + }, + { + "code": 6164, + "name": "UnableToSettleExpiredUserPosition", + "msg": "UnableToSettleExpiredUserPosition" + }, + { + "code": 6165, + "name": "UnequalMarketIndexForSpotTransfer", + "msg": "UnequalMarketIndexForSpotTransfer" + }, + { + "code": 6166, + "name": "InvalidPerpPositionDetected", + "msg": "InvalidPerpPositionDetected" + }, + { + "code": 6167, + "name": "InvalidSpotPositionDetected", + "msg": "InvalidSpotPositionDetected" + }, + { + "code": 6168, + "name": "InvalidAmmDetected", + "msg": "InvalidAmmDetected" + }, + { + "code": 6169, + "name": "InvalidAmmForFillDetected", + "msg": "InvalidAmmForFillDetected" + }, + { + "code": 6170, + "name": "InvalidAmmLimitPriceOverride", + "msg": "InvalidAmmLimitPriceOverride" + }, + { + "code": 6171, + "name": "InvalidOrderFillPrice", + "msg": "InvalidOrderFillPrice" + }, + { + "code": 6172, + "name": "SpotMarketBalanceInvariantViolated", + "msg": "SpotMarketBalanceInvariantViolated" + }, + { + "code": 6173, + "name": "SpotMarketVaultInvariantViolated", + "msg": "SpotMarketVaultInvariantViolated" + }, + { + "code": 6174, + "name": "InvalidPDA", + "msg": "InvalidPDA" + }, + { + "code": 6175, + "name": "InvalidPDASigner", + "msg": "InvalidPDASigner" + }, + { + "code": 6176, + "name": "RevenueSettingsCannotSettleToIF", + "msg": "RevenueSettingsCannotSettleToIF" + }, + { + "code": 6177, + "name": "NoRevenueToSettleToIF", + "msg": "NoRevenueToSettleToIF" + }, + { + "code": 6178, + "name": "NoAmmPerpPnlDeficit", + "msg": "NoAmmPerpPnlDeficit" + }, + { + "code": 6179, + "name": "SufficientPerpPnlPool", + "msg": "SufficientPerpPnlPool" + }, + { + "code": 6180, + "name": "InsufficientPerpPnlPool", + "msg": "InsufficientPerpPnlPool" + }, + { + "code": 6181, + "name": "PerpPnlDeficitBelowThreshold", + "msg": "PerpPnlDeficitBelowThreshold" + }, + { + "code": 6182, + "name": "MaxRevenueWithdrawPerPeriodReached", + "msg": "MaxRevenueWithdrawPerPeriodReached" + }, + { + "code": 6183, + "name": "MaxIFWithdrawReached", + "msg": "InvalidSpotPositionDetected" + }, + { + "code": 6184, + "name": "NoIFWithdrawAvailable", + "msg": "NoIFWithdrawAvailable" + }, + { + "code": 6185, + "name": "InvalidIFUnstake", + "msg": "InvalidIFUnstake" + }, + { + "code": 6186, + "name": "InvalidIFUnstakeSize", + "msg": "InvalidIFUnstakeSize" + }, + { + "code": 6187, + "name": "InvalidIFUnstakeCancel", + "msg": "InvalidIFUnstakeCancel" + }, + { + "code": 6188, + "name": "InvalidIFForNewStakes", + "msg": "InvalidIFForNewStakes" + }, + { + "code": 6189, + "name": "InvalidIFRebase", + "msg": "InvalidIFRebase" + }, + { + "code": 6190, + "name": "InvalidInsuranceUnstakeSize", + "msg": "InvalidInsuranceUnstakeSize" + }, + { + "code": 6191, + "name": "InvalidOrderLimitPrice", + "msg": "InvalidOrderLimitPrice" + }, + { + "code": 6192, + "name": "InvalidIFDetected", + "msg": "InvalidIFDetected" + }, + { + "code": 6193, + "name": "InvalidAmmMaxSpreadDetected", + "msg": "InvalidAmmMaxSpreadDetected" + }, + { + "code": 6194, + "name": "InvalidConcentrationCoef", + "msg": "InvalidConcentrationCoef" + }, + { + "code": 6195, + "name": "InvalidSrmVault", + "msg": "InvalidSrmVault" + }, + { + "code": 6196, + "name": "InvalidVaultOwner", + "msg": "InvalidVaultOwner" + }, + { + "code": 6197, + "name": "InvalidMarketStatusForFills", + "msg": "InvalidMarketStatusForFills" + }, + { + "code": 6198, + "name": "IFWithdrawRequestInProgress", + "msg": "IFWithdrawRequestInProgress" + }, + { + "code": 6199, + "name": "NoIFWithdrawRequestInProgress", + "msg": "NoIFWithdrawRequestInProgress" + }, + { + "code": 6200, + "name": "IFWithdrawRequestTooSmall", + "msg": "IFWithdrawRequestTooSmall" + }, + { + "code": 6201, + "name": "IncorrectSpotMarketAccountPassed", + "msg": "IncorrectSpotMarketAccountPassed" + }, + { + "code": 6202, + "name": "BlockchainClockInconsistency", + "msg": "BlockchainClockInconsistency" + }, + { + "code": 6203, + "name": "InvalidIFSharesDetected", + "msg": "InvalidIFSharesDetected" + }, + { + "code": 6204, + "name": "NewLPSizeTooSmall", + "msg": "NewLPSizeTooSmall" + }, + { + "code": 6205, + "name": "MarketStatusInvalidForNewLP", + "msg": "MarketStatusInvalidForNewLP" + }, + { + "code": 6206, + "name": "InvalidMarkTwapUpdateDetected", + "msg": "InvalidMarkTwapUpdateDetected" + }, + { + "code": 6207, + "name": "MarketSettlementAttemptOnActiveMarket", + "msg": "MarketSettlementAttemptOnActiveMarket" + }, + { + "code": 6208, + "name": "MarketSettlementRequiresSettledLP", + "msg": "MarketSettlementRequiresSettledLP" + }, + { + "code": 6209, + "name": "MarketSettlementAttemptTooEarly", + "msg": "MarketSettlementAttemptTooEarly" + }, + { + "code": 6210, + "name": "MarketSettlementTargetPriceInvalid", + "msg": "MarketSettlementTargetPriceInvalid" + }, + { + "code": 6211, + "name": "UnsupportedSpotMarket", + "msg": "UnsupportedSpotMarket" + }, + { + "code": 6212, + "name": "SpotOrdersDisabled", + "msg": "SpotOrdersDisabled" + }, + { + "code": 6213, + "name": "MarketBeingInitialized", + "msg": "Market Being Initialized" + }, + { + "code": 6214, + "name": "InvalidUserSubAccountId", + "msg": "Invalid Sub Account Id" + }, + { + "code": 6215, + "name": "InvalidTriggerOrderCondition", + "msg": "Invalid Trigger Order Condition" + }, + { + "code": 6216, + "name": "InvalidSpotPosition", + "msg": "Invalid Spot Position" + }, + { + "code": 6217, + "name": "CantTransferBetweenSameUserAccount", + "msg": "Cant transfer between same user account" + }, + { + "code": 6218, + "name": "InvalidPerpPosition", + "msg": "Invalid Perp Position" + }, + { + "code": 6219, + "name": "UnableToGetLimitPrice", + "msg": "Unable To Get Limit Price" + }, + { + "code": 6220, + "name": "InvalidLiquidation", + "msg": "Invalid Liquidation" + }, + { + "code": 6221, + "name": "SpotFulfillmentConfigDisabled", + "msg": "Spot Fulfillment Config Disabled" + }, + { + "code": 6222, + "name": "InvalidMaker", + "msg": "Invalid Maker" + }, + { + "code": 6223, + "name": "FailedUnwrap", + "msg": "Failed Unwrap" + }, + { + "code": 6224, + "name": "MaxNumberOfUsers", + "msg": "Max Number Of Users" + }, + { + "code": 6225, + "name": "InvalidOracleForSettlePnl", + "msg": "InvalidOracleForSettlePnl" + }, + { + "code": 6226, + "name": "MarginOrdersOpen", + "msg": "MarginOrdersOpen" + }, + { + "code": 6227, + "name": "TierViolationLiquidatingPerpPnl", + "msg": "TierViolationLiquidatingPerpPnl" + }, + { + "code": 6228, + "name": "CouldNotLoadUserData", + "msg": "CouldNotLoadUserData" + }, + { + "code": 6229, + "name": "UserWrongMutability", + "msg": "UserWrongMutability" + }, + { + "code": 6230, + "name": "InvalidUserAccount", + "msg": "InvalidUserAccount" + }, + { + "code": 6231, + "name": "CouldNotLoadUserStatsData", + "msg": "CouldNotLoadUserData" + }, + { + "code": 6232, + "name": "UserStatsWrongMutability", + "msg": "UserWrongMutability" + }, + { + "code": 6233, + "name": "InvalidUserStatsAccount", + "msg": "InvalidUserAccount" + }, + { + "code": 6234, + "name": "UserNotFound", + "msg": "UserNotFound" + }, + { + "code": 6235, + "name": "UnableToLoadUserAccount", + "msg": "UnableToLoadUserAccount" + }, + { + "code": 6236, + "name": "UserStatsNotFound", + "msg": "UserStatsNotFound" + }, + { + "code": 6237, + "name": "UnableToLoadUserStatsAccount", + "msg": "UnableToLoadUserStatsAccount" + }, + { + "code": 6238, + "name": "UserNotInactive", + "msg": "User Not Inactive" + }, + { + "code": 6239, + "name": "RevertFill", + "msg": "RevertFill" + }, + { + "code": 6240, + "name": "InvalidMarketAccountforDeletion", + "msg": "Invalid MarketAccount for Deletion" + }, + { + "code": 6241, + "name": "InvalidSpotFulfillmentParams", + "msg": "Invalid Spot Fulfillment Params" + }, + { + "code": 6242, + "name": "FailedToGetMint", + "msg": "Failed to Get Mint" + }, + { + "code": 6243, + "name": "FailedPhoenixCPI", + "msg": "FailedPhoenixCPI" + }, + { + "code": 6244, + "name": "FailedToDeserializePhoenixMarket", + "msg": "FailedToDeserializePhoenixMarket" + }, + { + "code": 6245, + "name": "InvalidPricePrecision", + "msg": "InvalidPricePrecision" + }, + { + "code": 6246, + "name": "InvalidPhoenixProgram", + "msg": "InvalidPhoenixProgram" + }, + { + "code": 6247, + "name": "InvalidPhoenixMarket", + "msg": "InvalidPhoenixMarket" + }, + { + "code": 6248, + "name": "InvalidSwap", + "msg": "InvalidSwap" + }, + { + "code": 6249, + "name": "SwapLimitPriceBreached", + "msg": "SwapLimitPriceBreached" + }, + { + "code": 6250, + "name": "SpotMarketReduceOnly", + "msg": "SpotMarketReduceOnly" + }, + { + "code": 6251, + "name": "FundingWasNotUpdated", + "msg": "FundingWasNotUpdated" + }, + { + "code": 6252, + "name": "ImpossibleFill", + "msg": "ImpossibleFill" + }, + { + "code": 6253, + "name": "CantUpdatePerpBidAskTwap", + "msg": "CantUpdatePerpBidAskTwap" + }, + { + "code": 6254, + "name": "UserReduceOnly", + "msg": "UserReduceOnly" + }, + { + "code": 6255, + "name": "InvalidMarginCalculation", + "msg": "InvalidMarginCalculation" + }, + { + "code": 6256, + "name": "CantPayUserInitFee", + "msg": "CantPayUserInitFee" + }, + { + "code": 6257, + "name": "CantReclaimRent", + "msg": "CantReclaimRent" + }, + { + "code": 6258, + "name": "InsuranceFundOperationPaused", + "msg": "InsuranceFundOperationPaused" + }, + { + "code": 6259, + "name": "NoUnsettledPnl", + "msg": "NoUnsettledPnl" + }, + { + "code": 6260, + "name": "PnlPoolCantSettleUser", + "msg": "PnlPoolCantSettleUser" + }, + { + "code": 6261, + "name": "OracleNonPositive", + "msg": "OracleInvalid" + }, + { + "code": 6262, + "name": "OracleTooVolatile", + "msg": "OracleTooVolatile" + }, + { + "code": 6263, + "name": "OracleTooUncertain", + "msg": "OracleTooUncertain" + }, + { + "code": 6264, + "name": "OracleStaleForMargin", + "msg": "OracleStaleForMargin" + }, + { + "code": 6265, + "name": "OracleInsufficientDataPoints", + "msg": "OracleInsufficientDataPoints" + }, + { + "code": 6266, + "name": "OracleStaleForAMM", + "msg": "OracleStaleForAMM" + }, + { + "code": 6267, + "name": "UnableToParsePullOracleMessage", + "msg": "Unable to parse pull oracle message" + }, + { + "code": 6268, + "name": "MaxBorrows", + "msg": "Can not borow more than max borrows" + }, + { + "code": 6269, + "name": "OracleUpdatesNotMonotonic", + "msg": "Updates must be monotonically increasing" + }, + { + "code": 6270, + "name": "OraclePriceFeedMessageMismatch", + "msg": "Trying to update price feed with the wrong feed id" + }, + { + "code": 6271, + "name": "OracleUnsupportedMessageType", + "msg": "The message in the update must be a PriceFeedMessage" + }, + { + "code": 6272, + "name": "OracleDeserializeMessageFailed", + "msg": "Could not deserialize the message in the update" + }, + { + "code": 6273, + "name": "OracleWrongGuardianSetOwner", + "msg": "Wrong guardian set owner in update price atomic" + }, + { + "code": 6274, + "name": "OracleWrongWriteAuthority", + "msg": "Oracle post update atomic price feed account must be drift program" + }, + { + "code": 6275, + "name": "OracleWrongVaaOwner", + "msg": "Oracle vaa owner must be wormhole program" + }, + { + "code": 6276, + "name": "OracleTooManyPriceAccountUpdates", + "msg": "Multi updates must have 2 or fewer accounts passed in remaining accounts" + }, + { + "code": 6277, + "name": "OracleMismatchedVaaAndPriceUpdates", + "msg": "Don't have the same remaining accounts number and merkle price updates left" + }, + { + "code": 6278, + "name": "OracleBadRemainingAccountPublicKey", + "msg": "Remaining account passed is not a valid pda" + }, + { + "code": 6279, + "name": "FailedOpenbookV2CPI", + "msg": "FailedOpenbookV2CPI" + }, + { + "code": 6280, + "name": "InvalidOpenbookV2Program", + "msg": "InvalidOpenbookV2Program" + }, + { + "code": 6281, + "name": "InvalidOpenbookV2Market", + "msg": "InvalidOpenbookV2Market" + }, + { + "code": 6282, + "name": "NonZeroTransferFee", + "msg": "Non zero transfer fee" + }, + { + "code": 6283, + "name": "LiquidationOrderFailedToFill", + "msg": "Liquidation order failed to fill" + }, + { + "code": 6284, + "name": "InvalidPredictionMarketOrder", + "msg": "Invalid prediction market order" + } + ] +} + +export const IDL: Drift = { + "version": "2.92.0", + "name": "drift", + "instructions": [ + { + "name": "initializeUser", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "initializeUserStats", + "accounts": [ + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "initializeReferrerName", + "accounts": [ + { + "name": "referrerName", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "deposit", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "amount", + "type": "u64" + }, + { + "name": "reduceOnly", + "type": "bool" + } + ] + }, + { + "name": "withdraw", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "amount", + "type": "u64" + }, + { + "name": "reduceOnly", + "type": "bool" + } + ] + }, + { + "name": "transferDeposit", + "accounts": [ + { + "name": "fromUser", + "isMut": true, + "isSigner": false + }, + { + "name": "toUser", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "placePerpOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + } + ] + }, + { + "name": "cancelOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "orderId", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "cancelOrderByUserId", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "userOrderId", + "type": "u8" + } + ] + }, + { + "name": "cancelOrders", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "marketType", + "type": { + "option": { + "defined": "MarketType" + } + } + }, + { + "name": "marketIndex", + "type": { + "option": "u16" + } + }, + { + "name": "direction", + "type": { + "option": { + "defined": "PositionDirection" + } + } + } + ] + }, + { + "name": "cancelOrdersByIds", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "orderIds", + "type": { + "vec": "u32" + } + } + ] + }, + { + "name": "modifyOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "orderId", + "type": { + "option": "u32" + } + }, + { + "name": "modifyOrderParams", + "type": { + "defined": "ModifyOrderParams" + } + } + ] + }, + { + "name": "modifyOrderByUserId", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "userOrderId", + "type": "u8" + }, + { + "name": "modifyOrderParams", + "type": { + "defined": "ModifyOrderParams" + } + } + ] + }, + { + "name": "placeAndTakePerpOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + }, + { + "name": "makerOrderId", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "placeAndMakePerpOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "taker", + "isMut": true, + "isSigner": false + }, + { + "name": "takerStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + }, + { + "name": "takerOrderId", + "type": "u32" + } + ] + }, + { + "name": "placeSpotOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + } + ] + }, + { + "name": "placeAndTakeSpotOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + }, + { + "name": "fulfillmentType", + "type": { + "option": { + "defined": "SpotFulfillmentType" + } + } + }, + { + "name": "makerOrderId", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "placeAndMakeSpotOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "taker", + "isMut": true, + "isSigner": false + }, + { + "name": "takerStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "OrderParams" + } + }, + { + "name": "takerOrderId", + "type": "u32" + }, + { + "name": "fulfillmentType", + "type": { + "option": { + "defined": "SpotFulfillmentType" + } + } + } + ] + }, + { + "name": "placeOrders", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "params", + "type": { + "vec": { + "defined": "OrderParams" + } + } + } + ] + }, + { + "name": "beginSwap", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "outSpotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "inSpotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "outTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "inTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "instructions", + "isMut": false, + "isSigner": false, + "docs": [ + "Instructions Sysvar for instruction introspection" + ] + } + ], + "args": [ + { + "name": "inMarketIndex", + "type": "u16" + }, + { + "name": "outMarketIndex", + "type": "u16" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "endSwap", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "outSpotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "inSpotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "outTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "inTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "instructions", + "isMut": false, + "isSigner": false, + "docs": [ + "Instructions Sysvar for instruction introspection" + ] + } + ], + "args": [ + { + "name": "inMarketIndex", + "type": "u16" + }, + { + "name": "outMarketIndex", + "type": "u16" + }, + { + "name": "limitPrice", + "type": { + "option": "u64" + } + }, + { + "name": "reduceOnly", + "type": { + "option": { + "defined": "SwapReduceOnly" + } + } + } + ] + }, + { + "name": "addPerpLpShares", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "nShares", + "type": "u64" + }, + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "removePerpLpShares", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "sharesToBurn", + "type": "u64" + }, + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "removePerpLpSharesInExpiringMarket", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "sharesToBurn", + "type": "u64" + }, + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "updateUserName", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "updateUserCustomMarginRatio", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "marginRatio", + "type": "u32" + } + ] + }, + { + "name": "updateUserMarginTradingEnabled", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "marginTradingEnabled", + "type": "bool" + } + ] + }, + { + "name": "updateUserDelegate", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "delegate", + "type": "publicKey" + } + ] + }, + { + "name": "updateUserReduceOnly", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "reduceOnly", + "type": "bool" + } + ] + }, + { + "name": "updateUserAdvancedLp", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "subAccountId", + "type": "u16" + }, + { + "name": "advancedLp", + "type": "bool" + } + ] + }, + { + "name": "deleteUser", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [] + }, + { + "name": "reclaimRent", + "accounts": [ + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "fillPerpOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "fillerStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "orderId", + "type": { + "option": "u32" + } + }, + { + "name": "makerOrderId", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "revertFill", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "fillerStats", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "fillSpotOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "fillerStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "orderId", + "type": { + "option": "u32" + } + }, + { + "name": "fulfillmentType", + "type": { + "option": { + "defined": "SpotFulfillmentType" + } + } + }, + { + "name": "makerOrderId", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "triggerOrder", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "orderId", + "type": "u32" + } + ] + }, + { + "name": "forceCancelOrders", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateUserIdle", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateUserOpenOrdersCount", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "filler", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "adminDisableUpdatePerpBidAskTwap", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "disable", + "type": "bool" + } + ] + }, + { + "name": "settlePnl", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "settleMultiplePnls", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndexes", + "type": { + "vec": "u16" + } + }, + { + "name": "mode", + "type": { + "defined": "SettlePnlMode" + } + } + ] + }, + { + "name": "settleFundingPayment", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "settleLp", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "settleExpiredMarket", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "liquidatePerp", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "liquidatorMaxBaseAssetAmount", + "type": "u64" + }, + { + "name": "limitPrice", + "type": { + "option": "u64" + } + } + ] + }, + { + "name": "liquidatePerpWithFill", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "liquidateSpot", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "assetMarketIndex", + "type": "u16" + }, + { + "name": "liabilityMarketIndex", + "type": "u16" + }, + { + "name": "liquidatorMaxLiabilityTransfer", + "type": "u128" + }, + { + "name": "limitPrice", + "type": { + "option": "u64" + } + } + ] + }, + { + "name": "liquidateBorrowForPerpPnl", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "spotMarketIndex", + "type": "u16" + }, + { + "name": "liquidatorMaxLiabilityTransfer", + "type": "u128" + }, + { + "name": "limitPrice", + "type": { + "option": "u64" + } + } + ] + }, + { + "name": "liquidatePerpPnlForDeposit", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "spotMarketIndex", + "type": "u16" + }, + { + "name": "liquidatorMaxPnlTransfer", + "type": "u128" + }, + { + "name": "limitPrice", + "type": { + "option": "u64" + } + } + ] + }, + { + "name": "setUserStatusToBeingLiquidated", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "resolvePerpPnlDeficit", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "spotMarketIndex", + "type": "u16" + }, + { + "name": "perpMarketIndex", + "type": "u16" + } + ] + }, + { + "name": "resolvePerpBankruptcy", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "quoteSpotMarketIndex", + "type": "u16" + }, + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "resolveSpotBankruptcy", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "liquidator", + "isMut": true, + "isSigner": false + }, + { + "name": "liquidatorStats", + "isMut": true, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "settleRevenueToInsuranceFund", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "spotMarketIndex", + "type": "u16" + } + ] + }, + { + "name": "updateFundingRate", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "updatePrelaunchOracle", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "oracle", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updatePerpBidAskTwap", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "keeperStats", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [] + }, + { + "name": "updateSpotMarketCumulativeInterest", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateAmms", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "marketIndexes", + "type": { + "array": [ + "u16", + 5 + ] + } + } + ] + }, + { + "name": "updateSpotMarketExpiry", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "expiryTs", + "type": "i64" + } + ] + }, + { + "name": "updateUserQuoteAssetInsuranceStake", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateUserGovTokenInsuranceStake", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "initializeInsuranceFundStake", + "accounts": [ + { + "name": "spotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "addInsuranceFundStake", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "requestRemoveInsuranceFundStake", + "accounts": [ + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "cancelRequestRemoveInsuranceFundStake", + "accounts": [ + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "removeInsuranceFundStake", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "transferProtocolIfShares", + "accounts": [ + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "transferConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundStake", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "insuranceFundVault", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "shares", + "type": "u128" + } + ] + }, + { + "name": "updatePythPullOracle", + "accounts": [ + { + "name": "keeper", + "isMut": true, + "isSigner": true + }, + { + "name": "pythSolanaReceiver", + "isMut": false, + "isSigner": false + }, + { + "name": "encodedVaa", + "isMut": false, + "isSigner": false + }, + { + "name": "priceFeed", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feedId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "params", + "type": "bytes" + } + ] + }, + { + "name": "postPythPullOracleUpdateAtomic", + "accounts": [ + { + "name": "keeper", + "isMut": true, + "isSigner": true + }, + { + "name": "pythSolanaReceiver", + "isMut": false, + "isSigner": false + }, + { + "name": "guardianSet", + "isMut": false, + "isSigner": false + }, + { + "name": "priceFeed", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feedId", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "params", + "type": "bytes" + } + ] + }, + { + "name": "postMultiPythPullOracleUpdatesAtomic", + "accounts": [ + { + "name": "keeper", + "isMut": true, + "isSigner": true + }, + { + "name": "pythSolanaReceiver", + "isMut": false, + "isSigner": false + }, + { + "name": "guardianSet", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "params", + "type": "bytes" + } + ] + }, + { + "name": "initialize", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "quoteAssetMint", + "isMut": false, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "initializeSpotMarket", + "accounts": [ + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketMint", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "optimalUtilization", + "type": "u32" + }, + { + "name": "optimalBorrowRate", + "type": "u32" + }, + { + "name": "maxBorrowRate", + "type": "u32" + }, + { + "name": "oracleSource", + "type": { + "defined": "OracleSource" + } + }, + { + "name": "initialAssetWeight", + "type": "u32" + }, + { + "name": "maintenanceAssetWeight", + "type": "u32" + }, + { + "name": "initialLiabilityWeight", + "type": "u32" + }, + { + "name": "maintenanceLiabilityWeight", + "type": "u32" + }, + { + "name": "imfFactor", + "type": "u32" + }, + { + "name": "liquidatorFee", + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "type": "u32" + }, + { + "name": "activeStatus", + "type": "bool" + }, + { + "name": "assetTier", + "type": { + "defined": "AssetTier" + } + }, + { + "name": "scaleInitialAssetWeightStart", + "type": "u64" + }, + { + "name": "withdrawGuardThreshold", + "type": "u64" + }, + { + "name": "orderTickSize", + "type": "u64" + }, + { + "name": "orderStepSize", + "type": "u64" + }, + { + "name": "ifTotalFactor", + "type": "u32" + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "deleteInitializedSpotMarket", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "insuranceFundVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "initializeSerumFulfillmentConfig", + "accounts": [ + { + "name": "baseSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "quoteSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "serumProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "serumMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "serumOpenOrders", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "serumFulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "updateSerumFulfillmentConfigStatus", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "serumFulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + } + ], + "args": [ + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + } + ] + }, + { + "name": "initializeOpenbookV2FulfillmentConfig", + "accounts": [ + { + "name": "baseSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "quoteSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "openbookV2Program", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookV2Market", + "isMut": false, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookV2FulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "openbookV2FulfillmentConfigStatus", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookV2FulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + } + ], + "args": [ + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + } + ] + }, + { + "name": "initializePhoenixFulfillmentConfig", + "accounts": [ + { + "name": "baseSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "quoteSpotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "phoenixProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "phoenixMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "phoenixFulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "phoenixFulfillmentConfigStatus", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "phoenixFulfillmentConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + } + ], + "args": [ + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + } + ] + }, + { + "name": "updateSerumVault", + "accounts": [ + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "srmVault", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "initializePerpMarket", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "ammBaseAssetReserve", + "type": "u128" + }, + { + "name": "ammQuoteAssetReserve", + "type": "u128" + }, + { + "name": "ammPeriodicity", + "type": "i64" + }, + { + "name": "ammPegMultiplier", + "type": "u128" + }, + { + "name": "oracleSource", + "type": { + "defined": "OracleSource" + } + }, + { + "name": "contractTier", + "type": { + "defined": "ContractTier" + } + }, + { + "name": "marginRatioInitial", + "type": "u32" + }, + { + "name": "marginRatioMaintenance", + "type": "u32" + }, + { + "name": "liquidatorFee", + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "type": "u32" + }, + { + "name": "imfFactor", + "type": "u32" + }, + { + "name": "activeStatus", + "type": "bool" + }, + { + "name": "baseSpread", + "type": "u32" + }, + { + "name": "maxSpread", + "type": "u32" + }, + { + "name": "maxOpenInterest", + "type": "u128" + }, + { + "name": "maxRevenueWithdrawPerPeriod", + "type": "u64" + }, + { + "name": "quoteMaxInsurance", + "type": "u64" + }, + { + "name": "orderStepSize", + "type": "u64" + }, + { + "name": "orderTickSize", + "type": "u64" + }, + { + "name": "minOrderSize", + "type": "u64" + }, + { + "name": "concentrationCoefScale", + "type": "u128" + }, + { + "name": "curveUpdateIntensity", + "type": "u8" + }, + { + "name": "ammJitIntensity", + "type": "u8" + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "initializePredictionMarket", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "deleteInitializedPerpMarket", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marketIndex", + "type": "u16" + } + ] + }, + { + "name": "moveAmmPrice", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "baseAssetReserve", + "type": "u128" + }, + { + "name": "quoteAssetReserve", + "type": "u128" + }, + { + "name": "sqrtK", + "type": "u128" + } + ] + }, + { + "name": "recenterPerpMarketAmm", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "pegMultiplier", + "type": "u128" + }, + { + "name": "sqrtK", + "type": "u128" + } + ] + }, + { + "name": "updatePerpMarketAmmSummaryStats", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "UpdatePerpMarketSummaryStatsParams" + } + } + ] + }, + { + "name": "updatePerpMarketExpiry", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "expiryTs", + "type": "i64" + } + ] + }, + { + "name": "settleExpiredMarketPoolsToRevenuePool", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "depositIntoPerpMarketFeePool", + "accounts": [ + { + "name": "state", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "sourceVault", + "isMut": true, + "isSigner": false + }, + { + "name": "driftSigner", + "isMut": false, + "isSigner": false + }, + { + "name": "quoteSpotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "depositIntoSpotMarketVault", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "sourceVault", + "isMut": true, + "isSigner": false + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "depositIntoSpotMarketRevenuePool", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": true, + "isSigner": true + }, + { + "name": "spotMarketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "repegAmmCurve", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "newPegCandidate", + "type": "u128" + } + ] + }, + { + "name": "updatePerpMarketAmmOracleTwap", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + } + ], + "args": [] + }, + { + "name": "resetPerpMarketAmmOracleTwap", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + } + ], + "args": [] + }, + { + "name": "updateK", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "sqrtK", + "type": "u128" + } + ] + }, + { + "name": "updatePerpMarketMarginRatio", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "marginRatioInitial", + "type": "u32" + }, + { + "name": "marginRatioMaintenance", + "type": "u32" + } + ] + }, + { + "name": "updatePerpMarketFundingPeriod", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "fundingPeriod", + "type": "i64" + } + ] + }, + { + "name": "updatePerpMarketMaxImbalances", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "unrealizedMaxImbalance", + "type": "u64" + }, + { + "name": "maxRevenueWithdrawPerPeriod", + "type": "u64" + }, + { + "name": "quoteMaxInsurance", + "type": "u64" + } + ] + }, + { + "name": "updatePerpMarketLiquidationFee", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "liquidatorFee", + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "type": "u32" + } + ] + }, + { + "name": "updateInsuranceFundUnstakingPeriod", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "insuranceFundUnstakingPeriod", + "type": "i64" + } + ] + }, + { + "name": "updateSpotMarketLiquidationFee", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "liquidatorFee", + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "type": "u32" + } + ] + }, + { + "name": "updateWithdrawGuardThreshold", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "withdrawGuardThreshold", + "type": "u64" + } + ] + }, + { + "name": "updateSpotMarketIfFactor", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "spotMarketIndex", + "type": "u16" + }, + { + "name": "userIfFactor", + "type": "u32" + }, + { + "name": "totalIfFactor", + "type": "u32" + } + ] + }, + { + "name": "updateSpotMarketRevenueSettlePeriod", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "revenueSettlePeriod", + "type": "i64" + } + ] + }, + { + "name": "updateSpotMarketStatus", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "status", + "type": { + "defined": "MarketStatus" + } + } + ] + }, + { + "name": "updateSpotMarketPausedOperations", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "pausedOperations", + "type": "u8" + } + ] + }, + { + "name": "updateSpotMarketAssetTier", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "assetTier", + "type": { + "defined": "AssetTier" + } + } + ] + }, + { + "name": "updateSpotMarketMarginWeights", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "initialAssetWeight", + "type": "u32" + }, + { + "name": "maintenanceAssetWeight", + "type": "u32" + }, + { + "name": "initialLiabilityWeight", + "type": "u32" + }, + { + "name": "maintenanceLiabilityWeight", + "type": "u32" + }, + { + "name": "imfFactor", + "type": "u32" + } + ] + }, + { + "name": "updateSpotMarketBorrowRate", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "optimalUtilization", + "type": "u32" + }, + { + "name": "optimalBorrowRate", + "type": "u32" + }, + { + "name": "maxBorrowRate", + "type": "u32" + }, + { + "name": "minBorrowRate", + "type": { + "option": "u8" + } + } + ] + }, + { + "name": "updateSpotMarketMaxTokenDeposits", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxTokenDeposits", + "type": "u64" + } + ] + }, + { + "name": "updateSpotMarketMaxTokenBorrows", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxTokenBorrowsFraction", + "type": "u16" + } + ] + }, + { + "name": "updateSpotMarketScaleInitialAssetWeightStart", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "scaleInitialAssetWeightStart", + "type": "u64" + } + ] + }, + { + "name": "updateSpotMarketOracle", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "oracle", + "type": "publicKey" + }, + { + "name": "oracleSource", + "type": { + "defined": "OracleSource" + } + } + ] + }, + { + "name": "updateSpotMarketStepSizeAndTickSize", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "stepSize", + "type": "u64" + }, + { + "name": "tickSize", + "type": "u64" + } + ] + }, + { + "name": "updateSpotMarketMinOrderSize", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "orderSize", + "type": "u64" + } + ] + }, + { + "name": "updateSpotMarketOrdersEnabled", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "ordersEnabled", + "type": "bool" + } + ] + }, + { + "name": "updateSpotMarketIfPausedOperations", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "pausedOperations", + "type": "u8" + } + ] + }, + { + "name": "updateSpotMarketName", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "updatePerpMarketStatus", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "status", + "type": { + "defined": "MarketStatus" + } + } + ] + }, + { + "name": "updatePerpMarketPausedOperations", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "pausedOperations", + "type": "u8" + } + ] + }, + { + "name": "updatePerpMarketContractTier", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "contractTier", + "type": { + "defined": "ContractTier" + } + } + ] + }, + { + "name": "updatePerpMarketImfFactor", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "imfFactor", + "type": "u32" + }, + { + "name": "unrealizedPnlImfFactor", + "type": "u32" + } + ] + }, + { + "name": "updatePerpMarketUnrealizedAssetWeight", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "unrealizedInitialAssetWeight", + "type": "u32" + }, + { + "name": "unrealizedMaintenanceAssetWeight", + "type": "u32" + } + ] + }, + { + "name": "updatePerpMarketConcentrationCoef", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "concentrationScale", + "type": "u128" + } + ] + }, + { + "name": "updatePerpMarketCurveUpdateIntensity", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "curveUpdateIntensity", + "type": "u8" + } + ] + }, + { + "name": "updatePerpMarketTargetBaseAssetAmountPerLp", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "targetBaseAssetAmountPerLp", + "type": "i32" + } + ] + }, + { + "name": "updatePerpMarketPerLpBase", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "perLpBase", + "type": "i8" + } + ] + }, + { + "name": "updateLpCooldownTime", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "lpCooldownTime", + "type": "u64" + } + ] + }, + { + "name": "updatePerpFeeStructure", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feeStructure", + "type": { + "defined": "FeeStructure" + } + } + ] + }, + { + "name": "updateSpotFeeStructure", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feeStructure", + "type": { + "defined": "FeeStructure" + } + } + ] + }, + { + "name": "updateInitialPctToLiquidate", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "initialPctToLiquidate", + "type": "u16" + } + ] + }, + { + "name": "updateLiquidationDuration", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "liquidationDuration", + "type": "u8" + } + ] + }, + { + "name": "updateLiquidationMarginBufferRatio", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "liquidationMarginBufferRatio", + "type": "u32" + } + ] + }, + { + "name": "updateOracleGuardRails", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "oracleGuardRails", + "type": { + "defined": "OracleGuardRails" + } + } + ] + }, + { + "name": "updateStateSettlementDuration", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "settlementDuration", + "type": "u16" + } + ] + }, + { + "name": "updateStateMaxNumberOfSubAccounts", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxNumberOfSubAccounts", + "type": "u16" + } + ] + }, + { + "name": "updateStateMaxInitializeUserFee", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxInitializeUserFee", + "type": "u16" + } + ] + }, + { + "name": "updatePerpMarketOracle", + "accounts": [ + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "admin", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "oracle", + "type": "publicKey" + }, + { + "name": "oracleSource", + "type": { + "defined": "OracleSource" + } + } + ] + }, + { + "name": "updatePerpMarketBaseSpread", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "baseSpread", + "type": "u32" + } + ] + }, + { + "name": "updateAmmJitIntensity", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "ammJitIntensity", + "type": "u8" + } + ] + }, + { + "name": "updatePerpMarketMaxSpread", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxSpread", + "type": "u32" + } + ] + }, + { + "name": "updatePerpMarketStepSizeAndTickSize", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "stepSize", + "type": "u64" + }, + { + "name": "tickSize", + "type": "u64" + } + ] + }, + { + "name": "updatePerpMarketName", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + }, + { + "name": "updatePerpMarketMinOrderSize", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "orderSize", + "type": "u64" + } + ] + }, + { + "name": "updatePerpMarketMaxSlippageRatio", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxSlippageRatio", + "type": "u16" + } + ] + }, + { + "name": "updatePerpMarketMaxFillReserveFraction", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxFillReserveFraction", + "type": "u16" + } + ] + }, + { + "name": "updatePerpMarketMaxOpenInterest", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "maxOpenInterest", + "type": "u128" + } + ] + }, + { + "name": "updatePerpMarketNumberOfUsers", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "numberOfUsers", + "type": { + "option": "u32" + } + }, + { + "name": "numberOfUsersWithBase", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "updatePerpMarketFeeAdjustment", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feeAdjustment", + "type": "i16" + } + ] + }, + { + "name": "updateSpotMarketFeeAdjustment", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "feeAdjustment", + "type": "i16" + } + ] + }, + { + "name": "updatePerpMarketFuel", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "fuelBoostTaker", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostMaker", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostPosition", + "type": { + "option": "u8" + } + } + ] + }, + { + "name": "updateSpotMarketFuel", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "spotMarket", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "fuelBoostDeposits", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostBorrows", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostTaker", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostMaker", + "type": { + "option": "u8" + } + }, + { + "name": "fuelBoostInsurance", + "type": { + "option": "u8" + } + } + ] + }, + { + "name": "initUserFuel", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "user", + "isMut": true, + "isSigner": false + }, + { + "name": "userStats", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "fuelBoostDeposits", + "type": { + "option": "u32" + } + }, + { + "name": "fuelBoostBorrows", + "type": { + "option": "u32" + } + }, + { + "name": "fuelBoostTaker", + "type": { + "option": "u32" + } + }, + { + "name": "fuelBoostMaker", + "type": { + "option": "u32" + } + }, + { + "name": "fuelBoostInsurance", + "type": { + "option": "u32" + } + } + ] + }, + { + "name": "updateAdmin", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "admin", + "type": "publicKey" + } + ] + }, + { + "name": "updateWhitelistMint", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "whitelistMint", + "type": "publicKey" + } + ] + }, + { + "name": "updateDiscountMint", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "discountMint", + "type": "publicKey" + } + ] + }, + { + "name": "updateExchangeStatus", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "exchangeStatus", + "type": "u8" + } + ] + }, + { + "name": "updatePerpAuctionDuration", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "minPerpAuctionDuration", + "type": "u8" + } + ] + }, + { + "name": "updateSpotAuctionDuration", + "accounts": [ + { + "name": "admin", + "isMut": false, + "isSigner": true + }, + { + "name": "state", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "defaultSpotAuctionDuration", + "type": "u8" + } + ] + }, + { + "name": "initializeProtocolIfSharesTransferConfig", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "protocolIfSharesTransferConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateProtocolIfSharesTransferConfig", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "protocolIfSharesTransferConfig", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "whitelistedSigners", + "type": { + "option": { + "array": [ + "publicKey", + 4 + ] + } + } + }, + { + "name": "maxTransferPerEpoch", + "type": { + "option": "u128" + } + } + ] + }, + { + "name": "initializePrelaunchOracle", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "prelaunchOracle", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + }, + { + "name": "rent", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "PrelaunchOracleParams" + } + } + ] + }, + { + "name": "updatePrelaunchOracleParams", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "prelaunchOracle", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": "PrelaunchOracleParams" + } + } + ] + }, + { + "name": "deletePrelaunchOracle", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "prelaunchOracle", + "isMut": true, + "isSigner": false + }, + { + "name": "perpMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "perpMarketIndex", + "type": "u16" + } + ] + }, + { + "name": "initializePythPullOracle", + "accounts": [ + { + "name": "admin", + "isMut": true, + "isSigner": true + }, + { + "name": "pythSolanaReceiver", + "isMut": false, + "isSigner": false + }, + { + "name": "priceFeed", + "isMut": true, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "state", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "feedId", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + } + ], + "accounts": [ + { + "name": "OpenbookV2FulfillmentConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "type": "publicKey" + }, + { + "name": "openbookV2ProgramId", + "type": "publicKey" + }, + { + "name": "openbookV2Market", + "type": "publicKey" + }, + { + "name": "openbookV2MarketAuthority", + "type": "publicKey" + }, + { + "name": "openbookV2EventHeap", + "type": "publicKey" + }, + { + "name": "openbookV2Bids", + "type": "publicKey" + }, + { + "name": "openbookV2Asks", + "type": "publicKey" + }, + { + "name": "openbookV2BaseVault", + "type": "publicKey" + }, + { + "name": "openbookV2QuoteVault", + "type": "publicKey" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "fulfillmentType", + "type": { + "defined": "SpotFulfillmentType" + } + }, + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 4 + ] + } + } + ] + } + }, + { + "name": "PhoenixV1FulfillmentConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "type": "publicKey" + }, + { + "name": "phoenixProgramId", + "type": "publicKey" + }, + { + "name": "phoenixLogAuthority", + "type": "publicKey" + }, + { + "name": "phoenixMarket", + "type": "publicKey" + }, + { + "name": "phoenixBaseVault", + "type": "publicKey" + }, + { + "name": "phoenixQuoteVault", + "type": "publicKey" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "fulfillmentType", + "type": { + "defined": "SpotFulfillmentType" + } + }, + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 4 + ] + } + } + ] + } + }, + { + "name": "SerumV3FulfillmentConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "type": "publicKey" + }, + { + "name": "serumProgramId", + "type": "publicKey" + }, + { + "name": "serumMarket", + "type": "publicKey" + }, + { + "name": "serumRequestQueue", + "type": "publicKey" + }, + { + "name": "serumEventQueue", + "type": "publicKey" + }, + { + "name": "serumBids", + "type": "publicKey" + }, + { + "name": "serumAsks", + "type": "publicKey" + }, + { + "name": "serumBaseVault", + "type": "publicKey" + }, + { + "name": "serumQuoteVault", + "type": "publicKey" + }, + { + "name": "serumOpenOrders", + "type": "publicKey" + }, + { + "name": "serumSignerNonce", + "type": "u64" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "fulfillmentType", + "type": { + "defined": "SpotFulfillmentType" + } + }, + { + "name": "status", + "type": { + "defined": "SpotFulfillmentConfigStatus" + } + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 4 + ] + } + } + ] + } + }, + { + "name": "insuranceFundStake", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "publicKey" + }, + { + "name": "ifShares", + "type": "u128" + }, + { + "name": "lastWithdrawRequestShares", + "type": "u128" + }, + { + "name": "ifBase", + "type": "u128" + }, + { + "name": "lastValidTs", + "type": "i64" + }, + { + "name": "lastWithdrawRequestValue", + "type": "u64" + }, + { + "name": "lastWithdrawRequestTs", + "type": "i64" + }, + { + "name": "costBasis", + "type": "i64" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 14 + ] + } + } + ] + } + }, + { + "name": "ProtocolIfSharesTransferConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "whitelistedSigners", + "type": { + "array": [ + "publicKey", + 4 + ] + } + }, + { + "name": "maxTransferPerEpoch", + "type": "u128" + }, + { + "name": "currentEpochTransfer", + "type": "u128" + }, + { + "name": "nextEpochTs", + "type": "i64" + }, + { + "name": "padding", + "type": { + "array": [ + "u128", + 8 + ] + } + } + ] + } + }, + { + "name": "PrelaunchOracle", + "type": { + "kind": "struct", + "fields": [ + { + "name": "price", + "type": "i64" + }, + { + "name": "maxPrice", + "type": "i64" + }, + { + "name": "confidence", + "type": "u64" + }, + { + "name": "lastUpdateSlot", + "type": "u64" + }, + { + "name": "ammLastUpdateSlot", + "type": "u64" + }, + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 70 + ] + } + } + ] + } + }, + { + "name": "PerpMarket", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "docs": [ + "The perp market's address. It is a pda of the market index" + ], + "type": "publicKey" + }, + { + "name": "amm", + "docs": [ + "The automated market maker" + ], + "type": { + "defined": "AMM" + } + }, + { + "name": "pnlPool", + "docs": [ + "The market's pnl pool. When users settle negative pnl, the balance increases.", + "When users settle positive pnl, the balance decreases. Can not go negative." + ], + "type": { + "defined": "PoolBalance" + } + }, + { + "name": "name", + "docs": [ + "Encoded display name for the perp market e.g. SOL-PERP" + ], + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "insuranceClaim", + "docs": [ + "The perp market's claim on the insurance fund" + ], + "type": { + "defined": "InsuranceClaim" + } + }, + { + "name": "unrealizedPnlMaxImbalance", + "docs": [ + "The max pnl imbalance before positive pnl asset weight is discounted", + "pnl imbalance is the difference between long and short pnl. When it's greater than 0,", + "the amm has negative pnl and the initial asset weight for positive pnl is discounted", + "precision = QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "expiryTs", + "docs": [ + "The ts when the market will be expired. Only set if market is in reduce only mode" + ], + "type": "i64" + }, + { + "name": "expiryPrice", + "docs": [ + "The price at which positions will be settled. Only set if market is expired", + "precision = PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "nextFillRecordId", + "docs": [ + "Every trade has a fill record id. This is the next id to be used" + ], + "type": "u64" + }, + { + "name": "nextFundingRateRecordId", + "docs": [ + "Every funding rate update has a record id. This is the next id to be used" + ], + "type": "u64" + }, + { + "name": "nextCurveRecordId", + "docs": [ + "Every amm k updated has a record id. This is the next id to be used" + ], + "type": "u64" + }, + { + "name": "imfFactor", + "docs": [ + "The initial margin fraction factor. Used to increase margin ratio for large positions", + "precision: MARGIN_PRECISION" + ], + "type": "u32" + }, + { + "name": "unrealizedPnlImfFactor", + "docs": [ + "The imf factor for unrealized pnl. Used to discount asset weight for large positive pnl", + "precision: MARGIN_PRECISION" + ], + "type": "u32" + }, + { + "name": "liquidatorFee", + "docs": [ + "The fee the liquidator is paid for taking over perp position", + "precision: LIQUIDATOR_FEE_PRECISION" + ], + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "docs": [ + "The fee the insurance fund receives from liquidation", + "precision: LIQUIDATOR_FEE_PRECISION" + ], + "type": "u32" + }, + { + "name": "marginRatioInitial", + "docs": [ + "The margin ratio which determines how much collateral is required to open a position", + "e.g. margin ratio of .1 means a user must have $100 of total collateral to open a $1000 position", + "precision: MARGIN_PRECISION" + ], + "type": "u32" + }, + { + "name": "marginRatioMaintenance", + "docs": [ + "The margin ratio which determines when a user will be liquidated", + "e.g. margin ratio of .05 means a user must have $50 of total collateral to maintain a $1000 position", + "else they will be liquidated", + "precision: MARGIN_PRECISION" + ], + "type": "u32" + }, + { + "name": "unrealizedPnlInitialAssetWeight", + "docs": [ + "The initial asset weight for positive pnl. Negative pnl always has an asset weight of 1", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "unrealizedPnlMaintenanceAssetWeight", + "docs": [ + "The maintenance asset weight for positive pnl. Negative pnl always has an asset weight of 1", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "numberOfUsersWithBase", + "docs": [ + "number of users in a position (base)" + ], + "type": "u32" + }, + { + "name": "numberOfUsers", + "docs": [ + "number of users in a position (pnl) or pnl (quote)" + ], + "type": "u32" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "status", + "docs": [ + "Whether a market is active, reduce only, expired, etc", + "Affects whether users can open/close positions" + ], + "type": { + "defined": "MarketStatus" + } + }, + { + "name": "contractType", + "docs": [ + "Currently only Perpetual markets are supported" + ], + "type": { + "defined": "ContractType" + } + }, + { + "name": "contractTier", + "docs": [ + "The contract tier determines how much insurance a market can receive, with more speculative markets receiving less insurance", + "It also influences the order perp markets can be liquidated, with less speculative markets being liquidated first" + ], + "type": { + "defined": "ContractTier" + } + }, + { + "name": "pausedOperations", + "type": "u8" + }, + { + "name": "quoteSpotMarketIndex", + "docs": [ + "The spot market that pnl is settled in" + ], + "type": "u16" + }, + { + "name": "feeAdjustment", + "docs": [ + "Between -100 and 100, represents what % to increase/decrease the fee by", + "E.g. if this is -50 and the fee is 5bps, the new fee will be 2.5bps", + "if this is 50 and the fee is 5bps, the new fee will be 7.5bps" + ], + "type": "i16" + }, + { + "name": "fuelBoostPosition", + "docs": [ + "fuel multiplier for perp funding", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostTaker", + "docs": [ + "fuel multiplier for perp taker", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostMaker", + "docs": [ + "fuel multiplier for perp maker", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 43 + ] + } + } + ] + } + }, + { + "name": "spotMarket", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "docs": [ + "The address of the spot market. It is a pda of the market index" + ], + "type": "publicKey" + }, + { + "name": "oracle", + "docs": [ + "The oracle used to price the markets deposits/borrows" + ], + "type": "publicKey" + }, + { + "name": "mint", + "docs": [ + "The token mint of the market" + ], + "type": "publicKey" + }, + { + "name": "vault", + "docs": [ + "The vault used to store the market's deposits", + "The amount in the vault should be equal to or greater than deposits - borrows" + ], + "type": "publicKey" + }, + { + "name": "name", + "docs": [ + "The encoded display name for the market e.g. SOL" + ], + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "historicalOracleData", + "type": { + "defined": "HistoricalOracleData" + } + }, + { + "name": "historicalIndexData", + "type": { + "defined": "HistoricalIndexData" + } + }, + { + "name": "revenuePool", + "docs": [ + "Revenue the protocol has collected in this markets token", + "e.g. for SOL-PERP, funds can be settled in usdc and will flow into the USDC revenue pool" + ], + "type": { + "defined": "PoolBalance" + } + }, + { + "name": "spotFeePool", + "docs": [ + "The fees collected from swaps between this market and the quote market", + "Is settled to the quote markets revenue pool" + ], + "type": { + "defined": "PoolBalance" + } + }, + { + "name": "insuranceFund", + "docs": [ + "Details on the insurance fund covering bankruptcies in this markets token", + "Covers bankruptcies for borrows with this markets token and perps settling in this markets token" + ], + "type": { + "defined": "InsuranceFund" + } + }, + { + "name": "totalSpotFee", + "docs": [ + "The total spot fees collected for this market", + "precision: QUOTE_PRECISION" + ], + "type": "u128" + }, + { + "name": "depositBalance", + "docs": [ + "The sum of the scaled balances for deposits across users and pool balances", + "To convert to the deposit token amount, multiply by the cumulative deposit interest", + "precision: SPOT_BALANCE_PRECISION" + ], + "type": "u128" + }, + { + "name": "borrowBalance", + "docs": [ + "The sum of the scaled balances for borrows across users and pool balances", + "To convert to the borrow token amount, multiply by the cumulative borrow interest", + "precision: SPOT_BALANCE_PRECISION" + ], + "type": "u128" + }, + { + "name": "cumulativeDepositInterest", + "docs": [ + "The cumulative interest earned by depositors", + "Used to calculate the deposit token amount from the deposit balance", + "precision: SPOT_CUMULATIVE_INTEREST_PRECISION" + ], + "type": "u128" + }, + { + "name": "cumulativeBorrowInterest", + "docs": [ + "The cumulative interest earned by borrowers", + "Used to calculate the borrow token amount from the borrow balance", + "precision: SPOT_CUMULATIVE_INTEREST_PRECISION" + ], + "type": "u128" + }, + { + "name": "totalSocialLoss", + "docs": [ + "The total socialized loss from borrows, in the mint's token", + "precision: token mint precision" + ], + "type": "u128" + }, + { + "name": "totalQuoteSocialLoss", + "docs": [ + "The total socialized loss from borrows, in the quote market's token", + "preicision: QUOTE_PRECISION" + ], + "type": "u128" + }, + { + "name": "withdrawGuardThreshold", + "docs": [ + "no withdraw limits/guards when deposits below this threshold", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "maxTokenDeposits", + "docs": [ + "The max amount of token deposits in this market", + "0 if there is no limit", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "depositTokenTwap", + "docs": [ + "24hr average of deposit token amount", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "borrowTokenTwap", + "docs": [ + "24hr average of borrow token amount", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "utilizationTwap", + "docs": [ + "24hr average of utilization", + "which is borrow amount over token amount", + "precision: SPOT_UTILIZATION_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastInterestTs", + "docs": [ + "Last time the cumulative deposit and borrow interest was updated" + ], + "type": "u64" + }, + { + "name": "lastTwapTs", + "docs": [ + "Last time the deposit/borrow/utilization averages were updated" + ], + "type": "u64" + }, + { + "name": "expiryTs", + "docs": [ + "The time the market is set to expire. Only set if market is in reduce only mode" + ], + "type": "i64" + }, + { + "name": "orderStepSize", + "docs": [ + "Spot orders must be a multiple of the step size", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "orderTickSize", + "docs": [ + "Spot orders must be a multiple of the tick size", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "minOrderSize", + "docs": [ + "The minimum order size", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "maxPositionSize", + "docs": [ + "The maximum spot position size", + "if the limit is 0, there is no limit", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "nextFillRecordId", + "docs": [ + "Every spot trade has a fill record id. This is the next id to use" + ], + "type": "u64" + }, + { + "name": "nextDepositRecordId", + "docs": [ + "Every deposit has a deposit record id. This is the next id to use" + ], + "type": "u64" + }, + { + "name": "initialAssetWeight", + "docs": [ + "The initial asset weight used to calculate a deposits contribution to a users initial total collateral", + "e.g. if the asset weight is .8, $100 of deposits contributes $80 to the users initial total collateral", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "maintenanceAssetWeight", + "docs": [ + "The maintenance asset weight used to calculate a deposits contribution to a users maintenance total collateral", + "e.g. if the asset weight is .9, $100 of deposits contributes $90 to the users maintenance total collateral", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "initialLiabilityWeight", + "docs": [ + "The initial liability weight used to calculate a borrows contribution to a users initial margin requirement", + "e.g. if the liability weight is .9, $100 of borrows contributes $90 to the users initial margin requirement", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "maintenanceLiabilityWeight", + "docs": [ + "The maintenance liability weight used to calculate a borrows contribution to a users maintenance margin requirement", + "e.g. if the liability weight is .8, $100 of borrows contributes $80 to the users maintenance margin requirement", + "precision: SPOT_WEIGHT_PRECISION" + ], + "type": "u32" + }, + { + "name": "imfFactor", + "docs": [ + "The initial margin fraction factor. Used to increase liability weight/decrease asset weight for large positions", + "precision: MARGIN_PRECISION" + ], + "type": "u32" + }, + { + "name": "liquidatorFee", + "docs": [ + "The fee the liquidator is paid for taking over borrow/deposit", + "precision: LIQUIDATOR_FEE_PRECISION" + ], + "type": "u32" + }, + { + "name": "ifLiquidationFee", + "docs": [ + "The fee the insurance fund receives from liquidation", + "precision: LIQUIDATOR_FEE_PRECISION" + ], + "type": "u32" + }, + { + "name": "optimalUtilization", + "docs": [ + "The optimal utilization rate for this market.", + "Used to determine the markets borrow rate", + "precision: SPOT_UTILIZATION_PRECISION" + ], + "type": "u32" + }, + { + "name": "optimalBorrowRate", + "docs": [ + "The borrow rate for this market when the market has optimal utilization", + "precision: SPOT_RATE_PRECISION" + ], + "type": "u32" + }, + { + "name": "maxBorrowRate", + "docs": [ + "The borrow rate for this market when the market has 1000 utilization", + "precision: SPOT_RATE_PRECISION" + ], + "type": "u32" + }, + { + "name": "decimals", + "docs": [ + "The market's token mint's decimals. To from decimals to a precision, 10^decimals" + ], + "type": "u32" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "ordersEnabled", + "docs": [ + "Whether or not spot trading is enabled" + ], + "type": "bool" + }, + { + "name": "oracleSource", + "type": { + "defined": "OracleSource" + } + }, + { + "name": "status", + "type": { + "defined": "MarketStatus" + } + }, + { + "name": "assetTier", + "docs": [ + "The asset tier affects how a deposit can be used as collateral and the priority for a borrow being liquidated" + ], + "type": { + "defined": "AssetTier" + } + }, + { + "name": "pausedOperations", + "type": "u8" + }, + { + "name": "ifPausedOperations", + "type": "u8" + }, + { + "name": "feeAdjustment", + "type": "i16" + }, + { + "name": "maxTokenBorrowsFraction", + "docs": [ + "What fraction of max_token_deposits", + "disabled when 0, 1 => 1/10000 => .01% of max_token_deposits", + "precision: X/10000" + ], + "type": "u16" + }, + { + "name": "flashLoanAmount", + "docs": [ + "For swaps, the amount of token loaned out in the begin_swap ix", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "flashLoanInitialTokenAmount", + "docs": [ + "For swaps, the amount in the users token account in the begin_swap ix", + "Used to calculate how much of the token left the system in end_swap ix", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "totalSwapFee", + "docs": [ + "The total fees received from swaps", + "precision: token mint precision" + ], + "type": "u64" + }, + { + "name": "scaleInitialAssetWeightStart", + "docs": [ + "When to begin scaling down the initial asset weight", + "disabled when 0", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "minBorrowRate", + "docs": [ + "The min borrow rate for this market when the market regardless of utilization", + "1 => 1/200 => .5%", + "precision: X/200" + ], + "type": "u8" + }, + { + "name": "fuelBoostDeposits", + "docs": [ + "fuel multiplier for spot deposits", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostBorrows", + "docs": [ + "fuel multiplier for spot borrows", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostTaker", + "docs": [ + "fuel multiplier for spot taker", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostMaker", + "docs": [ + "fuel multiplier for spot maker", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "fuelBoostInsurance", + "docs": [ + "fuel multiplier for spot insurance stake", + "precision: 10" + ], + "type": "u8" + }, + { + "name": "tokenProgram", + "type": "u8" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 41 + ] + } + } + ] + } + }, + { + "name": "State", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "publicKey" + }, + { + "name": "whitelistMint", + "type": "publicKey" + }, + { + "name": "discountMint", + "type": "publicKey" + }, + { + "name": "signer", + "type": "publicKey" + }, + { + "name": "srmVault", + "type": "publicKey" + }, + { + "name": "perpFeeStructure", + "type": { + "defined": "FeeStructure" + } + }, + { + "name": "spotFeeStructure", + "type": { + "defined": "FeeStructure" + } + }, + { + "name": "oracleGuardRails", + "type": { + "defined": "OracleGuardRails" + } + }, + { + "name": "numberOfAuthorities", + "type": "u64" + }, + { + "name": "numberOfSubAccounts", + "type": "u64" + }, + { + "name": "lpCooldownTime", + "type": "u64" + }, + { + "name": "liquidationMarginBufferRatio", + "type": "u32" + }, + { + "name": "settlementDuration", + "type": "u16" + }, + { + "name": "numberOfMarkets", + "type": "u16" + }, + { + "name": "numberOfSpotMarkets", + "type": "u16" + }, + { + "name": "signerNonce", + "type": "u8" + }, + { + "name": "minPerpAuctionDuration", + "type": "u8" + }, + { + "name": "defaultMarketOrderTimeInForce", + "type": "u8" + }, + { + "name": "defaultSpotAuctionDuration", + "type": "u8" + }, + { + "name": "exchangeStatus", + "type": "u8" + }, + { + "name": "liquidationDuration", + "type": "u8" + }, + { + "name": "initialPctToLiquidate", + "type": "u16" + }, + { + "name": "maxNumberOfSubAccounts", + "type": "u16" + }, + { + "name": "maxInitializeUserFee", + "type": "u16" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 10 + ] + } + } + ] + } + }, + { + "name": "User", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "docs": [ + "The owner/authority of the account" + ], + "type": "publicKey" + }, + { + "name": "delegate", + "docs": [ + "An addresses that can control the account on the authority's behalf. Has limited power, cant withdraw" + ], + "type": "publicKey" + }, + { + "name": "name", + "docs": [ + "Encoded display name e.g. \"toly\"" + ], + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "spotPositions", + "docs": [ + "The user's spot positions" + ], + "type": { + "array": [ + { + "defined": "SpotPosition" + }, + 8 + ] + } + }, + { + "name": "perpPositions", + "docs": [ + "The user's perp positions" + ], + "type": { + "array": [ + { + "defined": "PerpPosition" + }, + 8 + ] + } + }, + { + "name": "orders", + "docs": [ + "The user's orders" + ], + "type": { + "array": [ + { + "defined": "Order" + }, + 32 + ] + } + }, + { + "name": "lastAddPerpLpSharesTs", + "docs": [ + "The last time the user added perp lp positions" + ], + "type": "i64" + }, + { + "name": "totalDeposits", + "docs": [ + "The total values of deposits the user has made", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalWithdraws", + "docs": [ + "The total values of withdrawals the user has made", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalSocialLoss", + "docs": [ + "The total socialized loss the users has incurred upon the protocol", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "settledPerpPnl", + "docs": [ + "Fees (taker fees, maker rebate, referrer reward, filler reward) and pnl for perps", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "cumulativeSpotFees", + "docs": [ + "Fees (taker fees, maker rebate, filler reward) for spot", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "cumulativePerpFunding", + "docs": [ + "Cumulative funding paid/received for perps", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "liquidationMarginFreed", + "docs": [ + "The amount of margin freed during liquidation. Used to force the liquidation to occur over a period of time", + "Defaults to zero when not being liquidated", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastActiveSlot", + "docs": [ + "The last slot a user was active. Used to determine if a user is idle" + ], + "type": "u64" + }, + { + "name": "nextOrderId", + "docs": [ + "Every user order has an order id. This is the next order id to be used" + ], + "type": "u32" + }, + { + "name": "maxMarginRatio", + "docs": [ + "Custom max initial margin ratio for the user" + ], + "type": "u32" + }, + { + "name": "nextLiquidationId", + "docs": [ + "The next liquidation id to be used for user" + ], + "type": "u16" + }, + { + "name": "subAccountId", + "docs": [ + "The sub account id for this user" + ], + "type": "u16" + }, + { + "name": "status", + "docs": [ + "Whether the user is active, being liquidated or bankrupt" + ], + "type": "u8" + }, + { + "name": "isMarginTradingEnabled", + "docs": [ + "Whether the user has enabled margin trading" + ], + "type": "bool" + }, + { + "name": "idle", + "docs": [ + "User is idle if they haven't interacted with the protocol in 1 week and they have no orders, perp positions or borrows", + "Off-chain keeper bots can ignore users that are idle" + ], + "type": "bool" + }, + { + "name": "openOrders", + "docs": [ + "number of open orders" + ], + "type": "u8" + }, + { + "name": "hasOpenOrder", + "docs": [ + "Whether or not user has open order" + ], + "type": "bool" + }, + { + "name": "openAuctions", + "docs": [ + "number of open orders with auction" + ], + "type": "u8" + }, + { + "name": "hasOpenAuction", + "docs": [ + "Whether or not user has open order with auction" + ], + "type": "bool" + }, + { + "name": "padding1", + "type": { + "array": [ + "u8", + 5 + ] + } + }, + { + "name": "lastFuelBonusUpdateTs", + "type": "u32" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 12 + ] + } + } + ] + } + }, + { + "name": "UserStats", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "docs": [ + "The authority for all of a users sub accounts" + ], + "type": "publicKey" + }, + { + "name": "referrer", + "docs": [ + "The address that referred this user" + ], + "type": "publicKey" + }, + { + "name": "fees", + "docs": [ + "Stats on the fees paid by the user" + ], + "type": { + "defined": "UserFees" + } + }, + { + "name": "nextEpochTs", + "docs": [ + "The timestamp of the next epoch", + "Epoch is used to limit referrer rewards earned in single epoch" + ], + "type": "i64" + }, + { + "name": "makerVolume30d", + "docs": [ + "Rolling 30day maker volume for user", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "takerVolume30d", + "docs": [ + "Rolling 30day taker volume for user", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "fillerVolume30d", + "docs": [ + "Rolling 30day filler volume for user", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastMakerVolume30dTs", + "docs": [ + "last time the maker volume was updated" + ], + "type": "i64" + }, + { + "name": "lastTakerVolume30dTs", + "docs": [ + "last time the taker volume was updated" + ], + "type": "i64" + }, + { + "name": "lastFillerVolume30dTs", + "docs": [ + "last time the filler volume was updated" + ], + "type": "i64" + }, + { + "name": "ifStakedQuoteAssetAmount", + "docs": [ + "The amount of tokens staked in the quote spot markets if" + ], + "type": "u64" + }, + { + "name": "numberOfSubAccounts", + "docs": [ + "The current number of sub accounts" + ], + "type": "u16" + }, + { + "name": "numberOfSubAccountsCreated", + "docs": [ + "The number of sub accounts created. Can be greater than the number of sub accounts if user", + "has deleted sub accounts" + ], + "type": "u16" + }, + { + "name": "isReferrer", + "docs": [ + "Whether the user is a referrer. Sub account 0 can not be deleted if user is a referrer" + ], + "type": "bool" + }, + { + "name": "disableUpdatePerpBidAskTwap", + "type": "bool" + }, + { + "name": "padding1", + "type": { + "array": [ + "u8", + 2 + ] + } + }, + { + "name": "fuelInsurance", + "docs": [ + "accumulated fuel for token amounts of insurance" + ], + "type": "u32" + }, + { + "name": "fuelDeposits", + "docs": [ + "accumulated fuel for notional of deposits" + ], + "type": "u32" + }, + { + "name": "fuelBorrows", + "docs": [ + "accumulate fuel bonus for notional of borrows" + ], + "type": "u32" + }, + { + "name": "fuelPositions", + "docs": [ + "accumulated fuel for perp open interest" + ], + "type": "u32" + }, + { + "name": "fuelTaker", + "docs": [ + "accumulate fuel bonus for taker volume" + ], + "type": "u32" + }, + { + "name": "fuelMaker", + "docs": [ + "accumulate fuel bonus for maker volume" + ], + "type": "u32" + }, + { + "name": "ifStakedGovTokenAmount", + "docs": [ + "The amount of tokens staked in the governance spot markets if" + ], + "type": "u64" + }, + { + "name": "lastFuelIfBonusUpdateTs", + "docs": [ + "last unix ts user stats data was used to update if fuel (u32 to save space)" + ], + "type": "u32" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 12 + ] + } + } + ] + } + }, + { + "name": "ReferrerName", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "publicKey" + }, + { + "name": "user", + "type": "publicKey" + }, + { + "name": "userStats", + "type": "publicKey" + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + } + } + ] + } + } + ], + "types": [ + { + "name": "UpdatePerpMarketSummaryStatsParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "quoteAssetAmountWithUnsettledLp", + "type": { + "option": "i64" + } + }, + { + "name": "netUnsettledFundingPnl", + "type": { + "option": "i64" + } + }, + { + "name": "updateAmmSummaryStats", + "type": { + "option": "bool" + } + } + ] + } + }, + { + "name": "LiquidatePerpRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "oraclePrice", + "type": "i64" + }, + { + "name": "baseAssetAmount", + "type": "i64" + }, + { + "name": "quoteAssetAmount", + "type": "i64" + }, + { + "name": "lpShares", + "docs": [ + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u64" + }, + { + "name": "fillRecordId", + "type": "u64" + }, + { + "name": "userOrderId", + "type": "u32" + }, + { + "name": "liquidatorOrderId", + "type": "u32" + }, + { + "name": "liquidatorFee", + "docs": [ + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "ifFee", + "docs": [ + "precision: QUOTE_PRECISION" + ], + "type": "u64" + } + ] + } + }, + { + "name": "LiquidateSpotRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "assetMarketIndex", + "type": "u16" + }, + { + "name": "assetPrice", + "type": "i64" + }, + { + "name": "assetTransfer", + "type": "u128" + }, + { + "name": "liabilityMarketIndex", + "type": "u16" + }, + { + "name": "liabilityPrice", + "type": "i64" + }, + { + "name": "liabilityTransfer", + "docs": [ + "precision: token mint precision" + ], + "type": "u128" + }, + { + "name": "ifFee", + "docs": [ + "precision: token mint precision" + ], + "type": "u64" + } + ] + } + }, + { + "name": "LiquidateBorrowForPerpPnlRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "marketOraclePrice", + "type": "i64" + }, + { + "name": "pnlTransfer", + "type": "u128" + }, + { + "name": "liabilityMarketIndex", + "type": "u16" + }, + { + "name": "liabilityPrice", + "type": "i64" + }, + { + "name": "liabilityTransfer", + "type": "u128" + } + ] + } + }, + { + "name": "LiquidatePerpPnlForDepositRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "marketOraclePrice", + "type": "i64" + }, + { + "name": "pnlTransfer", + "type": "u128" + }, + { + "name": "assetMarketIndex", + "type": "u16" + }, + { + "name": "assetPrice", + "type": "i64" + }, + { + "name": "assetTransfer", + "type": "u128" + } + ] + } + }, + { + "name": "PerpBankruptcyRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "pnl", + "type": "i128" + }, + { + "name": "ifPayment", + "type": "u128" + }, + { + "name": "clawbackUser", + "type": { + "option": "publicKey" + } + }, + { + "name": "clawbackUserPayment", + "type": { + "option": "u128" + } + }, + { + "name": "cumulativeFundingRateDelta", + "type": "i128" + } + ] + } + }, + { + "name": "SpotBankruptcyRecord", + "type": { + "kind": "struct", + "fields": [ + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "borrowAmount", + "type": "u128" + }, + { + "name": "ifPayment", + "type": "u128" + }, + { + "name": "cumulativeDepositInterestDelta", + "type": "u128" + } + ] + } + }, + { + "name": "MarketIdentifier", + "type": { + "kind": "struct", + "fields": [ + { + "name": "marketType", + "type": { + "defined": "MarketType" + } + }, + { + "name": "marketIndex", + "type": "u16" + } + ] + } + }, + { + "name": "HistoricalOracleData", + "type": { + "kind": "struct", + "fields": [ + { + "name": "lastOraclePrice", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastOracleConf", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastOracleDelay", + "docs": [ + "number of slots since last update" + ], + "type": "i64" + }, + { + "name": "lastOraclePriceTwap", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastOraclePriceTwap5min", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastOraclePriceTwapTs", + "docs": [ + "unix_timestamp of last snapshot" + ], + "type": "i64" + } + ] + } + }, + { + "name": "HistoricalIndexData", + "type": { + "kind": "struct", + "fields": [ + { + "name": "lastIndexBidPrice", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastIndexAskPrice", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastIndexPriceTwap", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastIndexPriceTwap5min", + "docs": [ + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastIndexPriceTwapTs", + "docs": [ + "unix_timestamp of last snapshot" + ], + "type": "i64" + } + ] + } + }, + { + "name": "PrelaunchOracleParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "perpMarketIndex", + "type": "u16" + }, + { + "name": "price", + "type": { + "option": "i64" + } + }, + { + "name": "maxPrice", + "type": { + "option": "i64" + } + } + ] + } + }, + { + "name": "OrderParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "orderType", + "type": { + "defined": "OrderType" + } + }, + { + "name": "marketType", + "type": { + "defined": "MarketType" + } + }, + { + "name": "direction", + "type": { + "defined": "PositionDirection" + } + }, + { + "name": "userOrderId", + "type": "u8" + }, + { + "name": "baseAssetAmount", + "type": "u64" + }, + { + "name": "price", + "type": "u64" + }, + { + "name": "marketIndex", + "type": "u16" + }, + { + "name": "reduceOnly", + "type": "bool" + }, + { + "name": "postOnly", + "type": { + "defined": "PostOnlyParam" + } + }, + { + "name": "immediateOrCancel", + "type": "bool" + }, + { + "name": "maxTs", + "type": { + "option": "i64" + } + }, + { + "name": "triggerPrice", + "type": { + "option": "u64" + } + }, + { + "name": "triggerCondition", + "type": { + "defined": "OrderTriggerCondition" + } + }, + { + "name": "oraclePriceOffset", + "type": { + "option": "i32" + } + }, + { + "name": "auctionDuration", + "type": { + "option": "u8" + } + }, + { + "name": "auctionStartPrice", + "type": { + "option": "i64" + } + }, + { + "name": "auctionEndPrice", + "type": { + "option": "i64" + } + } + ] + } + }, + { + "name": "ModifyOrderParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "direction", + "type": { + "option": { + "defined": "PositionDirection" + } + } + }, + { + "name": "baseAssetAmount", + "type": { + "option": "u64" + } + }, + { + "name": "price", + "type": { + "option": "u64" + } + }, + { + "name": "reduceOnly", + "type": { + "option": "bool" + } + }, + { + "name": "postOnly", + "type": { + "option": { + "defined": "PostOnlyParam" + } + } + }, + { + "name": "immediateOrCancel", + "type": { + "option": "bool" + } + }, + { + "name": "maxTs", + "type": { + "option": "i64" + } + }, + { + "name": "triggerPrice", + "type": { + "option": "u64" + } + }, + { + "name": "triggerCondition", + "type": { + "option": { + "defined": "OrderTriggerCondition" + } + } + }, + { + "name": "oraclePriceOffset", + "type": { + "option": "i32" + } + }, + { + "name": "auctionDuration", + "type": { + "option": "u8" + } + }, + { + "name": "auctionStartPrice", + "type": { + "option": "i64" + } + }, + { + "name": "auctionEndPrice", + "type": { + "option": "i64" + } + }, + { + "name": "policy", + "type": { + "option": { + "defined": "ModifyOrderPolicy" + } + } + } + ] + } + }, + { + "name": "InsuranceClaim", + "type": { + "kind": "struct", + "fields": [ + { + "name": "revenueWithdrawSinceLastSettle", + "docs": [ + "The amount of revenue last settled", + "Positive if funds left the perp market,", + "negative if funds were pulled into the perp market", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "maxRevenueWithdrawPerPeriod", + "docs": [ + "The max amount of revenue that can be withdrawn per period", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "quoteMaxInsurance", + "docs": [ + "The max amount of insurance that perp market can use to resolve bankruptcy and pnl deficits", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "quoteSettledInsurance", + "docs": [ + "The amount of insurance that has been used to resolve bankruptcy and pnl deficits", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastRevenueWithdrawTs", + "docs": [ + "The last time revenue was settled in/out of market" + ], + "type": "i64" + } + ] + } + }, + { + "name": "PoolBalance", + "type": { + "kind": "struct", + "fields": [ + { + "name": "scaledBalance", + "docs": [ + "To get the pool's token amount, you must multiply the scaled balance by the market's cumulative", + "deposit interest", + "precision: SPOT_BALANCE_PRECISION" + ], + "type": "u128" + }, + { + "name": "marketIndex", + "docs": [ + "The spot market the pool is for" + ], + "type": "u16" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 6 + ] + } + } + ] + } + }, + { + "name": "AMM", + "type": { + "kind": "struct", + "fields": [ + { + "name": "oracle", + "docs": [ + "oracle price data public key" + ], + "type": "publicKey" + }, + { + "name": "historicalOracleData", + "docs": [ + "stores historically witnessed oracle data" + ], + "type": { + "defined": "HistoricalOracleData" + } + }, + { + "name": "baseAssetAmountPerLp", + "docs": [ + "accumulated base asset amount since inception per lp share", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "quoteAssetAmountPerLp", + "docs": [ + "accumulated quote asset amount since inception per lp share", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "feePool", + "docs": [ + "partition of fees from perp market trading moved from pnl settlements" + ], + "type": { + "defined": "PoolBalance" + } + }, + { + "name": "baseAssetReserve", + "docs": [ + "`x` reserves for constant product mm formula (x * y = k)", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "quoteAssetReserve", + "docs": [ + "`y` reserves for constant product mm formula (x * y = k)", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "concentrationCoef", + "docs": [ + "determines how close the min/max base asset reserve sit vs base reserves", + "allow for decreasing slippage without increasing liquidity and v.v.", + "precision: PERCENTAGE_PRECISION" + ], + "type": "u128" + }, + { + "name": "minBaseAssetReserve", + "docs": [ + "minimum base_asset_reserve allowed before AMM is unavailable", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "maxBaseAssetReserve", + "docs": [ + "maximum base_asset_reserve allowed before AMM is unavailable", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "sqrtK", + "docs": [ + "`sqrt(k)` in constant product mm formula (x * y = k). stored to avoid drift caused by integer math issues", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "pegMultiplier", + "docs": [ + "normalizing numerical factor for y, its use offers lowest slippage in cp-curve when market is balanced", + "precision: PEG_PRECISION" + ], + "type": "u128" + }, + { + "name": "terminalQuoteAssetReserve", + "docs": [ + "y when market is balanced. stored to save computation", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "baseAssetAmountLong", + "docs": [ + "always non-negative. tracks number of total longs in market (regardless of counterparty)", + "precision: BASE_PRECISION" + ], + "type": "i128" + }, + { + "name": "baseAssetAmountShort", + "docs": [ + "always non-positive. tracks number of total shorts in market (regardless of counterparty)", + "precision: BASE_PRECISION" + ], + "type": "i128" + }, + { + "name": "baseAssetAmountWithAmm", + "docs": [ + "tracks net position (longs-shorts) in market with AMM as counterparty", + "precision: BASE_PRECISION" + ], + "type": "i128" + }, + { + "name": "baseAssetAmountWithUnsettledLp", + "docs": [ + "tracks net position (longs-shorts) in market with LPs as counterparty", + "precision: BASE_PRECISION" + ], + "type": "i128" + }, + { + "name": "maxOpenInterest", + "docs": [ + "max allowed open interest, blocks trades that breach this value", + "precision: BASE_PRECISION" + ], + "type": "u128" + }, + { + "name": "quoteAssetAmount", + "docs": [ + "sum of all user's perp quote_asset_amount in market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "quoteEntryAmountLong", + "docs": [ + "sum of all long user's quote_entry_amount in market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "quoteEntryAmountShort", + "docs": [ + "sum of all short user's quote_entry_amount in market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "quoteBreakEvenAmountLong", + "docs": [ + "sum of all long user's quote_break_even_amount in market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "quoteBreakEvenAmountShort", + "docs": [ + "sum of all short user's quote_break_even_amount in market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "userLpShares", + "docs": [ + "total user lp shares of sqrt_k (protocol owned liquidity = sqrt_k - last_funding_rate)", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "lastFundingRate", + "docs": [ + "last funding rate in this perp market (unit is quote per base)", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastFundingRateLong", + "docs": [ + "last funding rate for longs in this perp market (unit is quote per base)", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastFundingRateShort", + "docs": [ + "last funding rate for shorts in this perp market (unit is quote per base)", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "last24hAvgFundingRate", + "docs": [ + "estimate of last 24h of funding rate perp market (unit is quote per base)", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "totalFee", + "docs": [ + "total fees collected by this perp market", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "totalMmFee", + "docs": [ + "total fees collected by the vAMM's bid/ask spread", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "totalExchangeFee", + "docs": [ + "total fees collected by exchange fee schedule", + "precision: QUOTE_PRECISION" + ], + "type": "u128" + }, + { + "name": "totalFeeMinusDistributions", + "docs": [ + "total fees minus any recognized upnl and pool withdraws", + "precision: QUOTE_PRECISION" + ], + "type": "i128" + }, + { + "name": "totalFeeWithdrawn", + "docs": [ + "sum of all fees from fee pool withdrawn to revenue pool", + "precision: QUOTE_PRECISION" + ], + "type": "u128" + }, + { + "name": "totalLiquidationFee", + "docs": [ + "all fees collected by market for liquidations", + "precision: QUOTE_PRECISION" + ], + "type": "u128" + }, + { + "name": "cumulativeFundingRateLong", + "docs": [ + "accumulated funding rate for longs since inception in market" + ], + "type": "i128" + }, + { + "name": "cumulativeFundingRateShort", + "docs": [ + "accumulated funding rate for shorts since inception in market" + ], + "type": "i128" + }, + { + "name": "totalSocialLoss", + "docs": [ + "accumulated social loss paid by users since inception in market" + ], + "type": "u128" + }, + { + "name": "askBaseAssetReserve", + "docs": [ + "transformed base_asset_reserve for users going long", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "askQuoteAssetReserve", + "docs": [ + "transformed quote_asset_reserve for users going long", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "bidBaseAssetReserve", + "docs": [ + "transformed base_asset_reserve for users going short", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "bidQuoteAssetReserve", + "docs": [ + "transformed quote_asset_reserve for users going short", + "precision: AMM_RESERVE_PRECISION" + ], + "type": "u128" + }, + { + "name": "lastOracleNormalisedPrice", + "docs": [ + "the last seen oracle price partially shrunk toward the amm reserve price", + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastOracleReservePriceSpreadPct", + "docs": [ + "the gap between the oracle price and the reserve price = y * peg_multiplier / x" + ], + "type": "i64" + }, + { + "name": "lastBidPriceTwap", + "docs": [ + "average estimate of bid price over funding_period", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastAskPriceTwap", + "docs": [ + "average estimate of ask price over funding_period", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastMarkPriceTwap", + "docs": [ + "average estimate of (bid+ask)/2 price over funding_period", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastMarkPriceTwap5min", + "docs": [ + "average estimate of (bid+ask)/2 price over FIVE_MINUTES" + ], + "type": "u64" + }, + { + "name": "lastUpdateSlot", + "docs": [ + "the last blockchain slot the amm was updated" + ], + "type": "u64" + }, + { + "name": "lastOracleConfPct", + "docs": [ + "the pct size of the oracle confidence interval", + "precision: PERCENTAGE_PRECISION" + ], + "type": "u64" + }, + { + "name": "netRevenueSinceLastFunding", + "docs": [ + "the total_fee_minus_distribution change since the last funding update", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastFundingRateTs", + "docs": [ + "the last funding rate update unix_timestamp" + ], + "type": "i64" + }, + { + "name": "fundingPeriod", + "docs": [ + "the peridocity of the funding rate updates" + ], + "type": "i64" + }, + { + "name": "orderStepSize", + "docs": [ + "the base step size (increment) of orders", + "precision: BASE_PRECISION" + ], + "type": "u64" + }, + { + "name": "orderTickSize", + "docs": [ + "the price tick size of orders", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "minOrderSize", + "docs": [ + "the minimum base size of an order", + "precision: BASE_PRECISION" + ], + "type": "u64" + }, + { + "name": "maxPositionSize", + "docs": [ + "the max base size a single user can have", + "precision: BASE_PRECISION" + ], + "type": "u64" + }, + { + "name": "volume24h", + "docs": [ + "estimated total of volume in market", + "QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "longIntensityVolume", + "docs": [ + "the volume intensity of long fills against AMM" + ], + "type": "u64" + }, + { + "name": "shortIntensityVolume", + "docs": [ + "the volume intensity of short fills against AMM" + ], + "type": "u64" + }, + { + "name": "lastTradeTs", + "docs": [ + "the blockchain unix timestamp at the time of the last trade" + ], + "type": "i64" + }, + { + "name": "markStd", + "docs": [ + "estimate of standard deviation of the fill (mark) prices", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "oracleStd", + "docs": [ + "estimate of standard deviation of the oracle price at each update", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastMarkPriceTwapTs", + "docs": [ + "the last unix_timestamp the mark twap was updated" + ], + "type": "i64" + }, + { + "name": "baseSpread", + "docs": [ + "the minimum spread the AMM can quote. also used as step size for some spread logic increases." + ], + "type": "u32" + }, + { + "name": "maxSpread", + "docs": [ + "the maximum spread the AMM can quote" + ], + "type": "u32" + }, + { + "name": "longSpread", + "docs": [ + "the spread for asks vs the reserve price" + ], + "type": "u32" + }, + { + "name": "shortSpread", + "docs": [ + "the spread for bids vs the reserve price" + ], + "type": "u32" + }, + { + "name": "longIntensityCount", + "docs": [ + "the count intensity of long fills against AMM" + ], + "type": "u32" + }, + { + "name": "shortIntensityCount", + "docs": [ + "the count intensity of short fills against AMM" + ], + "type": "u32" + }, + { + "name": "maxFillReserveFraction", + "docs": [ + "the fraction of total available liquidity a single fill on the AMM can consume" + ], + "type": "u16" + }, + { + "name": "maxSlippageRatio", + "docs": [ + "the maximum slippage a single fill on the AMM can push" + ], + "type": "u16" + }, + { + "name": "curveUpdateIntensity", + "docs": [ + "the update intensity of AMM formulaic updates (adjusting k). 0-100" + ], + "type": "u8" + }, + { + "name": "ammJitIntensity", + "docs": [ + "the jit intensity of AMM. larger intensity means larger participation in jit. 0 means no jit participation.", + "(0, 100] is intensity for protocol-owned AMM. (100, 200] is intensity for user LP-owned AMM." + ], + "type": "u8" + }, + { + "name": "oracleSource", + "docs": [ + "the oracle provider information. used to decode/scale the oracle public key" + ], + "type": { + "defined": "OracleSource" + } + }, + { + "name": "lastOracleValid", + "docs": [ + "tracks whether the oracle was considered valid at the last AMM update" + ], + "type": "bool" + }, + { + "name": "targetBaseAssetAmountPerLp", + "docs": [ + "the target value for `base_asset_amount_per_lp`, used during AMM JIT with LP split", + "precision: BASE_PRECISION" + ], + "type": "i32" + }, + { + "name": "perLpBase", + "docs": [ + "expo for unit of per_lp, base 10 (if per_lp_base=X, then per_lp unit is 10^X)" + ], + "type": "i8" + }, + { + "name": "padding1", + "type": "u8" + }, + { + "name": "padding2", + "type": "u16" + }, + { + "name": "totalFeeEarnedPerLp", + "type": "u64" + }, + { + "name": "netUnsettledFundingPnl", + "type": "i64" + }, + { + "name": "quoteAssetAmountWithUnsettledLp", + "type": "i64" + }, + { + "name": "referencePriceOffset", + "type": "i32" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 12 + ] + } + } + ] + } + }, + { + "name": "InsuranceFund", + "type": { + "kind": "struct", + "fields": [ + { + "name": "vault", + "type": "publicKey" + }, + { + "name": "totalShares", + "type": "u128" + }, + { + "name": "userShares", + "type": "u128" + }, + { + "name": "sharesBase", + "type": "u128" + }, + { + "name": "unstakingPeriod", + "type": "i64" + }, + { + "name": "lastRevenueSettleTs", + "type": "i64" + }, + { + "name": "revenueSettlePeriod", + "type": "i64" + }, + { + "name": "totalFactor", + "type": "u32" + }, + { + "name": "userFactor", + "type": "u32" + } + ] + } + }, + { + "name": "OracleGuardRails", + "type": { + "kind": "struct", + "fields": [ + { + "name": "priceDivergence", + "type": { + "defined": "PriceDivergenceGuardRails" + } + }, + { + "name": "validity", + "type": { + "defined": "ValidityGuardRails" + } + } + ] + } + }, + { + "name": "PriceDivergenceGuardRails", + "type": { + "kind": "struct", + "fields": [ + { + "name": "markOraclePercentDivergence", + "type": "u64" + }, + { + "name": "oracleTwap5minPercentDivergence", + "type": "u64" + } + ] + } + }, + { + "name": "ValidityGuardRails", + "type": { + "kind": "struct", + "fields": [ + { + "name": "slotsBeforeStaleForAmm", + "type": "i64" + }, + { + "name": "slotsBeforeStaleForMargin", + "type": "i64" + }, + { + "name": "confidenceIntervalMaxSize", + "type": "u64" + }, + { + "name": "tooVolatileRatio", + "type": "i64" + } + ] + } + }, + { + "name": "FeeStructure", + "type": { + "kind": "struct", + "fields": [ + { + "name": "feeTiers", + "type": { + "array": [ + { + "defined": "FeeTier" + }, + 10 + ] + } + }, + { + "name": "fillerRewardStructure", + "type": { + "defined": "OrderFillerRewardStructure" + } + }, + { + "name": "referrerRewardEpochUpperBound", + "type": "u64" + }, + { + "name": "flatFillerFee", + "type": "u64" + } + ] + } + }, + { + "name": "FeeTier", + "type": { + "kind": "struct", + "fields": [ + { + "name": "feeNumerator", + "type": "u32" + }, + { + "name": "feeDenominator", + "type": "u32" + }, + { + "name": "makerRebateNumerator", + "type": "u32" + }, + { + "name": "makerRebateDenominator", + "type": "u32" + }, + { + "name": "referrerRewardNumerator", + "type": "u32" + }, + { + "name": "referrerRewardDenominator", + "type": "u32" + }, + { + "name": "refereeFeeNumerator", + "type": "u32" + }, + { + "name": "refereeFeeDenominator", + "type": "u32" + } + ] + } + }, + { + "name": "OrderFillerRewardStructure", + "type": { + "kind": "struct", + "fields": [ + { + "name": "rewardNumerator", + "type": "u32" + }, + { + "name": "rewardDenominator", + "type": "u32" + }, + { + "name": "timeBasedRewardLowerBound", + "type": "u128" + } + ] + } + }, + { + "name": "UserFees", + "type": { + "kind": "struct", + "fields": [ + { + "name": "totalFeePaid", + "docs": [ + "Total taker fee paid", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalFeeRebate", + "docs": [ + "Total maker fee rebate", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalTokenDiscount", + "docs": [ + "Total discount from holding token", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalRefereeDiscount", + "docs": [ + "Total discount from being referred", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "totalReferrerReward", + "docs": [ + "Total reward to referrer", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "currentEpochReferrerReward", + "docs": [ + "Total reward to referrer this epoch", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + } + ] + } + }, + { + "name": "SpotPosition", + "type": { + "kind": "struct", + "fields": [ + { + "name": "scaledBalance", + "docs": [ + "The scaled balance of the position. To get the token amount, multiply by the cumulative deposit/borrow", + "interest of corresponding market.", + "precision: SPOT_BALANCE_PRECISION" + ], + "type": "u64" + }, + { + "name": "openBids", + "docs": [ + "How many spot bids the user has open", + "precision: token mint precision" + ], + "type": "i64" + }, + { + "name": "openAsks", + "docs": [ + "How many spot asks the user has open", + "precision: token mint precision" + ], + "type": "i64" + }, + { + "name": "cumulativeDeposits", + "docs": [ + "The cumulative deposits/borrows a user has made into a market", + "precision: token mint precision" + ], + "type": "i64" + }, + { + "name": "marketIndex", + "docs": [ + "The market index of the corresponding spot market" + ], + "type": "u16" + }, + { + "name": "balanceType", + "docs": [ + "Whether the position is deposit or borrow" + ], + "type": { + "defined": "SpotBalanceType" + } + }, + { + "name": "openOrders", + "docs": [ + "Number of open orders" + ], + "type": "u8" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 4 + ] + } + } + ] + } + }, + { + "name": "PerpPosition", + "type": { + "kind": "struct", + "fields": [ + { + "name": "lastCumulativeFundingRate", + "docs": [ + "The perp market's last cumulative funding rate. Used to calculate the funding payment owed to user", + "precision: FUNDING_RATE_PRECISION" + ], + "type": "i64" + }, + { + "name": "baseAssetAmount", + "docs": [ + "the size of the users perp position", + "precision: BASE_PRECISION" + ], + "type": "i64" + }, + { + "name": "quoteAssetAmount", + "docs": [ + "Used to calculate the users pnl. Upon entry, is equal to base_asset_amount * avg entry price - fees", + "Updated when the user open/closes position or settles pnl. Includes fees/funding", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "quoteBreakEvenAmount", + "docs": [ + "The amount of quote the user would need to exit their position at to break even", + "Updated when the user open/closes position or settles pnl. Includes fees/funding", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "quoteEntryAmount", + "docs": [ + "The amount quote the user entered the position with. Equal to base asset amount * avg entry price", + "Updated when the user open/closes position. Excludes fees/funding", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "openBids", + "docs": [ + "The amount of open bids the user has in this perp market", + "precision: BASE_PRECISION" + ], + "type": "i64" + }, + { + "name": "openAsks", + "docs": [ + "The amount of open asks the user has in this perp market", + "precision: BASE_PRECISION" + ], + "type": "i64" + }, + { + "name": "settledPnl", + "docs": [ + "The amount of pnl settled in this market since opening the position", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lpShares", + "docs": [ + "The number of lp (liquidity provider) shares the user has in this perp market", + "LP shares allow users to provide liquidity via the AMM", + "precision: BASE_PRECISION" + ], + "type": "u64" + }, + { + "name": "lastBaseAssetAmountPerLp", + "docs": [ + "The last base asset amount per lp the amm had", + "Used to settle the users lp position", + "precision: BASE_PRECISION" + ], + "type": "i64" + }, + { + "name": "lastQuoteAssetAmountPerLp", + "docs": [ + "The last quote asset amount per lp the amm had", + "Used to settle the users lp position", + "precision: QUOTE_PRECISION" + ], + "type": "i64" + }, + { + "name": "remainderBaseAssetAmount", + "docs": [ + "Settling LP position can lead to a small amount of base asset being left over smaller than step size", + "This records that remainder so it can be settled later on", + "precision: BASE_PRECISION" + ], + "type": "i32" + }, + { + "name": "marketIndex", + "docs": [ + "The market index for the perp market" + ], + "type": "u16" + }, + { + "name": "openOrders", + "docs": [ + "The number of open orders" + ], + "type": "u8" + }, + { + "name": "perLpBase", + "type": "i8" + } + ] + } + }, + { + "name": "Order", + "type": { + "kind": "struct", + "fields": [ + { + "name": "slot", + "docs": [ + "The slot the order was placed" + ], + "type": "u64" + }, + { + "name": "price", + "docs": [ + "The limit price for the order (can be 0 for market orders)", + "For orders with an auction, this price isn't used until the auction is complete", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "baseAssetAmount", + "docs": [ + "The size of the order", + "precision for perps: BASE_PRECISION", + "precision for spot: token mint precision" + ], + "type": "u64" + }, + { + "name": "baseAssetAmountFilled", + "docs": [ + "The amount of the order filled", + "precision for perps: BASE_PRECISION", + "precision for spot: token mint precision" + ], + "type": "u64" + }, + { + "name": "quoteAssetAmountFilled", + "docs": [ + "The amount of quote filled for the order", + "precision: QUOTE_PRECISION" + ], + "type": "u64" + }, + { + "name": "triggerPrice", + "docs": [ + "At what price the order will be triggered. Only relevant for trigger orders", + "precision: PRICE_PRECISION" + ], + "type": "u64" + }, + { + "name": "auctionStartPrice", + "docs": [ + "The start price for the auction. Only relevant for market/oracle orders", + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "auctionEndPrice", + "docs": [ + "The end price for the auction. Only relevant for market/oracle orders", + "precision: PRICE_PRECISION" + ], + "type": "i64" + }, + { + "name": "maxTs", + "docs": [ + "The time when the order will expire" + ], + "type": "i64" + }, + { + "name": "oraclePriceOffset", + "docs": [ + "If set, the order limit price is the oracle price + this offset", + "precision: PRICE_PRECISION" + ], + "type": "i32" + }, + { + "name": "orderId", + "docs": [ + "The id for the order. Each users has their own order id space" + ], + "type": "u32" + }, + { + "name": "marketIndex", + "docs": [ + "The perp/spot market index" + ], + "type": "u16" + }, + { + "name": "status", + "docs": [ + "Whether the order is open or unused" + ], + "type": { + "defined": "OrderStatus" + } + }, + { + "name": "orderType", + "docs": [ + "The type of order" + ], + "type": { + "defined": "OrderType" + } + }, + { + "name": "marketType", + "docs": [ + "Whether market is spot or perp" + ], + "type": { + "defined": "MarketType" + } + }, + { + "name": "userOrderId", + "docs": [ + "User generated order id. Can make it easier to place/cancel orders" + ], + "type": "u8" + }, + { + "name": "existingPositionDirection", + "docs": [ + "What the users position was when the order was placed" + ], + "type": { + "defined": "PositionDirection" + } + }, + { + "name": "direction", + "docs": [ + "Whether the user is going long or short. LONG = bid, SHORT = ask" + ], + "type": { + "defined": "PositionDirection" + } + }, + { + "name": "reduceOnly", + "docs": [ + "Whether the order is allowed to only reduce position size" + ], + "type": "bool" + }, + { + "name": "postOnly", + "docs": [ + "Whether the order must be a maker" + ], + "type": "bool" + }, + { + "name": "immediateOrCancel", + "docs": [ + "Whether the order must be canceled the same slot it is placed" + ], + "type": "bool" + }, + { + "name": "triggerCondition", + "docs": [ + "Whether the order is triggered above or below the trigger price. Only relevant for trigger orders" + ], + "type": { + "defined": "OrderTriggerCondition" + } + }, + { + "name": "auctionDuration", + "docs": [ + "How many slots the auction lasts" + ], + "type": "u8" + }, + { + "name": "padding", + "type": { + "array": [ + "u8", + 3 + ] + } + } + ] + } + }, + { + "name": "SwapDirection", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Add" + }, + { + "name": "Remove" + } + ] + } + }, + { + "name": "ModifyOrderId", + "type": { + "kind": "enum", + "variants": [ + { + "name": "UserOrderId", + "fields": [ + "u8" + ] + }, + { + "name": "OrderId", + "fields": [ + "u32" + ] + } + ] + } + }, + { + "name": "PositionDirection", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Long" + }, + { + "name": "Short" + } + ] + } + }, + { + "name": "SpotFulfillmentType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "SerumV3" + }, + { + "name": "Match" + }, + { + "name": "PhoenixV1" + }, + { + "name": "OpenbookV2" + } + ] + } + }, + { + "name": "SwapReduceOnly", + "type": { + "kind": "enum", + "variants": [ + { + "name": "In" + }, + { + "name": "Out" + } + ] + } + }, + { + "name": "TwapPeriod", + "type": { + "kind": "enum", + "variants": [ + { + "name": "FundingPeriod" + }, + { + "name": "FiveMin" + } + ] + } + }, + { + "name": "LiquidationMultiplierType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Discount" + }, + { + "name": "Premium" + } + ] + } + }, + { + "name": "MarginRequirementType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Initial" + }, + { + "name": "Fill" + }, + { + "name": "Maintenance" + } + ] + } + }, + { + "name": "OracleValidity", + "type": { + "kind": "enum", + "variants": [ + { + "name": "NonPositive" + }, + { + "name": "TooVolatile" + }, + { + "name": "TooUncertain" + }, + { + "name": "StaleForMargin" + }, + { + "name": "InsufficientDataPoints" + }, + { + "name": "StaleForAMM" + }, + { + "name": "Valid" + } + ] + } + }, + { + "name": "DriftAction", + "type": { + "kind": "enum", + "variants": [ + { + "name": "UpdateFunding" + }, + { + "name": "SettlePnl" + }, + { + "name": "TriggerOrder" + }, + { + "name": "FillOrderMatch" + }, + { + "name": "FillOrderAmm" + }, + { + "name": "Liquidate" + }, + { + "name": "MarginCalc" + }, + { + "name": "UpdateTwap" + }, + { + "name": "UpdateAMMCurve" + }, + { + "name": "OracleOrderPrice" + } + ] + } + }, + { + "name": "PositionUpdateType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Open" + }, + { + "name": "Increase" + }, + { + "name": "Reduce" + }, + { + "name": "Close" + }, + { + "name": "Flip" + } + ] + } + }, + { + "name": "DepositExplanation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "None" + }, + { + "name": "Transfer" + }, + { + "name": "Borrow" + }, + { + "name": "RepayBorrow" + } + ] + } + }, + { + "name": "DepositDirection", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Deposit" + }, + { + "name": "Withdraw" + } + ] + } + }, + { + "name": "OrderAction", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Place" + }, + { + "name": "Cancel" + }, + { + "name": "Fill" + }, + { + "name": "Trigger" + }, + { + "name": "Expire" + } + ] + } + }, + { + "name": "OrderActionExplanation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "None" + }, + { + "name": "InsufficientFreeCollateral" + }, + { + "name": "OraclePriceBreachedLimitPrice" + }, + { + "name": "MarketOrderFilledToLimitPrice" + }, + { + "name": "OrderExpired" + }, + { + "name": "Liquidation" + }, + { + "name": "OrderFilledWithAMM" + }, + { + "name": "OrderFilledWithAMMJit" + }, + { + "name": "OrderFilledWithMatch" + }, + { + "name": "OrderFilledWithMatchJit" + }, + { + "name": "MarketExpired" + }, + { + "name": "RiskingIncreasingOrder" + }, + { + "name": "ReduceOnlyOrderIncreasedPosition" + }, + { + "name": "OrderFillWithSerum" + }, + { + "name": "NoBorrowLiquidity" + }, + { + "name": "OrderFillWithPhoenix" + }, + { + "name": "OrderFilledWithAMMJitLPSplit" + }, + { + "name": "OrderFilledWithLPJit" + }, + { + "name": "DeriskLp" + }, + { + "name": "OrderFilledWithOpenbookV2" + } + ] + } + }, + { + "name": "LPAction", + "type": { + "kind": "enum", + "variants": [ + { + "name": "AddLiquidity" + }, + { + "name": "RemoveLiquidity" + }, + { + "name": "SettleLiquidity" + }, + { + "name": "RemoveLiquidityDerisk" + } + ] + } + }, + { + "name": "LiquidationType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "LiquidatePerp" + }, + { + "name": "LiquidateSpot" + }, + { + "name": "LiquidateBorrowForPerpPnl" + }, + { + "name": "LiquidatePerpPnlForDeposit" + }, + { + "name": "PerpBankruptcy" + }, + { + "name": "SpotBankruptcy" + } + ] + } + }, + { + "name": "SettlePnlExplanation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "None" + }, + { + "name": "ExpiredPosition" + } + ] + } + }, + { + "name": "StakeAction", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Stake" + }, + { + "name": "UnstakeRequest" + }, + { + "name": "UnstakeCancelRequest" + }, + { + "name": "Unstake" + }, + { + "name": "UnstakeTransfer" + }, + { + "name": "StakeTransfer" + } + ] + } + }, + { + "name": "FillMode", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Fill" + }, + { + "name": "PlaceAndMake" + }, + { + "name": "PlaceAndTake" + }, + { + "name": "Liquidation" + } + ] + } + }, + { + "name": "PerpFulfillmentMethod", + "type": { + "kind": "enum", + "variants": [ + { + "name": "AMM", + "fields": [ + { + "option": "u64" + } + ] + }, + { + "name": "Match", + "fields": [ + "publicKey", + "u16" + ] + } + ] + } + }, + { + "name": "SpotFulfillmentMethod", + "type": { + "kind": "enum", + "variants": [ + { + "name": "ExternalMarket" + }, + { + "name": "Match", + "fields": [ + "publicKey", + "u16" + ] + } + ] + } + }, + { + "name": "MarginCalculationMode", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Standard", + "fields": [ + { + "name": "trackOpenOrdersFraction", + "type": "bool" + } + ] + }, + { + "name": "Liquidation", + "fields": [ + { + "name": "marketToTrackMarginRequirement", + "type": { + "option": { + "defined": "MarketIdentifier" + } + } + } + ] + } + ] + } + }, + { + "name": "OracleSource", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Pyth" + }, + { + "name": "Switchboard" + }, + { + "name": "QuoteAsset" + }, + { + "name": "Pyth1K" + }, + { + "name": "Pyth1M" + }, + { + "name": "PythStableCoin" + }, + { + "name": "Prelaunch" + }, + { + "name": "PythPull" + }, + { + "name": "Pyth1KPull" + }, + { + "name": "Pyth1MPull" + }, + { + "name": "PythStableCoinPull" + }, + { + "name": "SwitchboardOnDemand" + } + ] + } + }, + { + "name": "PostOnlyParam", + "type": { + "kind": "enum", + "variants": [ + { + "name": "None" + }, + { + "name": "MustPostOnly" + }, + { + "name": "TryPostOnly" + }, + { + "name": "Slide" + } + ] + } + }, + { + "name": "ModifyOrderPolicy", + "type": { + "kind": "enum", + "variants": [ + { + "name": "TryModify" + }, + { + "name": "MustModify" + } + ] + } + }, + { + "name": "PerpOperation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "UpdateFunding" + }, + { + "name": "AmmFill" + }, + { + "name": "Fill" + }, + { + "name": "SettlePnl" + }, + { + "name": "SettlePnlWithPosition" + }, + { + "name": "Liquidation" + } + ] + } + }, + { + "name": "SpotOperation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "UpdateCumulativeInterest" + }, + { + "name": "Fill" + }, + { + "name": "Deposit" + }, + { + "name": "Withdraw" + }, + { + "name": "Liquidation" + } + ] + } + }, + { + "name": "InsuranceFundOperation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Init" + }, + { + "name": "Add" + }, + { + "name": "RequestRemove" + }, + { + "name": "Remove" + } + ] + } + }, + { + "name": "MarketStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Initialized" + }, + { + "name": "Active" + }, + { + "name": "FundingPaused" + }, + { + "name": "AmmPaused" + }, + { + "name": "FillPaused" + }, + { + "name": "WithdrawPaused" + }, + { + "name": "ReduceOnly" + }, + { + "name": "Settlement" + }, + { + "name": "Delisted" + } + ] + } + }, + { + "name": "ContractType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Perpetual" + }, + { + "name": "Future" + }, + { + "name": "Prediction" + } + ] + } + }, + { + "name": "ContractTier", + "type": { + "kind": "enum", + "variants": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "Speculative" + }, + { + "name": "HighlySpeculative" + }, + { + "name": "Isolated" + } + ] + } + }, + { + "name": "AMMLiquiditySplit", + "type": { + "kind": "enum", + "variants": [ + { + "name": "ProtocolOwned" + }, + { + "name": "LPOwned" + }, + { + "name": "Shared" + } + ] + } + }, + { + "name": "SettlePnlMode", + "type": { + "kind": "enum", + "variants": [ + { + "name": "MustSettle" + }, + { + "name": "TrySettle" + } + ] + } + }, + { + "name": "SpotBalanceType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Deposit" + }, + { + "name": "Borrow" + } + ] + } + }, + { + "name": "SpotFulfillmentConfigStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Enabled" + }, + { + "name": "Disabled" + } + ] + } + }, + { + "name": "AssetTier", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Collateral" + }, + { + "name": "Protected" + }, + { + "name": "Cross" + }, + { + "name": "Isolated" + }, + { + "name": "Unlisted" + } + ] + } + }, + { + "name": "ExchangeStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "DepositPaused" + }, + { + "name": "WithdrawPaused" + }, + { + "name": "AmmPaused" + }, + { + "name": "FillPaused" + }, + { + "name": "LiqPaused" + }, + { + "name": "FundingPaused" + }, + { + "name": "SettlePnlPaused" + } + ] + } + }, + { + "name": "UserStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "BeingLiquidated" + }, + { + "name": "Bankrupt" + }, + { + "name": "ReduceOnly" + }, + { + "name": "AdvancedLp" + } + ] + } + }, + { + "name": "AssetType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Base" + }, + { + "name": "Quote" + } + ] + } + }, + { + "name": "OrderStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Init" + }, + { + "name": "Open" + }, + { + "name": "Filled" + }, + { + "name": "Canceled" + } + ] + } + }, + { + "name": "OrderType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Market" + }, + { + "name": "Limit" + }, + { + "name": "TriggerMarket" + }, + { + "name": "TriggerLimit" + }, + { + "name": "Oracle" + } + ] + } + }, + { + "name": "OrderTriggerCondition", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Above" + }, + { + "name": "Below" + }, + { + "name": "TriggeredAbove" + }, + { + "name": "TriggeredBelow" + } + ] + } + }, + { + "name": "MarketType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Spot" + }, + { + "name": "Perp" + } + ] + } + } + ], + "events": [ + { + "name": "NewUserRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "userAuthority", + "type": "publicKey", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "subAccountId", + "type": "u16", + "index": false + }, + { + "name": "name", + "type": { + "array": [ + "u8", + 32 + ] + }, + "index": false + }, + { + "name": "referrer", + "type": "publicKey", + "index": false + } + ] + }, + { + "name": "DepositRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "userAuthority", + "type": "publicKey", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "direction", + "type": { + "defined": "DepositDirection" + }, + "index": false + }, + { + "name": "depositRecordId", + "type": "u64", + "index": false + }, + { + "name": "amount", + "type": "u64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "oraclePrice", + "type": "i64", + "index": false + }, + { + "name": "marketDepositBalance", + "type": "u128", + "index": false + }, + { + "name": "marketWithdrawBalance", + "type": "u128", + "index": false + }, + { + "name": "marketCumulativeDepositInterest", + "type": "u128", + "index": false + }, + { + "name": "marketCumulativeBorrowInterest", + "type": "u128", + "index": false + }, + { + "name": "totalDepositsAfter", + "type": "u64", + "index": false + }, + { + "name": "totalWithdrawsAfter", + "type": "u64", + "index": false + }, + { + "name": "explanation", + "type": { + "defined": "DepositExplanation" + }, + "index": false + }, + { + "name": "transferUser", + "type": { + "option": "publicKey" + }, + "index": false + } + ] + }, + { + "name": "SpotInterestRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "depositBalance", + "type": "u128", + "index": false + }, + { + "name": "cumulativeDepositInterest", + "type": "u128", + "index": false + }, + { + "name": "borrowBalance", + "type": "u128", + "index": false + }, + { + "name": "cumulativeBorrowInterest", + "type": "u128", + "index": false + }, + { + "name": "optimalUtilization", + "type": "u32", + "index": false + }, + { + "name": "optimalBorrowRate", + "type": "u32", + "index": false + }, + { + "name": "maxBorrowRate", + "type": "u32", + "index": false + } + ] + }, + { + "name": "FundingPaymentRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "userAuthority", + "type": "publicKey", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "fundingPayment", + "type": "i64", + "index": false + }, + { + "name": "baseAssetAmount", + "type": "i64", + "index": false + }, + { + "name": "userLastCumulativeFunding", + "type": "i64", + "index": false + }, + { + "name": "ammCumulativeFundingLong", + "type": "i128", + "index": false + }, + { + "name": "ammCumulativeFundingShort", + "type": "i128", + "index": false + } + ] + }, + { + "name": "FundingRateRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "recordId", + "type": "u64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "fundingRate", + "type": "i64", + "index": false + }, + { + "name": "fundingRateLong", + "type": "i128", + "index": false + }, + { + "name": "fundingRateShort", + "type": "i128", + "index": false + }, + { + "name": "cumulativeFundingRateLong", + "type": "i128", + "index": false + }, + { + "name": "cumulativeFundingRateShort", + "type": "i128", + "index": false + }, + { + "name": "oraclePriceTwap", + "type": "i64", + "index": false + }, + { + "name": "markPriceTwap", + "type": "u64", + "index": false + }, + { + "name": "periodRevenue", + "type": "i64", + "index": false + }, + { + "name": "baseAssetAmountWithAmm", + "type": "i128", + "index": false + }, + { + "name": "baseAssetAmountWithUnsettledLp", + "type": "i128", + "index": false + } + ] + }, + { + "name": "CurveRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "recordId", + "type": "u64", + "index": false + }, + { + "name": "pegMultiplierBefore", + "type": "u128", + "index": false + }, + { + "name": "baseAssetReserveBefore", + "type": "u128", + "index": false + }, + { + "name": "quoteAssetReserveBefore", + "type": "u128", + "index": false + }, + { + "name": "sqrtKBefore", + "type": "u128", + "index": false + }, + { + "name": "pegMultiplierAfter", + "type": "u128", + "index": false + }, + { + "name": "baseAssetReserveAfter", + "type": "u128", + "index": false + }, + { + "name": "quoteAssetReserveAfter", + "type": "u128", + "index": false + }, + { + "name": "sqrtKAfter", + "type": "u128", + "index": false + }, + { + "name": "baseAssetAmountLong", + "type": "u128", + "index": false + }, + { + "name": "baseAssetAmountShort", + "type": "u128", + "index": false + }, + { + "name": "baseAssetAmountWithAmm", + "type": "i128", + "index": false + }, + { + "name": "totalFee", + "type": "i128", + "index": false + }, + { + "name": "totalFeeMinusDistributions", + "type": "i128", + "index": false + }, + { + "name": "adjustmentCost", + "type": "i128", + "index": false + }, + { + "name": "oraclePrice", + "type": "i64", + "index": false + }, + { + "name": "fillRecord", + "type": "u128", + "index": false + }, + { + "name": "numberOfUsers", + "type": "u32", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + } + ] + }, + { + "name": "OrderRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "order", + "type": { + "defined": "Order" + }, + "index": false + } + ] + }, + { + "name": "OrderActionRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "action", + "type": { + "defined": "OrderAction" + }, + "index": false + }, + { + "name": "actionExplanation", + "type": { + "defined": "OrderActionExplanation" + }, + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "marketType", + "type": { + "defined": "MarketType" + }, + "index": false + }, + { + "name": "filler", + "type": { + "option": "publicKey" + }, + "index": false + }, + { + "name": "fillerReward", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "fillRecordId", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "baseAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "quoteAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "takerFee", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "makerFee", + "type": { + "option": "i64" + }, + "index": false + }, + { + "name": "referrerReward", + "type": { + "option": "u32" + }, + "index": false + }, + { + "name": "quoteAssetAmountSurplus", + "type": { + "option": "i64" + }, + "index": false + }, + { + "name": "spotFulfillmentMethodFee", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "taker", + "type": { + "option": "publicKey" + }, + "index": false + }, + { + "name": "takerOrderId", + "type": { + "option": "u32" + }, + "index": false + }, + { + "name": "takerOrderDirection", + "type": { + "option": { + "defined": "PositionDirection" + } + }, + "index": false + }, + { + "name": "takerOrderBaseAssetAmount", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "takerOrderCumulativeBaseAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "takerOrderCumulativeQuoteAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "maker", + "type": { + "option": "publicKey" + }, + "index": false + }, + { + "name": "makerOrderId", + "type": { + "option": "u32" + }, + "index": false + }, + { + "name": "makerOrderDirection", + "type": { + "option": { + "defined": "PositionDirection" + } + }, + "index": false + }, + { + "name": "makerOrderBaseAssetAmount", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "makerOrderCumulativeBaseAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "makerOrderCumulativeQuoteAssetAmountFilled", + "type": { + "option": "u64" + }, + "index": false + }, + { + "name": "oraclePrice", + "type": "i64", + "index": false + } + ] + }, + { + "name": "LPRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "action", + "type": { + "defined": "LPAction" + }, + "index": false + }, + { + "name": "nShares", + "type": "u64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "deltaBaseAssetAmount", + "type": "i64", + "index": false + }, + { + "name": "deltaQuoteAssetAmount", + "type": "i64", + "index": false + }, + { + "name": "pnl", + "type": "i64", + "index": false + } + ] + }, + { + "name": "LiquidationRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "liquidationType", + "type": { + "defined": "LiquidationType" + }, + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "liquidator", + "type": "publicKey", + "index": false + }, + { + "name": "marginRequirement", + "type": "u128", + "index": false + }, + { + "name": "totalCollateral", + "type": "i128", + "index": false + }, + { + "name": "marginFreed", + "type": "u64", + "index": false + }, + { + "name": "liquidationId", + "type": "u16", + "index": false + }, + { + "name": "bankrupt", + "type": "bool", + "index": false + }, + { + "name": "canceledOrderIds", + "type": { + "vec": "u32" + }, + "index": false + }, + { + "name": "liquidatePerp", + "type": { + "defined": "LiquidatePerpRecord" + }, + "index": false + }, + { + "name": "liquidateSpot", + "type": { + "defined": "LiquidateSpotRecord" + }, + "index": false + }, + { + "name": "liquidateBorrowForPerpPnl", + "type": { + "defined": "LiquidateBorrowForPerpPnlRecord" + }, + "index": false + }, + { + "name": "liquidatePerpPnlForDeposit", + "type": { + "defined": "LiquidatePerpPnlForDepositRecord" + }, + "index": false + }, + { + "name": "perpBankruptcy", + "type": { + "defined": "PerpBankruptcyRecord" + }, + "index": false + }, + { + "name": "spotBankruptcy", + "type": { + "defined": "SpotBankruptcyRecord" + }, + "index": false + } + ] + }, + { + "name": "SettlePnlRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "pnl", + "type": "i128", + "index": false + }, + { + "name": "baseAssetAmount", + "type": "i64", + "index": false + }, + { + "name": "quoteAssetAmountAfter", + "type": "i64", + "index": false + }, + { + "name": "quoteEntryAmount", + "type": "i64", + "index": false + }, + { + "name": "settlePrice", + "type": "i64", + "index": false + }, + { + "name": "explanation", + "type": { + "defined": "SettlePnlExplanation" + }, + "index": false + } + ] + }, + { + "name": "InsuranceFundRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "spotMarketIndex", + "type": "u16", + "index": false + }, + { + "name": "perpMarketIndex", + "type": "u16", + "index": false + }, + { + "name": "userIfFactor", + "type": "u32", + "index": false + }, + { + "name": "totalIfFactor", + "type": "u32", + "index": false + }, + { + "name": "vaultAmountBefore", + "type": "u64", + "index": false + }, + { + "name": "insuranceVaultAmountBefore", + "type": "u64", + "index": false + }, + { + "name": "totalIfSharesBefore", + "type": "u128", + "index": false + }, + { + "name": "totalIfSharesAfter", + "type": "u128", + "index": false + }, + { + "name": "amount", + "type": "i64", + "index": false + } + ] + }, + { + "name": "InsuranceFundStakeRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "userAuthority", + "type": "publicKey", + "index": false + }, + { + "name": "action", + "type": { + "defined": "StakeAction" + }, + "index": false + }, + { + "name": "amount", + "type": "u64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "insuranceVaultAmountBefore", + "type": "u64", + "index": false + }, + { + "name": "ifSharesBefore", + "type": "u128", + "index": false + }, + { + "name": "userIfSharesBefore", + "type": "u128", + "index": false + }, + { + "name": "totalIfSharesBefore", + "type": "u128", + "index": false + }, + { + "name": "ifSharesAfter", + "type": "u128", + "index": false + }, + { + "name": "userIfSharesAfter", + "type": "u128", + "index": false + }, + { + "name": "totalIfSharesAfter", + "type": "u128", + "index": false + } + ] + }, + { + "name": "SwapRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "user", + "type": "publicKey", + "index": false + }, + { + "name": "amountOut", + "type": "u64", + "index": false + }, + { + "name": "amountIn", + "type": "u64", + "index": false + }, + { + "name": "outMarketIndex", + "type": "u16", + "index": false + }, + { + "name": "inMarketIndex", + "type": "u16", + "index": false + }, + { + "name": "outOraclePrice", + "type": "i64", + "index": false + }, + { + "name": "inOraclePrice", + "type": "i64", + "index": false + }, + { + "name": "fee", + "type": "u64", + "index": false + } + ] + }, + { + "name": "SpotMarketVaultDepositRecord", + "fields": [ + { + "name": "ts", + "type": "i64", + "index": false + }, + { + "name": "marketIndex", + "type": "u16", + "index": false + }, + { + "name": "depositBalance", + "type": "u128", + "index": false + }, + { + "name": "cumulativeDepositInterestBefore", + "type": "u128", + "index": false + }, + { + "name": "cumulativeDepositInterestAfter", + "type": "u128", + "index": false + }, + { + "name": "depositTokenAmountBefore", + "type": "u64", + "index": false + }, + { + "name": "amount", + "type": "u64", + "index": false + } + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "InvalidSpotMarketAuthority", + "msg": "Invalid Spot Market Authority" + }, + { + "code": 6001, + "name": "InvalidInsuranceFundAuthority", + "msg": "Clearing house not insurance fund authority" + }, + { + "code": 6002, + "name": "InsufficientDeposit", + "msg": "Insufficient deposit" + }, + { + "code": 6003, + "name": "InsufficientCollateral", + "msg": "Insufficient collateral" + }, + { + "code": 6004, + "name": "SufficientCollateral", + "msg": "Sufficient collateral" + }, + { + "code": 6005, + "name": "MaxNumberOfPositions", + "msg": "Max number of positions taken" + }, + { + "code": 6006, + "name": "AdminControlsPricesDisabled", + "msg": "Admin Controls Prices Disabled" + }, + { + "code": 6007, + "name": "MarketDelisted", + "msg": "Market Delisted" + }, + { + "code": 6008, + "name": "MarketIndexAlreadyInitialized", + "msg": "Market Index Already Initialized" + }, + { + "code": 6009, + "name": "UserAccountAndUserPositionsAccountMismatch", + "msg": "User Account And User Positions Account Mismatch" + }, + { + "code": 6010, + "name": "UserHasNoPositionInMarket", + "msg": "User Has No Position In Market" + }, + { + "code": 6011, + "name": "InvalidInitialPeg", + "msg": "Invalid Initial Peg" + }, + { + "code": 6012, + "name": "InvalidRepegRedundant", + "msg": "AMM repeg already configured with amt given" + }, + { + "code": 6013, + "name": "InvalidRepegDirection", + "msg": "AMM repeg incorrect repeg direction" + }, + { + "code": 6014, + "name": "InvalidRepegProfitability", + "msg": "AMM repeg out of bounds pnl" + }, + { + "code": 6015, + "name": "SlippageOutsideLimit", + "msg": "Slippage Outside Limit Price" + }, + { + "code": 6016, + "name": "OrderSizeTooSmall", + "msg": "Order Size Too Small" + }, + { + "code": 6017, + "name": "InvalidUpdateK", + "msg": "Price change too large when updating K" + }, + { + "code": 6018, + "name": "AdminWithdrawTooLarge", + "msg": "Admin tried to withdraw amount larger than fees collected" + }, + { + "code": 6019, + "name": "MathError", + "msg": "Math Error" + }, + { + "code": 6020, + "name": "BnConversionError", + "msg": "Conversion to u128/u64 failed with an overflow or underflow" + }, + { + "code": 6021, + "name": "ClockUnavailable", + "msg": "Clock unavailable" + }, + { + "code": 6022, + "name": "UnableToLoadOracle", + "msg": "Unable To Load Oracles" + }, + { + "code": 6023, + "name": "PriceBandsBreached", + "msg": "Price Bands Breached" + }, + { + "code": 6024, + "name": "ExchangePaused", + "msg": "Exchange is paused" + }, + { + "code": 6025, + "name": "InvalidWhitelistToken", + "msg": "Invalid whitelist token" + }, + { + "code": 6026, + "name": "WhitelistTokenNotFound", + "msg": "Whitelist token not found" + }, + { + "code": 6027, + "name": "InvalidDiscountToken", + "msg": "Invalid discount token" + }, + { + "code": 6028, + "name": "DiscountTokenNotFound", + "msg": "Discount token not found" + }, + { + "code": 6029, + "name": "ReferrerNotFound", + "msg": "Referrer not found" + }, + { + "code": 6030, + "name": "ReferrerStatsNotFound", + "msg": "ReferrerNotFound" + }, + { + "code": 6031, + "name": "ReferrerMustBeWritable", + "msg": "ReferrerMustBeWritable" + }, + { + "code": 6032, + "name": "ReferrerStatsMustBeWritable", + "msg": "ReferrerMustBeWritable" + }, + { + "code": 6033, + "name": "ReferrerAndReferrerStatsAuthorityUnequal", + "msg": "ReferrerAndReferrerStatsAuthorityUnequal" + }, + { + "code": 6034, + "name": "InvalidReferrer", + "msg": "InvalidReferrer" + }, + { + "code": 6035, + "name": "InvalidOracle", + "msg": "InvalidOracle" + }, + { + "code": 6036, + "name": "OracleNotFound", + "msg": "OracleNotFound" + }, + { + "code": 6037, + "name": "LiquidationsBlockedByOracle", + "msg": "Liquidations Blocked By Oracle" + }, + { + "code": 6038, + "name": "MaxDeposit", + "msg": "Can not deposit more than max deposit" + }, + { + "code": 6039, + "name": "CantDeleteUserWithCollateral", + "msg": "Can not delete user that still has collateral" + }, + { + "code": 6040, + "name": "InvalidFundingProfitability", + "msg": "AMM funding out of bounds pnl" + }, + { + "code": 6041, + "name": "CastingFailure", + "msg": "Casting Failure" + }, + { + "code": 6042, + "name": "InvalidOrder", + "msg": "InvalidOrder" + }, + { + "code": 6043, + "name": "InvalidOrderMaxTs", + "msg": "InvalidOrderMaxTs" + }, + { + "code": 6044, + "name": "InvalidOrderMarketType", + "msg": "InvalidOrderMarketType" + }, + { + "code": 6045, + "name": "InvalidOrderForInitialMarginReq", + "msg": "InvalidOrderForInitialMarginReq" + }, + { + "code": 6046, + "name": "InvalidOrderNotRiskReducing", + "msg": "InvalidOrderNotRiskReducing" + }, + { + "code": 6047, + "name": "InvalidOrderSizeTooSmall", + "msg": "InvalidOrderSizeTooSmall" + }, + { + "code": 6048, + "name": "InvalidOrderNotStepSizeMultiple", + "msg": "InvalidOrderNotStepSizeMultiple" + }, + { + "code": 6049, + "name": "InvalidOrderBaseQuoteAsset", + "msg": "InvalidOrderBaseQuoteAsset" + }, + { + "code": 6050, + "name": "InvalidOrderIOC", + "msg": "InvalidOrderIOC" + }, + { + "code": 6051, + "name": "InvalidOrderPostOnly", + "msg": "InvalidOrderPostOnly" + }, + { + "code": 6052, + "name": "InvalidOrderIOCPostOnly", + "msg": "InvalidOrderIOCPostOnly" + }, + { + "code": 6053, + "name": "InvalidOrderTrigger", + "msg": "InvalidOrderTrigger" + }, + { + "code": 6054, + "name": "InvalidOrderAuction", + "msg": "InvalidOrderAuction" + }, + { + "code": 6055, + "name": "InvalidOrderOracleOffset", + "msg": "InvalidOrderOracleOffset" + }, + { + "code": 6056, + "name": "InvalidOrderMinOrderSize", + "msg": "InvalidOrderMinOrderSize" + }, + { + "code": 6057, + "name": "PlacePostOnlyLimitFailure", + "msg": "Failed to Place Post-Only Limit Order" + }, + { + "code": 6058, + "name": "UserHasNoOrder", + "msg": "User has no order" + }, + { + "code": 6059, + "name": "OrderAmountTooSmall", + "msg": "Order Amount Too Small" + }, + { + "code": 6060, + "name": "MaxNumberOfOrders", + "msg": "Max number of orders taken" + }, + { + "code": 6061, + "name": "OrderDoesNotExist", + "msg": "Order does not exist" + }, + { + "code": 6062, + "name": "OrderNotOpen", + "msg": "Order not open" + }, + { + "code": 6063, + "name": "FillOrderDidNotUpdateState", + "msg": "FillOrderDidNotUpdateState" + }, + { + "code": 6064, + "name": "ReduceOnlyOrderIncreasedRisk", + "msg": "Reduce only order increased risk" + }, + { + "code": 6065, + "name": "UnableToLoadAccountLoader", + "msg": "Unable to load AccountLoader" + }, + { + "code": 6066, + "name": "TradeSizeTooLarge", + "msg": "Trade Size Too Large" + }, + { + "code": 6067, + "name": "UserCantReferThemselves", + "msg": "User cant refer themselves" + }, + { + "code": 6068, + "name": "DidNotReceiveExpectedReferrer", + "msg": "Did not receive expected referrer" + }, + { + "code": 6069, + "name": "CouldNotDeserializeReferrer", + "msg": "Could not deserialize referrer" + }, + { + "code": 6070, + "name": "CouldNotDeserializeReferrerStats", + "msg": "Could not deserialize referrer stats" + }, + { + "code": 6071, + "name": "UserOrderIdAlreadyInUse", + "msg": "User Order Id Already In Use" + }, + { + "code": 6072, + "name": "NoPositionsLiquidatable", + "msg": "No positions liquidatable" + }, + { + "code": 6073, + "name": "InvalidMarginRatio", + "msg": "Invalid Margin Ratio" + }, + { + "code": 6074, + "name": "CantCancelPostOnlyOrder", + "msg": "Cant Cancel Post Only Order" + }, + { + "code": 6075, + "name": "InvalidOracleOffset", + "msg": "InvalidOracleOffset" + }, + { + "code": 6076, + "name": "CantExpireOrders", + "msg": "CantExpireOrders" + }, + { + "code": 6077, + "name": "CouldNotLoadMarketData", + "msg": "CouldNotLoadMarketData" + }, + { + "code": 6078, + "name": "PerpMarketNotFound", + "msg": "PerpMarketNotFound" + }, + { + "code": 6079, + "name": "InvalidMarketAccount", + "msg": "InvalidMarketAccount" + }, + { + "code": 6080, + "name": "UnableToLoadPerpMarketAccount", + "msg": "UnableToLoadMarketAccount" + }, + { + "code": 6081, + "name": "MarketWrongMutability", + "msg": "MarketWrongMutability" + }, + { + "code": 6082, + "name": "UnableToCastUnixTime", + "msg": "UnableToCastUnixTime" + }, + { + "code": 6083, + "name": "CouldNotFindSpotPosition", + "msg": "CouldNotFindSpotPosition" + }, + { + "code": 6084, + "name": "NoSpotPositionAvailable", + "msg": "NoSpotPositionAvailable" + }, + { + "code": 6085, + "name": "InvalidSpotMarketInitialization", + "msg": "InvalidSpotMarketInitialization" + }, + { + "code": 6086, + "name": "CouldNotLoadSpotMarketData", + "msg": "CouldNotLoadSpotMarketData" + }, + { + "code": 6087, + "name": "SpotMarketNotFound", + "msg": "SpotMarketNotFound" + }, + { + "code": 6088, + "name": "InvalidSpotMarketAccount", + "msg": "InvalidSpotMarketAccount" + }, + { + "code": 6089, + "name": "UnableToLoadSpotMarketAccount", + "msg": "UnableToLoadSpotMarketAccount" + }, + { + "code": 6090, + "name": "SpotMarketWrongMutability", + "msg": "SpotMarketWrongMutability" + }, + { + "code": 6091, + "name": "SpotMarketInterestNotUpToDate", + "msg": "SpotInterestNotUpToDate" + }, + { + "code": 6092, + "name": "SpotMarketInsufficientDeposits", + "msg": "SpotMarketInsufficientDeposits" + }, + { + "code": 6093, + "name": "UserMustSettleTheirOwnPositiveUnsettledPNL", + "msg": "UserMustSettleTheirOwnPositiveUnsettledPNL" + }, + { + "code": 6094, + "name": "CantUpdatePoolBalanceType", + "msg": "CantUpdatePoolBalanceType" + }, + { + "code": 6095, + "name": "InsufficientCollateralForSettlingPNL", + "msg": "InsufficientCollateralForSettlingPNL" + }, + { + "code": 6096, + "name": "AMMNotUpdatedInSameSlot", + "msg": "AMMNotUpdatedInSameSlot" + }, + { + "code": 6097, + "name": "AuctionNotComplete", + "msg": "AuctionNotComplete" + }, + { + "code": 6098, + "name": "MakerNotFound", + "msg": "MakerNotFound" + }, + { + "code": 6099, + "name": "MakerStatsNotFound", + "msg": "MakerNotFound" + }, + { + "code": 6100, + "name": "MakerMustBeWritable", + "msg": "MakerMustBeWritable" + }, + { + "code": 6101, + "name": "MakerStatsMustBeWritable", + "msg": "MakerMustBeWritable" + }, + { + "code": 6102, + "name": "MakerOrderNotFound", + "msg": "MakerOrderNotFound" + }, + { + "code": 6103, + "name": "CouldNotDeserializeMaker", + "msg": "CouldNotDeserializeMaker" + }, + { + "code": 6104, + "name": "CouldNotDeserializeMakerStats", + "msg": "CouldNotDeserializeMaker" + }, + { + "code": 6105, + "name": "AuctionPriceDoesNotSatisfyMaker", + "msg": "AuctionPriceDoesNotSatisfyMaker" + }, + { + "code": 6106, + "name": "MakerCantFulfillOwnOrder", + "msg": "MakerCantFulfillOwnOrder" + }, + { + "code": 6107, + "name": "MakerOrderMustBePostOnly", + "msg": "MakerOrderMustBePostOnly" + }, + { + "code": 6108, + "name": "CantMatchTwoPostOnlys", + "msg": "CantMatchTwoPostOnlys" + }, + { + "code": 6109, + "name": "OrderBreachesOraclePriceLimits", + "msg": "OrderBreachesOraclePriceLimits" + }, + { + "code": 6110, + "name": "OrderMustBeTriggeredFirst", + "msg": "OrderMustBeTriggeredFirst" + }, + { + "code": 6111, + "name": "OrderNotTriggerable", + "msg": "OrderNotTriggerable" + }, + { + "code": 6112, + "name": "OrderDidNotSatisfyTriggerCondition", + "msg": "OrderDidNotSatisfyTriggerCondition" + }, + { + "code": 6113, + "name": "PositionAlreadyBeingLiquidated", + "msg": "PositionAlreadyBeingLiquidated" + }, + { + "code": 6114, + "name": "PositionDoesntHaveOpenPositionOrOrders", + "msg": "PositionDoesntHaveOpenPositionOrOrders" + }, + { + "code": 6115, + "name": "AllOrdersAreAlreadyLiquidations", + "msg": "AllOrdersAreAlreadyLiquidations" + }, + { + "code": 6116, + "name": "CantCancelLiquidationOrder", + "msg": "CantCancelLiquidationOrder" + }, + { + "code": 6117, + "name": "UserIsBeingLiquidated", + "msg": "UserIsBeingLiquidated" + }, + { + "code": 6118, + "name": "LiquidationsOngoing", + "msg": "LiquidationsOngoing" + }, + { + "code": 6119, + "name": "WrongSpotBalanceType", + "msg": "WrongSpotBalanceType" + }, + { + "code": 6120, + "name": "UserCantLiquidateThemself", + "msg": "UserCantLiquidateThemself" + }, + { + "code": 6121, + "name": "InvalidPerpPositionToLiquidate", + "msg": "InvalidPerpPositionToLiquidate" + }, + { + "code": 6122, + "name": "InvalidBaseAssetAmountForLiquidatePerp", + "msg": "InvalidBaseAssetAmountForLiquidatePerp" + }, + { + "code": 6123, + "name": "InvalidPositionLastFundingRate", + "msg": "InvalidPositionLastFundingRate" + }, + { + "code": 6124, + "name": "InvalidPositionDelta", + "msg": "InvalidPositionDelta" + }, + { + "code": 6125, + "name": "UserBankrupt", + "msg": "UserBankrupt" + }, + { + "code": 6126, + "name": "UserNotBankrupt", + "msg": "UserNotBankrupt" + }, + { + "code": 6127, + "name": "UserHasInvalidBorrow", + "msg": "UserHasInvalidBorrow" + }, + { + "code": 6128, + "name": "DailyWithdrawLimit", + "msg": "DailyWithdrawLimit" + }, + { + "code": 6129, + "name": "DefaultError", + "msg": "DefaultError" + }, + { + "code": 6130, + "name": "InsufficientLPTokens", + "msg": "Insufficient LP tokens" + }, + { + "code": 6131, + "name": "CantLPWithPerpPosition", + "msg": "Cant LP with a market position" + }, + { + "code": 6132, + "name": "UnableToBurnLPTokens", + "msg": "Unable to burn LP tokens" + }, + { + "code": 6133, + "name": "TryingToRemoveLiquidityTooFast", + "msg": "Trying to remove liqudity too fast after adding it" + }, + { + "code": 6134, + "name": "InvalidSpotMarketVault", + "msg": "Invalid Spot Market Vault" + }, + { + "code": 6135, + "name": "InvalidSpotMarketState", + "msg": "Invalid Spot Market State" + }, + { + "code": 6136, + "name": "InvalidSerumProgram", + "msg": "InvalidSerumProgram" + }, + { + "code": 6137, + "name": "InvalidSerumMarket", + "msg": "InvalidSerumMarket" + }, + { + "code": 6138, + "name": "InvalidSerumBids", + "msg": "InvalidSerumBids" + }, + { + "code": 6139, + "name": "InvalidSerumAsks", + "msg": "InvalidSerumAsks" + }, + { + "code": 6140, + "name": "InvalidSerumOpenOrders", + "msg": "InvalidSerumOpenOrders" + }, + { + "code": 6141, + "name": "FailedSerumCPI", + "msg": "FailedSerumCPI" + }, + { + "code": 6142, + "name": "FailedToFillOnExternalMarket", + "msg": "FailedToFillOnExternalMarket" + }, + { + "code": 6143, + "name": "InvalidFulfillmentConfig", + "msg": "InvalidFulfillmentConfig" + }, + { + "code": 6144, + "name": "InvalidFeeStructure", + "msg": "InvalidFeeStructure" + }, + { + "code": 6145, + "name": "InsufficientIFShares", + "msg": "Insufficient IF shares" + }, + { + "code": 6146, + "name": "MarketActionPaused", + "msg": "the Market has paused this action" + }, + { + "code": 6147, + "name": "MarketPlaceOrderPaused", + "msg": "the Market status doesnt allow placing orders" + }, + { + "code": 6148, + "name": "MarketFillOrderPaused", + "msg": "the Market status doesnt allow filling orders" + }, + { + "code": 6149, + "name": "MarketWithdrawPaused", + "msg": "the Market status doesnt allow withdraws" + }, + { + "code": 6150, + "name": "ProtectedAssetTierViolation", + "msg": "Action violates the Protected Asset Tier rules" + }, + { + "code": 6151, + "name": "IsolatedAssetTierViolation", + "msg": "Action violates the Isolated Asset Tier rules" + }, + { + "code": 6152, + "name": "UserCantBeDeleted", + "msg": "User Cant Be Deleted" + }, + { + "code": 6153, + "name": "ReduceOnlyWithdrawIncreasedRisk", + "msg": "Reduce Only Withdraw Increased Risk" + }, + { + "code": 6154, + "name": "MaxOpenInterest", + "msg": "Max Open Interest" + }, + { + "code": 6155, + "name": "CantResolvePerpBankruptcy", + "msg": "Cant Resolve Perp Bankruptcy" + }, + { + "code": 6156, + "name": "LiquidationDoesntSatisfyLimitPrice", + "msg": "Liquidation Doesnt Satisfy Limit Price" + }, + { + "code": 6157, + "name": "MarginTradingDisabled", + "msg": "Margin Trading Disabled" + }, + { + "code": 6158, + "name": "InvalidMarketStatusToSettlePnl", + "msg": "Invalid Market Status to Settle Perp Pnl" + }, + { + "code": 6159, + "name": "PerpMarketNotInSettlement", + "msg": "PerpMarketNotInSettlement" + }, + { + "code": 6160, + "name": "PerpMarketNotInReduceOnly", + "msg": "PerpMarketNotInReduceOnly" + }, + { + "code": 6161, + "name": "PerpMarketSettlementBufferNotReached", + "msg": "PerpMarketSettlementBufferNotReached" + }, + { + "code": 6162, + "name": "PerpMarketSettlementUserHasOpenOrders", + "msg": "PerpMarketSettlementUserHasOpenOrders" + }, + { + "code": 6163, + "name": "PerpMarketSettlementUserHasActiveLP", + "msg": "PerpMarketSettlementUserHasActiveLP" + }, + { + "code": 6164, + "name": "UnableToSettleExpiredUserPosition", + "msg": "UnableToSettleExpiredUserPosition" + }, + { + "code": 6165, + "name": "UnequalMarketIndexForSpotTransfer", + "msg": "UnequalMarketIndexForSpotTransfer" + }, + { + "code": 6166, + "name": "InvalidPerpPositionDetected", + "msg": "InvalidPerpPositionDetected" + }, + { + "code": 6167, + "name": "InvalidSpotPositionDetected", + "msg": "InvalidSpotPositionDetected" + }, + { + "code": 6168, + "name": "InvalidAmmDetected", + "msg": "InvalidAmmDetected" + }, + { + "code": 6169, + "name": "InvalidAmmForFillDetected", + "msg": "InvalidAmmForFillDetected" + }, + { + "code": 6170, + "name": "InvalidAmmLimitPriceOverride", + "msg": "InvalidAmmLimitPriceOverride" + }, + { + "code": 6171, + "name": "InvalidOrderFillPrice", + "msg": "InvalidOrderFillPrice" + }, + { + "code": 6172, + "name": "SpotMarketBalanceInvariantViolated", + "msg": "SpotMarketBalanceInvariantViolated" + }, + { + "code": 6173, + "name": "SpotMarketVaultInvariantViolated", + "msg": "SpotMarketVaultInvariantViolated" + }, + { + "code": 6174, + "name": "InvalidPDA", + "msg": "InvalidPDA" + }, + { + "code": 6175, + "name": "InvalidPDASigner", + "msg": "InvalidPDASigner" + }, + { + "code": 6176, + "name": "RevenueSettingsCannotSettleToIF", + "msg": "RevenueSettingsCannotSettleToIF" + }, + { + "code": 6177, + "name": "NoRevenueToSettleToIF", + "msg": "NoRevenueToSettleToIF" + }, + { + "code": 6178, + "name": "NoAmmPerpPnlDeficit", + "msg": "NoAmmPerpPnlDeficit" + }, + { + "code": 6179, + "name": "SufficientPerpPnlPool", + "msg": "SufficientPerpPnlPool" + }, + { + "code": 6180, + "name": "InsufficientPerpPnlPool", + "msg": "InsufficientPerpPnlPool" + }, + { + "code": 6181, + "name": "PerpPnlDeficitBelowThreshold", + "msg": "PerpPnlDeficitBelowThreshold" + }, + { + "code": 6182, + "name": "MaxRevenueWithdrawPerPeriodReached", + "msg": "MaxRevenueWithdrawPerPeriodReached" + }, + { + "code": 6183, + "name": "MaxIFWithdrawReached", + "msg": "InvalidSpotPositionDetected" + }, + { + "code": 6184, + "name": "NoIFWithdrawAvailable", + "msg": "NoIFWithdrawAvailable" + }, + { + "code": 6185, + "name": "InvalidIFUnstake", + "msg": "InvalidIFUnstake" + }, + { + "code": 6186, + "name": "InvalidIFUnstakeSize", + "msg": "InvalidIFUnstakeSize" + }, + { + "code": 6187, + "name": "InvalidIFUnstakeCancel", + "msg": "InvalidIFUnstakeCancel" + }, + { + "code": 6188, + "name": "InvalidIFForNewStakes", + "msg": "InvalidIFForNewStakes" + }, + { + "code": 6189, + "name": "InvalidIFRebase", + "msg": "InvalidIFRebase" + }, + { + "code": 6190, + "name": "InvalidInsuranceUnstakeSize", + "msg": "InvalidInsuranceUnstakeSize" + }, + { + "code": 6191, + "name": "InvalidOrderLimitPrice", + "msg": "InvalidOrderLimitPrice" + }, + { + "code": 6192, + "name": "InvalidIFDetected", + "msg": "InvalidIFDetected" + }, + { + "code": 6193, + "name": "InvalidAmmMaxSpreadDetected", + "msg": "InvalidAmmMaxSpreadDetected" + }, + { + "code": 6194, + "name": "InvalidConcentrationCoef", + "msg": "InvalidConcentrationCoef" + }, + { + "code": 6195, + "name": "InvalidSrmVault", + "msg": "InvalidSrmVault" + }, + { + "code": 6196, + "name": "InvalidVaultOwner", + "msg": "InvalidVaultOwner" + }, + { + "code": 6197, + "name": "InvalidMarketStatusForFills", + "msg": "InvalidMarketStatusForFills" + }, + { + "code": 6198, + "name": "IFWithdrawRequestInProgress", + "msg": "IFWithdrawRequestInProgress" + }, + { + "code": 6199, + "name": "NoIFWithdrawRequestInProgress", + "msg": "NoIFWithdrawRequestInProgress" + }, + { + "code": 6200, + "name": "IFWithdrawRequestTooSmall", + "msg": "IFWithdrawRequestTooSmall" + }, + { + "code": 6201, + "name": "IncorrectSpotMarketAccountPassed", + "msg": "IncorrectSpotMarketAccountPassed" + }, + { + "code": 6202, + "name": "BlockchainClockInconsistency", + "msg": "BlockchainClockInconsistency" + }, + { + "code": 6203, + "name": "InvalidIFSharesDetected", + "msg": "InvalidIFSharesDetected" + }, + { + "code": 6204, + "name": "NewLPSizeTooSmall", + "msg": "NewLPSizeTooSmall" + }, + { + "code": 6205, + "name": "MarketStatusInvalidForNewLP", + "msg": "MarketStatusInvalidForNewLP" + }, + { + "code": 6206, + "name": "InvalidMarkTwapUpdateDetected", + "msg": "InvalidMarkTwapUpdateDetected" + }, + { + "code": 6207, + "name": "MarketSettlementAttemptOnActiveMarket", + "msg": "MarketSettlementAttemptOnActiveMarket" + }, + { + "code": 6208, + "name": "MarketSettlementRequiresSettledLP", + "msg": "MarketSettlementRequiresSettledLP" + }, + { + "code": 6209, + "name": "MarketSettlementAttemptTooEarly", + "msg": "MarketSettlementAttemptTooEarly" + }, + { + "code": 6210, + "name": "MarketSettlementTargetPriceInvalid", + "msg": "MarketSettlementTargetPriceInvalid" + }, + { + "code": 6211, + "name": "UnsupportedSpotMarket", + "msg": "UnsupportedSpotMarket" + }, + { + "code": 6212, + "name": "SpotOrdersDisabled", + "msg": "SpotOrdersDisabled" + }, + { + "code": 6213, + "name": "MarketBeingInitialized", + "msg": "Market Being Initialized" + }, + { + "code": 6214, + "name": "InvalidUserSubAccountId", + "msg": "Invalid Sub Account Id" + }, + { + "code": 6215, + "name": "InvalidTriggerOrderCondition", + "msg": "Invalid Trigger Order Condition" + }, + { + "code": 6216, + "name": "InvalidSpotPosition", + "msg": "Invalid Spot Position" + }, + { + "code": 6217, + "name": "CantTransferBetweenSameUserAccount", + "msg": "Cant transfer between same user account" + }, + { + "code": 6218, + "name": "InvalidPerpPosition", + "msg": "Invalid Perp Position" + }, + { + "code": 6219, + "name": "UnableToGetLimitPrice", + "msg": "Unable To Get Limit Price" + }, + { + "code": 6220, + "name": "InvalidLiquidation", + "msg": "Invalid Liquidation" + }, + { + "code": 6221, + "name": "SpotFulfillmentConfigDisabled", + "msg": "Spot Fulfillment Config Disabled" + }, + { + "code": 6222, + "name": "InvalidMaker", + "msg": "Invalid Maker" + }, + { + "code": 6223, + "name": "FailedUnwrap", + "msg": "Failed Unwrap" + }, + { + "code": 6224, + "name": "MaxNumberOfUsers", + "msg": "Max Number Of Users" + }, + { + "code": 6225, + "name": "InvalidOracleForSettlePnl", + "msg": "InvalidOracleForSettlePnl" + }, + { + "code": 6226, + "name": "MarginOrdersOpen", + "msg": "MarginOrdersOpen" + }, + { + "code": 6227, + "name": "TierViolationLiquidatingPerpPnl", + "msg": "TierViolationLiquidatingPerpPnl" + }, + { + "code": 6228, + "name": "CouldNotLoadUserData", + "msg": "CouldNotLoadUserData" + }, + { + "code": 6229, + "name": "UserWrongMutability", + "msg": "UserWrongMutability" + }, + { + "code": 6230, + "name": "InvalidUserAccount", + "msg": "InvalidUserAccount" + }, + { + "code": 6231, + "name": "CouldNotLoadUserStatsData", + "msg": "CouldNotLoadUserData" + }, + { + "code": 6232, + "name": "UserStatsWrongMutability", + "msg": "UserWrongMutability" + }, + { + "code": 6233, + "name": "InvalidUserStatsAccount", + "msg": "InvalidUserAccount" + }, + { + "code": 6234, + "name": "UserNotFound", + "msg": "UserNotFound" + }, + { + "code": 6235, + "name": "UnableToLoadUserAccount", + "msg": "UnableToLoadUserAccount" + }, + { + "code": 6236, + "name": "UserStatsNotFound", + "msg": "UserStatsNotFound" + }, + { + "code": 6237, + "name": "UnableToLoadUserStatsAccount", + "msg": "UnableToLoadUserStatsAccount" + }, + { + "code": 6238, + "name": "UserNotInactive", + "msg": "User Not Inactive" + }, + { + "code": 6239, + "name": "RevertFill", + "msg": "RevertFill" + }, + { + "code": 6240, + "name": "InvalidMarketAccountforDeletion", + "msg": "Invalid MarketAccount for Deletion" + }, + { + "code": 6241, + "name": "InvalidSpotFulfillmentParams", + "msg": "Invalid Spot Fulfillment Params" + }, + { + "code": 6242, + "name": "FailedToGetMint", + "msg": "Failed to Get Mint" + }, + { + "code": 6243, + "name": "FailedPhoenixCPI", + "msg": "FailedPhoenixCPI" + }, + { + "code": 6244, + "name": "FailedToDeserializePhoenixMarket", + "msg": "FailedToDeserializePhoenixMarket" + }, + { + "code": 6245, + "name": "InvalidPricePrecision", + "msg": "InvalidPricePrecision" + }, + { + "code": 6246, + "name": "InvalidPhoenixProgram", + "msg": "InvalidPhoenixProgram" + }, + { + "code": 6247, + "name": "InvalidPhoenixMarket", + "msg": "InvalidPhoenixMarket" + }, + { + "code": 6248, + "name": "InvalidSwap", + "msg": "InvalidSwap" + }, + { + "code": 6249, + "name": "SwapLimitPriceBreached", + "msg": "SwapLimitPriceBreached" + }, + { + "code": 6250, + "name": "SpotMarketReduceOnly", + "msg": "SpotMarketReduceOnly" + }, + { + "code": 6251, + "name": "FundingWasNotUpdated", + "msg": "FundingWasNotUpdated" + }, + { + "code": 6252, + "name": "ImpossibleFill", + "msg": "ImpossibleFill" + }, + { + "code": 6253, + "name": "CantUpdatePerpBidAskTwap", + "msg": "CantUpdatePerpBidAskTwap" + }, + { + "code": 6254, + "name": "UserReduceOnly", + "msg": "UserReduceOnly" + }, + { + "code": 6255, + "name": "InvalidMarginCalculation", + "msg": "InvalidMarginCalculation" + }, + { + "code": 6256, + "name": "CantPayUserInitFee", + "msg": "CantPayUserInitFee" + }, + { + "code": 6257, + "name": "CantReclaimRent", + "msg": "CantReclaimRent" + }, + { + "code": 6258, + "name": "InsuranceFundOperationPaused", + "msg": "InsuranceFundOperationPaused" + }, + { + "code": 6259, + "name": "NoUnsettledPnl", + "msg": "NoUnsettledPnl" + }, + { + "code": 6260, + "name": "PnlPoolCantSettleUser", + "msg": "PnlPoolCantSettleUser" + }, + { + "code": 6261, + "name": "OracleNonPositive", + "msg": "OracleInvalid" + }, + { + "code": 6262, + "name": "OracleTooVolatile", + "msg": "OracleTooVolatile" + }, + { + "code": 6263, + "name": "OracleTooUncertain", + "msg": "OracleTooUncertain" + }, + { + "code": 6264, + "name": "OracleStaleForMargin", + "msg": "OracleStaleForMargin" + }, + { + "code": 6265, + "name": "OracleInsufficientDataPoints", + "msg": "OracleInsufficientDataPoints" + }, + { + "code": 6266, + "name": "OracleStaleForAMM", + "msg": "OracleStaleForAMM" + }, + { + "code": 6267, + "name": "UnableToParsePullOracleMessage", + "msg": "Unable to parse pull oracle message" + }, + { + "code": 6268, + "name": "MaxBorrows", + "msg": "Can not borow more than max borrows" + }, + { + "code": 6269, + "name": "OracleUpdatesNotMonotonic", + "msg": "Updates must be monotonically increasing" + }, + { + "code": 6270, + "name": "OraclePriceFeedMessageMismatch", + "msg": "Trying to update price feed with the wrong feed id" + }, + { + "code": 6271, + "name": "OracleUnsupportedMessageType", + "msg": "The message in the update must be a PriceFeedMessage" + }, + { + "code": 6272, + "name": "OracleDeserializeMessageFailed", + "msg": "Could not deserialize the message in the update" + }, + { + "code": 6273, + "name": "OracleWrongGuardianSetOwner", + "msg": "Wrong guardian set owner in update price atomic" + }, + { + "code": 6274, + "name": "OracleWrongWriteAuthority", + "msg": "Oracle post update atomic price feed account must be drift program" + }, + { + "code": 6275, + "name": "OracleWrongVaaOwner", + "msg": "Oracle vaa owner must be wormhole program" + }, + { + "code": 6276, + "name": "OracleTooManyPriceAccountUpdates", + "msg": "Multi updates must have 2 or fewer accounts passed in remaining accounts" + }, + { + "code": 6277, + "name": "OracleMismatchedVaaAndPriceUpdates", + "msg": "Don't have the same remaining accounts number and merkle price updates left" + }, + { + "code": 6278, + "name": "OracleBadRemainingAccountPublicKey", + "msg": "Remaining account passed is not a valid pda" + }, + { + "code": 6279, + "name": "FailedOpenbookV2CPI", + "msg": "FailedOpenbookV2CPI" + }, + { + "code": 6280, + "name": "InvalidOpenbookV2Program", + "msg": "InvalidOpenbookV2Program" + }, + { + "code": 6281, + "name": "InvalidOpenbookV2Market", + "msg": "InvalidOpenbookV2Market" + }, + { + "code": 6282, + "name": "NonZeroTransferFee", + "msg": "Non zero transfer fee" + }, + { + "code": 6283, + "name": "LiquidationOrderFailedToFill", + "msg": "Liquidation order failed to fill" + }, + { + "code": 6284, + "name": "InvalidPredictionMarketOrder", + "msg": "Invalid prediction market order" + } + ] +} \ No newline at end of file diff --git a/DriftStakeVoterPlugin/idl/driftStakeVoter.ts b/DriftStakeVoterPlugin/idl/driftStakeVoter.ts new file mode 100644 index 0000000000..61496132c7 --- /dev/null +++ b/DriftStakeVoterPlugin/idl/driftStakeVoter.ts @@ -0,0 +1,745 @@ +export type DriftStakeVoter = { + version: '0.0.1' + name: 'drift_stake_voter' + instructions: [ + { + name: 'createRegistrar' + accounts: [ + { + name: 'registrar' + isMut: true + isSigner: false + docs: [ + 'There can only be a single registrar per Realm and governing mint of the Realm' + ] + }, + { + name: 'governanceProgramId' + isMut: false + isSigner: false + docs: [ + 'The program id of the spl-governance program the realm belongs to' + ] + }, + { + name: 'driftProgramId' + isMut: false + isSigner: false + }, + { + name: 'realm' + isMut: false + isSigner: false + docs: [ + 'An spl-governance Realm', + '', + 'Realm is validated in the instruction:', + '- Realm is owned by the governance_program_id', + '- governing_token_mint must be the community or council mint', + '- realm_authority is realm.authority' + ] + }, + { + name: 'governingTokenMint' + isMut: false + isSigner: false + docs: [ + 'Either the realm community mint or the council mint.', + 'It must match Realm.community_mint or Realm.config.council_mint', + '', + 'Note: Once the Realm voter plugin is enabled the governing_token_mint is used only as identity', + 'for the voting population and the tokens of that are no longer used' + ] + }, + { + name: 'realmAuthority' + isMut: false + isSigner: true + docs: ['realm_authority must sign and match Realm.authority'] + }, + { + name: 'payer' + isMut: true + isSigner: true + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'spotMarketIndex' + type: 'u16' + } + ] + }, + { + name: 'createVoterWeightRecord' + accounts: [ + { + name: 'registrar' + isMut: false + isSigner: false + }, + { + name: 'voterWeightRecord' + isMut: true + isSigner: false + }, + { + name: 'payer' + isMut: true + isSigner: true + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'governingTokenOwner' + type: 'publicKey' + } + ] + }, + { + name: 'updateVoterWeightRecord' + accounts: [ + { + name: 'registrar' + isMut: false + isSigner: false + }, + { + name: 'voterWeightRecord' + isMut: true + isSigner: false + }, + { + name: 'tokenOwnerRecord' + isMut: false + isSigner: false + docs: [ + 'TokenOwnerRecord for any of the configured spl-governance instances' + ] + }, + { + name: 'spotMarket' + isMut: false + isSigner: false + isOptional: true + }, + { + name: 'insuranceFundVault' + isMut: false + isSigner: false + isOptional: true + }, + { + name: 'insuranceFundStake' + isMut: false + isSigner: false + isOptional: true + }, + { + name: 'driftProgram' + isMut: false + isSigner: false + } + ] + args: [] + } + ] + accounts: [ + { + name: 'registrar' + docs: [ + 'Registrar which stores spl-governance configurations for the given Realm' + ] + type: { + kind: 'struct' + fields: [ + { + name: 'governanceProgramId' + docs: ['spl-governance program the Realm belongs to'] + type: 'publicKey' + }, + { + name: 'realm' + docs: ['Realm of the Registrar'] + type: 'publicKey' + }, + { + name: 'governingTokenMint' + docs: [ + 'Governing token mint the Registrar is for', + 'It can either be the Community or the Council mint of the Realm', + 'When the plugin is enabled the mint is only used as the identity of the governing power (voting population)', + 'and the actual token of the mint is not used' + ] + type: 'publicKey' + }, + { + name: 'driftProgramId' + type: 'publicKey' + }, + { + name: 'spotMarketIndex' + type: 'u16' + } + ] + } + }, + { + name: 'voterWeightRecord' + docs: [ + 'VoterWeightRecord account as defined in spl-governance-addin-api', + "It's redefined here without account_discriminator for Anchor to treat it as native account", + '', + 'The account is used as an api interface to provide voting power to the governance program from external addin contracts' + ] + type: { + kind: 'struct' + fields: [ + { + name: 'realm' + docs: ['The Realm the VoterWeightRecord belongs to'] + type: 'publicKey' + }, + { + name: 'governingTokenMint' + docs: [ + 'Governing Token Mint the VoterWeightRecord is associated with', + 'Note: The addin can take deposits of any tokens and is not restricted to the community or council tokens only' + ] + type: 'publicKey' + }, + { + name: 'governingTokenOwner' + docs: [ + 'The owner of the governing token and voter', + 'This is the actual owner (voter) and corresponds to TokenOwnerRecord.governing_token_owner' + ] + type: 'publicKey' + }, + { + name: 'voterWeight' + docs: [ + "Voter's weight", + 'The weight of the voter provided by the addin for the given realm, governing_token_mint and governing_token_owner (voter)' + ] + type: 'u64' + }, + { + name: 'voterWeightExpiry' + docs: [ + 'The slot when the voting weight expires', + 'It should be set to None if the weight never expires', + 'If the voter weight decays with time, for example for time locked based weights, then the expiry must be set', + 'As a common pattern Revise instruction to update the weight should be invoked before governance instruction within the same transaction', + 'and the expiry set to the current slot to provide up to date weight' + ] + type: { + option: 'u64' + } + }, + { + name: 'weightAction' + docs: [ + "The governance action the voter's weight pertains to", + "It allows to provided voter's weight specific to the particular action the weight is evaluated for", + 'When the action is provided then the governance program asserts the executing action is the same as specified by the addin' + ] + type: { + option: { + defined: 'VoterWeightAction' + } + } + }, + { + name: 'weightActionTarget' + docs: [ + "The target the voter's weight action pertains to", + "It allows to provided voter's weight specific to the target the weight is evaluated for", + 'For example when addin supplies weight to vote on a particular proposal then it must specify the proposal as the action target', + 'When the target is provided then the governance program asserts the target is the same as specified by the addin' + ] + type: { + option: 'publicKey' + } + }, + { + name: 'reserved' + docs: ['Reserved space for future versions'] + type: { + array: ['u8', 8] + } + } + ] + } + } + ] + types: [ + { + name: 'CollectionItemChangeType' + docs: ['Enum defining collection item change type'] + type: { + kind: 'enum' + variants: [ + { + name: 'Upsert' + }, + { + name: 'Remove' + } + ] + } + }, + { + name: 'VoterWeightAction' + docs: [ + 'VoterWeightAction enum as defined in spl-governance-addin-api', + "It's redefined here for Anchor to export it to IDL" + ] + type: { + kind: 'enum' + variants: [ + { + name: 'CastVote' + }, + { + name: 'CommentProposal' + }, + { + name: 'CreateGovernance' + }, + { + name: 'CreateProposal' + }, + { + name: 'SignOffProposal' + } + ] + } + } + ] + errors: [ + { + code: 6000 + name: 'InvalidRealmAuthority' + msg: 'Invalid Realm Authority' + }, + { + code: 6001 + name: 'InvalidRealmForRegistrar' + msg: 'Invalid Realm for Registrar' + }, + { + code: 6002 + name: 'InvalidVoterWeightRecordRealm' + msg: 'Invalid VoterWeightRecord Realm' + }, + { + code: 6003 + name: 'InvalidVoterWeightRecordMint' + msg: 'Invalid VoterWeightRecord Mint' + }, + { + code: 6004 + name: 'TokenOwnerRecordFromOwnRealmNotAllowed' + msg: 'TokenOwnerRecord from own realm is not allowed' + }, + { + code: 6005 + name: 'GovernanceProgramNotConfigured' + msg: 'Governance program not configured' + }, + { + code: 6006 + name: 'GoverningTokenOwnerMustMatch' + msg: 'Governing TokenOwner must match' + }, + { + code: 6007 + name: 'DriftError' + msg: 'DriftError' + } + ] +} + +export const IDL: DriftStakeVoter = { + version: '0.0.1', + name: 'drift_stake_voter', + instructions: [ + { + name: 'createRegistrar', + accounts: [ + { + name: 'registrar', + isMut: true, + isSigner: false, + docs: [ + 'There can only be a single registrar per Realm and governing mint of the Realm', + ], + }, + { + name: 'governanceProgramId', + isMut: false, + isSigner: false, + docs: [ + 'The program id of the spl-governance program the realm belongs to', + ], + }, + { + name: 'driftProgramId', + isMut: false, + isSigner: false, + }, + { + name: 'realm', + isMut: false, + isSigner: false, + docs: [ + 'An spl-governance Realm', + '', + 'Realm is validated in the instruction:', + '- Realm is owned by the governance_program_id', + '- governing_token_mint must be the community or council mint', + '- realm_authority is realm.authority', + ], + }, + { + name: 'governingTokenMint', + isMut: false, + isSigner: false, + docs: [ + 'Either the realm community mint or the council mint.', + 'It must match Realm.community_mint or Realm.config.council_mint', + '', + 'Note: Once the Realm voter plugin is enabled the governing_token_mint is used only as identity', + 'for the voting population and the tokens of that are no longer used', + ], + }, + { + name: 'realmAuthority', + isMut: false, + isSigner: true, + docs: ['realm_authority must sign and match Realm.authority'], + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'spotMarketIndex', + type: 'u16', + }, + ], + }, + { + name: 'createVoterWeightRecord', + accounts: [ + { + name: 'registrar', + isMut: false, + isSigner: false, + }, + { + name: 'voterWeightRecord', + isMut: true, + isSigner: false, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'governingTokenOwner', + type: 'publicKey', + }, + ], + }, + { + name: 'updateVoterWeightRecord', + accounts: [ + { + name: 'registrar', + isMut: false, + isSigner: false, + }, + { + name: 'voterWeightRecord', + isMut: true, + isSigner: false, + }, + { + name: 'tokenOwnerRecord', + isMut: false, + isSigner: false, + docs: [ + 'TokenOwnerRecord for any of the configured spl-governance instances', + ], + }, + { + name: 'spotMarket', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'insuranceFundVault', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'insuranceFundStake', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'driftProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + ], + accounts: [ + { + name: 'registrar', + docs: [ + 'Registrar which stores spl-governance configurations for the given Realm', + ], + type: { + kind: 'struct', + fields: [ + { + name: 'governanceProgramId', + docs: ['spl-governance program the Realm belongs to'], + type: 'publicKey', + }, + { + name: 'realm', + docs: ['Realm of the Registrar'], + type: 'publicKey', + }, + { + name: 'governingTokenMint', + docs: [ + 'Governing token mint the Registrar is for', + 'It can either be the Community or the Council mint of the Realm', + 'When the plugin is enabled the mint is only used as the identity of the governing power (voting population)', + 'and the actual token of the mint is not used', + ], + type: 'publicKey', + }, + { + name: 'driftProgramId', + type: 'publicKey', + }, + { + name: 'spotMarketIndex', + type: 'u16', + }, + ], + }, + }, + { + name: 'voterWeightRecord', + docs: [ + 'VoterWeightRecord account as defined in spl-governance-addin-api', + "It's redefined here without account_discriminator for Anchor to treat it as native account", + '', + 'The account is used as an api interface to provide voting power to the governance program from external addin contracts', + ], + type: { + kind: 'struct', + fields: [ + { + name: 'realm', + docs: ['The Realm the VoterWeightRecord belongs to'], + type: 'publicKey', + }, + { + name: 'governingTokenMint', + docs: [ + 'Governing Token Mint the VoterWeightRecord is associated with', + 'Note: The addin can take deposits of any tokens and is not restricted to the community or council tokens only', + ], + type: 'publicKey', + }, + { + name: 'governingTokenOwner', + docs: [ + 'The owner of the governing token and voter', + 'This is the actual owner (voter) and corresponds to TokenOwnerRecord.governing_token_owner', + ], + type: 'publicKey', + }, + { + name: 'voterWeight', + docs: [ + "Voter's weight", + 'The weight of the voter provided by the addin for the given realm, governing_token_mint and governing_token_owner (voter)', + ], + type: 'u64', + }, + { + name: 'voterWeightExpiry', + docs: [ + 'The slot when the voting weight expires', + 'It should be set to None if the weight never expires', + 'If the voter weight decays with time, for example for time locked based weights, then the expiry must be set', + 'As a common pattern Revise instruction to update the weight should be invoked before governance instruction within the same transaction', + 'and the expiry set to the current slot to provide up to date weight', + ], + type: { + option: 'u64', + }, + }, + { + name: 'weightAction', + docs: [ + "The governance action the voter's weight pertains to", + "It allows to provided voter's weight specific to the particular action the weight is evaluated for", + 'When the action is provided then the governance program asserts the executing action is the same as specified by the addin', + ], + type: { + option: { + defined: 'VoterWeightAction', + }, + }, + }, + { + name: 'weightActionTarget', + docs: [ + "The target the voter's weight action pertains to", + "It allows to provided voter's weight specific to the target the weight is evaluated for", + 'For example when addin supplies weight to vote on a particular proposal then it must specify the proposal as the action target', + 'When the target is provided then the governance program asserts the target is the same as specified by the addin', + ], + type: { + option: 'publicKey', + }, + }, + { + name: 'reserved', + docs: ['Reserved space for future versions'], + type: { + array: ['u8', 8], + }, + }, + ], + }, + }, + ], + types: [ + { + name: 'CollectionItemChangeType', + docs: ['Enum defining collection item change type'], + type: { + kind: 'enum', + variants: [ + { + name: 'Upsert', + }, + { + name: 'Remove', + }, + ], + }, + }, + { + name: 'VoterWeightAction', + docs: [ + 'VoterWeightAction enum as defined in spl-governance-addin-api', + "It's redefined here for Anchor to export it to IDL", + ], + type: { + kind: 'enum', + variants: [ + { + name: 'CastVote', + }, + { + name: 'CommentProposal', + }, + { + name: 'CreateGovernance', + }, + { + name: 'CreateProposal', + }, + { + name: 'SignOffProposal', + }, + ], + }, + }, + ], + errors: [ + { + code: 6000, + name: 'InvalidRealmAuthority', + msg: 'Invalid Realm Authority', + }, + { + code: 6001, + name: 'InvalidRealmForRegistrar', + msg: 'Invalid Realm for Registrar', + }, + { + code: 6002, + name: 'InvalidVoterWeightRecordRealm', + msg: 'Invalid VoterWeightRecord Realm', + }, + { + code: 6003, + name: 'InvalidVoterWeightRecordMint', + msg: 'Invalid VoterWeightRecord Mint', + }, + { + code: 6004, + name: 'TokenOwnerRecordFromOwnRealmNotAllowed', + msg: 'TokenOwnerRecord from own realm is not allowed', + }, + { + code: 6005, + name: 'GovernanceProgramNotConfigured', + msg: 'Governance program not configured', + }, + { + code: 6006, + name: 'GoverningTokenOwnerMustMatch', + msg: 'Governing TokenOwner must match', + }, + { + code: 6007, + name: 'DriftError', + msg: 'DriftError', + }, + ], +} diff --git a/GatewayPlugin/config.ts b/GatewayPlugin/config.ts new file mode 100644 index 0000000000..9c2b1df115 --- /dev/null +++ b/GatewayPlugin/config.ts @@ -0,0 +1,48 @@ +// A list of "passes" offered by Civic to verify or gate access to a DAO. +export const availablePasses: { + name: string + value: string + description: string + isSybilResistance: boolean +}[] = [ + // Default + { + name: 'Uniqueness', + value: 'uniqobk8oGh4XBLMqM68K8M2zNu3CdYX7q5go7whQiv', + description: + 'A biometric proof of personhood, preventing Sybil attacks while retaining privacy', + isSybilResistance: true, + }, + { + name: 'ID Verification', + value: 'bni1ewus6aMxTxBi5SAfzEmmXLf8KcVFRmTfproJuKw', + description: + 'A KYC process for your DAO, allowing users to prove their identity by presenting a government-issued ID', + isSybilResistance: false, + }, + { + name: 'Bot Resistance', + value: 'ignREusXmGrscGNUesoU9mxfds9AiYTezUKex2PsZV6', + description: 'A simple CAPTCHA to prevent bots from spamming your DAO', + isSybilResistance: false, + }, + { + name: 'Other', + value: '', + description: + 'Set up your own custom verification (contact Civic.com for options)', + isSybilResistance: false, + }, +] + +// Infer the types from the available passes, giving type safety on the `other` and `default` pass types +type ArrayElement< + ArrayType extends readonly unknown[] +> = ArrayType extends readonly (infer ElementType)[] ? ElementType : never +export type CivicPass = ArrayElement + +// Use this when populating a dropdown +export const defaultPass: CivicPass = availablePasses[0] +// Use this in cases where you are implicitly adding sybil resistance to a DAO (e.g. QV DAO creation), rather than +// offering a choice - this allows defaultPass to be something *other than* sybil resistance without breaking things. +export const defaultSybilResistancePass = availablePasses[0] diff --git a/GatewayPlugin/sdk/accounts.tsx b/GatewayPlugin/sdk/accounts.tsx deleted file mode 100644 index 9af8edad64..0000000000 --- a/GatewayPlugin/sdk/accounts.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import { PublicKey } from '@solana/web3.js' -import { - getTokenOwnerRecordAddress, - ProgramAccount, - Realm, -} from '@solana/spl-governance' -import { GatewayClient } from '@solana/governance-program-library/dist' -import { getRegistrarPDA, getVoterWeightRecord } from '@utils/plugin/accounts' -import { notify } from '@utils/notifications' - -export const getGatekeeperNetwork = async ( - client: GatewayClient, - realm: ProgramAccount -): Promise => { - // Get the registrar for the realm - const { registrar } = await getRegistrarPDA( - realm.pubkey, - realm.account.communityMint, - client.program.programId - ) - const registrarObject = await client.program.account.registrar.fetch( - registrar - ) - - // Find the gatekeeper network from the registrar - return registrarObject.gatekeeperNetwork -} - -export const getPredecessorProgramId = async ( - client: GatewayClient, - realm: ProgramAccount -): Promise => { - // Get the registrar for the realm - const { registrar } = await getRegistrarPDA( - realm.pubkey, - realm.account.communityMint, - client.program.programId - ) - const registrarObject = await client.program.account.registrar.fetch( - registrar - ) - - // Find the gatekeeper network from the registrar - return registrarObject.previousVoterWeightPluginProgramId -} - -export const getPreviousVotingWeightRecord = async ( - client: GatewayClient, - realm: ProgramAccount, - walletPk: PublicKey -): Promise => { - // TODO cache this to avoid lookup every time someone votes - const predecessorProgramId = await getPredecessorProgramId(client, realm) - - if (predecessorProgramId) { - // this gateway plugin registrar has a predecessor plugin - get its voting weight record - const { voterWeightPk } = await getVoterWeightRecord( - realm.pubkey, - realm.account.communityMint, - walletPk, - predecessorProgramId - ) - return voterWeightPk - } - - // this gateway plugin registrar has no predecessor plugin. - // The previous voting weight record is the token owner record - return getTokenOwnerRecordAddress( - realm.owner, - realm.pubkey, - realm.account.communityMint, - walletPk - ) -} - -export const getVoteInstruction = async ( - client: GatewayClient, - gatewayToken: PublicKey, - realm: ProgramAccount, - walletPk: PublicKey -) => { - // Throw if the user has no gateway token (TODO handle this later) - if (!gatewayToken) { - const error = new Error( - `Unable to execute transaction: No Civic Pass found` - ) - notify({ type: 'error', message: `${error}` }) - throw error - } - - // get the user's voter weight account address - const { voterWeightPk } = await getVoterWeightRecord( - realm.pubkey, - realm.account.communityMint, - walletPk, - client.program.programId - ) - - // Get the registrar for the realm - const { registrar } = await getRegistrarPDA( - realm.pubkey, - realm.account.communityMint, - client.program.programId - ) - - // the previous voting weight record in the chain of plugins, - // or the token owner record if this is the first plugin in the chain - const inputVoterWeight = await getPreviousVotingWeightRecord( - client, - realm, - walletPk - ) - - // call updateVotingWeightRecord on the plugin - return client.program.methods - .updateVoterWeightRecord() - .accounts({ - registrar, - voterWeightRecord: voterWeightPk, - inputVoterWeight, - gatewayToken, - }) - .instruction() -} diff --git a/GatewayPlugin/sdk/api.ts b/GatewayPlugin/sdk/api.ts index ecce0caab5..d95e6d92e6 100644 --- a/GatewayPlugin/sdk/api.ts +++ b/GatewayPlugin/sdk/api.ts @@ -1,16 +1,65 @@ -import { PublicKey } from '@solana/web3.js' -import { GatewayClient } from '@solana/governance-program-library' +import {PublicKey} from '@solana/web3.js' +import {GatewayClient} from '@solana/governance-program-library' +import {ProgramAccount, Realm, SYSTEM_PROGRAM_ID} from "@solana/spl-governance"; +import {getRegistrarPDA} from "@utils/plugin/accounts"; -export const tryGetGatewayRegistrar = async ( - registrarPk: PublicKey, - client: GatewayClient + +// Create an instruction to create a registrar account for a given realm +export const createCivicRegistrarIx = async ( + realm: ProgramAccount, + payer: PublicKey, + gatewayClient: GatewayClient, + gatekeeperNetwork: PublicKey, + predecessor?: PublicKey ) => { - try { - const existingRegistrar = await client.program.account.registrar.fetch( - registrarPk - ) - return existingRegistrar - } catch (e) { - return null - } + const {registrar} = getRegistrarPDA( + realm.pubkey, + realm.account.communityMint, + gatewayClient.program.programId + ) + + const remainingAccounts = predecessor + ? [{pubkey: predecessor, isSigner: false, isWritable: false}] + : [] + + return gatewayClient!.program.methods + .createRegistrar(!!predecessor) + .accounts({ + registrar, + realm: realm.pubkey, + governanceProgramId: realm.owner, + realmAuthority: realm.account.authority!, + governingTokenMint: realm.account.communityMint!, + gatekeeperNetwork, + payer, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .remainingAccounts(remainingAccounts) + .instruction() } +// Create an instruction to configure a registrar account for a given realm +export const configureCivicRegistrarIx = async ( + realm: ProgramAccount, + gatewayClient: GatewayClient, + gatekeeperNetwork: PublicKey, + predecessor?: PublicKey +) => { + const {registrar} = getRegistrarPDA( + realm.pubkey, + realm.account.communityMint, + gatewayClient.program.programId + ) + const remainingAccounts = predecessor + ? [{pubkey: predecessor, isSigner: false, isWritable: false}] + : [] + return gatewayClient.program.methods + .configureRegistrar(false) + .accounts({ + registrar, + realm: realm.pubkey, + realmAuthority: realm.account.authority!, + gatekeeperNetwork: gatekeeperNetwork, + }) + .remainingAccounts(remainingAccounts) + .instruction() +} \ No newline at end of file diff --git a/GatewayPlugin/store/gatewayPluginStore.ts b/GatewayPlugin/store/gatewayPluginStore.ts deleted file mode 100644 index af001e7b2e..0000000000 --- a/GatewayPlugin/store/gatewayPluginStore.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { BN } from '@project-serum/anchor' -import { MaxVoterWeightRecord, ProgramAccount } from '@solana/spl-governance' -import { VotingClient } from '@utils/uiTypes/VotePlugin' -import create, { State } from 'zustand' -import { PublicKey } from '@solana/web3.js' - -interface gatewayPluginStore extends State { - state: { - gatewayToken: PublicKey | null - gatekeeperNetwork: PublicKey | null - votingPower: BN - maxVoteRecord: ProgramAccount | null - isLoadingGatewayToken: boolean - } - setGatewayToken: (gatewayToken: PublicKey, votingClient: VotingClient) => void - setGatekeeperNetwork: (gatekeeperNetwork: PublicKey) => void - setVotingPower: (gatewayToken: PublicKey) => void - setMaxVoterWeight: ( - maxVoterRecord: ProgramAccount | null - ) => void - setIsLoadingGatewayToken: (val: boolean) => void -} - -const defaultState = { - gatewayToken: null, - gatekeeperNetwork: null, - votingPower: new BN(0), - maxVoteRecord: null, - isLoadingGatewayToken: false, -} - -const useGatewayPluginStore = create((set, _get) => ({ - state: { - ...defaultState, - }, - setIsLoadingGatewayToken: (val) => { - set((s) => { - s.state.isLoadingGatewayToken = val - }) - }, - setGatewayToken: (gatewayToken, votingClient) => { - votingClient._setCurrentVoterGatewayToken(gatewayToken) - set((s) => { - s.state.gatewayToken = gatewayToken - }) - _get().setVotingPower(gatewayToken) - }, - setGatekeeperNetwork: (gatekeeperNetwork) => { - set((s) => { - s.state.gatekeeperNetwork = gatekeeperNetwork - }) - }, - - setVotingPower: () => { - set((s) => { - s.state.votingPower = new BN(1) - }) - }, - setMaxVoterWeight: (maxVoterRecord) => { - set((s) => { - s.state.maxVoteRecord = maxVoterRecord - }) - }, -})) - -export default useGatewayPluginStore diff --git a/HeliumVotePlugin/components/ClaimUnreleasedPositions.tsx b/HeliumVotePlugin/components/ClaimUnreleasedPositions.tsx new file mode 100644 index 0000000000..db761c946d --- /dev/null +++ b/HeliumVotePlugin/components/ClaimUnreleasedPositions.tsx @@ -0,0 +1,184 @@ +import { useEffect, useState } from 'react' +import { TransactionInstruction } from '@solana/web3.js' +import { SecondaryButton } from '@components/Button' +import { chunks } from '@utils/helpers' +import { + registrarKey, + positionKey, + voterWeightRecordKey, +} from '@helium/voter-stake-registry-sdk' +import { + sendTransactionsV3, + SequenceType, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { ProposalState } from '@solana/spl-governance' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useAddressQuery_CommunityTokenOwner } from '@hooks/queries/addresses/tokenOwnerRecord' +import { useConnection } from '@solana/wallet-adapter-react' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmProposalsQuery } from '@hooks/queries/proposal' +import {useHeliumClient} from "../../VoterWeightPlugins/useHeliumClient"; + +const NFT_SOL_BALANCE = 0.0014616 + +const ClaimUnreleasedPositions = ({ + inAccountDetails, +}: { + inAccountDetails?: boolean +}) => { + const wallet = useWalletOnePointOh() + const [isLoading, setIsLoading] = useState(false) + const { connection } = useConnection() + const [ownVoteRecords, setOwnVoteRecords] = useState([]) + const [solToBeClaimed, setSolToBeClaimed] = useState(0) + const realm = useRealmQuery().data?.result + const { heliumClient } = useHeliumClient(); + const { data: proposalsArray } = useRealmProposalsQuery() + const { data: tokenOwnerRecord } = useAddressQuery_CommunityTokenOwner() + const isHeliumVsr = !!heliumClient; + + const releasePositions = async () => { + if (!wallet?.publicKey) throw new Error('no wallet') + if (!realm) throw new Error() + if (!tokenOwnerRecord) throw new Error() + if (!heliumClient) throw new Error("No Helium client") + + setIsLoading(true) + const instructions: TransactionInstruction[] = [] + const [registrar] = registrarKey( + realm.pubkey, + realm.account.communityMint, + heliumClient!.program.programId + ) + + const [voterWeightPk] = voterWeightRecordKey( + registrar, + wallet.publicKey, + heliumClient!.program.programId + ) + + const voteRecords = ownVoteRecords + for (const i of voteRecords) { + const proposal = proposalsArray?.find((x) => + x.pubkey.equals(i.account.proposal) + ) + const [posKey] = positionKey( + i.account.nftMint, + heliumClient.program.programId + ) + if ( + proposal === undefined || + proposal.account.state === ProposalState.Voting + ) { + // ignore this one as it's still in voting + continue + } + + const relinquishVoteIx = await heliumClient.program.methods + .relinquishVoteV0() + .accounts({ + registrar, + voterWeightRecord: voterWeightPk, + governance: proposal.account.governance, + proposal: i.account.proposal, + voterTokenOwnerRecord: tokenOwnerRecord, + voterAuthority: wallet.publicKey, + voteRecord: i.publicKey, + beneficiary: wallet!.publicKey!, + }) + .remainingAccounts([ + { pubkey: i.publicKey, isSigner: false, isWritable: true }, + { pubkey: posKey, isSigner: false, isWritable: true }, + ]) + .instruction() + instructions.push(relinquishVoteIx) + } + try { + const insertChunks = chunks(instructions, 10).map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [], + batchIdx + ), + sequenceType: SequenceType.Parallel, + } + }) + await sendTransactionsV3({ + connection, + wallet: wallet!, + transactionInstructions: insertChunks, + }) + setIsLoading(false) + getVoteRecords() + } catch (e) { + setIsLoading(false) + console.log(e) + } + } + const getVoteRecords = async () => { + const currentClient = heliumClient; + if (!currentClient) return + const voteRecords = + (await currentClient.program.account['nftVoteRecord']?.all([ + { + memcmp: { + offset: 72, + bytes: wallet!.publicKey!.toBase58(), + }, + }, + ])) || [] + + const voteRecordsFiltered = voteRecords.filter((x) => { + const proposal = proposalsArray?.find((p) => + p.pubkey.equals(x.account.proposal) + ) + + return ( + proposal && + proposal.account.governingTokenMint.toBase58() === + realm?.account.communityMint.toBase58() && + proposal.account.state !== ProposalState.Voting + ) + }) + setOwnVoteRecords(voteRecordsFiltered) + setSolToBeClaimed(voteRecordsFiltered.length * NFT_SOL_BALANCE) + } + + useEffect(() => { + if (wallet?.publicKey && isHeliumVsr && heliumClient) { + getVoteRecords() + } + // 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 + }, [heliumClient, isHeliumVsr, wallet?.publicKey?.toBase58()]) + + if (isHeliumVsr) { + return ( + <> + {((!inAccountDetails && solToBeClaimed > 0) || + (inAccountDetails && solToBeClaimed != 0)) && ( +
+
+
+ Relinquish your old votes and claim {solToBeClaimed.toFixed(4)}{' '} + SOL from past proposal voting costs. +
+ releasePositions()} + className="w-1/2 max-w-[200px]" + > + Relinquish + +
+
+ )} + + ) + } else { + return null + } +} + +export default ClaimUnreleasedPositions diff --git a/HeliumVotePlugin/components/DelegateTokensModal.tsx b/HeliumVotePlugin/components/DelegateTokensModal.tsx new file mode 100644 index 0000000000..d686570922 --- /dev/null +++ b/HeliumVotePlugin/components/DelegateTokensModal.tsx @@ -0,0 +1,108 @@ +import React, { useState, useEffect } from 'react' +import { PublicKey } from '@solana/web3.js' +import Modal from '@components/Modal' +import Button, { SecondaryButton } from '@components/Button' +import { notify } from '@utils/notifications' +import { SubDaoWithMeta } from 'HeliumVotePlugin/sdk/types' +import { useSubDaos } from 'HeliumVotePlugin/hooks/useSubDaos' +import { LoadingDots } from '@components/Loading' + +interface DelegateTokensModalProps { + isOpen: boolean + onClose: () => void + onSubmit: (subDao: SubDaoWithMeta) => Promise +} + +export const DelegateTokensModal: React.FC = ({ + isOpen, + onClose, + onSubmit, +}) => { + const { loading, error, result: subDaos } = useSubDaos() + const [isSubmitting, setIsSubmitting] = useState(false) + const [selectedSubDaoPk, setSelectedSubDaoPk] = useState( + null + ) + + useEffect(() => { + if (error) { + notify({ + type: 'error', + message: error.message || 'Unable to fetch subdaos', + }) + } + }, [error]) + + const handleOnSubmit = async () => { + try { + setIsSubmitting(true) + await onSubmit( + subDaos!.find((subDao) => subDao.pubkey.equals(selectedSubDaoPk!))! + ) + onClose() + } catch (e) { + setIsSubmitting(false) + notify({ + type: 'error', + message: e.message || 'Unable to delegate tokens', + }) + } + } + + return ( + +

Delegate Tokens

+ {loading ? ( + <> +
+
Fetching Delegatable SubDaos
+
+
+ +
+ + ) : ( +
+
Select an existing subdao to delegate to
+
+
+ Once delegated, you can't perform any actions on this position + until you undelegate +
+
+ {subDaos?.map((subDao) => { + const isSelected = selectedSubDaoPk?.equals(subDao.pubkey) + + return ( +
setSelectedSubDaoPk(subDao.pubkey)} + key={subDao.pubkey.toBase58()} + > + + {subDao.dntMetadata.name} +
+ ) + })} +
+
+ )} +
+ + Cancel +
+
+ ) +} diff --git a/HeliumVotePlugin/components/LockCommunityTokensBtn.tsx b/HeliumVotePlugin/components/LockCommunityTokensBtn.tsx new file mode 100644 index 0000000000..6aba135379 --- /dev/null +++ b/HeliumVotePlugin/components/LockCommunityTokensBtn.tsx @@ -0,0 +1,38 @@ +import React from 'react' +import { BN } from '@coral-xyz/anchor' +import { LockClosedIcon } from '@heroicons/react/solid' +import useRealm from '@hooks/useRealm' +import { SecondaryButton } from '@components/Button' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' + +export const LockCommunityTokensBtn: React.FC<{ + className?: string + onClick: () => void +}> = ({ onClick, className = '' }) => { + const { realmTokenAccount } = useRealm() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + + const hasTokensInWallet = + realmTokenAccount && realmTokenAccount.account.amount.gt(new BN(0)) + + const tooltipContent = !connected + ? 'Connect your wallet to lock' + : !hasTokensInWallet + ? "You don't have any governance tokens in your wallet to lock." + : '' + + return ( + +
+ + Lock Tokens +
+
+ ) +} diff --git a/HeliumVotePlugin/components/LockTokensAccount.tsx b/HeliumVotePlugin/components/LockTokensAccount.tsx new file mode 100644 index 0000000000..ad667c8752 --- /dev/null +++ b/HeliumVotePlugin/components/LockTokensAccount.tsx @@ -0,0 +1,416 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react' +import { useAsync } from 'react-async-hook' +import { BN } from '@coral-xyz/anchor' +import { + LightningBoltIcon, + LinkIcon, + LockClosedIcon, +} from '@heroicons/react/solid' +import useRealm from '@hooks/useRealm' +import { + fmtMintAmount, + getMintDecimalAmount, + getMintDecimalAmountFromNatural, + getMintNaturalAmountFromDecimalAsBN, +} from '@tools/sdk/units' +import PreviousRouteBtn from '@components/PreviousRouteBtn' +import { TokenDeposit } from '@components/TokenBalance/TokenDeposit' +import { GoverningTokenRole } from '@solana/spl-governance' +import InlineNotification from '@components/InlineNotification' +import tokenPriceService from '@utils/services/tokenPrice' +import { getMintMetadata } from '@components/instructions/programs/splToken' +import { abbreviateAddress } from '@utils/formatting' +import Button from '@components/Button' +import { daysToSecs } from '@utils/dateTools' +import { LockCommunityTokensBtn } from './LockCommunityTokensBtn' +import { LockTokensModal, LockTokensModalFormValues } from './LockTokensModal' +import { useCreatePosition } from '../hooks/useCreatePosition' +import { calcLockupMultiplier } from '../utils/calcLockupMultiplier' +import { VotingPowerBox } from './VotingPowerBox' +import { PositionCard } from './PositionCard' +import useHeliumVsrStore from '../hooks/useHeliumVsrStore' +import { PublicKey } from '@solana/web3.js' +import { notify } from '@utils/notifications' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useSubDaos } from 'HeliumVotePlugin/hooks/useSubDaos' +import { useAddressQuery_CommunityTokenOwner } from '@hooks/queries/addresses/tokenOwnerRecord' +import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { useSelectedDelegatorStore } from 'stores/useSelectedDelegatorStore' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { fetchJupiterPrice } from '@hooks/queries/jupiterPrice' +import {useHeliumClient} from "../../VoterWeightPlugins/useHeliumClient"; +import {Registrar} from "../sdk/types"; +import {useVotingClients} from "@hooks/useVotingClients"; + +export const LockTokensAccount: React.FC<{ + // tokenOwnerRecordPk: string | string[] | undefined // @asktree: this was unused + children: React.ReactNode +}> = (props) => { + const { error, createPosition } = useCreatePosition() + const [isLockModalOpen, setIsLockModalOpen] = useState(false) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const { data: tokenOwnerRecordPk } = useAddressQuery_CommunityTokenOwner() + + const connected = !!wallet?.connected + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const realm = useRealmQuery().data?.result + const config = useRealmConfigQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const { realmTokenAccount, realmInfo } = useRealm() + + const selectedCommunityDelegator = useSelectedDelegatorStore( + (s) => s.communityDelegator + ) + // if we have a community token delegator selected (this is rare), use that. otherwise use user wallet. + const tokenOwnerRecordWalletPk = + selectedCommunityDelegator !== undefined + ? selectedCommunityDelegator + : // I wanted to eliminate `null` as a possible type + wallet?.publicKey ?? undefined + + const { heliumClient: vsrClient } = useHeliumClient(); + const votingClients = useVotingClients(); + + const vsrRegistrar = useAsync( + async () => { + if (realm && vsrClient) { + return vsrClient.getRegistrarAccount(realm?.pubkey, realm?.account.communityMint) as Promise + } + }, + [realm, vsrClient] + ) + + const { + loading: loadingSubDaos, + error: subDaosError, + result: subDaos, + } = useSubDaos() + + const [ + loading, + positions, + votingPower, + amountLocked, + getPositions, + ] = useHeliumVsrStore((s) => [ + s.state.isLoading, + s.state.positions, + s.state.votingPower, + s.state.amountLocked, + s.getPositions, + ]) + + const sortedPositions = useMemo( + () => + positions.sort((a, b) => { + if (a.hasGenesisMultiplier || b.hasGenesisMultiplier) { + if (b.hasGenesisMultiplier) { + return a.amountDepositedNative.gt(b.amountDepositedNative) ? 0 : -1 + } + return -1 + } + + return a.amountDepositedNative.gt(b.amountDepositedNative) ? -1 : 0 + }), + [positions] + ) + + useEffect(() => { + if (subDaosError) { + notify({ + type: 'error', + message: subDaosError.message || 'Unable to fetch subdaos', + }) + } + }, [subDaosError]) + + useAsync(async () => { + try { + if ( + config?.account.communityTokenConfig.voterWeightAddin && + realm?.pubkey && + wallet?.publicKey && + vsrClient + ) { + await getPositions({ + votingClient: votingClients('community'), // community mint is hardcoded for getPositions + realmPk: realm.pubkey, + communityMintPk: realm.account.communityMint, + walletPk: tokenOwnerRecordWalletPk + ? new PublicKey(tokenOwnerRecordWalletPk) + : wallet.publicKey, + client: vsrClient, + connection: connection.current, + }) + } + } catch (e) { + notify({ + type: 'error', + message: 'Unable to fetch positions', + }) + } + }, [tokenOwnerRecordWalletPk, vsrClient]) + + const hasTokensInWallet = + realmTokenAccount && realmTokenAccount.account.amount.gt(new BN(0)) + + const availableTokensDisplay = + hasTokensInWallet && mint + ? fmtMintAmount(mint, realmTokenAccount?.account.amount as BN) + : '0' + + const amountLockedDisplay = + amountLocked && mint ? fmtMintAmount(mint, amountLocked) : '0' + + const maxLockupAmount = + hasTokensInWallet && mint + ? getMintDecimalAmount( + mint, + realmTokenAccount?.account.amount as BN + ).toNumber() + : 0 + + const { result: tokenPrice } = useAsync( + async () => + realm + ? await fetchJupiterPrice(realm.account.communityMint).then((x) => + x.found ? x.result.price : 0 + ) + : undefined, + [realm] + ) + + const availableTokensPrice = + hasTokensInWallet && mint && realm?.account.communityMint + ? getMintDecimalAmountFromNatural( + mint, + realmTokenAccount?.account.amount + ).toNumber() * (tokenPrice ?? 0) + : 0 + + const lockedTokensPrice = + amountLocked.gte(new BN(0)) && mint && realm?.account.communityMint + ? getMintDecimalAmountFromNatural(mint, amountLocked).toNumber() * + (tokenPrice ?? 0) + : 0 + + const tokenName = realm?.account.communityMint + ? getMintMetadata(realm?.account.communityMint)?.name || + tokenPriceService.getTokenInfo(realm?.account.communityMint.toBase58()) + ?.name || + abbreviateAddress(realm?.account.communityMint) + : '' + + const handleCalcLockupMultiplier = useCallback( + (lockupPeriodInDays: number) => + calcLockupMultiplier({ + lockupSecs: daysToSecs(lockupPeriodInDays), + registrar: vsrRegistrar.result ?? null, + realm, + }), + [realm, vsrRegistrar.result] + ) + + const handleLockTokens = async (values: LockTokensModalFormValues) => { + const { amount, lockupPeriodInDays, lockupKind } = values + const amountToLock = getMintNaturalAmountFromDecimalAsBN( + amount, + mint!.decimals + ) + await createPosition({ + amount: amountToLock, + lockupPeriodsInDays: lockupPeriodInDays, + lockupKind: lockupKind.value, + tokenOwnerRecordPk: tokenOwnerRecordPk ?? null, //@asktree: using `null` in 2023 huh.. discusting... + }) + + if (!error) { + await getPositions({ + votingClient: votingClients('community'), // community mint is hardcoded for getPositions + realmPk: realm!.pubkey, + communityMintPk: realm!.account.communityMint, + walletPk: wallet!.publicKey!, + client: vsrClient!, + connection: connection.current, + }) + } + } + + const mainBoxesClasses = 'bg-bkg-1 col-span-1 p-4 rounded-md' + const isLoading = loading || loadingSubDaos + const isSameWallet = + (connected && !ownTokenRecord) || + (connected && + !!ownTokenRecord && + wallet!.publicKey!.equals(ownTokenRecord!.account.governingTokenOwner)) + + return ( +
+
+
+ +
+
+ {realmInfo?.ogImage && ( + + )} +

+ + {realmInfo?.displayName} + + My governance power{' '} +

+ + {isSameWallet && ( +
+ setIsLockModalOpen(true)} + /> +
+ )} +
+ {!isSameWallet && connected && ( +
+ +
+ )} + {connected ? ( +
+
+ {isLoading ? ( + <> +
+
+
+ + ) : ( + <> +
+ {mint && ( + + )} +
+ {isSameWallet && ( + <> +
+

{`${tokenName} Available`}

+ + {availableTokensDisplay} + {availableTokensPrice ? ( + + $ + {Intl.NumberFormat('en', { + notation: 'compact', + }).format(availableTokensPrice)} + + ) : null} + +
+
+

Locked

+ + {amountLockedDisplay} + + $ + {Intl.NumberFormat('en', { + notation: 'compact', + }).format(lockedTokensPrice)} + + +
+ + )} + + )} +
+

Locked Positions

+
+ {!loading && + sortedPositions.map((pos, idx) => ( + + ))} + {isSameWallet && ( +
+ +

+ Increase your voting power by locking your tokens. +

+ +
+ )} +
+
+ ) : ( +
+ + Connect your wallet +
+ )} + {isLockModalOpen && ( + setIsLockModalOpen(false)} + onSubmit={handleLockTokens} + /> + )} +
+ +
+
+ {connected && isSameWallet && props.children} +
+ ) +} diff --git a/HeliumVotePlugin/components/LockTokensModal.tsx b/HeliumVotePlugin/components/LockTokensModal.tsx new file mode 100644 index 0000000000..7f1d780c50 --- /dev/null +++ b/HeliumVotePlugin/components/LockTokensModal.tsx @@ -0,0 +1,377 @@ +import React, { useEffect, useState } from 'react' +import Modal from '@components/Modal' +import { useForm } from 'react-hook-form' +import Button, { LinkButton, SecondaryButton } from '@components/Button' +import ButtonGroup from '@components/ButtonGroup' +import Input from '@components/inputs/Input' +import { getMintMinAmountAsDecimal } from '@tools/sdk/units' +import { precision } from '@utils/formatting' +import { getFormattedStringFromDays, yearsToDays } from '@utils/dateTools' +import Tooltip from '@components/Tooltip' +import { QuestionMarkCircleIcon } from '@heroicons/react/solid' +import { notify } from '@utils/notifications' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' + +const defaultLockupPeriods = [ + { + value: 183, + display: '6m', + }, + { + value: yearsToDays(1), + display: '1y', + }, + { + value: yearsToDays(2), + display: '2y', + }, + { + value: yearsToDays(3), + display: '3y', + }, + { + value: yearsToDays(4), + display: '4y', + }, +] + +export enum LockupKind { + none = 'none', + cliff = 'cliff', + constant = 'constant', +} + +const lockupInfosByType = { + [LockupKind.cliff]: [ + 'Tokens are locked for a fixed duration and are released in full at the end of it.', + 'Vote weight declines linearly until release.', + 'Example: You lock 10.000 tokens for two years. They are then unavailable for the next two years. After this time, you can withdraw them again.', + ], + [LockupKind.constant]: [ + 'Tokens are locked indefinitely. At any time you can start the unlock process which lasts for the initially chosen lockup duration.', + 'Vote weight stays constant until you start the unlock process, then it declines linearly until release.', + 'Example: You lock 10.000 tokens with a lockup duration of one year. After two years you decide to start the unlocking process. Another year after that, you can withdraw the tokens.', + ], +} + +export interface LockTokensModalFormValues { + lockupKind: { value: LockupKind; display: string } + amount: number + lockupPeriod: { value: number; display: string } + lockupPeriodInDays: number +} + +export const LockTokensModal: React.FC<{ + isOpen: boolean + mode?: 'lock' | 'extend' | 'split' + minLockupTimeInDays?: number + maxLockupTimeInDays?: number + maxLockupAmount: number + calcMultiplierFn: (lockupPeriodInDays: number) => number + onClose: () => void + onSubmit: (values: LockTokensModalFormValues) => Promise +}> = ({ + isOpen = false, + mode = 'lock', + minLockupTimeInDays = 0, + maxLockupTimeInDays = Infinity, + maxLockupAmount, + calcMultiplierFn, + onClose, + onSubmit, +}) => { + const mint = useRealmCommunityMintInfoQuery().data?.result + + const [isSubmitting, setIsSubmitting] = useState(false) + const [showCustomDuration, setShowCustomDuration] = useState(false) + const [showLockupKindInfo, setShowLockupKindInfo] = useState(false) + const mintMinAmount = mint ? getMintMinAmountAsDecimal(mint) : 1 + const currentPrecision = precision(mintMinAmount) + const hasMinLockup = minLockupTimeInDays && minLockupTimeInDays > 0 + const hasMaxLockup = maxLockupTimeInDays && maxLockupTimeInDays !== Infinity + const lockupKindOptions = [ + { value: LockupKind.cliff, display: 'Decaying' }, + { value: LockupKind.constant, display: 'Constant' }, + ] + + const lockupPeriodOptions = [ + ...(hasMinLockup + ? [ + { + value: minLockupTimeInDays, + display: 'min', + }, + ] + : []), + ...defaultLockupPeriods.filter( + (lp) => lp.value > minLockupTimeInDays && lp.value <= maxLockupTimeInDays + ), + ] + + const { setValue, watch, handleSubmit } = useForm({ + defaultValues: { + lockupKind: lockupKindOptions[0], + lockupPeriod: lockupPeriodOptions[0], + lockupPeriodInDays: lockupPeriodOptions[0].value, + }, + }) + + const { lockupKind, amount, lockupPeriod, lockupPeriodInDays } = watch() + + useEffect(() => { + if (lockupPeriod) { + setValue('lockupPeriodInDays', lockupPeriod?.value) + } + }, [lockupPeriod, setValue]) + + const handleAmountChange = (e: React.ChangeEvent) => { + if (!Number(e.target.value)) { + return setValue('amount', Number(e.target.value)) + } + + setValue( + 'amount', + parseFloat( + Math.max( + Number(mintMinAmount), + Math.min(Number(maxLockupAmount), Number(e.target.value)) + ).toFixed(currentPrecision) + ) + ) + } + + const handleOnSubmit = handleSubmit( + async (values: LockTokensModalFormValues) => { + try { + setIsSubmitting(true) + await onSubmit(values) + onClose() + } catch (e) { + setIsSubmitting(false) + notify({ + type: 'error', + message: e.message || 'Unable to lock tokens', + }) + } + } + ) + + const labelClasses = 'mb-2 text-fgd-2 text-sm' + const lockupMultiplier = calcMultiplierFn(lockupPeriodInDays) + return ( + +
+

+ { + { + lock: 'Lock Tokens', + extend: 'Extend Lockup', + }[mode] + } +

+ {hasMinLockup && !showLockupKindInfo ? ( +
+
+ Select a new lockup period longer than the existing{' '} + + {getFormattedStringFromDays(minLockupTimeInDays)} + +
+ {mode === 'split' ? ( + <> +
+
+ Splitting a Landrush position after the Landrush period will + result in the split tokens losing the multiplier! +
+ + ) : null} +
+ ) : null} + {!showLockupKindInfo && ( + <> + {['lock', 'split'].includes(mode) && ( + <> +
+
Lockup Type
+ setShowLockupKindInfo(true)} + > + About Lockup Types + +
+
+ lt.display)} + onChange={(kind) => + setValue( + 'lockupKind', + lockupKindOptions.find((lt) => lt.display === kind)! + ) + } + /> +
+
+
+ Amount to Lock + setValue('amount', maxLockupAmount)} + > + Max: {maxLockupAmount} + +
+ +
+ + )} +
+
+
Duration
+ setShowCustomDuration((oldValue) => !oldValue)} + > + Custom Duration + +
+ p.display)} + onChange={(period) => { + setValue( + 'lockupPeriod', + lockupPeriodOptions.find((p) => p.display === period)! + ) + setShowCustomDuration(false) + }} + /> +
+ {showCustomDuration && ( + <> +
+ Number of days +
+ { + setValue('lockupPeriodInDays', Number(value)) + }} + onBlur={({ target: { value } }) => { + const val = Number(value) + setValue( + 'lockupPeriodInDays', + val > minLockupTimeInDays + ? val > maxLockupTimeInDays + ? maxLockupTimeInDays + : val + : minLockupTimeInDays + ) + }} + /> + + )} +
+ {lockupKind.value === LockupKind.constant + ? 'Vote Weight Multiplier' + : 'Initial Vote Weight Multiplier'} + {lockupKind.value !== LockupKind.constant ? ( + + + + ) : null} + + {lockupMultiplier}x + +
+
+
100 ? 100 : lockupMultiplier}%`, + }} + className="bg-primary-light h-2 rounded-lg" + >
+
+ + )} + {showLockupKindInfo ? ( + <> + {lockupKindOptions.map((type) => ( +
+

{type.display}

+

+ {lockupInfosByType[type.value].map((info) => ( +

+ {info} +

+ ))} +

+
+ ))} + + + ) : ( + <> +
+ + Cancel +
+ + )} +
+
+ ) +} diff --git a/HeliumVotePlugin/components/PositionCard.tsx b/HeliumVotePlugin/components/PositionCard.tsx new file mode 100644 index 0000000000..7a3c0adf21 --- /dev/null +++ b/HeliumVotePlugin/components/PositionCard.tsx @@ -0,0 +1,633 @@ +import React, { useCallback, useState, useMemo } from 'react' +import { fmtMintAmount, getMintDecimalAmount } from '@tools/sdk/units' +import tokenPriceService from '@utils/services/tokenPrice' +import { abbreviateAddress } from '@utils/formatting' +import { useSolanaUnixNow } from '@hooks/useSolanaUnixNow' +import { BN } from '@coral-xyz/anchor' +import Button from '@components/Button' +import { HNT_MINT } from '@helium/spl-utils' +import { notify } from '@utils/notifications' +import { + daysToSecs, + secsToDays, + getMinDurationFmt, + getTimeLeftFromNowFmt, +} from '@utils/dateTools' +import {PositionWithMeta, Registrar, SubDaoWithMeta} from '../sdk/types' +import useHeliumVsrStore from '../hooks/useHeliumVsrStore' +import { + LockTokensModal, + LockTokensModalFormValues, +} from '../components/LockTokensModal' +import { TransferTokensModal } from './TransferTokensModal' +import { calcLockupMultiplier } from '../utils/calcLockupMultiplier' +import { useFlipPositionLockupKind } from '../hooks/useFlipPositionLockupKind' +import { useExtendPosition } from '../hooks/useExtendPosition' +import { useSplitPosition } from '../hooks/useSplitPosition' +import { useTransferPosition } from '../hooks/useTransferPosition' +import { useClosePosition } from '../hooks/useClosePosition' +import { DelegateTokensModal } from './DelegateTokensModal' +import { useDelegatePosition } from '../hooks/useDelegatePosition' +import { useUndelegatePosition } from '../hooks/useUndelegatePosition' +import { useClaimDelegatedPositionRewards } from '../hooks/useClaimDelegatedPositionRewards' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { PublicKey } from '@solana/web3.js' +import { PromptModal } from './PromptModal' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' +import queryClient from '@hooks/queries/queryClient' +import { tokenAccountQueryKeys } from '@hooks/queries/tokenAccount' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import {useHeliumClient} from "../../VoterWeightPlugins/useHeliumClient"; +import {useVotingClients} from "@hooks/useVotingClients"; +import {useAsync} from "react-async-hook"; + +interface PositionCardProps { + subDaos?: SubDaoWithMeta[] + position: PositionWithMeta + tokenOwnerRecordPk: PublicKey | null + isOwner: boolean +} + +export const PositionCard: React.FC = ({ + subDaos, + position, + tokenOwnerRecordPk, + isOwner, +}) => { + const { unixNow = 0 } = useSolanaUnixNow() + const [isTransferModalOpen, setIsTransferModalOpen] = useState(false) + const [isExtendModalOpen, setIsExtendModalOpen] = useState(false) + const [isSplitModalOpen, setIsSplitModalOpen] = useState(false) + const [isDelegateModalOpen, setIsDelegateModalOpen] = useState(false) + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const [isLoading, positions, getPositions] = useHeliumVsrStore((s) => [ + s.state.isLoading, + s.state.positions, + s.getPositions, + ]) + const { heliumClient: vsrClient } = useHeliumClient(); + const votingClients = useVotingClients(); + + const vsrRegistrar = useAsync( + async () => { + if (realm && vsrClient) { + return vsrClient.getRegistrarAccount(realm?.pubkey, realm?.account.communityMint) as Promise + } + }, + [realm, vsrClient] + ) + + const transferablePositions: PositionWithMeta[] = useMemo(() => { + if (!unixNow || !positions.length) { + return [] + } + + const lockup = position.lockup + const lockupKind = Object.keys(lockup.kind)[0] + const positionLockupPeriodInDays = secsToDays( + lockupKind === 'constant' + ? lockup.endTs.sub(lockup.startTs).toNumber() + : lockup.endTs.sub(new BN(unixNow || 0)).toNumber() + ) + + return positions.filter((pos) => { + const lockup = pos.lockup + const lockupKind = Object.keys(lockup.kind)[0] + const lockupPeriodInDays = secsToDays( + lockupKind === 'constant' + ? lockup.endTs.sub(lockup.startTs).toNumber() + : lockup.endTs.sub(new BN(unixNow)).toNumber() + ) + + return ( + (unixNow >= pos.genesisEnd.toNumber() || + unixNow <= + position.votingMint.genesisVotePowerMultiplierExpirationTs.toNumber() || + !pos.hasGenesisMultiplier) && + !pos.isDelegated && + !position.pubkey.equals(pos.pubkey) && + lockupPeriodInDays >= positionLockupPeriodInDays + ) + }) + }, [position, unixNow, positions]) + + const { + loading: isExtending, + error: extendingError, + extendPosition, + } = useExtendPosition() + + const { + loading: isSpliting, + error: splitingError, + splitPosition, + } = useSplitPosition() + + const { + loading: isFlipping, + error: flippingError, + flipPositionLockupKind, + } = useFlipPositionLockupKind() + + const { + loading: isTransfering, + error: transferingError, + transferPosition, + } = useTransferPosition() + + const { + loading: isClosing, + error: closingError, + closePosition, + } = useClosePosition() + + const { + loading: isDelegating, + error: delegatingError, + delegatePosition, + } = useDelegatePosition() + + const { + loading: isUndelegating, + error: undelegatingError, + undelegatePosition, + } = useUndelegatePosition() + + const { + loading: isClaimingRewards, + error: claimingRewardsError, + claimDelegatedPositionRewards, + } = useClaimDelegatedPositionRewards() + + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + + const { lockup, hasGenesisMultiplier, votingMint } = position + const lockupKind = Object.keys(lockup.kind)[0] as string + const isConstant = lockupKind === 'constant' + const lockupExpired = + !isConstant && lockup.endTs.sub(new BN(unixNow)).lt(new BN(0)) + + const lockedTokens = fmtMintAmount( + position.votingMint.mint.account, + position.amountDepositedNative + ) + + const isRealmCommunityMint = + realm?.account.communityMint && + realm.account.communityMint.equals(position.votingMint.mint.publicKey) + + const maxActionableAmount = mint + ? getMintDecimalAmount(mint, position.amountDepositedNative).toNumber() + : 0 + const canDelegate = + isRealmCommunityMint && realm.account.communityMint.equals(HNT_MINT) + + const tokenInfo = tokenPriceService.getTokenInfo( + position.votingMint.mint.publicKey.toBase58() + ) + + const handleCalcLockupMultiplier = useCallback( + (lockupPeriodInDays: number) => + calcLockupMultiplier({ + lockupSecs: daysToSecs(lockupPeriodInDays), + registrar: vsrRegistrar.result ?? null, + realm, + }), + [realm, vsrRegistrar.result] + ) + + const refetchState = async () => { + queryClient.invalidateQueries({ + queryKey: tokenAccountQueryKeys.all(connection.endpoint), + }) + await getPositions({ + votingClient: votingClients('community'), // community mint is hardcoded for getPositions + realmPk: realm!.pubkey, + communityMintPk: realm!.account.communityMint, + walletPk: wallet!.publicKey!, + client: vsrClient!, + connection: connection.current, + }) + } + + const handleFlipPositionLockupKind = async () => { + try { + await flipPositionLockupKind({ position, tokenOwnerRecordPk }) + + if (!flippingError) { + await refetchState() + } + } catch (e) { + notify({ + type: 'error', + message: + e.message || isConstant + ? 'Unable to unlock position' + : 'Unable to pause unlock', + }) + } + } + + const handleExtendTokens = async (values: LockTokensModalFormValues) => { + await extendPosition({ + position, + lockupPeriodsInDays: values.lockupPeriodInDays, + tokenOwnerRecordPk, + }) + + if (!extendingError) { + await refetchState() + } + } + + const handleSplitTokens = async (values: LockTokensModalFormValues) => { + await splitPosition({ + sourcePosition: position, + amount: values.amount, + lockupKind: values.lockupKind.value, + lockupPeriodsInDays: values.lockupPeriodInDays, + tokenOwnerRecordPk: tokenOwnerRecordPk, + }) + + if (!splitingError) { + await refetchState() + } + } + + const handleTransferTokens = async ( + targetPosition: PositionWithMeta, + amount: number + ) => { + await transferPosition({ + sourcePosition: position, + amount, + targetPosition, + }) + + if (!transferingError) { + await refetchState() + } + } + + const handleDelegateTokens = async (subDao: SubDaoWithMeta) => { + await delegatePosition({ + position, + subDao, + tokenOwnerRecordPk, + }) + + if (!delegatingError) { + await refetchState() + } + } + + const handleUndelegateTokens = async () => { + try { + await undelegatePosition({ position, tokenOwnerRecordPk }) + + if (!undelegatingError) { + await refetchState() + } + } catch (e) { + notify({ + type: 'error', + message: e.message || 'Unable to undelegate tokens', + }) + } + } + + const handleClaimRewards = async () => { + try { + await claimDelegatedPositionRewards({ position, tokenOwnerRecordPk }) + + if (!claimingRewardsError) { + await refetchState() + } + } catch (e) { + notify({ + type: 'error', + message: e.message || 'Unable to claim rewards', + }) + } + } + + const handleClose = async () => { + try { + await closePosition({ + position, + tokenOwnerRecordPk, + }) + + if (!closingError) { + await refetchState() + } + } catch (e) { + notify({ + type: 'error', + message: e.message || 'Unable to close position', + }) + } + } + + const CardLabel = ({ label, value }) => { + return ( +
+

{label}

+

{value}

+
+ ) + } + + const delegatedSubDaoMetadata = position.delegatedSubDao + ? subDaos?.find((sd) => sd.pubkey.equals(position.delegatedSubDao!)) + ?.dntMetadata + : null + + const isSubmitting = + isExtending || + isSpliting || + isClosing || + isTransfering || + isFlipping || + isDelegating || + isUndelegating || + isClaimingRewards + + const lockupKindDisplay = isConstant ? 'Constant' : 'Decaying' + const hasActiveVotes = position.numActiveVotes > 0 + return ( +
+ {hasGenesisMultiplier && ( +
+ Landrush +
+ )} + {isLoading ? ( + <> +
+
+
+ + ) : ( + <> +
+ {tokenInfo?.logoURI && ( + + )} +

+ {lockedTokens}{' '} + {!tokenInfo?.logoURI && + abbreviateAddress(position.votingMint.mint.publicKey)} + + {tokenInfo?.symbol} + +

+
+
+
+ + {isRealmCommunityMint && ( + + )} + + {hasGenesisMultiplier && ( + + )} +
+ {isOwner && ( +
+ {position.isDelegated ? ( +
+ {delegatedSubDaoMetadata ? ( + + + {delegatedSubDaoMetadata.name} + + ) : null} + + +
+ ) : ( + <> + {lockupExpired ? ( + + ) : ( +
+
+ + +
+ + {isConstant ? ( + + ) : ( + + )} + {canDelegate && ( + + )} +
+ )} + + )} +
+ )} +
+ + )} + {isExtendModalOpen && ( + setIsExtendModalOpen(false)} + onSubmit={handleExtendTokens} + /> + )} + {isSplitModalOpen && + (!hasActiveVotes ? ( + setIsSplitModalOpen(false)} + onSubmit={handleSplitTokens} + /> + ) : ( + setIsSplitModalOpen(false)} + /> + ))} + {isTransferModalOpen && + (!hasActiveVotes ? ( + setIsTransferModalOpen(false)} + onSubmit={handleTransferTokens} + /> + ) : ( + setIsTransferModalOpen(false)} + /> + ))} + {canDelegate && isDelegateModalOpen && ( + setIsDelegateModalOpen(false)} + onSubmit={handleDelegateTokens} + /> + )} +
+ ) +} diff --git a/HeliumVotePlugin/components/PromptModal.tsx b/HeliumVotePlugin/components/PromptModal.tsx new file mode 100644 index 0000000000..67a2f13417 --- /dev/null +++ b/HeliumVotePlugin/components/PromptModal.tsx @@ -0,0 +1,69 @@ +import React, { useState } from 'react' +import Modal from '@components/Modal' +import Button, { SecondaryButton } from '@components/Button' +import { notify } from '@utils/notifications' + +interface PromptModalProps { + isOpen: boolean + title?: string + message: string + type?: 'success' | 'info' | 'error' + onClose: () => void + closeBtnText?: string + onConfirm?: () => Promise + confirmBtnText?: string +} + +export const PromptModal: React.FC = ({ + isOpen, + message, + title = '', + type = 'success', + onClose, + closeBtnText = 'Close', + onConfirm, + confirmBtnText = 'Confirm', +}) => { + const [confirming, setConfirming] = useState(false) + const handleOnConfirm = async () => { + setConfirming(true) + + try { + await onConfirm!() + } catch (e) { + notify({ + type: 'error', + message: e.message || 'Unable to confirm', + }) + } + } + + const textClass = { + success: 'text-green', + info: 'text-primary', + error: 'text-red', + }[type] + + return ( + +
+
{title}
+
+
{message}
+
+
+ {onConfirm ? ( + + ) : null} + {closeBtnText} +
+
+ ) +} diff --git a/HeliumVotePlugin/components/TransferTokensModal.tsx b/HeliumVotePlugin/components/TransferTokensModal.tsx new file mode 100644 index 0000000000..4cfa299452 --- /dev/null +++ b/HeliumVotePlugin/components/TransferTokensModal.tsx @@ -0,0 +1,187 @@ +import React, { useState } from 'react' +import { PublicKey } from '@solana/web3.js' +import Modal from '@components/Modal' +import Button, { LinkButton, SecondaryButton } from '@components/Button' +import { getMinDurationFmt, getTimeLeftFromNowFmt } from '@utils/dateTools' +import { notify } from '@utils/notifications' +import { PositionWithMeta } from '../sdk/types' +import { getMintMinAmountAsDecimal } from '@tools/sdk/units' +import { precision } from '@utils/formatting' +import Input from '@components/inputs/Input' +import { useSolanaUnixNow } from '@hooks/useSolanaUnixNow' +import { BN } from '@coral-xyz/anchor' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' + +interface TransferTokensModalProps { + isOpen: boolean + positions: PositionWithMeta[] + maxTransferAmount: number + onClose: () => void + onSubmit: (positon: PositionWithMeta, amount: number) => Promise +} + +export const TransferTokensModal: React.FC = ({ + isOpen, + positions, + maxTransferAmount, + onClose, + onSubmit, +}) => { + const { unixNow = 0 } = useSolanaUnixNow() + const mint = useRealmCommunityMintInfoQuery().data?.result + const [isSubmitting, setIsSubmitting] = useState(false) + const [amount, setAmount] = useState(null) + const [selectedPosPk, setSelectedPosPk] = useState(null) + const mintMinAmount = mint ? getMintMinAmountAsDecimal(mint) : 1 + const currentPrecision = precision(mintMinAmount) + + const handleAmountChange = (e: React.ChangeEvent) => { + if (!Number(e.target.value)) { + return setAmount(Number(e.target.value)) + } + + setAmount( + parseFloat( + Math.max( + Number(mintMinAmount), + Math.min(Number(maxTransferAmount), Number(e.target.value)) + ).toFixed(currentPrecision) + ) + ) + } + + const handleOnSubmit = async () => { + if (amount && selectedPosPk) { + try { + setIsSubmitting(true) + await onSubmit( + positions.find((pos) => pos.pubkey.equals(selectedPosPk))!, + amount + ) + onClose() + } catch (e) { + setIsSubmitting(false) + notify({ + type: 'error', + message: e.message || 'Unable to transfer tokens', + }) + } + } + } + + const CardLabel = ({ label, value }) => { + return ( +
+

{label}

+

{value}

+
+ ) + } + + const labelClasses = 'mb-2 text-fgd-2 text-sm' + const hasTransferablePositions = positions.length > 0 + return ( + +

Transfer Tokens

+
+ {hasTransferablePositions ? ( + <> +
Select an existing positon to transfer to
+
+ + ) : null} +
+ You can only transfer to positions that have a greater than or equal + lockup time. +
+
+
+ {hasTransferablePositions + ? 'You cant transfer to Landrush positions after the Landrush period, and transfering out of one after the Landrush period, will result in losing the multiplier!' + : 'There are no positions that meet this criteria.'} +
+
+ {hasTransferablePositions ? ( + <> +
+
+ Amount to Transfer + setAmount(maxTransferAmount)} + > + Max: {maxTransferAmount} + +
+ +
+
+ {positions.map((pos) => { + const lockup = pos.lockup + const lockupKind = Object.keys(lockup.kind)[0] as string + const isConstant = lockupKind === 'constant' + const isSelected = selectedPosPk?.equals(pos.pubkey) + + return ( +
setSelectedPosPk(pos.pubkey)} + key={pos.pubkey.toBase58()} + > + + + +
+ ) + })} +
+ + ) : null} +
+ + Cancel +
+
+ ) +} diff --git a/HeliumVotePlugin/components/VotingPowerBox.tsx b/HeliumVotePlugin/components/VotingPowerBox.tsx new file mode 100644 index 0000000000..c4e4122eca --- /dev/null +++ b/HeliumVotePlugin/components/VotingPowerBox.tsx @@ -0,0 +1,60 @@ +import React from 'react' +import BigNumber from 'bignumber.js' +import { BN } from '@coral-xyz/anchor' +import { MintInfo } from '@solana/spl-token' +import { getMintDecimalAmount } from '@tools/sdk/units' +import { LightningBoltIcon } from '@heroicons/react/solid' +import Tooltip from '@components/Tooltip' + +interface VotingPowerBoxProps { + votingPower: BN + mint: MintInfo + votingPowerFromDeposits: BN + className?: string + style?: any +} + +export const VotingPowerBox: React.FC = ({ + votingPower, + mint, + votingPowerFromDeposits, + className = '', + style, +}) => { + const votingPowerBigNum = + votingPower && mint + ? getMintDecimalAmount(mint, votingPower) + : new BigNumber(0) + + const votingPowerFromDepositsBigNum = + votingPowerFromDeposits && mint + ? getMintDecimalAmount(mint, votingPowerFromDeposits) + : new BigNumber(0) + + return ( + <> + {' '} +
+
+

Votes

+ + {votingPowerBigNum.toFormat(2)}{' '} + {!votingPowerFromDeposits.isZero() && !votingPower.isZero() && ( + +
+ + {`${votingPowerBigNum + .div(votingPowerFromDepositsBigNum) + .toFixed(2)}x`} +
+
+ )} +
+
+
+ + ) +} diff --git a/HeliumVotePlugin/components/VotingPowerCard.tsx b/HeliumVotePlugin/components/VotingPowerCard.tsx new file mode 100644 index 0000000000..78fc7167e8 --- /dev/null +++ b/HeliumVotePlugin/components/VotingPowerCard.tsx @@ -0,0 +1,169 @@ +import React, { useEffect, useState } from 'react' +import { BN } from '@coral-xyz/anchor' +import { GoverningTokenRole } from '@solana/spl-governance' +import useRealm from '@hooks/useRealm' +import { fmtMintAmount } from '@tools/sdk/units' +import { getMintMetadata } from '@components/instructions/programs/splToken' +import InlineNotification from '@components/InlineNotification' +import { TokenDeposit } from '@components/TokenBalance/TokenDeposit' +import useHeliumVsrStore from 'HeliumVotePlugin/hooks/useHeliumVsrStore' +import { MintInfo } from '@solana/spl-token' +import { VotingPowerBox } from './VotingPowerBox' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' + +export const VotingPowerCard: React.FC<{ + inAccountDetails?: boolean +}> = ({ inAccountDetails }) => { + const loading = useHeliumVsrStore((s) => s.state.isLoading) + const [hasGovPower, setHasGovPower] = useState(false) + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + + const councilDepositVisible = !!councilMint + + const isLoading = !mint || !councilMint || loading + const isSameWallet = + (connected && !ownTokenRecord) || + (connected && + ownTokenRecord && + wallet!.publicKey!.equals(ownTokenRecord!.account.governingTokenOwner)) + + return ( + <> + {!isLoading ? ( + <> + {!hasGovPower && !inAccountDetails && connected && ( +
+ You do not have any governance power in this dao +
+ )} + {!connected && ( +
+ Connect your wallet to see governance power +
+ )} + {connected && ( + + )} + {councilDepositVisible && ( +
+ +
+ )} + + ) : ( + <> +
+
+ + )} + + ) +} + +const TokenDepositLock = ({ + mint, + setHasGovPower, + isSameWallet = false, +}: { + mint: MintInfo | undefined + setHasGovPower: (hasGovPower: boolean) => void + isSameWallet: boolean +}) => { + const realm = useRealmQuery().data?.result + const { realmTokenAccount } = useRealm() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const [amountLocked, votingPower] = useHeliumVsrStore((s) => [ + s.state.amountLocked, + s.state.votingPower, + ]) + + const tokenName = + getMintMetadata(realm?.account.communityMint)?.name ?? realm?.account.name + + const hasTokensInWallet = + realmTokenAccount && realmTokenAccount.account.amount.gt(new BN(0)) + + const availableTokens = + hasTokensInWallet && mint + ? fmtMintAmount(mint, realmTokenAccount?.account.amount as BN) + : '0' + + const lockTokensFmt = + amountLocked && mint ? fmtMintAmount(mint, amountLocked) : '0' + + useEffect(() => { + if ( + availableTokens != '0' || + amountLocked.gt(new BN(0)) || + hasTokensInWallet + ) { + setHasGovPower(true) + } else { + setHasGovPower(false) + } + }, [availableTokens, amountLocked, hasTokensInWallet, setHasGovPower]) + + const tokensToShow = + hasTokensInWallet && realmTokenAccount + ? fmtMintAmount(mint, realmTokenAccount.account.amount) + : hasTokensInWallet + ? availableTokens + : 0 + + if (!mint || mint.supply.isZero()) return null + return ( + <> + {isSameWallet && hasTokensInWallet && connected ? ( +
+ +
+ ) : null} + {votingPower.gt(new BN(0)) && ( +
+ +
+ )} + {amountLocked.gt(new BN(0)) ? ( +
+ {amountLocked.gt(new BN(0)) && ( +

+ {tokenName} Locked + + {lockTokensFmt} + +

+ )} +
+ ) : null} + + ) +} diff --git a/HeliumVotePlugin/hooks/useClaimDelegatedPositionRewards.ts b/HeliumVotePlugin/hooks/useClaimDelegatedPositionRewards.ts new file mode 100644 index 0000000000..6638442f52 --- /dev/null +++ b/HeliumVotePlugin/hooks/useClaimDelegatedPositionRewards.ts @@ -0,0 +1,128 @@ +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { Program, BN } from '@coral-xyz/anchor' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { useAsyncCallback } from 'react-async-hook' +import { PositionWithMeta } from '../sdk/types' +import { + PROGRAM_ID, + EPOCH_LENGTH, + init, + delegatedPositionKey, +} from '@helium/helium-sub-daos-sdk' +import { useSolanaUnixNow } from '@hooks/useSolanaUnixNow' +import { chunks } from '@utils/helpers' +import { + sendTransactionsV3, + SequenceType, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { notify } from '@utils/notifications' +import { withCreateTokenOwnerRecord } from '@solana/spl-governance' +import useRealm from '@hooks/useRealm' +import { useRealmQuery } from '@hooks/queries/realm' + +export const useClaimDelegatedPositionRewards = () => { + const { connection, wallet, anchorProvider: provider } = useWalletDeprecated() + const { unixNow } = useSolanaUnixNow() + const realm = useRealmQuery().data?.result + const { realmInfo } = useRealm() + const { error, loading, execute } = useAsyncCallback( + async ({ + position, + tokenOwnerRecordPk, + programId = PROGRAM_ID, + }: { + position: PositionWithMeta + tokenOwnerRecordPk: PublicKey | null + programId?: PublicKey + }) => { + const isInvalid = + !unixNow || + !connection || + !connection.current || + !provider || + !wallet || + !realm || + !realmInfo || + !position.isDelegated + + const idl = await Program.fetchIdl(programId, provider) + const hsdProgram = await init(provider as any, programId, idl) + + if (loading) return + + if (isInvalid || !hsdProgram) { + throw new Error('Unable to Undelegate Position, Invalid params') + } else { + const currentEpoch = new BN(unixNow).div(new BN(EPOCH_LENGTH)) + const instructions: TransactionInstruction[] = [] + const delegatedPosKey = delegatedPositionKey(position.pubkey)[0] + const delegatedPosAcc = await hsdProgram.account.delegatedPositionV0.fetch( + delegatedPosKey + ) + + if (!tokenOwnerRecordPk) { + await withCreateTokenOwnerRecord( + instructions, + realm.owner, + realmInfo.programVersion!, + realm.pubkey, + wallet!.publicKey!, + realm.account.communityMint, + wallet!.publicKey! + ) + } + + const { lastClaimedEpoch } = delegatedPosAcc + for ( + let epoch = lastClaimedEpoch.add(new BN(1)); + epoch.lt(currentEpoch); + epoch = epoch.add(new BN(1)) + ) { + instructions.push( + await hsdProgram.methods + .claimRewardsV0({ + epoch, + }) + .accounts({ + position: position.pubkey, + subDao: delegatedPosAcc.subDao, + }) + .instruction() + ) + } + + // This is an arbitrary threshold and we assume that up to 3 instructions can be inserted as a single Tx + const ixsChunks = chunks(instructions, 3) + const txsChunks = ixsChunks.map((txBatch, batchIdx) => ({ + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [], + batchIdx + ), + sequenceType: SequenceType.Sequential, + })) + + notify({ message: 'Claiming Rewards' }) + await sendTransactionsV3({ + transactionInstructions: txsChunks, + wallet, + connection: connection.current, + callbacks: { + afterAllTxConfirmed: () => + notify({ + message: 'Claiming Rewards successful', + type: 'success', + }), + }, + }) + } + } + ) + + return { + error, + loading, + claimDelegatedPositionRewards: execute, + } +} diff --git a/HeliumVotePlugin/hooks/useClosePosition.ts b/HeliumVotePlugin/hooks/useClosePosition.ts new file mode 100644 index 0000000000..cacbb2ed2b --- /dev/null +++ b/HeliumVotePlugin/hooks/useClosePosition.ts @@ -0,0 +1,119 @@ +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { BN } from '@coral-xyz/anchor' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { useAsyncCallback } from 'react-async-hook' +import { PositionWithMeta } from '../sdk/types' +import useRealm from '@hooks/useRealm' +import { useSolanaUnixNow } from '@hooks/useSolanaUnixNow' +import { SequenceType } from '@blockworks-foundation/mangolana/lib/globalTypes' +import { notify } from '@utils/notifications' +import { + sendTransactionsV3, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { withCreateTokenOwnerRecord } from '@solana/spl-governance' +import { useRealmQuery } from '@hooks/queries/realm' +import {useHeliumClient} from "../../VoterWeightPlugins/useHeliumClient"; + +export const useClosePosition = () => { + const { unixNow } = useSolanaUnixNow() + const { connection, wallet } = useWalletDeprecated() + const realm = useRealmQuery().data?.result + const { realmInfo } = useRealm() + const { heliumClient } = useHeliumClient(); + const { error, loading, execute } = useAsyncCallback( + async ({ + position, + tokenOwnerRecordPk, + }: { + position: PositionWithMeta + tokenOwnerRecordPk: PublicKey | null + }) => { + const lockup = position.lockup + const lockupKind = Object.keys(lockup.kind)[0] + const isInvalid = + !connection || + !connection.current || + !realm || + !realmInfo || + !heliumClient || + !wallet || + position.numActiveVotes > 0 || + // lockupExpired + !( + lockupKind !== 'constant' && + lockup.endTs.sub(new BN(unixNow!)).lt(new BN(0)) + ) + + if (loading) return + + if (isInvalid) { + throw new Error('Unable to Close Position, Invalid params') + } else { + const instructions: TransactionInstruction[] = [] + + if (!tokenOwnerRecordPk) { + await withCreateTokenOwnerRecord( + instructions, + realm.owner, + realmInfo.programVersion!, + realm.pubkey, + wallet!.publicKey!, + realm.account.communityMint, + wallet!.publicKey! + ) + } + + instructions.push( + await heliumClient.program.methods + .withdrawV0({ + amount: position.amountDepositedNative, + }) + .accounts({ + position: position.pubkey, + depositMint: realm.account.communityMint, + }) + .instruction() + ) + + instructions.push( + await heliumClient.program.methods + .closePositionV0() + .accounts({ + position: position.pubkey, + }) + .instruction() + ) + + notify({ message: 'Closing' }) + await sendTransactionsV3({ + transactionInstructions: [ + { + instructionsSet: txBatchesToInstructionSetWithSigners( + instructions, + [], + 0 + ), + sequenceType: SequenceType.Sequential, + }, + ], + wallet, + connection: connection.current, + callbacks: { + afterAllTxConfirmed: () => + notify({ + message: 'Closed successful', + type: 'success', + }), + }, + }) + } + } + ) + + return { + error, + loading, + closePosition: execute, + } +} diff --git a/HeliumVotePlugin/hooks/useCreatePosition.ts b/HeliumVotePlugin/hooks/useCreatePosition.ts new file mode 100644 index 0000000000..1783a64081 --- /dev/null +++ b/HeliumVotePlugin/hooks/useCreatePosition.ts @@ -0,0 +1,157 @@ +import { BN } from '@coral-xyz/anchor' +import { MintLayout, Token, TOKEN_PROGRAM_ID } from '@solana/spl-token' +import { withCreateTokenOwnerRecord } from '@solana/spl-governance' +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { + Keypair, + PublicKey, + SystemProgram, + TransactionInstruction, +} from '@solana/web3.js' +import { useAsyncCallback } from 'react-async-hook' +import { positionKey } from '@helium/voter-stake-registry-sdk' +import useRealm from '@hooks/useRealm' +import { LockupKind } from 'HeliumVotePlugin/components/LockTokensModal' +import { notify } from '@utils/notifications' +import { + sendTransactionsV3, + SequenceType, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { useRealmQuery } from '@hooks/queries/realm' +import {useHeliumClient} from "../../VoterWeightPlugins/useHeliumClient"; + +export const useCreatePosition = () => { + const { connection, wallet } = useWalletDeprecated() + const realm = useRealmQuery().data?.result + const { realmInfo } = useRealm() + const {heliumClient} = useHeliumClient(); + const registrarPk = realm && heliumClient ? + heliumClient.getRegistrarPDA(realm.pubkey, realm.account.communityMint).registrar : undefined; + + const { error, loading, execute } = useAsyncCallback( + async ({ + amount, + lockupKind = LockupKind.cliff, + lockupPeriodsInDays, + tokenOwnerRecordPk, + }: { + amount: BN + lockupKind: LockupKind + lockupPeriodsInDays: number + tokenOwnerRecordPk: PublicKey | null + }) => { + const isInvalid = + !connection || + !connection.current || + !registrarPk || + !realm || + !heliumClient || + !wallet || + !realmInfo || + !realmInfo.programVersion + + if (loading) return + + if (isInvalid) { + throw new Error('Unable to Create Position, Invalid params') + } else { + const mintKeypair = Keypair.generate() + const position = positionKey(mintKeypair.publicKey)[0] + const instructions: TransactionInstruction[] = [] + const mintRent = await connection.current.getMinimumBalanceForRentExemption( + MintLayout.span + ) + + instructions.push( + SystemProgram.createAccount({ + fromPubkey: wallet!.publicKey!, + newAccountPubkey: mintKeypair.publicKey, + lamports: mintRent, + space: MintLayout.span, + programId: TOKEN_PROGRAM_ID, + }) + ) + + instructions.push( + Token.createInitMintInstruction( + TOKEN_PROGRAM_ID, + mintKeypair.publicKey, + 0, + position, + position + ) + ) + + if (!tokenOwnerRecordPk) { + await withCreateTokenOwnerRecord( + instructions, + realm.owner, + realmInfo.programVersion!, + realm.pubkey, + wallet!.publicKey!, + realm.account.communityMint, + wallet!.publicKey! + ) + } + + instructions.push( + await heliumClient.program.methods + .initializePositionV0({ + kind: { [lockupKind]: {} }, + periods: lockupPeriodsInDays, + } as any) + .accounts({ + registrar: registrarPk, + mint: mintKeypair.publicKey, + depositMint: realm.account.communityMint, + recipient: wallet!.publicKey!, + }) + .instruction() + ) + + instructions.push( + await heliumClient.program.methods + .depositV0({ + amount, + }) + .accounts({ + registrar: registrarPk, + position, + mint: realm.account.communityMint, + }) + .instruction() + ) + + notify({ message: 'Locking' }) + await sendTransactionsV3({ + transactionInstructions: [ + { + instructionsSet: txBatchesToInstructionSetWithSigners( + instructions, + [[mintKeypair]], + 0 + ), + sequenceType: SequenceType.Sequential, + }, + ], + wallet, + connection: connection.current, + callbacks: { + afterAllTxConfirmed: () => + notify({ + message: 'Locking successful', + type: 'success', + }), + }, + }) + } + } + ) + + return { + error, + loading, + createPosition: execute, + } +} diff --git a/HeliumVotePlugin/hooks/useDelegatePosition.ts b/HeliumVotePlugin/hooks/useDelegatePosition.ts new file mode 100644 index 0000000000..8e9da169f2 --- /dev/null +++ b/HeliumVotePlugin/hooks/useDelegatePosition.ts @@ -0,0 +1,105 @@ +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { Program } from '@coral-xyz/anchor' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { useAsyncCallback } from 'react-async-hook' +import { PositionWithMeta, SubDaoWithMeta } from '../sdk/types' +import { PROGRAM_ID, init } from '@helium/helium-sub-daos-sdk' +import { + SequenceType, + sendTransactionsV3, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { notify } from '@utils/notifications' +import useRealm from '@hooks/useRealm' +import { withCreateTokenOwnerRecord } from '@solana/spl-governance' +import { useRealmQuery } from '@hooks/queries/realm' + +export const useDelegatePosition = () => { + const { connection, wallet, anchorProvider: provider } = useWalletDeprecated() + const realm = useRealmQuery().data?.result + const { realmInfo } = useRealm() + const { error, loading, execute } = useAsyncCallback( + async ({ + position, + subDao, + tokenOwnerRecordPk, + programId = PROGRAM_ID, + }: { + position: PositionWithMeta + subDao: SubDaoWithMeta + tokenOwnerRecordPk: PublicKey | null + programId?: PublicKey + }) => { + const isInvalid = + !connection || + !connection.current || + !provider || + !wallet || + !realm || + !realmInfo || + position.isDelegated + + const idl = await Program.fetchIdl(programId, provider) + const hsdProgram = await init(provider as any, programId, idl) + + if (loading) return + + if (isInvalid || !hsdProgram) { + throw new Error('Unable to Delegate Position, Invalid params') + } else { + const instructions: TransactionInstruction[] = [] + + if (!tokenOwnerRecordPk) { + await withCreateTokenOwnerRecord( + instructions, + realm.owner, + realmInfo.programVersion!, + realm.pubkey, + wallet!.publicKey!, + realm.account.communityMint, + wallet!.publicKey! + ) + } + + instructions.push( + await hsdProgram.methods + .delegateV0() + .accounts({ + position: position.pubkey, + subDao: subDao.pubkey, + }) + .instruction() + ) + + notify({ message: 'Delegating' }) + await sendTransactionsV3({ + transactionInstructions: [ + { + instructionsSet: txBatchesToInstructionSetWithSigners( + instructions, + [], + 0 + ), + sequenceType: SequenceType.Sequential, + }, + ], + wallet, + connection: connection.current, + callbacks: { + afterAllTxConfirmed: () => + notify({ + message: 'Delegation successful', + type: 'success', + }), + }, + }) + } + } + ) + + return { + error, + loading, + delegatePosition: execute, + } +} diff --git a/HeliumVotePlugin/hooks/useExtendPosition.ts b/HeliumVotePlugin/hooks/useExtendPosition.ts new file mode 100644 index 0000000000..22d1fe7e8a --- /dev/null +++ b/HeliumVotePlugin/hooks/useExtendPosition.ts @@ -0,0 +1,126 @@ +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { Program } from '@coral-xyz/anchor' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { useAsyncCallback } from 'react-async-hook' +import { PositionWithMeta } from '../sdk/types' +import { PROGRAM_ID, init, daoKey } from '@helium/helium-sub-daos-sdk' +import useRealm from '@hooks/useRealm' +import { notify } from '@utils/notifications' +import { + SequenceType, + sendTransactionsV3, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { withCreateTokenOwnerRecord } from '@solana/spl-governance' +import { useRealmQuery } from '@hooks/queries/realm' +import {useHeliumClient} from "../../VoterWeightPlugins/useHeliumClient"; + +export const useExtendPosition = () => { + const { connection, wallet, anchorProvider: provider } = useWalletDeprecated() + const realm = useRealmQuery().data?.result + const { realmInfo } = useRealm() + const {heliumClient} = useHeliumClient(); + const { error, loading, execute } = useAsyncCallback( + async ({ + position, + lockupPeriodsInDays, + tokenOwnerRecordPk, + programId = PROGRAM_ID, + }: { + position: PositionWithMeta + lockupPeriodsInDays: number + tokenOwnerRecordPk: PublicKey | null + programId?: PublicKey + }) => { + const isInvalid = + !connection || + !connection.current || + !provider || + !realm || + !wallet || + !heliumClient || + !realmInfo; + + const idl = await Program.fetchIdl(programId, provider) + const hsdProgram = await init(provider as any, programId, idl) + + if (loading) return + + if (isInvalid || !hsdProgram) { + throw new Error('Unable to Extend Position, Invalid params') + } else { + const instructions: TransactionInstruction[] = [] + const [dao] = daoKey(realm.account.communityMint) + const isDao = Boolean(await connection.current.getAccountInfo(dao)) + + if (!tokenOwnerRecordPk) { + await withCreateTokenOwnerRecord( + instructions, + realm.owner, + realmInfo.programVersion!, + realm.pubkey, + wallet!.publicKey!, + realm.account.communityMint, + wallet!.publicKey! + ) + } + + if (isDao) { + instructions.push( + await hsdProgram.methods + .resetLockupV0({ + kind: position.lockup.kind, + periods: lockupPeriodsInDays, + } as any) + .accounts({ + position: position.pubkey, + dao: dao, + }) + .instruction() + ) + } else { + instructions.push( + await heliumClient.program.methods + .resetLockupV0({ + kind: position.lockup.kind, + periods: lockupPeriodsInDays, + } as any) + .accounts({ + position: position.pubkey, + }) + .instruction() + ) + } + + notify({ message: 'Extending' }) + await sendTransactionsV3({ + transactionInstructions: [ + { + instructionsSet: txBatchesToInstructionSetWithSigners( + instructions, + [], + 0 + ), + sequenceType: SequenceType.Sequential, + }, + ], + wallet, + connection: connection.current, + callbacks: { + afterAllTxConfirmed: () => + notify({ + message: 'Extension successful', + type: 'success', + }), + }, + }) + } + } + ) + + return { + error, + loading, + extendPosition: execute, + } +} diff --git a/HeliumVotePlugin/hooks/useFlipPositionLockupKind.ts b/HeliumVotePlugin/hooks/useFlipPositionLockupKind.ts new file mode 100644 index 0000000000..7b597887cf --- /dev/null +++ b/HeliumVotePlugin/hooks/useFlipPositionLockupKind.ts @@ -0,0 +1,144 @@ +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { BN, Program } from '@coral-xyz/anchor' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { useAsyncCallback } from 'react-async-hook' +import { PositionWithMeta } from '../sdk/types' +import { PROGRAM_ID, init, daoKey } from '@helium/helium-sub-daos-sdk' +import { secsToDays } from '@utils/dateTools' +import useRealm from '@hooks/useRealm' +import { notify } from '@utils/notifications' +import { + SequenceType, + sendTransactionsV3, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { useSolanaUnixNow } from '@hooks/useSolanaUnixNow' +import { withCreateTokenOwnerRecord } from '@solana/spl-governance' +import { useRealmQuery } from '@hooks/queries/realm' +import {useHeliumClient} from "../../VoterWeightPlugins/useHeliumClient"; + +export const useFlipPositionLockupKind = () => { + const { unixNow } = useSolanaUnixNow() + const { connection, wallet, anchorProvider: provider } = useWalletDeprecated() + const realm = useRealmQuery().data?.result + const { realmInfo } = useRealm() + const {heliumClient} = useHeliumClient(); + const { error, loading, execute } = useAsyncCallback( + async ({ + position, + tokenOwnerRecordPk, + programId = PROGRAM_ID, + }: { + position: PositionWithMeta + tokenOwnerRecordPk: PublicKey | null + programId?: PublicKey + }) => { + const isInvalid = + !connection || + !connection.current || + !realm || + !wallet || + !heliumClient || + !unixNow || + !realmInfo || + position.numActiveVotes > 0 + + const lockupKind = Object.keys(position.lockup.kind)[0] as string + const isConstant = lockupKind === 'constant' + const idl = await Program.fetchIdl(programId, provider) + const hsdProgram = await init(provider as any, programId, idl) + + if (loading) return + + if (isInvalid) { + if (isConstant) { + throw new Error('Unable to Unlock Position, Invalid params') + } else { + throw new Error('Unable to Pause Position, Invalid params') + } + } else { + const instructions: TransactionInstruction[] = [] + const [dao] = daoKey(realm.account.communityMint) + const kind = isConstant ? { cliff: {} } : { constant: {} } + const isDao = Boolean(await connection.current.getAccountInfo(dao)) + const positionLockupPeriodInDays = Math.ceil( + secsToDays( + isConstant + ? position.lockup.endTs.sub(position.lockup.startTs).toNumber() + : position.lockup.endTs.sub(new BN(unixNow)).toNumber() + ) + ) + + if (!tokenOwnerRecordPk) { + await withCreateTokenOwnerRecord( + instructions, + realm.owner, + realmInfo.programVersion!, + realm.pubkey, + wallet!.publicKey!, + realm.account.communityMint, + wallet!.publicKey! + ) + } + + if (isDao) { + instructions.push( + await hsdProgram.methods + .resetLockupV0({ + kind, + periods: positionLockupPeriodInDays, + } as any) + .accounts({ + position: position.pubkey, + dao, + }) + .instruction() + ) + } else { + instructions.push( + await heliumClient.program.methods + .resetLockupV0({ + kind, + periods: positionLockupPeriodInDays, + } as any) + .accounts({ + position: position.pubkey, + }) + .instruction() + ) + } + + notify({ message: isConstant ? `Unlocking` : `Pausing` }) + await sendTransactionsV3({ + transactionInstructions: [ + { + instructionsSet: txBatchesToInstructionSetWithSigners( + instructions, + [], + 0 + ), + sequenceType: SequenceType.Sequential, + }, + ], + wallet, + connection: connection.current, + callbacks: { + afterAllTxConfirmed: () => + notify({ + message: isConstant + ? `Unlocking successful` + : `Pausing successful`, + type: 'success', + }), + }, + }) + } + } + ) + + return { + error, + loading, + flipPositionLockupKind: execute, + } +} diff --git a/HeliumVotePlugin/hooks/useHeliumVsrStore.ts b/HeliumVotePlugin/hooks/useHeliumVsrStore.ts new file mode 100644 index 0000000000..9fa88de99c --- /dev/null +++ b/HeliumVotePlugin/hooks/useHeliumVsrStore.ts @@ -0,0 +1,86 @@ +import create, { State } from 'zustand' +import { BN } from '@coral-xyz/anchor' +import { ProgramAccount } from '@solana/spl-governance' +import { PositionWithMeta } from 'HeliumVotePlugin/sdk/types' +import { + GetPositionsArgs as GetPosArgs, + getPositions, +} from '../utils/getPositions' +import { VotingClient } from '@utils/uiTypes/VotePlugin' +import { MaxVoterWeightRecord } from '@solana/spl-governance' + +interface HeliumVsrStoreState { + positions: PositionWithMeta[] + amountLocked: BN + votingPower: BN + maxVoteRecord: ProgramAccount | null + isLoading: boolean +} + +interface GetPositionsArgs extends GetPosArgs { + votingClient: VotingClient +} + +interface PropagatePositionsArgs { + votingClient: VotingClient +} + +interface HeliumVsrStore extends State { + state: HeliumVsrStoreState + resetState: () => void + setMaxVoterWeight: ( + maxVoterRecord: ProgramAccount | null + ) => void + getPositions: (args: GetPositionsArgs) => Promise + propagatePositions: (args: PropagatePositionsArgs) => void +} + +const defaultState: HeliumVsrStoreState = { + positions: [], + amountLocked: new BN(0), + votingPower: new BN(0), + maxVoteRecord: null, + isLoading: false, +} + +const useHeliumVsrStore = create((set, _get) => ({ + state: { + ...defaultState, + }, + resetState: () => { + set((s) => { + s.state = { ...defaultState } + }) + }, + setMaxVoterWeight: (maxVoterRecord) => { + set((s) => { + s.state.maxVoteRecord = maxVoterRecord + }) + }, + getPositions: async ({ votingClient, ...args }) => { + set((s) => { + s.state.isLoading = true + }) + + try { + const { positions, amountLocked, votingPower } = await getPositions(args) + votingClient._setCurrentHeliumVsrPositions(positions) + set((s) => { + s.state.positions = positions + s.state.amountLocked = amountLocked + s.state.votingPower = votingPower + }) + } catch (e) { + throw new Error(e) + } finally { + set((s) => { + s.state.isLoading = false + }) + } + }, + propagatePositions: ({ votingClient }) => { + votingClient._setCurrentHeliumVsrPositions(_get().state.positions) + }, +})) + +export default useHeliumVsrStore diff --git a/HeliumVotePlugin/hooks/useSplitPosition.ts b/HeliumVotePlugin/hooks/useSplitPosition.ts new file mode 100644 index 0000000000..b478eabf3f --- /dev/null +++ b/HeliumVotePlugin/hooks/useSplitPosition.ts @@ -0,0 +1,208 @@ +import { Program } from '@coral-xyz/anchor' +import { MintLayout, Token, TOKEN_PROGRAM_ID } from '@solana/spl-token' +import { withCreateTokenOwnerRecord } from '@solana/spl-governance' +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { + Keypair, + PublicKey, + SystemProgram, + TransactionInstruction, +} from '@solana/web3.js' +import { useAsyncCallback } from 'react-async-hook' +import { PositionWithMeta } from '../sdk/types' +import { PROGRAM_ID, init, daoKey } from '@helium/helium-sub-daos-sdk' +import useRealm from '@hooks/useRealm' +import { LockupKind } from 'HeliumVotePlugin/components/LockTokensModal' +import { getMintNaturalAmountFromDecimalAsBN } from '@tools/sdk/units' +import { positionKey } from '@helium/voter-stake-registry-sdk' +import { notify } from '@utils/notifications' +import { + sendTransactionsV3, + SequenceType, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { chunks } from '@utils/helpers' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' +import {useHeliumClient} from "../../VoterWeightPlugins/useHeliumClient"; + +export const useSplitPosition = () => { + const { connection, wallet, anchorProvider: provider } = useWalletDeprecated() + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const { realmInfo } = useRealm() + const {heliumClient} = useHeliumClient(); + const registrarPk = realm && heliumClient ? + heliumClient.getRegistrarPDA(realm.pubkey, realm.account.communityMint).registrar : undefined; + const { error, loading, execute } = useAsyncCallback( + async ({ + sourcePosition, + amount, + lockupKind = LockupKind.cliff, + lockupPeriodsInDays, + tokenOwnerRecordPk, + programId = PROGRAM_ID, + }: { + sourcePosition: PositionWithMeta + amount: number + lockupKind: LockupKind + lockupPeriodsInDays: number + tokenOwnerRecordPk: PublicKey | null + programId?: PublicKey + }) => { + const isInvalid = + !connection || + !connection.current || + !provider || + !realm || + !registrarPk || + !realm || + !heliumClient || + !wallet || + !realmInfo || + !realmInfo.programVersion || + !mint || + !wallet + + const idl = await Program.fetchIdl(programId, provider) + const hsdProgram = await init(provider as any, programId, idl) + + if (loading) return + + if (isInvalid || !hsdProgram) { + throw new Error('Unable to Split Position, Invalid params') + } else { + const mintKeypair = Keypair.generate() + const [dao] = daoKey(realm.account.communityMint) + const [targetPosition] = positionKey(mintKeypair.publicKey) + const isDao = Boolean(await connection.current.getAccountInfo(dao)) + const instructions: TransactionInstruction[] = [] + const mintRent = await connection.current.getMinimumBalanceForRentExemption( + MintLayout.span + ) + const amountToTransfer = getMintNaturalAmountFromDecimalAsBN( + amount, + mint!.decimals + ) + + instructions.push( + SystemProgram.createAccount({ + fromPubkey: wallet!.publicKey!, + newAccountPubkey: mintKeypair.publicKey, + lamports: mintRent, + space: MintLayout.span, + programId: TOKEN_PROGRAM_ID, + }) + ) + + instructions.push( + Token.createInitMintInstruction( + TOKEN_PROGRAM_ID, + mintKeypair.publicKey, + 0, + targetPosition, + targetPosition + ) + ) + + if (!tokenOwnerRecordPk) { + await withCreateTokenOwnerRecord( + instructions, + realm.owner, + realmInfo.programVersion!, + realm.pubkey, + wallet!.publicKey!, + realm.account.communityMint, + wallet!.publicKey! + ) + } + + instructions.push( + await heliumClient.program.methods + .initializePositionV0({ + kind: { [lockupKind]: {} }, + periods: lockupPeriodsInDays, + } as any) + .accounts({ + registrar: registrarPk, + mint: mintKeypair.publicKey, + depositMint: realm.account.communityMint, + recipient: wallet!.publicKey!, + }) + .instruction() + ) + + if (isDao) { + instructions.push( + await hsdProgram.methods + .transferV0({ + amount: amountToTransfer, + }) + .accounts({ + sourcePosition: sourcePosition.pubkey, + targetPosition: targetPosition, + depositMint: realm.account.communityMint, + dao: dao, + }) + .instruction() + ) + } else { + instructions.push( + await heliumClient.program.methods + .transferV0({ + amount: amountToTransfer, + }) + .accounts({ + sourcePosition: sourcePosition.pubkey, + targetPosition: targetPosition, + depositMint: realm.account.communityMint, + }) + .instruction() + ) + } + + if (amountToTransfer.eq(sourcePosition.amountDepositedNative)) { + instructions.push( + await heliumClient.program.methods + .closePositionV0() + .accounts({ + position: sourcePosition.pubkey, + }) + .instruction() + ) + } + + // This is an arbitrary threshold and we assume that up to 2 instructions can be inserted as a single Tx + const ixsChunks = chunks(instructions, 2) + const txsChunks = ixsChunks.map((txBatch, batchIdx) => ({ + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [[mintKeypair], [], []], + batchIdx + ), + sequenceType: SequenceType.Sequential, + })) + + notify({ message: 'Splitting Position' }) + await sendTransactionsV3({ + transactionInstructions: txsChunks, + wallet, + connection: connection.current, + callbacks: { + afterAllTxConfirmed: () => + notify({ + message: 'Spliting successful', + type: 'success', + }), + }, + }) + } + } + ) + + return { + error, + loading, + splitPosition: execute, + } +} diff --git a/HeliumVotePlugin/hooks/useSubDaos.ts b/HeliumVotePlugin/hooks/useSubDaos.ts new file mode 100644 index 0000000000..da2711a557 --- /dev/null +++ b/HeliumVotePlugin/hooks/useSubDaos.ts @@ -0,0 +1,16 @@ +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { web3 } from '@coral-xyz/anchor' +import { useAsync, UseAsyncReturn } from 'react-async-hook' +import { SubDaoWithMeta } from '../sdk/types' +import { PROGRAM_ID } from '@helium/helium-sub-daos-sdk' +import { getSubDaos } from '../utils/getSubDaos' + +export const useSubDaos = ( + programId: web3.PublicKey = PROGRAM_ID +): UseAsyncReturn => { + const { + connection: { current }, + anchorProvider: provider, + } = useWalletDeprecated() + return useAsync(getSubDaos, [current, provider, programId]) +} diff --git a/HeliumVotePlugin/hooks/useTransferPosition.ts b/HeliumVotePlugin/hooks/useTransferPosition.ts new file mode 100644 index 0000000000..d45f9d8b8e --- /dev/null +++ b/HeliumVotePlugin/hooks/useTransferPosition.ts @@ -0,0 +1,133 @@ +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { Program } from '@coral-xyz/anchor' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { useAsyncCallback } from 'react-async-hook' +import { PositionWithMeta } from '../sdk/types' +import { PROGRAM_ID, init, daoKey } from '@helium/helium-sub-daos-sdk' +import { getMintNaturalAmountFromDecimalAsBN } from '@tools/sdk/units' +import { notify } from '@utils/notifications' +import { + SequenceType, + sendTransactionsV3, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' +import {useHeliumClient} from "../../VoterWeightPlugins/useHeliumClient"; + +export const useTransferPosition = () => { + const { connection, wallet, anchorProvider: provider } = useWalletDeprecated() + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const {heliumClient} = useHeliumClient(); + const { error, loading, execute } = useAsyncCallback( + async ({ + sourcePosition, + amount, + targetPosition, + programId = PROGRAM_ID, + }: { + sourcePosition: PositionWithMeta + amount: number + targetPosition: PositionWithMeta + programId?: PublicKey + }) => { + const isInvalid = + !connection || + !connection.current || + !provider || + !realm || + !mint || + !wallet || + !heliumClient || + sourcePosition.numActiveVotes > 0 || + targetPosition.numActiveVotes > 0 + + const idl = await Program.fetchIdl(programId, provider) + const hsdProgram = await init(provider as any, programId, idl) + + if (loading) return + + if (isInvalid || !hsdProgram) { + throw new Error('Unable to Transfer Position, Invalid params') + } else { + const instructions: TransactionInstruction[] = [] + const [dao] = daoKey(realm.account.communityMint) + const isDao = Boolean(await connection.current.getAccountInfo(dao)) + const amountToTransfer = getMintNaturalAmountFromDecimalAsBN( + amount, + mint!.decimals + ) + + if (isDao) { + instructions.push( + await hsdProgram.methods + .transferV0({ + amount: amountToTransfer, + }) + .accounts({ + sourcePosition: sourcePosition.pubkey, + targetPosition: targetPosition.pubkey, + depositMint: realm.account.communityMint, + dao: dao, + }) + .instruction() + ) + } else { + instructions.push( + await heliumClient.program.methods + .transferV0({ + amount: amountToTransfer, + }) + .accounts({ + sourcePosition: sourcePosition.pubkey, + targetPosition: targetPosition.pubkey, + depositMint: realm.account.communityMint, + }) + .instruction() + ) + } + + if (amountToTransfer.eq(sourcePosition.amountDepositedNative)) { + instructions.push( + await heliumClient.program.methods + .closePositionV0() + .accounts({ + position: sourcePosition.pubkey, + }) + .instruction() + ) + } + + notify({ message: 'Transferring' }) + await sendTransactionsV3({ + transactionInstructions: [ + { + instructionsSet: txBatchesToInstructionSetWithSigners( + instructions, + [], + 0 + ), + sequenceType: SequenceType.Sequential, + }, + ], + wallet, + connection: connection.current, + callbacks: { + afterAllTxConfirmed: () => + notify({ + message: 'Transfer successful', + type: 'success', + }), + }, + }) + } + } + ) + + return { + error, + loading, + transferPosition: execute, + } +} diff --git a/HeliumVotePlugin/hooks/useUndelegatePosition.ts b/HeliumVotePlugin/hooks/useUndelegatePosition.ts new file mode 100644 index 0000000000..4ac19a3fe1 --- /dev/null +++ b/HeliumVotePlugin/hooks/useUndelegatePosition.ts @@ -0,0 +1,112 @@ +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { Program } from '@coral-xyz/anchor' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { useAsyncCallback } from 'react-async-hook' +import { PositionWithMeta } from '../sdk/types' +import { + PROGRAM_ID, + init, + delegatedPositionKey, +} from '@helium/helium-sub-daos-sdk' +import { notify } from '@utils/notifications' +import { + SequenceType, + sendTransactionsV3, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { withCreateTokenOwnerRecord } from '@solana/spl-governance' +import useRealm from '@hooks/useRealm' +import { useRealmQuery } from '@hooks/queries/realm' + +export const useUndelegatePosition = () => { + const { connection, wallet, anchorProvider: provider } = useWalletDeprecated() + const realm = useRealmQuery().data?.result + + const { realmInfo } = useRealm() + const { error, loading, execute } = useAsyncCallback( + async ({ + position, + tokenOwnerRecordPk, + programId = PROGRAM_ID, + }: { + position: PositionWithMeta + tokenOwnerRecordPk: PublicKey | null + programId?: PublicKey + }) => { + const isInvalid = + !connection || + !connection.current || + !provider || + !wallet || + !realm || + !realmInfo || + !position.isDelegated + + const idl = await Program.fetchIdl(programId, provider) + const hsdProgram = await init(provider as any, programId, idl) + + if (loading) return + + if (isInvalid || !hsdProgram) { + throw new Error('Unable to Undelegate Position, Invalid params') + } else { + const instructions: TransactionInstruction[] = [] + const delegatedPosKey = delegatedPositionKey(position.pubkey)[0] + const delegatedPosAcc = await hsdProgram.account.delegatedPositionV0.fetch( + delegatedPosKey + ) + + if (!tokenOwnerRecordPk) { + await withCreateTokenOwnerRecord( + instructions, + realm.owner, + realmInfo.programVersion!, + realm.pubkey, + wallet!.publicKey!, + realm.account.communityMint, + wallet!.publicKey! + ) + } + + instructions.push( + await hsdProgram.methods + .closeDelegationV0() + .accounts({ + position: position.pubkey, + subDao: delegatedPosAcc.subDao, + }) + .instruction() + ) + + notify({ message: 'UnDelegating' }) + await sendTransactionsV3({ + transactionInstructions: [ + { + instructionsSet: txBatchesToInstructionSetWithSigners( + instructions, + [], + 0 + ), + sequenceType: SequenceType.Sequential, + }, + ], + wallet, + connection: connection.current, + callbacks: { + afterAllTxConfirmed: () => + notify({ + message: 'UnDelegation successful', + type: 'success', + }), + }, + }) + } + } + ) + + return { + error, + loading, + undelegatePosition: execute, + } +} diff --git a/HeliumVotePlugin/sdk/client.ts b/HeliumVotePlugin/sdk/client.ts new file mode 100644 index 0000000000..b6341f95fc --- /dev/null +++ b/HeliumVotePlugin/sdk/client.ts @@ -0,0 +1,111 @@ +import {Program, Provider, web3 } from '@coral-xyz/anchor' +import { VoterStakeRegistry, IDL } from '@helium/idls/lib/types/voter_stake_registry' +import {PROGRAM_ID, init, registrarKey, voterWeightRecordKey} from '@helium/voter-stake-registry-sdk' +import {Client, DEFAULT_GOVERNANCE_PROGRAM_ID} from "@solana/governance-program-library"; +import {PublicKey, TransactionInstruction} from "@solana/web3.js"; +import {getTokenOwnerRecordAddress, VoterWeightAction} from "@solana/spl-governance"; +import {AccountData} from "@utils/uiTypes/VotePlugin"; +import {getAssociatedTokenAddress} from "@blockworks-foundation/mango-v4"; +import BN from "bn.js"; +import {getPositions, GetPositionsReturn} from "../utils/getPositions"; + +export class HeliumVsrClient extends Client { + constructor( + public program: Program, + public devnet: boolean, + readonly governanceProgramId: PublicKey + ) { + super(program, devnet) + } + + readonly requiresInputVoterWeight = false; + + // NO-OP TODO: Double-check + async createVoterWeightRecord(): Promise { + return null; + } + + // NO-OP + async createMaxVoterWeightRecord(): Promise { + return null; + } + + async updateVoterWeightRecord(voter: PublicKey, realm: PublicKey, mint: PublicKey, action: VoterWeightAction) { + const { positions } = await this.getPositions(voter, realm, mint); + const tokenOwnerRecord = await getTokenOwnerRecordAddress(this.governanceProgramId, realm, mint, voter); + + const remainingAccounts: AccountData[] = [] + const [registrar] = registrarKey( + realm, + mint, + this.program.programId + ) + + for (const pos of positions) { + const tokenAccount = await getAssociatedTokenAddress( + pos.mint, + voter, + true + ) + + remainingAccounts.push( + new AccountData(tokenAccount), + new AccountData(pos.pubkey) + ) + } + + const [voterWeightPk] = voterWeightRecordKey( + registrar, + voter, + this.program.programId + ) + + const ix = await this.program.methods + .updateVoterWeightRecordV0({ + owner: voter, + voterWeightAction: { + [action]: {}, + }, + } as any) + .accounts({ + registrar, + voterWeightRecord: voterWeightPk, + voterTokenOwnerRecord: tokenOwnerRecord, + }) + .remainingAccounts(remainingAccounts.slice(0, 10)) + .instruction(); + + return { pre: [ix] } + } + // NO-OP + async updateMaxVoterWeightRecord(): Promise { + return null; + } + async calculateVoterWeight(voter: PublicKey, realm: PublicKey, mint: PublicKey): Promise { + const positionDetails = await this.getPositions(voter, realm, mint); + return positionDetails.votingPower + } + + private async getPositions(voter: PublicKey, realm: PublicKey, mint: PublicKey): Promise { + return getPositions({ + realmPk: realm, + walletPk: voter, + communityMintPk: mint, + client: this, + connection: this.program.provider.connection + }) + } + + static async connect( + provider: Provider, + programId: web3.PublicKey = PROGRAM_ID, + devnet = false, + governanceProgramId = DEFAULT_GOVERNANCE_PROGRAM_ID + ): Promise { + return new HeliumVsrClient( + (await init(provider as any, programId)) as any, + devnet, + governanceProgramId, + ) + } +} diff --git a/HeliumVotePlugin/sdk/types.ts b/HeliumVotePlugin/sdk/types.ts new file mode 100644 index 0000000000..bc4d2c2590 --- /dev/null +++ b/HeliumVotePlugin/sdk/types.ts @@ -0,0 +1,38 @@ +import { PublicKey } from '@solana/web3.js' +import { BN, IdlAccounts, IdlTypes } from '@coral-xyz/anchor' +import { VoterStakeRegistry as HeliumVoterStakeRegistry } from '@helium/idls/lib/types/voter_stake_registry' +import { HeliumSubDaos } from '@helium/idls/lib/types/helium_sub_daos' +import { TokenProgramAccount } from '@utils/tokens' +import { MintInfo } from '@solana/spl-token' +import { Sft } from '@metaplex-foundation/js' + +export type VotingMintConfig = IdlTypes['VotingMintConfigV0'] +type RegistrarV0 = IdlAccounts['registrar'] +export type Lockup = IdlTypes['Lockup'] +export type PositionV0 = IdlAccounts['positionV0'] +export type DelegatedPositionV0 = IdlAccounts['delegatedPositionV0'] +export interface Registrar extends RegistrarV0 { + votingMints: VotingMintConfig[] +} +export interface Position extends Omit { + lockup: Lockup +} +export interface PositionWithMeta extends Position { + pubkey: PublicKey + isDelegated: boolean + delegatedSubDao: PublicKey | null + hasRewards: boolean + hasGenesisMultiplier: boolean + votingPower: BN + votingMint: VotingMintConfig & { + mint: TokenProgramAccount + } +} +export type LockupKind = IdlTypes['LockupKind'] +/* export type InitializePositionV0Args = IdlTypes['InitializePositionArgsV0'] + */ +export type SubDao = IdlAccounts['subDaoV0'] +export interface SubDaoWithMeta extends Omit { + pubkey: PublicKey + dntMetadata: Sft +} diff --git a/HeliumVotePlugin/utils/calcLockupMultiplier.ts b/HeliumVotePlugin/utils/calcLockupMultiplier.ts new file mode 100644 index 0000000000..40408037c0 --- /dev/null +++ b/HeliumVotePlugin/utils/calcLockupMultiplier.ts @@ -0,0 +1,63 @@ +import { PublicKey } from '@solana/web3.js' +import { ProgramAccount, Realm } from '@solana/spl-governance' +import { Registrar, VotingMintConfig } from '../sdk/types' + +export const calcMultiplier = ({ + baselineScaledFactor, + maxExtraLockupScaledFactor, + lockupSecs, + lockupSaturationSecs, +}: { + baselineScaledFactor: number + maxExtraLockupScaledFactor: number + lockupSecs: number + lockupSaturationSecs: number +}): number => { + let multiplier = 0 + const base = baselineScaledFactor !== 0 ? baselineScaledFactor : 1e9 + + multiplier = + (Math.min(lockupSecs / lockupSaturationSecs, 1) * + maxExtraLockupScaledFactor) / + base + + return multiplier +} + +export const calcLockupMultiplier = ({ + lockupSecs, + registrar, + realm, +}: { + lockupSecs: number + registrar: Registrar | null + realm: ProgramAccount | undefined +}) => { + let multiplier = 0 + const mintCfgs = registrar?.votingMints || [] + const mintCfg = mintCfgs?.find((cfg) => + cfg.mint.equals(realm?.account.communityMint || PublicKey.default) + ) + + if (mintCfg && !mintCfg.mint.equals(PublicKey.default)) { + const { + baselineVoteWeightScaledFactor, + lockupSaturationSecs, + maxExtraLockupVoteWeightScaledFactor, + // genesisVotePowerMultiplier, + // genesisVotePowerMultiplierExpirationTs + } = mintCfg as VotingMintConfig + const baselineScaledFactorNum = baselineVoteWeightScaledFactor.toNumber() + const maxExtraLockupVoteWeightScaledFactorNum = maxExtraLockupVoteWeightScaledFactor.toNumber() + const lockupSaturationSecsNum = lockupSaturationSecs.toNumber() + + multiplier = calcMultiplier({ + baselineScaledFactor: baselineScaledFactorNum, + maxExtraLockupScaledFactor: maxExtraLockupVoteWeightScaledFactorNum, + lockupSecs, + lockupSaturationSecs: lockupSaturationSecsNum, + }) + } + + return parseFloat(multiplier.toFixed(2)) +} diff --git a/HeliumVotePlugin/utils/calcPositionVotingPower.ts b/HeliumVotePlugin/utils/calcPositionVotingPower.ts new file mode 100644 index 0000000000..b7a217317d --- /dev/null +++ b/HeliumVotePlugin/utils/calcPositionVotingPower.ts @@ -0,0 +1,48 @@ +import { BN } from '@coral-xyz/anchor' +import { calcMultiplier } from './calcLockupMultiplier' +import { Position, VotingMintConfig, Registrar, LockupKind } from '../sdk/types' + +export const calcPositionVotingPower = ({ + position, + registrar, + unixNow, +}: { + position: Position | null + registrar: Registrar | null + unixNow: BN +}) => { + let votingPower = new BN(0) + const mintCfgs = registrar?.votingMints || [] + const mintCfg = position ? mintCfgs[position.votingMintConfigIdx] : undefined + + if (position && mintCfg) { + const { + lockupSaturationSecs, + baselineVoteWeightScaledFactor, + maxExtraLockupVoteWeightScaledFactor, + genesisVotePowerMultiplier = 1, + } = mintCfg as VotingMintConfig + const hasGenesisMultiplier = position.genesisEnd.gt(unixNow) + const lockup = position!.lockup + const lockupKind = Object.keys(lockup.kind as LockupKind)[0] + const currTs = lockupKind === 'constant' ? lockup.startTs : unixNow + const lockupSecs = lockup.endTs.sub(currTs).toNumber() + const amountLockedNative = position!.amountDepositedNative + const baselineScaledFactorNum = baselineVoteWeightScaledFactor.toNumber() + const maxExtraLockupVoteWeightScaledFactorNum = maxExtraLockupVoteWeightScaledFactor.toNumber() + const lockupSaturationSecsNum = lockupSaturationSecs.toNumber() + + const multiplier = + (hasGenesisMultiplier ? genesisVotePowerMultiplier : 1) * + calcMultiplier({ + baselineScaledFactor: baselineScaledFactorNum, + maxExtraLockupScaledFactor: maxExtraLockupVoteWeightScaledFactorNum, + lockupSecs, + lockupSaturationSecs: lockupSaturationSecsNum, + }) + + votingPower = amountLockedNative.muln(multiplier) + } + + return votingPower +} diff --git a/HeliumVotePlugin/utils/getPositions.ts b/HeliumVotePlugin/utils/getPositions.ts new file mode 100644 index 0000000000..e8a8c87c79 --- /dev/null +++ b/HeliumVotePlugin/utils/getPositions.ts @@ -0,0 +1,150 @@ +import { BN, Program } from '@coral-xyz/anchor' +import { Metaplex } from '@metaplex-foundation/js' +import { Connection, PublicKey, SYSVAR_CLOCK_PUBKEY } from '@solana/web3.js' +import { registrarKey, positionKey } from '@helium/voter-stake-registry-sdk' +import { + PROGRAM_ID, + EPOCH_LENGTH, + init, + delegatedPositionKey, +} from '@helium/helium-sub-daos-sdk' +import { tryGetMint } from '@utils/tokens' +import { calcPositionVotingPower } from './calcPositionVotingPower' +import { HeliumVsrClient } from '../sdk/client' +import { + Registrar, + PositionWithMeta, + PositionV0, + DelegatedPositionV0, +} from '../sdk/types' +import { chunks } from '@utils/helpers' +import { HNT_MINT } from '@helium/spl-utils' + +export interface GetPositionsArgs { + realmPk: PublicKey + walletPk: PublicKey + communityMintPk: PublicKey + client: HeliumVsrClient + connection: Connection +} + +export interface GetPositionsReturn { + positions: PositionWithMeta[] + amountLocked: BN + votingPower: BN +} + +export const getPositions = async ( + args: GetPositionsArgs +): Promise => { + const { realmPk, walletPk, communityMintPk, client, connection } = args + const positions: PositionWithMeta[] = [] + let amountLocked = new BN(0) + let votingPower = new BN(0) + const clock = await connection.getAccountInfo(SYSVAR_CLOCK_PUBKEY) + const now = new BN(Number(clock!.data.readBigInt64LE(8 * 4))) + const isHNT = communityMintPk.equals(HNT_MINT) + const metaplex = new Metaplex(connection) + const registrarPk = registrarKey(realmPk, communityMintPk)[0] + const registrar = (await client.program.account.registrar.fetch( + registrarPk + )) as Registrar + const mintCfgs = registrar.votingMints + const mints = {} + for (const mcfg of mintCfgs) { + const mint = await tryGetMint(connection, mcfg.mint) + mints[mcfg.mint.toBase58()] = mint + } + + const nfts = ( + await metaplex.nfts().findAllByOwner({ owner: walletPk }) + ).filter((nft) => nft.collection?.address.equals(registrar.collection)) + const posKeys = nfts.map((nft) => positionKey((nft as any).mintAddress)[0]) + const positionAccInfos = ( + await Promise.all( + chunks(posKeys, 99).map((chunk) => + connection.getMultipleAccountsInfo(chunk) + ) + ) + ).flat() + + const delegatedPosKeys = posKeys.map( + (posKey) => delegatedPositionKey(posKey)[0] + ) + + const delegatedPositionAccs = isHNT + ? await (async () => { + const idl = await Program.fetchIdl(PROGRAM_ID, client.program.provider) + const hsdProgram = await init( + client.program.provider as any, + PROGRAM_ID, + idl + ) + + return ( + await Promise.all( + chunks(delegatedPosKeys, 99).map((chunk) => + connection.getMultipleAccountsInfo(chunk) + ) + ) + ) + .flat() + .map((delegatedPos) => + delegatedPos + ? (hsdProgram.coder.accounts.decode( + 'DelegatedPositionV0', + delegatedPos.data + ) as DelegatedPositionV0) + : null + ) + })() + : [] + + positions.push( + ...positionAccInfos.map((posAccInfo, idx) => { + const pos = client.program.coder.accounts.decode( + 'PositionV0', + posAccInfo!.data + ) as PositionV0 + + const isDelegated = !!delegatedPositionAccs[idx] + const delegatedSubDao = isDelegated + ? delegatedPositionAccs[idx]?.subDao + : null + const hasRewards = isDelegated + ? delegatedPositionAccs[idx]!.lastClaimedEpoch.add(new BN(1)).lt( + now.div(new BN(EPOCH_LENGTH)) + ) + : false + + const posVotingPower = calcPositionVotingPower({ + position: pos, + registrar, + unixNow: now, + }) + + amountLocked = amountLocked.add(pos.amountDepositedNative) + votingPower = votingPower.add(posVotingPower) + + return { + ...pos, + pubkey: posKeys[idx], + isDelegated, + delegatedSubDao, + hasRewards, + hasGenesisMultiplier: pos.genesisEnd.gt(now), + votingPower: posVotingPower, + votingMint: { + ...mintCfgs[pos.votingMintConfigIdx], + mint: mints[mintCfgs[pos.votingMintConfigIdx].mint.toBase58()], + }, + } as PositionWithMeta + }) + ) + + return { + positions, + amountLocked, + votingPower, + } +} diff --git a/HeliumVotePlugin/utils/getSubDaos.ts b/HeliumVotePlugin/utils/getSubDaos.ts new file mode 100644 index 0000000000..d44e925082 --- /dev/null +++ b/HeliumVotePlugin/utils/getSubDaos.ts @@ -0,0 +1,53 @@ +import { AnchorProvider, Program } from '@coral-xyz/anchor' +import { Metaplex } from '@metaplex-foundation/js' +import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes' +import { Connection, PublicKey } from '@solana/web3.js' +import { SubDaoWithMeta } from '../sdk/types' +import { PROGRAM_ID, init, daoKey } from '@helium/helium-sub-daos-sdk' +import { HNT_MINT } from '@helium/spl-utils' + +export const getSubDaos = async ( + connection: Connection, + provider: AnchorProvider, + programId: PublicKey = PROGRAM_ID +): Promise => { + try { + const subDaos: SubDaoWithMeta[] = [] + const idl = await Program.fetchIdl(programId, provider) + const hsdProgram = await init(provider as any, programId, idl) + + const metaplex = new Metaplex(connection) + const dao = await daoKey(HNT_MINT, programId)[0] + const subdaos = await hsdProgram.account.subDaoV0.all([ + { + memcmp: { + offset: 8, + bytes: bs58.encode(dao.toBuffer()), + }, + }, + ]) + + const dntMetadatas = await Promise.all( + subdaos.map(async (subDao) => + metaplex.nfts().findByMint({ + mintAddress: subDao.account.dntMint, + }) + ) + ) + + subDaos.push( + ...subdaos.map((subDao, idx) => { + return { + ...subDao.account, + pubkey: subDao.publicKey, + dntMetadata: dntMetadatas[idx], + } as SubDaoWithMeta + }) + ) + + return subDaos + } catch (error) { + console.error(error) + throw error + } +} diff --git a/HeliumVotePlugin/utils/getUnusedPositionsForProposal.ts b/HeliumVotePlugin/utils/getUnusedPositionsForProposal.ts new file mode 100644 index 0000000000..2185b21156 --- /dev/null +++ b/HeliumVotePlugin/utils/getUnusedPositionsForProposal.ts @@ -0,0 +1,36 @@ +import { Connection, PublicKey } from '@solana/web3.js' +import { nftVoteRecordKey } from '@helium/voter-stake-registry-sdk' +import { HeliumVsrClient } from '../sdk/client' +import { PositionWithMeta } from '../sdk/types' +import { chunks } from '@utils/helpers' + +export interface GetUnusedPositionsForProposalArgs { + connection: Connection + client: HeliumVsrClient + positions: PositionWithMeta[] + proposalPk: PublicKey +} + +export const getUnusedPositionsForProposal = async ( + args: GetUnusedPositionsForProposalArgs +): Promise => { + const { connection, client, positions, proposalPk } = args + const unusedPositions: PositionWithMeta[] = [] + const nftVoteRecordKeys = positions.map( + (pos) => nftVoteRecordKey(proposalPk, pos.mint, client.program.programId)[0] + ) + + const nftVoteRecordAccountInfos = ( + await Promise.all( + chunks(nftVoteRecordKeys, 99).map((chunk) => + connection.getMultipleAccountsInfo(chunk) + ) + ) + ).flat() + + unusedPositions.push( + ...positions.filter((_pos, idx) => !nftVoteRecordAccountInfos[idx]) + ) + + return unusedPositions +} diff --git a/HeliumVotePlugin/utils/getUsedPositionsForProposal.ts b/HeliumVotePlugin/utils/getUsedPositionsForProposal.ts new file mode 100644 index 0000000000..5eb38b887a --- /dev/null +++ b/HeliumVotePlugin/utils/getUsedPositionsForProposal.ts @@ -0,0 +1,36 @@ +import { Connection, PublicKey } from '@solana/web3.js' +import { nftVoteRecordKey } from '@helium/voter-stake-registry-sdk' +import { HeliumVsrClient } from '../sdk/client' +import { PositionWithMeta } from '../sdk/types' +import { chunks } from '@utils/helpers' + +export interface GetUsedPositionsForProposalArgs { + connection: Connection + client: HeliumVsrClient + positions: PositionWithMeta[] + proposalPk: PublicKey +} + +export const getUsedPositionsForProposal = async ( + args: GetUsedPositionsForProposalArgs +): Promise => { + const { connection, client, positions, proposalPk } = args + const usedPositions: PositionWithMeta[] = [] + const nftVoteRecordKeys = positions.map( + (pos) => nftVoteRecordKey(proposalPk, pos.mint, client.program.programId)[0] + ) + + const nftVoteRecordAccountInfos = ( + await Promise.all( + chunks(nftVoteRecordKeys, 99).map((chunk) => + connection.getMultipleAccountsInfo(chunk) + ) + ) + ).flat() + + usedPositions.push( + ...positions.filter((_pos, idx) => !!nftVoteRecordAccountInfos[idx]) + ) + + return usedPositions +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..f49a4e16e6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/NftVotePlugin/NftProposalStore.tsx b/NftVotePlugin/NftProposalStore.tsx index b436ae94f2..9f01f7a0f9 100644 --- a/NftVotePlugin/NftProposalStore.tsx +++ b/NftVotePlugin/NftProposalStore.tsx @@ -1,5 +1,5 @@ import create, { State } from 'zustand' -import { NftVoterClient } from '@solana/governance-program-library' +import { NftVoterClient } from '@utils/uiTypes/NftVoterClient' import { ProgramAccount, Proposal } from '@solana/spl-governance' import { getUsedNftsForProposal, NftVoteRecord } from './accounts' import { PublicKey } from '@solana/web3.js' diff --git a/NftVotePlugin/NftProposalVoteState.tsx b/NftVotePlugin/NftProposalVoteState.tsx index 2ba6eeaa2d..c087e8c524 100644 --- a/NftVotePlugin/NftProposalVoteState.tsx +++ b/NftVotePlugin/NftProposalVoteState.tsx @@ -1,40 +1,46 @@ -import useRealm from '@hooks/useRealm' -import { nftPluginsPks } from '@hooks/useVotingPlugins' +import { NFT_PLUGINS_PKS } from '@constants/plugins' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' import { ProgramAccount, Proposal, ProposalState } from '@solana/spl-governance' import { useEffect } from 'react' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import useWalletStore from 'stores/useWalletStore' import useNftProposalStore from './NftProposalStore' -import useNftPluginStore from './store/nftPluginStore' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { useProposalVoteRecordQuery } from '@hooks/queries/voteRecord' +import { useVotingPop } from '@components/VotePanel/hooks' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import {useNftClient} from "../VoterWeightPlugins/useNftClient"; const NftProposalVoteState = ({ proposal, }: { proposal?: ProgramAccount }) => { - const { config, ownTokenRecord } = useRealm() - const { voteRecordsByVoter } = useWalletStore((s) => s.selectedProposal) - const plugin = useVotePluginsClientStore((s) => s.state.nftClient) + const config = useRealmConfigQuery().data?.result + + const { nftClient } = useNftClient(); const getCountedNfts = useNftProposalStore((s) => s.getCountedNfts) const countedNfts = useNftProposalStore((s) => s.countedNftsForProposal) - const wallet = useWalletStore((s) => s.current) - const votingPower = useNftPluginStore((s) => s.state.votingPower) + const wallet = useWalletOnePointOh() + const votingPop = useVotingPop() + const { totalCalculatedVoterWeight, isReady } = useRealmVoterWeightPlugins( + votingPop + ) const isNftPlugin = config?.account.communityTokenConfig.voterWeightAddin && - nftPluginsPks.includes( + NFT_PLUGINS_PKS.includes( config?.account.communityTokenConfig.voterWeightAddin?.toBase58() ) - const ownVoteRecord = ownTokenRecord - ? voteRecordsByVoter[ownTokenRecord.account.governingTokenOwner.toBase58()] - : wallet?.publicKey && voteRecordsByVoter[wallet.publicKey.toBase58()] + const ownVoteRecord = useProposalVoteRecordQuery('electoral').data?.result + const showVoteRecords = + isReady && + totalCalculatedVoterWeight?.value && countedNfts.length > 0 && - countedNfts.length < votingPower.toNumber() && + countedNfts.length < totalCalculatedVoterWeight.value.toNumber() && !ownVoteRecord const useComponent = - plugin && + nftClient && proposal && wallet?.connected && isNftPlugin && @@ -43,8 +49,9 @@ const NftProposalVoteState = ({ useEffect(() => { if (useComponent) { - getCountedNfts(plugin, proposal, wallet.publicKey!) + getCountedNfts(nftClient, proposal, wallet.publicKey!) } + // 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 }, [useComponent]) return showVoteRecords && useComponent ? ( diff --git a/NftVotePlugin/accounts.ts b/NftVotePlugin/accounts.ts index f05491c69c..048e93d311 100644 --- a/NftVotePlugin/accounts.ts +++ b/NftVotePlugin/accounts.ts @@ -1,5 +1,6 @@ -import { NftVoterClient } from '@solana/governance-program-library' +import { NftVoterClient } from '@utils/uiTypes/NftVoterClient' import { PublicKey } from '@solana/web3.js' + export interface NftVoteRecord { account: { governingTokenOwner: PublicKey @@ -45,3 +46,29 @@ export const getNftVoteRecordProgramAddress = async ( nftVoteRecordBump, } } + +export const getNftActionTicketProgramAddress = ( + ticketType: string, + registrar: PublicKey, + owner: PublicKey, + nftMintAddress: string, + clientProgramId: PublicKey +) => { + const [ + nftActionTicket, + nftActionTicketBump, + ] = PublicKey.findProgramAddressSync( + [ + Buffer.from(ticketType), + registrar.toBuffer(), + owner.toBuffer(), + new PublicKey(nftMintAddress).toBuffer(), + ], + clientProgramId + ) + + return { + nftActionTicket, + nftActionTicketBump, + } +} diff --git a/NftVotePlugin/getCnftParamAndProof.ts b/NftVotePlugin/getCnftParamAndProof.ts new file mode 100644 index 0000000000..abdc26da48 --- /dev/null +++ b/NftVotePlugin/getCnftParamAndProof.ts @@ -0,0 +1,88 @@ +import { Connection, PublicKey } from '@solana/web3.js' +import { ConcurrentMerkleTreeAccount } from '@solana/spl-account-compression' +import * as bs58 from 'bs58' +import { fetchDasAssetProofById } from '@hooks/queries/digitalAssets' +import { getNetworkFromEndpoint } from '@utils/connection' +import * as anchor from '@coral-xyz/anchor' + +export function decode(stuff: string) { + return bufferToArray(bs58.decode(stuff)) +} + +function bufferToArray(buffer: Buffer): number[] { + const nums: number[] = [] + for (let i = 0; i < buffer.length; i++) { + nums.push(buffer[i]) + } + return nums +} + +/** + * This is a helper function only for nft-voter-v2 used. + * Given a cNFT, getCnftParamAndProof will to get its the metadata, leaf information and merkle proof. + * All these data will be sent to the program to verify the ownership of the cNFT. + * @param connection + * @param compressedNft + * @returns {param, additionalAccounts} + */ +export async function getCnftParamAndProof( + connection: Connection, + compressedNft: any +) { + const network = getNetworkFromEndpoint(connection.rpcEndpoint) + if (network === 'localnet') throw new Error() + const { result: assetProof } = await fetchDasAssetProofById( + network, + new PublicKey(compressedNft.id) + ) + const treeAccount = await ConcurrentMerkleTreeAccount.fromAccountAddress( + connection, + new PublicKey(compressedNft.compression.tree) + ) + const canopyHeight = treeAccount.getCanopyDepth() + const root = decode(assetProof.root) + const proofLength = assetProof.proof.length + + const reducedProofs = assetProof.proof.slice( + 0, + proofLength - (canopyHeight ? canopyHeight : 0) + ) + + const creators = compressedNft.creators.map((creator) => { + return { + address: new PublicKey(creator.address), + verified: creator.verified, + share: creator.share, + } + }) + + const rawCollection = compressedNft.grouping.find( + (x) => x.group_key === 'collection' + ) + const param = { + name: compressedNft.content.metadata.name, + symbol: compressedNft.content.metadata.symbol, + uri: compressedNft.content.json_uri, + sellerFeeBasisPoints: compressedNft.royalty.basis_points, + primarySaleHappened: compressedNft.royalty.primary_sale_happened, + creators, + isMutable: compressedNft.mutable, + editionNonce: compressedNft.supply.edition_nonce, + collection: { + key: rawCollection ? new PublicKey(rawCollection.group_value) : null, + verified: true, + }, + root, + leafOwner: new PublicKey(compressedNft.ownership.owner), + leafDelegate: new PublicKey( + compressedNft.ownership.delegate || compressedNft.ownership.owner + ), + nonce: new anchor.BN(compressedNft.compression.leaf_id), + index: compressedNft.compression.leaf_id, + proofLen: reducedProofs.length, + } + + const additionalAccounts = [compressedNft.compression.tree, ...reducedProofs] + + return { param: param, additionalAccounts: additionalAccounts } +} diff --git a/NftVotePlugin/store/nftPluginStore.ts b/NftVotePlugin/store/nftPluginStore.ts index 910a511199..3035058650 100644 --- a/NftVotePlugin/store/nftPluginStore.ts +++ b/NftVotePlugin/store/nftPluginStore.ts @@ -1,63 +1,27 @@ -import { BN } from '@project-serum/anchor' import { MaxVoterWeightRecord, ProgramAccount } from '@solana/spl-governance' -import { NFTWithMeta, VotingClient } from '@utils/uiTypes/VotePlugin' import create, { State } from 'zustand' interface nftPluginStore extends State { state: { - votingNfts: NFTWithMeta[] - votingPower: BN maxVoteRecord: ProgramAccount | null - isLoadingNfts: boolean } - setVotingNfts: ( - nfts: NFTWithMeta[], - votingClient: VotingClient, - nftMintRegistrar: any - ) => void - setVotingPower: (nfts: NFTWithMeta[], nftMintRegistrar: any) => void setMaxVoterWeight: ( maxVoterRecord: ProgramAccount | null ) => void - setIsLoadingNfts: (val: boolean) => void } const defaultState = { - votingNfts: [], - votingPower: new BN(0), maxVoteRecord: null, - isLoadingNfts: false, } +/** + * @deprecated + * instead of using this, query directly whatever it is you wanna query. we can make a query for getting voting NFTs. + */ const useNftPluginStore = create((set, _get) => ({ state: { ...defaultState, }, - setIsLoadingNfts: (val) => { - set((s) => { - s.state.isLoadingNfts = val - }) - }, - setVotingNfts: (nfts, votingClient, nftMintRegistrar) => { - votingClient._setCurrentVoterNfts(nfts) - set((s) => { - s.state.votingNfts = nfts - }) - _get().setVotingPower(nfts, nftMintRegistrar) - }, - setVotingPower: (nfts, nftMintRegistrar) => { - const votingPower = nfts - .map( - (x) => - nftMintRegistrar?.collectionConfigs?.find( - (j) => j.collection?.toBase58() === x.collection.mintAddress - )?.weight || new BN(0) - ) - .reduce((prev, next) => prev.add(next), new BN(0)) - set((s) => { - s.state.votingPower = votingPower - }) - }, setMaxVoterWeight: (maxVoterRecord) => { set((s) => { s.state.maxVoteRecord = maxVoterRecord diff --git a/ParclVotePlugin/ParclVoterWeightPluginClient.ts b/ParclVotePlugin/ParclVoterWeightPluginClient.ts new file mode 100644 index 0000000000..b196eddd61 --- /dev/null +++ b/ParclVotePlugin/ParclVoterWeightPluginClient.ts @@ -0,0 +1,101 @@ +import {Client} from "@solana/governance-program-library"; +import {PublicKey, TransactionInstruction} from "@solana/web3.js"; +import BN from "bn.js"; +import {StakeAccount, StakeConnection} from "@parcl-oss/staking"; +import {Provider, Wallet} from "@coral-xyz/anchor"; +import {VoterWeightAction} from "@solana/spl-governance"; +import {convertVoterWeightActionToType} from "../VoterWeightPlugins/lib/utils"; +import queryClient from "@hooks/queries/queryClient"; + +// A wrapper for the StakeConnection from @parcl-oss/staking, that implements the generic plugin client interface +export class ParclVoterWeightPluginClient extends Client { + readonly requiresInputVoterWeight = false; + // The parcl plugin does not have a registrar account + async getRegistrarAccount(): Promise { + return null; + } + + async getMaxVoterWeightRecordPDA() { + const maxVoterWeightPk = (await this.client.program.methods.updateMaxVoterWeight().pubkeys()).maxVoterRecord + + if (!maxVoterWeightPk) return null; + + return { + maxVoterWeightPk, + maxVoterWeightRecordBump: 0 // This is wrong for Parcl - but it doesn't matter as it is not used + } + } + + async getVoterWeightRecordPDA(realm: PublicKey, mint: PublicKey, voter: PublicKey) { + const { voterWeightAccount } = await this.getUpdateVoterWeightPks([], voter, VoterWeightAction.CastVote, PublicKey.default); + + return { + voterWeightPk: voterWeightAccount, + voterWeightRecordBump: 0 // This is wrong for Parcl - but it doesn't matter as it is not used + }; + } + + // NO-OP Parcl records are created through the Parcl dApp. + async createVoterWeightRecord(): Promise { + return null; + } + + // NO-OP + async createMaxVoterWeightRecord(): Promise { + return null; + } + + private async getStakeAccount(voter: PublicKey): Promise { + return queryClient.fetchQuery({ + queryKey: ['parcl getStakeAccount', voter], + queryFn: async() => { + const account = await this.client.getMainAccount(voter) + return account !== undefined ? account : null + }, + }) + } + + private async getUpdateVoterWeightPks(instructions: TransactionInstruction[], voter: PublicKey, action: VoterWeightAction, target?: PublicKey) { + const stakeAccount = await this.getStakeAccount(voter) + + if (!stakeAccount) throw new Error("Stake account not found for voter " + voter.toString()); + return this.client.withUpdateVoterWeight( + instructions, + stakeAccount, + { [convertVoterWeightActionToType(action)]: {} } as any, + target + ); + } + + async updateVoterWeightRecord(voter: PublicKey, realm: PublicKey, mint: PublicKey, action: VoterWeightAction, inputRecordCallback?: () => Promise, target?: PublicKey) { + const instructions: TransactionInstruction[] = []; + await this.getUpdateVoterWeightPks(instructions, voter, action, target); + + return { pre: instructions }; + } + // NO-OP + async updateMaxVoterWeightRecord(): Promise { + return null; + } + async calculateVoterWeight(voter: PublicKey): Promise { + const stakeAccount = await this.getStakeAccount(voter) + + if (stakeAccount) { + return stakeAccount.getVoterWeight(await this.client.getTime()).toBN() + } else { + return new BN(0) + } + } + constructor(program: typeof StakeConnection.prototype.program, private client: StakeConnection, devnet:boolean) { + super(program, devnet); + } + + static async connect(provider: Provider, devnet = false, wallet: Wallet): Promise { + const parclClient = await StakeConnection.connect( + provider.connection, + wallet + ) + + return new ParclVoterWeightPluginClient(parclClient.program, parclClient, devnet); + } +} \ No newline at end of file diff --git a/ParclVotePlugin/components/ParclAccountDetails.tsx b/ParclVotePlugin/components/ParclAccountDetails.tsx new file mode 100644 index 0000000000..16fa342857 --- /dev/null +++ b/ParclVotePlugin/components/ParclAccountDetails.tsx @@ -0,0 +1,163 @@ +import { MintInfo } from '@solana/spl-token' +import BN from 'bn.js' +import { GoverningTokenType } from '@solana/spl-governance' +import { fmtMintAmount } from '@tools/sdk/units' +import { useEffect } from 'react' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { useRealmCommunityMintInfoQuery, useRealmCouncilMintInfoQuery } from '@hooks/queries/mintInfo' +import ParclVotingPower from './ParclVotingPower' +import { useUserTokenAccountsQuery } from '@hooks/queries/tokenAccount' +import { useRealmQuery } from '@hooks/queries/realm' +import { PublicKey } from '@solana/web3.js' +import VanillaWithdrawTokensButton from '@components/TokenBalance/VanillaWithdrawTokensButton' +import { Deposit } from '@components/GovernancePower/Power/Vanilla/Deposit' + +export const PARCL_INSTRUCTIONS = + 'You can deposit PRCL tokens at https://app.parcl.co/staking' + +const TokenDeposit = ({ + mintInfo, + mintAddress, + inAccountDetails, + setHasGovPower, + role +}: { + mintInfo: MintInfo | undefined, + mintAddress: PublicKey, + inAccountDetails?: boolean, + role: 'council' | 'community', + setHasGovPower?: (hasGovPower: boolean) => void +}) => { + const wallet = useWalletOnePointOh() + const { data: tokenAccounts } = useUserTokenAccountsQuery() + const connected = !!wallet?.connected + + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const config = useRealmConfigQuery().data?.result + + const relevantTokenConfig = role === "community" + ? config?.account.communityTokenConfig + : config?.account.councilTokenConfig; + + const isMembership = + relevantTokenConfig?.tokenType === GoverningTokenType.Membership + const isDormant = + relevantTokenConfig?.tokenType === GoverningTokenType.Dormant; + + const depositTokenRecord = ownTokenRecord + const depositTokenAccount = tokenAccounts?.find((a) => + a.account.mint.equals(mintAddress) + ); + + const hasTokensInWallet = + depositTokenAccount && depositTokenAccount.account.amount.gt(new BN(0)) + + const hasTokensDeposited = + depositTokenRecord && + depositTokenRecord.account.governingTokenDepositAmount.gt(new BN(0)) + + const availableTokens = + depositTokenRecord && mintInfo + ? fmtMintAmount( + mintInfo, + depositTokenRecord.account.governingTokenDepositAmount + ) + : '0' + + useEffect(() => { + if (availableTokens != '0' || hasTokensDeposited || hasTokensInWallet) { + if (setHasGovPower) setHasGovPower(true) + } + }, [availableTokens, hasTokensDeposited, hasTokensInWallet, setHasGovPower]) + + const canShowAvailableTokensMessage = hasTokensInWallet && connected + const tokensToShow = + hasTokensInWallet && depositTokenAccount + ? fmtMintAmount(mintInfo, depositTokenAccount.account.amount) + : hasTokensInWallet + ? availableTokens + : 0 + + // Do not show deposits for mints with zero supply because nobody can deposit anyway + if (!mintInfo || mintInfo.supply.isZero()) { + return null + } + + return ( +
+ {(availableTokens != '0' || inAccountDetails) && ( +
+ +
+ )} +
+ You have {tokensToShow} {hasTokensDeposited ? `more ` : ``} tokens + available to deposit. +
+ { + role === "community" + ?
{PARCL_INSTRUCTIONS}
+ : null + } + { + !isDormant + ? + : null + } +
+ {!isMembership && // Membership tokens can't be withdrawn (that is their whole point, actually) + !isDormant && + inAccountDetails && ( + + )} +
+
+ ) +} + +const ParclAccountDetails = () => { + const realm = useRealmQuery().data?.result + const communityMint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result; + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const councilMintAddress = realm?.account.config.councilMint; + const hasLoaded = communityMint && councilMint && realm && councilMintAddress; + + return ( + <> + {hasLoaded ? ( +
+ {!connected ? ( +
+ Connect your wallet to see governance power +
+ ) : + ( + <> + + + + )} +
+ ) : ( + <> +
+
+ + )} + + ) +} + +export default ParclAccountDetails diff --git a/ParclVotePlugin/components/ParclVotingPower.tsx b/ParclVotePlugin/components/ParclVotingPower.tsx new file mode 100644 index 0000000000..7d9649f2e8 --- /dev/null +++ b/ParclVotePlugin/components/ParclVotingPower.tsx @@ -0,0 +1,113 @@ +import { BigNumber } from 'bignumber.js' +import { useMemo } from 'react' +import { useRealmQuery } from '@hooks/queries/realm' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import { useConnection } from '@solana/wallet-adapter-react' +import { getParclGovPower } from '@hooks/queries/governancePower' +import { useAsync } from 'react-async-hook' +import BN from 'bn.js' +import { getMintMetadata } from '@components/instructions/programs/splToken' +import VotingPowerPct from '@components/ProposalVotingPower/VotingPowerPct' +import clsx from 'clsx' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { GoverningTokenType } from '@solana/spl-governance' +import useParclScalingFactor from '@hooks/parcl/useScalingFactor' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useUserTokenAccountsQuery } from '@hooks/queries/tokenAccount' + +interface Props { + className?: string + role: 'community' | 'council' + hideIfZero?: boolean + children?: React.ReactNode +} + +export default function ParclVotingPower({ + role, + hideIfZero, + children, + ...props +}: Props) { + const realm = useRealmQuery().data?.result + const realmConfig = useRealmConfigQuery().data?.result + const { data: tokenAccounts } = useUserTokenAccountsQuery() + const wallet = useWalletOnePointOh() + + const { connection } = useConnection() + + const relevantMint = + role === 'community' + ? realm?.account.communityMint + : realm?.account.config.councilMint + + const mintInfo = useMintInfoByPubkeyQuery(relevantMint).data?.result + + const { result: personalAmount } = useAsync( + async () => + wallet?.publicKey && role === 'community' + ? getParclGovPower(connection, wallet.publicKey) + : tokenAccounts?.find( + (a) => relevantMint && a.account.mint.equals(relevantMint) + )?.account.amount as BN, + [connection, wallet, role, relevantMint, tokenAccounts] + ) + + const parclScalingFactor = useParclScalingFactor() ?? 1; + + const totalAmount = personalAmount ?? new BN(0) + + const formattedTotal = useMemo( + () => + mintInfo && totalAmount !== undefined + ? new BigNumber(totalAmount.toString()) + .multipliedBy( + role === 'community' + ? parclScalingFactor + : 1 + ) + .shiftedBy(-mintInfo.decimals) + .integerValue() + .toString() + : undefined, + [totalAmount, mintInfo] + ) + + const tokenName = + getMintMetadata(relevantMint)?.name ?? realm?.account.name ?? '' + + const disabled = + realmConfig?.account.councilTokenConfig.tokenType === + GoverningTokenType.Dormant + + return ( +
+
+
+ {tokenName} + {role === 'council' ? ' Council' : ''} Votes +
+
+
+
+ {formattedTotal ?? 0} +
+
+ + {mintInfo && ( + + )} +
+
+ {children} +
+ ) +} diff --git a/PythVotePlugin/components/PythAccountDetails.tsx b/PythVotePlugin/components/PythAccountDetails.tsx new file mode 100644 index 0000000000..09c81443b1 --- /dev/null +++ b/PythVotePlugin/components/PythAccountDetails.tsx @@ -0,0 +1,142 @@ +import { MintInfo } from '@solana/spl-token' +import BN from 'bn.js' +import useRealm from '@hooks/useRealm' +import { GoverningTokenType } from '@solana/spl-governance' +import { fmtMintAmount } from '@tools/sdk/units' +import { useEffect } from 'react' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { + useUserCommunityTokenOwnerRecord, +} from '@hooks/queries/tokenOwnerRecord' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import VanillaWithdrawTokensButton from '@components/TokenBalance/VanillaWithdrawTokensButton' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' +import PythVotingPower from './PythVotingPower' + +export const PYTH_INSTRUCTIONS = "You can deposit Pyth tokens at https://staking.pyth.network/. If you previously deposited tokens on https://app.realms.today/dao/PYTH, use the button below to withdraw them immediately. Those tokens have no voting power." + +const TokenDeposit = ({ + mint, + inAccountDetails, + setHasGovPower, +}: { + mint: MintInfo | undefined + inAccountDetails?: boolean + setHasGovPower?: (hasGovPower: boolean) => void +}) => { + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const config = useRealmConfigQuery().data?.result + + const relevantTokenConfig = config?.account.communityTokenConfig + const isMembership = + relevantTokenConfig?.tokenType === GoverningTokenType.Membership + + const { realmTokenAccount } = useRealm() + + const depositTokenRecord = ownTokenRecord + const depositTokenAccount = realmTokenAccount + + const hasTokensInWallet = + depositTokenAccount && depositTokenAccount.account.amount.gt(new BN(0)) + + const hasTokensDeposited = + depositTokenRecord && + depositTokenRecord.account.governingTokenDepositAmount.gt(new BN(0)) + + const availableTokens = + depositTokenRecord && mint + ? fmtMintAmount( + mint, + depositTokenRecord.account.governingTokenDepositAmount + ) + : '0' + + useEffect(() => { + if (availableTokens != '0' || hasTokensDeposited || hasTokensInWallet) { + if (setHasGovPower) setHasGovPower(true) + } + }, [availableTokens, hasTokensDeposited, hasTokensInWallet, setHasGovPower]) + + const canShowAvailableTokensMessage = hasTokensInWallet && connected + const tokensToShow = + hasTokensInWallet && depositTokenAccount + ? fmtMintAmount(mint, depositTokenAccount.account.amount) + : hasTokensInWallet + ? availableTokens + : 0 + + // Do not show deposits for mints with zero supply because nobody can deposit anyway + if (!mint || mint.supply.isZero()) { + return null + } + + return ( +
+ {(availableTokens != '0' || inAccountDetails) && ( +
+ +
+ )} + +
+ You have {tokensToShow} {hasTokensDeposited ? `more ` : ``} tokens available to deposit. +
+
+ {PYTH_INSTRUCTIONS} +
+ +
+ {!isMembership && // Membership tokens can't be withdrawn (that is their whole point, actually) + inAccountDetails && ( + + )} +
+
+ ) +} + +const PythAccountDetails = () => { + const mint = useRealmCommunityMintInfoQuery().data?.result + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const hasLoaded = mint + + return ( + <> + {hasLoaded ? ( +
+ {!connected && ( +
+ Connect your wallet to see governance power +
+ )} + {( + + )} +
+ ) : ( + <> +
+
+ + )} + + ) +} + +export default PythAccountDetails diff --git a/PythVotePlugin/components/PythVotingPower.tsx b/PythVotePlugin/components/PythVotingPower.tsx new file mode 100644 index 0000000000..39bc29442c --- /dev/null +++ b/PythVotePlugin/components/PythVotingPower.tsx @@ -0,0 +1,109 @@ +import { BigNumber } from 'bignumber.js' +import { useMemo } from 'react' +import { useRealmQuery } from '@hooks/queries/realm' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import { useConnection } from '@solana/wallet-adapter-react' +import { getPythGovPower } from '@hooks/queries/governancePower' +import { useAsync } from 'react-async-hook' +import BN from 'bn.js' +import { getMintMetadata } from '@components/instructions/programs/splToken' +import VotingPowerPct from '@components/ProposalVotingPower/VotingPowerPct' +import clsx from 'clsx' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { GoverningTokenType } from '@solana/spl-governance' +import usePythScalingFactor from '@hooks/PythNetwork/useScalingFactor' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' + +export const PYTH_INSTRUCTIONS = "You can deposit Pyth tokens at https://staking.pyth.network/. If you previously deposited tokens on https://app.realms.today/dao/PYTH, use the button below to withdraw them immediately. Those tokens have no voting power." + +interface Props { + className?: string + role: 'community' | 'council' + hideIfZero?: boolean + children?: React.ReactNode +} + +export default function PythVotingPower({ + role, + hideIfZero, + children, + ...props +}: Props) { + const realm = useRealmQuery().data?.result + const realmConfig = useRealmConfigQuery().data?.result + + const wallet = useWalletOnePointOh(); + + + const { connection } = useConnection() + + const relevantMint = + role === 'community' + ? realm?.account.communityMint + : realm?.account.config.councilMint + + const mintInfo = useMintInfoByPubkeyQuery(relevantMint).data?.result + + const { result: personalAmount } = useAsync( + async () => wallet?.publicKey && getPythGovPower(connection, wallet?.publicKey), + [connection, wallet] + ) + + const pythScalingFactor: number | undefined = usePythScalingFactor(); + + const totalAmount = personalAmount ?? new BN(0) + + const formattedTotal = useMemo( + () => + mintInfo && totalAmount !== undefined + ? new BigNumber(totalAmount.toString()) + .multipliedBy(pythScalingFactor ?? 1) + .shiftedBy(-mintInfo.decimals) + .integerValue() + .toString() + : undefined, + [totalAmount, mintInfo] + ) + + const tokenName = + getMintMetadata(relevantMint)?.name ?? realm?.account.name ?? '' + + const disabled = + role === 'community' + ? realmConfig?.account.communityTokenConfig.tokenType === + GoverningTokenType.Dormant + : realmConfig?.account.councilTokenConfig.tokenType === + GoverningTokenType.Dormant + + return ( +
+
+
+ {tokenName} + {role === 'council' ? ' Council' : ''} Votes +
+
+
+
+ {formattedTotal ?? 0} +
+
+ + {mintInfo && ( + + )} +
+
+ {children} +
+ ) +} diff --git a/QuadraticPlugin/sdk/api.ts b/QuadraticPlugin/sdk/api.ts new file mode 100644 index 0000000000..1edbff051f --- /dev/null +++ b/QuadraticPlugin/sdk/api.ts @@ -0,0 +1,100 @@ +import { PublicKey } from '@solana/web3.js' +import {Coefficients, QuadraticClient } from '@solana/governance-program-library' +import { + ProgramAccount, + Realm, + SYSTEM_PROGRAM_ID, +} from '@solana/spl-governance' +import { getRegistrarPDA } from '@utils/plugin/accounts' + +// By default, the quadratic plugin will use a function ax-2 + bx - c +// resulting in a vote weight that is the square root of the token balance +// The `a` coefficient is set to 1000, which, assuming the governance token has 6 decimals, +// will result in a vote weight that is the square root of the token balance in major denomination. +// For example, if the token balance is 100, then the vote weight will be: +// sqrt(100 * 10^6) = 10,000 * 10^3 = 10,000,000 = 10 votes +// This should be handled dynamically by the UI in the future. +export const DEFAULT_COEFFICIENTS: Coefficients = [1000, 0, 0] + +export const toAnchorType = (coefficients: Coefficients) => ({ + a: coefficients[0], + b: coefficients[1], + c: coefficients[2], +}) + +export type AnchorParams = { + quadraticCoefficients: { + a: number; + b: number; + c: number; + } +} + +// Create an instruction to create a registrar account for a given realm +export const createQuadraticRegistrarIx = async ( + realm: ProgramAccount, + payer: PublicKey, + quadraticClient: QuadraticClient, + coefficients?: Coefficients, + predecessor?: PublicKey +) => { + const { registrar } = getRegistrarPDA( + realm.pubkey, + realm.account.communityMint, + quadraticClient.program.programId + ) + + const remainingAccounts = predecessor + ? [{ pubkey: predecessor, isSigner: false, isWritable: false }] + : [] + + return quadraticClient!.program.methods + .createRegistrar( + toAnchorType(coefficients || DEFAULT_COEFFICIENTS), + !!predecessor + ) + .accounts({ + registrar, + realm: realm.pubkey, + governanceProgramId: realm.owner, + realmAuthority: realm.account.authority!, + governingTokenMint: realm.account.communityMint!, + payer, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .remainingAccounts(remainingAccounts) + .instruction() +} +// Create an instruction to configure a registrar account for a given realm +export const configureQuadraticRegistrarIx = async ( + realm: ProgramAccount, + quadraticClient: QuadraticClient, + coefficients?: Coefficients, + predecessor?: PublicKey +) => { + const { registrar } = getRegistrarPDA( + realm.pubkey, + realm.account.communityMint, + quadraticClient.program.programId + ) + const remainingAccounts = predecessor + ? [{ pubkey: predecessor, isSigner: false, isWritable: false }] + : [] + return quadraticClient.program.methods + .configureRegistrar( + toAnchorType(coefficients || DEFAULT_COEFFICIENTS), + !!predecessor + ) + .accounts({ + registrar, + realm: realm.pubkey, + realmAuthority: realm.account.authority!, + }) + .remainingAccounts(remainingAccounts) + .instruction() +} + +export const coefficientsEqual = (x: Coefficients, y: Coefficients | undefined): boolean => { + if (!y) return false + return x[0] === y[0] && x[1] === y[1] && x[2] === y[2] +} \ No newline at end of file diff --git a/README.md b/README.md index 823ed208b1..34a1477118 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,7 @@ -# Switchboard Add-in Support +### Using custom Swap API endpoints -## To set this up for development with Switchboard, the first step is to get [this](https://github.com/switchboard-xyz/switchboard-core/blob/main/switchboard_v2/tests/addin-tests.ts) to work. +You can set custom URLs via the configuration for any self-hosted Jupiter APIs, like the [V6 Swap API](https://station.jup.ag/docs/apis/self-hosted) or [Paid Hosted APIs](https://station.jup.ag/docs/apis/self-hosted#paid-hosted-apis) Here is an example: -- [install anchor](https://project-serum.github.io/anchor/getting-started/installation.html#installing-dependencies)[install anchor](https://project-serum.github.io/anchor/getting-started/installation.html#installing-dependencies) if you don't currently have it installed -- navigate to the `switchboard_v2` directory within `switchboard-core` and run `anchor test`. This will build switchboardv2 and run the addin-tests.ts script, which will set up a realm, governance, queue, oracles, permissions, and proposal. -- you will need to make sure the pubkeys of the governance program and switchboard program throughout the codebase are pointed to your local pubkeys of those programs: -- you can determine the pubkeys of the localnet switchboardv2 and governance programs by navigating to `switchboard-core/switchboard_v2/target/deploy` and running `solana-keygen pubkey switchboard_v2-keypair.json` and `solana-keygen pubkey spl_governance-keypair.json` respectively -- You'll need to set the `declare_id!(...)` in Switchboardv2's `lib.rs` to point at your localnet switchboard program's pubkey, and you'll need to set Switchboardv2's `lib.rs` `GOVERNANCE_PID` variable to the spl_governance pubkey. -- you'll also need to ensure that `sbv2.ts` variable GOVERNANCE_PID points at the correct pubkey for your localnet governance program -- when you want to run the UI, start a local validator by running `solana-test-validator`. This will created a directory called `test-ledger` in the location you run the command. -- run the addin test suite, `anchor test` -- start the governance-ui by running `yarn dev` - -## Working on governance-ui - -- most of the work is in `hooks/useRealm.ts` and `hooks/useVotingPlugins.ts` in the governance-ui. The UI work is in `components/TokenBalance` - -# NextJS Typescript Boilerplate - -Bootstrap a developer-friendly NextJS app configured with: - -- [Typescript](https://www.typescriptlang.org/) -- Linting with [ESLint](https://eslint.org/) -- Formatting with [Prettier](https://prettier.io/) -- Linting, typechecking and formatting on by default using [`husky`](https://github.com/typicode/husky) for commit hooks -- Testing with [Jest](https://jestjs.io/) and [`react-testing-library`](https://testing-library.com/docs/react-testing-library/intro) - -## Deploy your own - -Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): - -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-typescript-eslint-jest&project-name=with-typescript-eslint-jest&repository-name=with-typescript-eslint-jest) - -## How to use - -Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: - -```bash -npx create-next-app --example with-typescript-eslint-jest with-typescript-eslint-jest-app -# or -yarn create next-app --example with-typescript-eslint-jest with-typescript-eslint-jest-app ``` - -Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). +NEXT_PUBLIC_JUPTER_SWAP_API_ENDPOINT=https://quote-api.jup.ag/v6 +``` \ No newline at end of file diff --git a/Strategies/components/CreateRefLink.tsx b/Strategies/components/CreateRefLink.tsx deleted file mode 100644 index d00c9746f0..0000000000 --- a/Strategies/components/CreateRefLink.tsx +++ /dev/null @@ -1,220 +0,0 @@ -import { - MangoAccount, - ReferrerIdRecord, - makeRegisterReferrerIdInstruction, - MangoGroup, - INFO_LEN, -} from '@blockworks-foundation/mango-client' -import Button, { LinkButton } from '@components/Button' -import Input from '@components/inputs/Input' -import Tooltip from '@components/Tooltip' -import { DuplicateIcon } from '@heroicons/react/outline' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { PublicKey, Transaction } from '@solana/web3.js' -import { notify } from '@utils/notifications' -import { sendTransaction } from '@utils/send' -import { useState, useEffect } from 'react' -import useWalletStore from 'stores/useWalletStore' -import { tryGetMangoAccount } from 'Strategies/protocols/mango/tools' -import { MarketStore } from 'Strategies/store/marketStore' -const minMngoToCreateLink = 10000 -const CreateRefForm = ({ - selectedMangoAccount, - market, - mint, -}: { - selectedMangoAccount: MangoAccount - market: MarketStore - mint: PublicKey -}) => { - const connection = useWalletStore((s) => s.connection) - - const link = - connection.cluster === 'devnet' - ? `http://devnet.mango.markets/?ref=` - : `https://trade.mango.markets/?ref` - const depositIndex = market.group!.tokens.findIndex( - (x) => x.mint.toBase58() === mint.toBase58() - ) - const { canUseTransferInstruction } = useGovernanceAssets() - - const wallet = useWalletStore((s) => s.current) - const currentPosition = selectedMangoAccount - .getUiDeposit( - market.cache!.rootBankCache[depositIndex], - market.group!, - depositIndex - ) - .toNumber() - const [existingLinks, setExistingLinks] = useState([]) - const [linkGenerated, setLinkGenerated] = useState(false) - const [linkName, setLinkName] = useState('') - const connected = useWalletStore((s) => s.connected) - const handleCreateLink = async () => { - setLinkGenerated(false) - try { - const signers = [] - const programId = market.client!.programId - const mangoGroup = market.group - const { referrerPda, encodedReferrerId } = await getReferrerPda( - mangoGroup!, - linkName, - programId - ) - const instruction = makeRegisterReferrerIdInstruction( - programId, - mangoGroup!.publicKey, - selectedMangoAccount!.publicKey, - referrerPda, - wallet!.publicKey!, - encodedReferrerId - ) - - const transaction = new Transaction() - transaction.add(instruction) - await sendTransaction({ - transaction, - wallet: wallet!, - connection: connection.current, - signers, - sendingMessage: 'Creating ref link', - successMessage: 'Ref link created', - }) - setLinkGenerated(true) - } catch (e) { - setLinkGenerated(false) - notify({ type: 'error', message: "Can't generate link" }) - } - } - const getReferrerPda = async ( - mangoGroup: MangoGroup, - referrerId: string, - programId: PublicKey - ): Promise<{ referrerPda: PublicKey; encodedReferrerId: Buffer }> => { - const encoded = Buffer.from(referrerId, 'utf8') - if (encoded.length > INFO_LEN) { - throw new Error( - `info string too long. Must be less than or equal to ${INFO_LEN} bytes` - ) - } - - const encodedReferrerId = Buffer.concat([ - encoded, - Buffer.alloc(INFO_LEN - encoded.length, 0), - ]) - - // Generate the PDA pubkey - const [referrerIdRecordPk] = await PublicKey.findProgramAddress( - [ - mangoGroup.publicKey.toBytes(), - new Buffer('ReferrerIdRecord', 'utf-8'), - encodedReferrerId, - ], - programId - ) - - return { referrerPda: referrerIdRecordPk, encodedReferrerId } - } - useEffect(() => { - const getRefLinks = async () => { - const client = market.client - const mangoAccountPk = selectedMangoAccount!.publicKey - const account = await tryGetMangoAccount(market, mangoAccountPk) - if (account) { - const referrerIds = await client?.getReferrerIdsForMangoAccount(account) - if (referrerIds) { - setExistingLinks(referrerIds) - } - } - } - if (selectedMangoAccount) { - getRefLinks() - } else { - setExistingLinks([]) - } - setLinkName('') - }, [selectedMangoAccount]) - return ( -
- setLinkName(e.target.value)} - /> - - {linkGenerated || existingLinks.length > 0 ? ( -
- {linkGenerated && ( -
-
-
- {link} - {linkName} -
-
-
- { - navigator.clipboard.writeText(`${link}${linkName}`) - }} - > - - -
-
- )} - {existingLinks.map((x) => ( -
-
-
- {link} - {x.referrerId} -
-
-
- { - navigator.clipboard.writeText(`${link}${x.referrerId}`) - }} - > - - -
-
- ))} -
- ) : null} -
- ) -} - -export default CreateRefForm diff --git a/Strategies/components/Delegate.tsx b/Strategies/components/Delegate.tsx deleted file mode 100644 index 62843358f5..0000000000 --- a/Strategies/components/Delegate.tsx +++ /dev/null @@ -1,179 +0,0 @@ -import { - MangoAccount, - makeSetDelegateInstruction, -} from '@blockworks-foundation/mango-client' -import AdditionalProposalOptions from '@components/AdditionalProposalOptions' -import Button from '@components/Button' -import Input from '@components/inputs/Input' -import Loading from '@components/Loading' -import Tooltip from '@components/Tooltip' -import useCreateProposal from '@hooks/useCreateProposal' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import useQueryContext from '@hooks/useQueryContext' -import useRealm from '@hooks/useRealm' -import { - ProgramAccount, - Governance, - getInstructionDataFromBase64, - serializeInstructionToBase64, -} from '@solana/spl-governance' -import { PublicKey } from '@solana/web3.js' -import { abbreviateAddress } from '@utils/formatting' -import { validateInstruction } from '@utils/instructionTools' -import { notify } from '@utils/notifications' -import { getValidatedPublickKey } from '@utils/validations' -import { InstructionDataWithHoldUpTime } from 'actions/createProposal' -import { useRouter } from 'next/router' -import { useState } from 'react' -import { MarketStore } from 'Strategies/store/marketStore' -import * as yup from 'yup' - -const DelegateForm = ({ - selectedMangoAccount, - governance, - market, -}: { - selectedMangoAccount: MangoAccount - governance: ProgramAccount - market: MarketStore -}) => { - const router = useRouter() - const { symbol } = useRealm() - const { fmtUrlWithCluster } = useQueryContext() - const { handleCreateProposal } = useCreateProposal() - const { canUseTransferInstruction } = useGovernanceAssets() - const groupConfig = market.groupConfig! - const [voteByCouncil, setVoteByCouncil] = useState(false) - const [isLoading, setIsLoading] = useState(false) - const [form, setForm] = useState({ - title: '', - description: '', - delegateAddress: '', - }) - const [formErrors, setFormErrors] = useState({}) - const proposalTitle = `Set delegate for MNGO account: ${abbreviateAddress( - selectedMangoAccount?.publicKey - )}` - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - - const handleProposeDelegate = async () => { - const isValid = await validateInstruction({ schema, form, setFormErrors }) - if (!isValid) { - return - } - setIsLoading(true) - const delegateMangoAccount = makeSetDelegateInstruction( - groupConfig.mangoProgramId, - groupConfig.publicKey, - selectedMangoAccount!.publicKey, - governance!.pubkey, - new PublicKey(form.delegateAddress) - ) - try { - const instructionData: InstructionDataWithHoldUpTime = { - data: getInstructionDataFromBase64( - serializeInstructionToBase64(delegateMangoAccount) - ), - holdUpTime: governance!.account!.config.minInstructionHoldUpTime, - prerequisiteInstructions: [], - } - const proposalAddress = await handleCreateProposal({ - title: form.title || proposalTitle, - description: form.description, - instructionsData: [instructionData], - governance: governance!, - voteByCouncil, - }) - const url = fmtUrlWithCluster( - `/dao/${symbol}/proposal/${proposalAddress}` - ) - router.push(url) - } catch (e) { - console.log(e) - notify({ type: 'error', message: "Can't create proposal" }) - } - } - const schema = yup.object().shape({ - delegateAddress: yup - .string() - .test( - 'accountTests', - 'Delegate address validation error', - function (val: string) { - if (val) { - try { - return !!getValidatedPublickKey(val) - } catch (e) { - console.log(e) - return this.createError({ - message: `${e}`, - }) - } - } else { - return this.createError({ - message: `Delegate address is required`, - }) - } - } - ), - }) - return ( -
- - handleSetForm({ - value: e.target.value, - propertyName: 'delegateAddress', - }) - } - /> - - handleSetForm({ - value: evt.target.value, - propertyName: 'title', - }) - } - setDescription={(evt) => - handleSetForm({ - value: evt.target.value, - propertyName: 'description', - }) - } - voteByCouncil={voteByCouncil} - setVoteByCouncil={setVoteByCouncil} - /> - -
- ) -} - -export default DelegateForm diff --git a/Strategies/components/DepositModal.tsx b/Strategies/components/DepositModal.tsx index f8c23c3da4..f8e3e9a343 100644 --- a/Strategies/components/DepositModal.tsx +++ b/Strategies/components/DepositModal.tsx @@ -1,10 +1,9 @@ import Modal from '@components/Modal' import ModalHeader from './ModalHeader' import SolendModalContent from './SolendModalContent' -import MangoDeposit from './MangoDepositComponent' -import BigNumber from 'bignumber.js' import { SolendStrategy } from 'Strategies/types/types' -import EverlendModalContent from './EverlendModalContent' +import { PsyFiStrategies } from './psyfi' +import { AssetAccount } from '@utils/uiTypes/assets' const DepositModal = ({ onClose, @@ -15,15 +14,20 @@ const DepositModal = ({ protocolLogoSrc, handledTokenName, strategyName, - currentPosition, createProposalFcn, - mangoAccounts, governedTokenAccount, +}: { + onClose: () => void + proposedInvestment: any + handledMint: string + apy: string + protocolName: string + protocolLogoSrc: string + handledTokenName: string + strategyName: string + createProposalFcn: any + governedTokenAccount: AssetAccount }) => { - const currentPositionFtm = new BigNumber( - currentPosition.toFixed(0) - ).toFormat() - return ( ) : null} - {protocolName === 'Mango' ? ( - - ) : null} - {protocolName === 'Everlend' ? ( - { - const [selectedTab, setSelectedTab] = useState(Tabs.DEPOSIT) - const [depositedAmount, setDepositedAmount] = useState(0) - const [maxDepositAmount, setMaxDepositAmount] = useState(0) - const tabs = Object.values(Tabs) - const connection = useWalletStore((s) => s.connection) - - const isSol = governedTokenAccount.isSol - const owner = isSol - ? governedTokenAccount!.pubkey - : governedTokenAccount!.extensions!.token!.account.owner - - useEffect(() => { - const loadMaxAmount = async () => { - const poolMintATA = await findAssociatedTokenAccount( - owner, - new PublicKey(proposedInvestment.poolMint) - ) - let poolMintATABalance = 0 - let tokenMintATABalance = 0 - try { - const fetchedTokenMintATABalance = await connection.current.getTokenAccountBalance( - poolMintATA - ) - - poolMintATABalance = calcUserTokenBalanceByPoolToken( - Number(fetchedTokenMintATABalance.value.uiAmount), - proposedInvestment.decimals, - proposedInvestment.rateEToken, - false - ) - } catch (e) { - console.log(e) - } - try { - if (isSol) { - const fetchedBalance = await connection.current.getBalance(owner) - tokenMintATABalance = lamportsToSol(fetchedBalance) - } else { - const fetchedBalance = await connection.current.getTokenAccountBalance( - governedTokenAccount!.pubkey - ) - tokenMintATABalance = Number(fetchedBalance.value.uiAmount) - } - } catch (e) { - console.log(e) - } - setDepositedAmount(poolMintATABalance) - setMaxDepositAmount(tokenMintATABalance) - } - loadMaxAmount() - }, [proposedInvestment, handledMint]) - - return ( -
-
- setSelectedTab(tab)} - values={tabs} - /> -
- {selectedTab === Tabs.DEPOSIT && ( - - )} - {selectedTab === Tabs.WITHDRAW && ( - - )} -
- ) -} - -export default EverlendModalContent diff --git a/Strategies/components/MangoDepositComponent.tsx b/Strategies/components/MangoDepositComponent.tsx deleted file mode 100644 index 73bfd0a86e..0000000000 --- a/Strategies/components/MangoDepositComponent.tsx +++ /dev/null @@ -1,491 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import { - MangoAccount, - MangoAccountLayout, - PublicKey, -} from '@blockworks-foundation/mango-client' -import Button, { LinkButton } from '@components/Button' -import Input from '@components/inputs/Input' -import Loading from '@components/Loading' -import Tooltip from '@components/Tooltip' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import useQueryContext from '@hooks/useQueryContext' -import useRealm from '@hooks/useRealm' -import { getProgramVersionForRealm } from '@models/registry/api' -import { - getNativeTreasuryAddress, - RpcContext, - withCreateNativeTreasury, -} from '@solana/spl-governance' -import { SystemProgram, TransactionInstruction } from '@solana/web3.js' -import { - fmtMintAmount, - getMintDecimalAmount, - getMintMinAmountAsDecimal, - parseMintNaturalAmountFromDecimal, -} from '@tools/sdk/units' -import { abbreviateAddress, precision } from '@utils/formatting' -import tokenService from '@utils/services/token' -import BigNumber from 'bignumber.js' -import { useRouter } from 'next/router' -import { useEffect, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' -import useMarketStore, { MarketStore } from 'Strategies/store/marketStore' -import { HandleCreateProposalWithStrategy } from 'Strategies/types/types' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import ButtonGroup from '@components/ButtonGroup' -import Switch from '@components/Switch' -import Select from '@components/inputs/Select' -import CreateRefForm from './CreateRefLink' -import DelegateForm from './Delegate' -import AdditionalProposalOptions from '@components/AdditionalProposalOptions' -import { validateInstruction } from '@utils/instructionTools' -import * as yup from 'yup' -import { getValidatedPublickKey } from '@utils/validations' -import { AssetAccount } from '@utils/uiTypes/assets' -import WithdrawModal from './WithdrawModal' - -const DEPOSIT = 'Deposit' -const CREATE_REF_LINK = 'Create Referral Link' -const DELEGATE_ACCOUNT = 'Delegate' -const WITHDRAW = 'Withdraw' - -const MangoDepositComponent = ({ - handledMint, - currentPositionFtm, - createProposalFcn, - mangoAccounts, - governedTokenAccount, -}: { - handledMint: string - currentPositionFtm: string - createProposalFcn: HandleCreateProposalWithStrategy - mangoAccounts: MangoAccount[] - governedTokenAccount: AssetAccount -}) => { - const router = useRouter() - const { fmtUrlWithCluster } = useQueryContext() - const { - proposals, - realmInfo, - realm, - ownVoterWeight, - mint, - councilMint, - symbol, - config, - } = useRealm() - const [isDepositing, setIsDepositing] = useState(false) - const [ - selectedMangoAccount, - setSelectedMangoAccount, - ] = useState( - mangoAccounts.length ? mangoAccounts[0] : null - ) - const [voteByCouncil, setVoteByCouncil] = useState(false) - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const market = useMarketStore((s) => s) - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const tokenInfo = tokenService.getTokenInfo(handledMint) - const { canUseTransferInstruction } = useGovernanceAssets() - const treasuryAmount = governedTokenAccount.extensions.amount! - const mintInfo = governedTokenAccount.extensions?.mint?.account - const [form, setForm] = useState({ - title: '', - description: '', - delegateAddress: '', - delegateDeposit: false, - amount: '', - }) - const [formErrors, setFormErrors] = useState({}) - const proposalTitle = `Deposit ${form.amount} ${ - tokenService.getTokenInfo( - governedTokenAccount.extensions.mint!.publicKey.toBase58() - )?.symbol || 'tokens' - } to Mango account` - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - const [proposalType, setProposalType] = useState('Deposit') - const mintMinAmount = mintInfo ? getMintMinAmountAsDecimal(mintInfo) : 1 - const maxAmount = mintInfo - ? getMintDecimalAmount(mintInfo, treasuryAmount) - : new BigNumber(0) - const maxAmountFtm = fmtMintAmount(mintInfo, treasuryAmount) - const currentPrecision = precision(mintMinAmount) - const group = market!.group! - const depositIndex = group.tokens.findIndex( - (x) => x.mint.toBase58() === handledMint - ) - const tabs = [ - { val: DEPOSIT, isVisible: true }, - { val: CREATE_REF_LINK, isVisible: selectedMangoAccount !== null }, - { val: DELEGATE_ACCOUNT, isVisible: selectedMangoAccount !== null }, - { val: WITHDRAW, isVisible: selectedMangoAccount !== null }, - ] - .filter((x) => x.isVisible) - .map((x) => x.val) - const validateAmountOnBlur = () => { - handleSetForm({ - propertyName: 'amount', - value: parseFloat( - Math.max( - Number(mintMinAmount), - Math.min(Number(Number.MAX_SAFE_INTEGER), Number(form.amount)) - ).toFixed(currentPrecision) - ), - }) - } - useEffect(() => { - if (selectedMangoAccount === null) { - setProposalType(DEPOSIT) - } - }, [selectedMangoAccount]) - const handleSolPayment = async () => { - const instructions: TransactionInstruction[] = [] - const toAddress = await getNativeTreasuryAddress( - realm!.owner, - governedTokenAccount!.governance!.pubkey - ) - const hasSolAccount = await connection.current.getParsedAccountInfo( - toAddress - ) - if (!hasSolAccount.value) { - await withCreateNativeTreasury( - instructions, - realm!.owner, - realmInfo?.programVersion!, - governedTokenAccount!.governance!.pubkey, - wallet!.publicKey! - ) - } - - const minRentAmount = await connection.current.getMinimumBalanceForRentExemption( - MangoAccountLayout.span - ) - - const transferIx = SystemProgram.transfer({ - fromPubkey: wallet!.publicKey!, - toPubkey: toAddress, - lamports: minRentAmount, - }) - instructions.push(transferIx) - return instructions - } - const handleDeposit = async () => { - const isValid = await validateInstruction({ schema, form, setFormErrors }) - if (!isValid) { - return - } - try { - setIsDepositing(true) - const prerequisiteInstructions: TransactionInstruction[] = [] - const mangoAccountPk = selectedMangoAccount?.publicKey || null - if (!mangoAccountPk) { - const solAccountInstruction = await handleSolPayment() - prerequisiteInstructions.push(...solAccountInstruction) - } - const rpcContext = new RpcContext( - new PublicKey(realm!.owner.toString()), - getProgramVersionForRealm(realmInfo!), - wallet!, - connection.current, - connection.endpoint - ) - const mintAmount = parseMintNaturalAmountFromDecimal( - form.amount!, - governedTokenAccount.extensions!.mint!.account.decimals - ) - const ownTokenRecord = ownVoterWeight.getTokenRecordToCreateProposal( - governedTokenAccount!.governance!.account.config, - voteByCouncil - ) - const defaultProposalMint = voteByCouncil - ? realm?.account.config.councilMint - : !mint?.supply.isZero() || - config?.account.communityTokenConfig.maxVoterWeightAddin - ? realm!.account.communityMint - : !councilMint?.supply.isZero() - ? realm!.account.config.councilMint - : undefined - - const proposalAddress = await createProposalFcn( - rpcContext, - handledMint, - { - ...form, - mintAmount, - mangoAccountPk, - mangoAccounts, - proposalCount: Object.keys(proposals).length, - }, - realm!, - governedTokenAccount!, - ownTokenRecord, - defaultProposalMint!, - governedTokenAccount!.governance!.account!.proposalCount, - prerequisiteInstructions, - false, - market, - client - ) - const url = fmtUrlWithCluster( - `/dao/${symbol}/proposal/${proposalAddress}` - ) - router.push(url) - } catch (e) { - console.log(e) - } - setIsDepositing(false) - } - const schema = yup.object().shape({ - delegateAddress: yup - .string() - .test( - 'accountTests', - 'Delegate address validation error', - function (val: string) { - if (!form.delegateDeposit) { - return true - } - if (val) { - try { - return !!getValidatedPublickKey(val) - } catch (e) { - console.log(e) - return this.createError({ - message: `${e}`, - }) - } - } else { - return this.createError({ - message: `Delegate address is required`, - }) - } - } - ), - amount: yup.number().required('Amount is required').min(mintMinAmount), - }) - return ( -
- -
- setProposalType(v)} - values={tabs} - /> -
- {proposalType === DELEGATE_ACCOUNT && ( - - )} - {proposalType === CREATE_REF_LINK && ( - - )} - {proposalType === WITHDRAW && ( - - )} - - {proposalType === DEPOSIT && ( -
-
- Amount -
- Bal: {maxAmountFtm} - - handleSetForm({ - propertyName: 'amount', - value: maxAmount.toNumber(), - }) - } - className="font-bold ml-2 text-primary-light" - > - Max - -
-
- - handleSetForm({ propertyName: 'amount', value: e.target.value }) - } - step={mintMinAmount} - onBlur={validateAmountOnBlur} - /> - {selectedMangoAccount === null && ( - <> -
- Delegate deposit - - handleSetForm({ - propertyName: 'delegateDeposit', - value: checked, - }) - } - /> -
- {form.delegateDeposit && ( - - handleSetForm({ - propertyName: 'delegateAddress', - value: e.target.value, - }) - } - /> - )} - - )} - - handleSetForm({ - value: evt.target.value, - propertyName: 'title', - }) - } - setDescription={(evt) => - handleSetForm({ - value: evt.target.value, - propertyName: 'description', - }) - } - voteByCouncil={voteByCouncil} - setVoteByCouncil={setVoteByCouncil} - /> -
-
- Current Deposits - - {currentPositionFtm || 0}{' '} - - {tokenInfo?.symbol} - - -
-
- Proposed Deposit - - {form.amount?.toLocaleString() || ( - Enter an amount - )}{' '} - - {form.amount && tokenInfo?.symbol} - - -
-
- -
- )} -
- ) -} - -export default MangoDepositComponent - -const MangoAccountItem = ({ - value, - market, - depositIndex, -}: { - value: MangoAccount | null - market: MarketStore - depositIndex: number -}) => { - const group = market!.group! - return value ? ( -
-
{abbreviateAddress(value.publicKey)}
-
- Deposit:{' '} - {new BigNumber( - value - .getUiDeposit( - market.cache!.rootBankCache[depositIndex], - group, - depositIndex - ) - .toNumber() - ).toFormat(2)} -
- {value.delegate.toBase58() && ( -
Delegate: {abbreviateAddress(value.delegate)}
- )} -
- ) : ( -
Create new account
- ) -} diff --git a/Strategies/components/WithdrawModal.tsx b/Strategies/components/WithdrawModal.tsx deleted file mode 100644 index 57fa7628c2..0000000000 --- a/Strategies/components/WithdrawModal.tsx +++ /dev/null @@ -1,405 +0,0 @@ -import { - BN, - makeCloseSpotOpenOrdersInstruction, - makeWithdraw2Instruction, - MangoAccount, - PublicKey, -} from '@blockworks-foundation/mango-client' -import AdditionalProposalOptions from '@components/AdditionalProposalOptions' -import Button from '@components/Button' -import Input from '@components/inputs/Input' -import { WSOL_MINT_PK } from '@components/instructions/tools' -import Loading from '@components/Loading' -import Tooltip from '@components/Tooltip' -import { CheckCircleIcon } from '@heroicons/react/outline' -import useCreateProposal from '@hooks/useCreateProposal' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import useQueryContext from '@hooks/useQueryContext' -import useRealm from '@hooks/useRealm' -import { - closeAccount, - initializeAccount, - WRAPPED_SOL_MINT, -} from '@project-serum/serum/lib/token-instructions' -import { - getInstructionDataFromBase64, - Governance, - ProgramAccount, - serializeInstructionToBase64, - TOKEN_PROGRAM_ID, -} from '@solana/spl-governance' -import { ASSOCIATED_TOKEN_PROGRAM_ID, Token } from '@solana/spl-token' -import { - Keypair, - LAMPORTS_PER_SOL, - SystemProgram, - TransactionInstruction, -} from '@solana/web3.js' -import { tryParsePublicKey } from '@tools/core/pubkey' -import { parseMintNaturalAmountFromDecimal } from '@tools/sdk/units' -import { getATA } from '@utils/ataTools' -import { abbreviateAddress } from '@utils/formatting' -import { validateInstruction } from '@utils/instructionTools' -import { notify } from '@utils/notifications' -import tokenService from '@utils/services/token' -import { tryGetMint, tryGetTokenAccount } from '@utils/tokens' -import { - getValidateAccount, - getValidatedPublickKey, - validateDoseTokenAccountMatchMint, -} from '@utils/validations' -import { InstructionDataWithHoldUpTime } from 'actions/createProposal' -import BigNumber from 'bignumber.js' -import { useRouter } from 'next/router' -import { useState } from 'react' -import useWalletStore from 'stores/useWalletStore' -import { MarketStore } from 'Strategies/store/marketStore' -import * as yup from 'yup' - -const emptyPk = '11111111111111111111111111111111' - -const WithdrawModal = ({ - selectedMangoAccount, - governance, - market, -}: { - selectedMangoAccount: MangoAccount - governance: ProgramAccount - market: MarketStore -}) => { - const { canUseTransferInstruction } = useGovernanceAssets() - const router = useRouter() - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const { symbol } = useRealm() - const group = market.group! - const [isLoading, setIsLoading] = useState(false) - const [form, setForm] = useState({ - title: '', - description: '', - withdrawAddress: '', - amount: '', - }) - const [voteByCouncil, setVoteByCouncil] = useState(false) - const [depositIdx, setDepositIdx] = useState( - selectedMangoAccount.deposits.findIndex((x) => !x.isZero()) || 0 - ) - const [formErrors, setFormErrors] = useState({}) - const selectedDepositMInt = group?.tokens[depositIdx]?.mint - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - const { handleCreateProposal } = useCreateProposal() - const { fmtUrlWithCluster } = useQueryContext() - const proposalTitle = `Withdraw from mango account to: ${ - form && tryParsePublicKey(form.withdrawAddress) - ? abbreviateAddress(new PublicKey(form.withdrawAddress)) - : '' - }` - const schema = yup.object().shape({ - withdrawAddress: yup - .string() - .test( - 'addressTest', - 'Address validation error', - async function (val: string) { - if (val) { - try { - const currentConnection = connection.current - const pubKey = getValidatedPublickKey(val) - const account = await getValidateAccount( - currentConnection, - pubKey - ) - if (account?.value !== null) { - const tokenAccount = await tryGetTokenAccount( - currentConnection, - pubKey - ) - if (tokenAccount && selectedDepositMInt) { - await validateDoseTokenAccountMatchMint( - tokenAccount.account, - selectedDepositMInt - ) - } - } - return true - } catch (e) { - console.log(e) - return this.createError({ - message: `${e}`, - }) - } - } else { - return this.createError({ - message: `Address is required`, - }) - } - } - ), - amount: yup.string().required('Amount is required'), - }) - const handlePropose = async (idx: number) => { - const isValid = await validateInstruction({ schema, form, setFormErrors }) - if (!isValid) { - return - } - const mintPk = group?.tokens[idx].mint - const isWSolMint = mintPk.toBase58() === WSOL_MINT_PK.toBase58() - const tokenIndex = group.getTokenIndex(mintPk) - const publicKey = - group?.rootBankAccounts?.[tokenIndex]?.nodeBankAccounts[0].publicKey - const vault = - group?.rootBankAccounts?.[tokenIndex]?.nodeBankAccounts[0].vault - //address from form can be changed to ata during code run if needed - //or wsol address if we withdraw sol - let address = new PublicKey(form.withdrawAddress) - const mintInfo = await tryGetMint(connection.current, mintPk) - //can be changed if WSol mint winch will be transformed to SOL - let mintAmount = parseMintNaturalAmountFromDecimal( - form.amount!, - mintInfo!.account.decimals! - ) - let wrappedSolAccount: null | Keypair = null - const prerequisiteInstructions: TransactionInstruction[] = [] - if (isWSolMint) { - mintAmount = Number(form.amount) * LAMPORTS_PER_SOL - wrappedSolAccount = new Keypair() - address = wrappedSolAccount.publicKey - const space = 165 - const rent = await connection.current.getMinimumBalanceForRentExemption( - space, - 'processed' - ) - prerequisiteInstructions.push( - SystemProgram.createAccount({ - fromPubkey: wallet!.publicKey!, - newAccountPubkey: wrappedSolAccount?.publicKey, - lamports: rent, - space: space, - programId: TOKEN_PROGRAM_ID, - }), - initializeAccount({ - account: wrappedSolAccount?.publicKey, - mint: WRAPPED_SOL_MINT, - owner: new PublicKey(form.withdrawAddress), - }) - ) - } else { - //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: address, - mintPK: mintPk, - wallet: wallet!, - } - ) - address = receiverAddress - 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 - new PublicKey(form.withdrawAddress), // owner of token account - wallet!.publicKey! // fee payer - ) - ) - } - } - - setIsLoading(true) - const proposalInstructions: InstructionDataWithHoldUpTime[] = [] - for (const i in selectedMangoAccount.spotOpenOrders) { - if (selectedMangoAccount.spotOpenOrders[i].toBase58() !== emptyPk) { - const closeOpenOrders = makeCloseSpotOpenOrdersInstruction( - market.client!.programId, - group.publicKey, - selectedMangoAccount.publicKey, - selectedMangoAccount.owner, - group.dexProgramId, - selectedMangoAccount.spotOpenOrders[i], - group.spotMarkets[i].spotMarket, - group.signerKey, - true - ) - const closeInstruction: InstructionDataWithHoldUpTime = { - data: getInstructionDataFromBase64( - serializeInstructionToBase64(closeOpenOrders) - ), - holdUpTime: governance!.account!.config.minInstructionHoldUpTime, - prerequisiteInstructions: [], - } - proposalInstructions.push(closeInstruction) - } - } - - const instruction = makeWithdraw2Instruction( - market.client!.programId, - group.publicKey, - selectedMangoAccount.publicKey, - selectedMangoAccount.owner, - group.mangoCache, - group.tokens[tokenIndex].rootBank, - publicKey!, - vault!, - address, - group.signerKey, - [], - new BN(mintAmount), - false - ) - const instructionData: InstructionDataWithHoldUpTime = { - data: getInstructionDataFromBase64( - serializeInstructionToBase64(instruction) - ), - holdUpTime: governance!.account!.config.minInstructionHoldUpTime, - prerequisiteInstructions: prerequisiteInstructions, - prerequisiteInstructionsSigners: wrappedSolAccount - ? [wrappedSolAccount] - : [], - chunkSplitByDefault: true, - chunkBy: 1, - } - proposalInstructions.push(instructionData) - if ( - wrappedSolAccount && - (selectedMangoAccount.owner.toBase58() === form.withdrawAddress || - selectedMangoAccount.owner.toBase58() === governance.pubkey.toBase58()) - ) { - const closeAobInstruction = closeAccount({ - source: wrappedSolAccount.publicKey, - destination: new PublicKey(form.withdrawAddress), - owner: new PublicKey(form.withdrawAddress), - }) - const closeAobInstructionData: InstructionDataWithHoldUpTime = { - data: getInstructionDataFromBase64( - serializeInstructionToBase64(closeAobInstruction) - ), - holdUpTime: governance!.account!.config.minInstructionHoldUpTime, - prerequisiteInstructions: [], - prerequisiteInstructionsSigners: [], - chunkSplitByDefault: true, - chunkBy: 1, - } - proposalInstructions.push(closeAobInstructionData) - } - - try { - const proposalAddress = await handleCreateProposal({ - title: form.title || proposalTitle, - description: form.description, - instructionsData: [...proposalInstructions], - governance: governance!, - voteByCouncil, - }) - const url = fmtUrlWithCluster( - `/dao/${symbol}/proposal/${proposalAddress}` - ) - router.push(url) - } catch (e) { - console.log(e) - notify({ type: 'error', message: "Can't create proposal" }) - } - setIsLoading(false) - } - return ( -
- {selectedMangoAccount?.deposits.map((x, idx) => { - const mint = group?.tokens[idx].mint - const tokenInfo = tokenService.getTokenInfo(mint!.toBase58()) - const symbol = tokenInfo?.symbol - return !x.isZero() ? ( -
setDepositIdx(idx)} - > -
- {' '} - {new BigNumber( - selectedMangoAccount - .getUiDeposit(market.cache!.rootBankCache[idx], group!, idx) - .toNumber() - ).toFormat(2)}{' '} - - {symbol ? symbol : abbreviateAddress(mint)} - -
- {idx === depositIdx && ( - - )} -
- ) : null - })} -
- - handleSetForm({ - value: e.target.value, - propertyName: 'withdrawAddress', - }) - } - /> - - handleSetForm({ - value: e.target.value, - propertyName: 'amount', - }) - } - /> - - handleSetForm({ - value: evt.target.value, - propertyName: 'title', - }) - } - setDescription={(evt) => - handleSetForm({ - value: evt.target.value, - propertyName: 'description', - }) - } - voteByCouncil={voteByCouncil} - setVoteByCouncil={setVoteByCouncil} - /> -
- -
- ) -} - -export default WithdrawModal diff --git a/Strategies/components/everlend/EverlendDeposit.tsx b/Strategies/components/everlend/EverlendDeposit.tsx deleted file mode 100644 index 2ca1681ddc..0000000000 --- a/Strategies/components/everlend/EverlendDeposit.tsx +++ /dev/null @@ -1,246 +0,0 @@ -import Button, { LinkButton } from '@components/Button' -import Tooltip from '@components/Tooltip' -import Input from '@components/inputs/Input' -import { useState } from 'react' -import { useRouter } from 'next/router' -import useQueryContext from '@hooks/useQueryContext' -import useRealm from '@hooks/useRealm' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import useWalletStore from 'stores/useWalletStore' -import tokenService from '@utils/services/token' - -import { - getMintMinAmountAsDecimal, - getMintNaturalAmountFromDecimalAsBN, -} from '@tools/sdk/units' -import { RpcContext } from '@solana/spl-governance' -import { PublicKey } from '@solana/web3.js' -import { getProgramVersionForRealm } from '@models/registry/api' -import { AssetAccount } from '@utils/uiTypes/assets' -import { CreateEverlendProposal } from '../../protocols/everlend/tools' -import AdditionalProposalOptions from '@components/AdditionalProposalOptions' -import * as yup from 'yup' -import { precision } from '@utils/formatting' -import { validateInstruction } from '@utils/instructionTools' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import Loading from '@components/Loading' - -interface IProps { - proposedInvestment - handledMint: string - createProposalFcn: CreateEverlendProposal - governedTokenAccount: AssetAccount - depositedAmount: number - maxDepositAmount: number -} - -const EverlendDeposit = ({ - proposedInvestment, - createProposalFcn, - governedTokenAccount, - depositedAmount, - maxDepositAmount, -}: IProps) => { - const [amount, setAmount] = useState(0) - const tokenSymbol = tokenService.getTokenInfo( - governedTokenAccount.extensions.mint!.publicKey.toBase58() - )?.symbol - - const proposalTitle = `Deposit ${amount} ${ - tokenSymbol || 'tokens' - } to the Everlend pool` - - const [proposalInfo, setProposalInfo] = useState({ - title: '', - description: '', - }) - const [formErrors, setFormErrors] = useState({}) - const [isDepositing, setIsDepositing] = useState(false) - const router = useRouter() - const { fmtUrlWithCluster } = useQueryContext() - const { - realmInfo, - realm, - mint, - councilMint, - ownVoterWeight, - symbol, - config, - } = useRealm() - const [voteByCouncil, setVoteByCouncil] = useState(false) - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - - const { canUseTransferInstruction } = useGovernanceAssets() - - const mintInfo = governedTokenAccount.extensions?.mint?.account - - const mintMinAmount = mintInfo ? getMintMinAmountAsDecimal(mintInfo) : 1 - const currentPrecision = precision(mintMinAmount) - const maxAmountFormatted = maxDepositAmount.toFixed(4) - - const handleDeposit = async () => { - const isValid = await validateInstruction({ - schema, - form: { amount }, - setFormErrors, - }) - if (!isValid) { - return - } - try { - setIsDepositing(true) - const rpcContext = new RpcContext( - new PublicKey(realm!.owner), - getProgramVersionForRealm(realmInfo!), - wallet!, - connection.current, - connection.endpoint - ) - const ownTokenRecord = ownVoterWeight.getTokenRecordToCreateProposal( - governedTokenAccount!.governance!.account.config, - voteByCouncil - ) - const defaultProposalMint = voteByCouncil - ? realm?.account.config.councilMint - : !mint?.supply.isZero() || - config?.account.communityTokenConfig.maxVoterWeightAddin - ? realm!.account.communityMint - : !councilMint?.supply.isZero() - ? realm!.account.config.councilMint - : undefined - - const proposalAddress = await createProposalFcn( - rpcContext, - { - title: proposalInfo.title || proposalTitle, - description: proposalInfo.description, - amountFmt: String(amount), - bnAmount: getMintNaturalAmountFromDecimalAsBN( - amount, - governedTokenAccount.extensions.mint!.account.decimals - ), - action: 'Deposit', - poolPubKey: proposedInvestment.poolPubKey, - tokenMint: proposedInvestment.handledMint, - poolMint: proposedInvestment.poolMint, - }, - realm!, - governedTokenAccount!, - ownTokenRecord, - defaultProposalMint!, - governedTokenAccount!.governance!.account!.proposalCount, - false, - connection, - wallet!, - client - ) - const url = fmtUrlWithCluster( - `/dao/${symbol}/proposal/${proposalAddress[0]}` - ) - router.push(url) - } catch (e) { - console.error(e) - } - setIsDepositing(false) - } - - const schema = yup.object().shape({ - amount: yup - .number() - .required('Amount is required') - .max(Number(maxAmountFormatted)), - }) - - const validateAmountOnBlur = () => { - setAmount( - parseFloat( - Math.max( - Number(mintMinAmount), - Math.min(Number(Number.MAX_SAFE_INTEGER), Number(amount)) - ).toFixed(currentPrecision) - ) - ) - } - - return ( -
-
- Amount -
- Bal:{' '} - {Number(maxAmountFormatted)} - { - setAmount(Number(maxAmountFormatted)) - }} - className="font-bold ml-2 text-primary-light" - > - Max - -
-
- setAmount(e.target.value)} - value={amount} - onBlur={validateAmountOnBlur} - error={formErrors['amount']} - /> - { - setProposalInfo((prev) => ({ ...prev, title: evt.target.value })) - }} - setDescription={(evt) => - setProposalInfo((prev) => ({ - ...prev, - description: evt.target.value, - })) - } - voteByCouncil={voteByCouncil} - setVoteByCouncil={setVoteByCouncil} - /> -
-
- Current Deposits - - {depositedAmount}{' '} - {tokenSymbol} - -
-
- Proposed Deposit - - {amount?.toLocaleString() || ( - Enter an amount - )}{' '} - - {amount && tokenSymbol} - - -
-
-
- -
-
- ) -} - -export default EverlendDeposit diff --git a/Strategies/components/everlend/EverlendWithdraw.tsx b/Strategies/components/everlend/EverlendWithdraw.tsx deleted file mode 100644 index 43762d3a11..0000000000 --- a/Strategies/components/everlend/EverlendWithdraw.tsx +++ /dev/null @@ -1,250 +0,0 @@ -import { useState } from 'react' -import Button, { LinkButton } from '@components/Button' -import Input from '@components/inputs/Input' -import Tooltip from '@components/Tooltip' -import { RpcContext } from '@solana/spl-governance' -import { PublicKey } from '@solana/web3.js' -import { getProgramVersionForRealm } from '@models/registry/api' -import { - getMintMinAmountAsDecimal, - getMintNaturalAmountFromDecimalAsBN, -} from '@tools/sdk/units' -import { CreateEverlendProposal } from '../../protocols/everlend/tools' -import { AssetAccount } from '@utils/uiTypes/assets' -import useRealm from '@hooks/useRealm' -import useWalletStore from 'stores/useWalletStore' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import useQueryContext from '@hooks/useQueryContext' -import { useRouter } from 'next/router' -import AdditionalProposalOptions from '@components/AdditionalProposalOptions' -import tokenService from '@utils/services/token' -import * as yup from 'yup' -import { precision } from '@utils/formatting' -import { validateInstruction } from '@utils/instructionTools' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import Loading from '@components/Loading' -import { TreasuryStrategy } from '../../types/types' - -interface IProps { - proposedInvestment: TreasuryStrategy & { - poolMint: string - rateEToken: number - decimals: number - poolPubKey: string - } - handledMint: string - createProposalFcn: CreateEverlendProposal - governedTokenAccount: AssetAccount - depositedAmount: number -} - -const EverlendWithdraw = ({ - proposedInvestment, - createProposalFcn, - governedTokenAccount, - depositedAmount, -}: IProps) => { - const [amount, setAmount] = useState(0) - const [isWithdrawing, setIsWithdrawing] = useState(false) - const [proposalInfo, setProposalInfo] = useState({ - title: '', - description: '', - }) - const [formErrors, setFormErrors] = useState({}) - - const { - realmInfo, - realm, - mint, - councilMint, - ownVoterWeight, - symbol, - config, - } = useRealm() - const { canUseTransferInstruction } = useGovernanceAssets() - const [voteByCouncil, setVoteByCouncil] = useState(false) - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const { fmtUrlWithCluster } = useQueryContext() - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const router = useRouter() - - const tokenSymbol = tokenService.getTokenInfo( - governedTokenAccount.extensions.mint!.publicKey.toBase58() - )?.symbol - - const proposalTitle = `Withdraw ${amount} ${ - tokenSymbol || 'tokens' - } from the Everlend pool` - - const mintInfo = governedTokenAccount.extensions?.mint?.account - const mintMinAmount = mintInfo ? getMintMinAmountAsDecimal(mintInfo) : 1 - const currentPrecision = precision(mintMinAmount) - - const handleWithdraw = async () => { - const isValid = await validateInstruction({ - schema, - form: { amount }, - setFormErrors, - }) - if (!isValid) { - return - } - try { - setIsWithdrawing(true) - const rpcContext = new RpcContext( - new PublicKey(realm!.owner), - getProgramVersionForRealm(realmInfo!), - wallet!, - connection.current, - connection.endpoint - ) - const ownTokenRecord = ownVoterWeight.getTokenRecordToCreateProposal( - governedTokenAccount!.governance!.account.config, - voteByCouncil - ) - const defaultProposalMint = voteByCouncil - ? realm?.account.config.councilMint - : !mint?.supply.isZero() || - config?.account.communityTokenConfig.maxVoterWeightAddin - ? realm!.account.communityMint - : !councilMint?.supply.isZero() - ? realm!.account.config.councilMint - : undefined - - const amountToRate = Number( - (amount * proposedInvestment.rateEToken).toFixed( - proposedInvestment.decimals - ) - ) - - const proposalAddress = await createProposalFcn( - rpcContext, - { - title: proposalInfo.title || proposalTitle, - description: proposalInfo.description, - amountFmt: String(amount), - bnAmount: getMintNaturalAmountFromDecimalAsBN( - amountToRate, - governedTokenAccount.extensions.mint!.account.decimals - ), - action: 'Withdraw', - poolPubKey: proposedInvestment.poolPubKey, - tokenMint: proposedInvestment.handledMint, - poolMint: proposedInvestment.poolMint, - }, - realm!, - governedTokenAccount!, - ownTokenRecord, - defaultProposalMint!, - governedTokenAccount!.governance!.account!.proposalCount, - false, - connection, - wallet!, - client - ) - const url = fmtUrlWithCluster( - `/dao/${symbol}/proposal/${proposalAddress[0]}` - ) - router.push(url) - } catch (e) { - console.error(e) - } - setIsWithdrawing(false) - } - - const schema = yup.object().shape({ - amount: yup.number().required('Amount is required').max(depositedAmount), - }) - - const validateAmountOnBlur = () => { - setAmount( - parseFloat( - Math.max( - Number(mintMinAmount), - Math.min(Number(Number.MAX_SAFE_INTEGER), Number(amount)) - ).toFixed(currentPrecision) - ) - ) - } - - return ( -
-
- Amount -
- Bal: {depositedAmount} - setAmount(depositedAmount)} - className="font-bold ml-2 text-primary-light" - > - Max - -
-
- - setAmount(e.target.value)} - value={amount} - onBlur={validateAmountOnBlur} - error={formErrors['amount']} - /> - - - setProposalInfo((prev) => ({ ...prev, title: evt.target.value })) - } - setDescription={(evt) => - setProposalInfo((prev) => ({ - ...prev, - description: evt.target.value, - })) - } - voteByCouncil={voteByCouncil} - setVoteByCouncil={setVoteByCouncil} - /> -
-
- Current Deposits - - {depositedAmount}{' '} - {tokenSymbol} - -
-
- Proposed Withdraw - - {amount?.toLocaleString() || ( - Enter an amount - )}{' '} - - {amount && tokenSymbol} - - -
-
- -
- -
-
- ) -} - -export default EverlendWithdraw diff --git a/Strategies/components/psyfi/Deposit.tsx b/Strategies/components/psyfi/Deposit.tsx new file mode 100644 index 0000000000..7577d0c54a --- /dev/null +++ b/Strategies/components/psyfi/Deposit.tsx @@ -0,0 +1,431 @@ +import { getAssociatedTokenAddress } from '@blockworks-foundation/mango-v4' +import AdditionalProposalOptions from '@components/AdditionalProposalOptions' +import Button, { LinkButton } from '@components/Button' +import Input from '@components/inputs/Input' +import Select from '@components/inputs/Select' +import Loading from '@components/Loading' +import Tooltip from '@components/Tooltip' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import useQueryContext from '@hooks/useQueryContext' +import useRealm from '@hooks/useRealm' +import { getProgramVersionForRealm } from '@models/registry/api' +import { BN } from '@coral-xyz/anchor' +import { RpcContext } from '@solana/spl-governance' +import { PublicKey } from '@solana/web3.js' +import { + getMintDecimalAmount, + getMintDecimalAmountFromNatural, + getMintMinAmountAsDecimal, + getMintNaturalAmountFromDecimalAsBN, +} from '@tools/sdk/units' +import { precision } from '@utils/formatting' +import tokenPriceService from '@utils/services/tokenPrice' +import { AssetAccount } from '@utils/uiTypes/assets' +import BigNumber from 'bignumber.js' +import { useRouter } from 'next/router' +import { pdas } from 'psyfi-euros-test' +import React, { useCallback, useEffect, useState } from 'react' +import { + Action, + CreatePsyFiStrategy, + DepositReceipt, + PsyFiStrategyForm, + PsyFiStrategyInfo, +} from 'Strategies/protocols/psyfi/types' +import { PsyFiStrategy } from 'Strategies/types/types' +import { usePsyFiProgram } from './hooks/usePsyFiProgram' +import { notify } from '@utils/notifications' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { useLegacyVoterWeight } from '@hooks/queries/governancePower' +import {useVotingClients} from "@hooks/useVotingClients"; +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; + +const SOL_BUFFER = 0.02 + +export const Deposit: React.FC<{ + proposedInvestment: PsyFiStrategy + governedTokenAccount: AssetAccount + handledMint: string + createProposalFcn: CreatePsyFiStrategy +}> = ({ + createProposalFcn, + handledMint, + proposedInvestment, + governedTokenAccount, +}) => { + const router = useRouter() + const { fmtUrlWithCluster } = useQueryContext() + const realm = useRealmQuery().data?.result + const config = useRealmConfigQuery().data?.result + const { symbol } = router.query + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const { result: ownVoterWeight } = useLegacyVoterWeight() + + const { realmInfo } = useRealm() + const { + canUseTransferInstruction, + governedTokenAccountsWithoutNfts, + } = useGovernanceAssets() + const votingClients = useVotingClients(); + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const [ownedStrategyTokenAccount, setOwnedStrategyTokenAccount] = useState< + AssetAccount | undefined + >() + const [underlyingDeposited, setUnderlyingDeposited] = useState< + number | undefined + >() + const [depositReceipt, setDepositReceipt] = useState< + DepositReceipt | undefined + >() + const [depositReceiptPubkey, setDepositReceiptPubkey] = useState() + const [isDepositing, setIsDepositing] = useState(false) + const { voteByCouncil, setVoteByCouncil } = useVoteByCouncilToggle(); + const [form, setForm] = useState({ + strategy: proposedInvestment, + title: '', + description: '', + }) + const [formErrors, setFormErrors] = useState({}) + const psyFiProgram = usePsyFiProgram() + + const handleSetForm = useCallback(({ propertyName, value }) => { + setFormErrors({}) + setForm((prevForm) => ({ ...prevForm, [propertyName]: value })) + }, []) + const tokenInfo = tokenPriceService.getTokenInfo(handledMint) + const tokenSymbol = tokenPriceService.getTokenInfo( + governedTokenAccount.extensions.mint!.publicKey.toBase58() + )?.symbol + const mintInfo = governedTokenAccount.extensions?.mint?.account + const treasuryAmount = new BN( + governedTokenAccount.isSol + ? governedTokenAccount.extensions.amount!.toNumber() + : governedTokenAccount.extensions.token!.account.amount + ) + const mintMinAmount = mintInfo ? getMintMinAmountAsDecimal(mintInfo) : 1 + let maxAmount = mintInfo + ? getMintDecimalAmount(mintInfo, treasuryAmount) + : new BigNumber(0) + if (governedTokenAccount.isSol) { + maxAmount = maxAmount.minus(SOL_BUFFER) + } + const maxAmountFtm = maxAmount.toNumber().toFixed(4) + const currentPrecision = precision(mintMinAmount) + + const validateAmountOnBlur = useCallback(() => { + handleSetForm({ + propertyName: 'amount', + value: parseFloat( + Math.max( + Number(mintMinAmount), + Math.min(Number(Number.MAX_SAFE_INTEGER), Number(form.amount)) + ).toFixed(currentPrecision) + ), + }) + }, [handleSetForm, mintMinAmount, form.amount, currentPrecision]) + + useEffect(() => { + ;(async () => { + // TODO: Dry this up with the other areas of the code that use the owner + const owner = governedTokenAccount.isSol + ? governedTokenAccount!.pubkey + : governedTokenAccount!.extensions!.token!.account.owner + // Derive the deposit receipt address + const [address] = await pdas.deriveDepositReceipt( + // @ts-ignore: Anchor version difference + psyFiProgram, + owner, + form.strategy.vaultAccounts.pubkey, + form.strategy.vaultInfo.status.currentEpoch + ) + setDepositReceiptPubkey(address) + + // @ts-ignore: More anchor type stuff + const currentDepositReceipt = ((await psyFiProgram.account.depositReceipt.fetchNullable( + address + )) as unknown) as DepositReceipt | undefined + setDepositReceipt(currentDepositReceipt) + })() + // 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.strategy, psyFiProgram]) + + // Find the owned strategy token account, if one exists + useEffect(() => { + ;(async () => { + const owner = governedTokenAccount.isSol + ? governedTokenAccount!.pubkey + : governedTokenAccount!.extensions!.token!.account.owner + const tokenAddress = await getAssociatedTokenAddress( + form.strategy.vaultAccounts.lpTokenMint, + owner, + true + ) + + // Cross ref with this governances' token accounts and pull holdings + // NOTE: This knowingly restricts to ATAs. + const existingStrategyTokenAccount = governedTokenAccountsWithoutNfts.find( + (x) => x.pubkey.equals(tokenAddress) + ) + setOwnedStrategyTokenAccount(existingStrategyTokenAccount) + if ( + existingStrategyTokenAccount && + existingStrategyTokenAccount.extensions.amount!.gtn(0) + ) { + // Get the token supply + const strategyTokenSupply = existingStrategyTokenAccount.extensions + .mint!.account.supply + const ownedAmount = existingStrategyTokenAccount.extensions.amount! + // Get the amount of underlying represented by the vault + const underlyingBn = getMintNaturalAmountFromDecimalAsBN( + form.strategy.liquidity, + governedTokenAccount.extensions.mint!.account.decimals + ) + // Calculate ownership from ratio + const amountOwned = underlyingBn + .mul(ownedAmount) + .div(strategyTokenSupply) + const underlyingOwned = getMintDecimalAmountFromNatural( + governedTokenAccount.extensions.mint!.account, + amountOwned + ).toNumber() + setUnderlyingDeposited(underlyingOwned) + } + })() + }, [form.strategy, governedTokenAccount, governedTokenAccountsWithoutNfts]) + + const handleDeposit = useCallback(async () => { + try { + setIsDepositing(true) + const rpcContext = new RpcContext( + new PublicKey(realm!.owner.toString()), + getProgramVersionForRealm(realmInfo!), + wallet!, + connection.current, + connection.endpoint + ) + const ownTokenRecord = ownVoterWeight!.getTokenRecordToCreateProposal( + governedTokenAccount!.governance!.account.config, + voteByCouncil + ) + const defaultProposalMint = voteByCouncil + ? realm?.account.config.councilMint + : !mint?.supply.isZero() || + config?.account.communityTokenConfig.maxVoterWeightAddin + ? realm!.account.communityMint + : !councilMint?.supply.isZero() + ? realm!.account.config.councilMint + : undefined + + if (!depositReceiptPubkey) { + // This should be unreachable + throw new Error('Deposit receipt key must be derived first') + } + const strategyInfo: PsyFiStrategyInfo = { + depositReceipt, + depositReceiptPubkey, + ownedStrategyTokenAccount: ownedStrategyTokenAccount, + } + const proposalAddress = await createProposalFcn( + rpcContext, + { + ...form, + action: Action.Deposit, + bnAmount: getMintNaturalAmountFromDecimalAsBN( + form.amount as number, + governedTokenAccount.extensions.mint!.account.decimals + ), + }, + psyFiProgram, + strategyInfo, + realm!, + governedTokenAccount!, + ownTokenRecord, + defaultProposalMint!, + governedTokenAccount!.governance!.account!.proposalCount, + false, + connection, + votingClients(voteByCouncil? 'council' : 'community') + ) + const url = fmtUrlWithCluster( + `/dao/${symbol}/proposal/${proposalAddress}` + ) + router.push(url) + setIsDepositing(false) + } catch (error) { + console.log('ERROR', error) + notify({ type: 'error', message: `Error ${error}` }) + setIsDepositing(false) + } + // 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 + }, [ + votingClients, + config, + connection, + councilMint, + depositReceipt, + depositReceiptPubkey, + fmtUrlWithCluster, + form, + governedTokenAccount, + mint, + ownedStrategyTokenAccount, + ownVoterWeight, + psyFiProgram, + realm, + realmInfo, + router, + symbol, + voteByCouncil, + wallet, + ]) + + useEffect(() => { + if (form.title === '' || form.description === '') { + setForm({ + ...form, + title: + form.title === '' + ? `Deposit ${tokenSymbol} into ${form.strategy.strategyName} strategy` + : form.title, + description: + form.description === '' + ? `Deposit ${tokenSymbol} into ${form.strategy.strategyName} strategy` + : form.description, + }) + } + }, [form, setForm, tokenSymbol]) + + return ( + <> + + + +
+ Amount +
+ Bal: {maxAmountFtm} + + handleSetForm({ + propertyName: 'amount', + value: maxAmount.toNumber(), + }) + } + className="font-bold ml-2 text-primary-light" + > + Max + +
+
+ + handleSetForm({ propertyName: 'amount', value: e.target.value }) + } + step={mintMinAmount} + onBlur={validateAmountOnBlur} + /> + + handleSetForm({ + value: evt.target.value, + propertyName: 'title', + }) + } + setDescription={(evt) => + handleSetForm({ + value: evt.target.value, + propertyName: 'description', + }) + } + voteByCouncil={voteByCouncil} + setVoteByCouncil={setVoteByCouncil} + /> + +
+
+ Pending Deposits + + {depositReceipt + ? getMintDecimalAmountFromNatural( + governedTokenAccount.extensions.mint!.account, + depositReceipt.depositAmount + ).toNumber() + : 0}{' '} + {tokenInfo?.symbol} + +
+
+ Current Deposit + + {underlyingDeposited?.toLocaleString() || 0}{' '} + {tokenInfo?.symbol} + +
+
+ + + ) +} diff --git a/Strategies/components/psyfi/PsyFiStrategies.tsx b/Strategies/components/psyfi/PsyFiStrategies.tsx new file mode 100644 index 0000000000..15eed767f0 --- /dev/null +++ b/Strategies/components/psyfi/PsyFiStrategies.tsx @@ -0,0 +1,31 @@ +import { AssetAccount } from '@utils/uiTypes/assets' +import { CreatePsyFiStrategy } from 'Strategies/protocols/psyfi/types' +import { PsyFiStrategy } from 'Strategies/types/types' +import { Deposit } from './Deposit' + +export const PsyFiStrategies: React.FC<{ + proposedInvestment: PsyFiStrategy + governedTokenAccount: AssetAccount + handledMint: string + createProposalFcn: CreatePsyFiStrategy +}> = ({ + createProposalFcn, + handledMint, + proposedInvestment, + governedTokenAccount, +}) => { + return ( +
+ {/* + TODO: Add a higher level selector that determines the action (Deposit, + Withdraw, Cancel pending deposit, etc) and separate out the action components. + */} + +
+ ) +} diff --git a/Strategies/components/psyfi/hooks/usePsyFiProgram.ts b/Strategies/components/psyfi/hooks/usePsyFiProgram.ts new file mode 100644 index 0000000000..7703d697a6 --- /dev/null +++ b/Strategies/components/psyfi/hooks/usePsyFiProgram.ts @@ -0,0 +1,26 @@ +import { AnchorProvider, Program } from '@coral-xyz/anchor' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { PsyFiEuros, PsyFiIdl } from 'psyfi-euros-test' +import { useMemo } from 'react' +import { MAINNET_PROGRAM_KEYS } from '../programIds' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' + +export const usePsyFiProgram = () => { + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + + // construct the PsyFi program. This could be pulled into a hook + return useMemo(() => { + const anchorProvider = new AnchorProvider( + connection.current, + wallet as any, + {} + ) + return new Program( + PsyFiIdl, + MAINNET_PROGRAM_KEYS.PSYFI_V2, + anchorProvider + ) + // 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 + }, [connection.current, wallet]) +} diff --git a/Strategies/components/psyfi/index.ts b/Strategies/components/psyfi/index.ts new file mode 100644 index 0000000000..d17ff3be06 --- /dev/null +++ b/Strategies/components/psyfi/index.ts @@ -0,0 +1 @@ +export * from './PsyFiStrategies' diff --git a/Strategies/components/psyfi/pdas.ts b/Strategies/components/psyfi/pdas.ts new file mode 100644 index 0000000000..e1672066a6 --- /dev/null +++ b/Strategies/components/psyfi/pdas.ts @@ -0,0 +1,14 @@ +import { PublicKey } from '@solana/web3.js' + +export const deriveVaultCollateralAccount = async ( + programKey: PublicKey, + vaultAccount: PublicKey +) => { + return await PublicKey.findProgramAddress( + [ + new PublicKey(vaultAccount).toBuffer(), + Buffer.from('VaultCollateralAccount'), + ], + programKey + ) +} diff --git a/Strategies/components/psyfi/programIds.ts b/Strategies/components/psyfi/programIds.ts new file mode 100644 index 0000000000..da4718135e --- /dev/null +++ b/Strategies/components/psyfi/programIds.ts @@ -0,0 +1,14 @@ +import { PublicKey } from '@solana/web3.js' +export const MAINNET_PROGRAM_KEYS = { + PSYFI_V2: new PublicKey('PSYFiYqguvMXwpDooGdYV6mju92YEbFobbvW617VNcq'), + PSYSTAKE: new PublicKey('pSystkitWgLkzprdAvraP8DSBiXwee715wiSXGJe8yr'), +} + +export const DEVNET_PROGRAM_KEYS = { + PSYFI_V2: new PublicKey('95q3X9ADJv5hWt93oSaPqABPnP1rqfmjgrnto9v83LPK'), + PSYSTAKE: new PublicKey('5LrZkBFgDkFiKEePeT2N9VuKfd2k8Rrad9PG6mKGbCRk'), +} + +export const EURO_PRIMITIVE_PROGRAM_ID = new PublicKey( + 'FASQhaZQT53W9eT9wWnPoBFw8xzZDey9TbMmJj6jCQTs' +) diff --git a/Strategies/components/solend/SolendDeposit.tsx b/Strategies/components/solend/SolendDeposit.tsx index 80d3569233..765aa20904 100644 --- a/Strategies/components/solend/SolendDeposit.tsx +++ b/Strategies/components/solend/SolendDeposit.tsx @@ -1,4 +1,3 @@ -import { PublicKey } from '@blockworks-foundation/mango-client' import Button, { LinkButton } from '@components/Button' import Input from '@components/inputs/Input' import Loading from '@components/Loading' @@ -7,7 +6,7 @@ import useGovernanceAssets from '@hooks/useGovernanceAssets' import useQueryContext from '@hooks/useQueryContext' import useRealm from '@hooks/useRealm' import { getProgramVersionForRealm } from '@models/registry/api' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { RpcContext } from '@solana/spl-governance' import { getMintDecimalAmount, @@ -15,11 +14,10 @@ import { getMintNaturalAmountFromDecimalAsBN, } from '@tools/sdk/units' import { precision } from '@utils/formatting' -import tokenService from '@utils/services/token' +import tokenPriceService from '@utils/services/tokenPrice' import BigNumber from 'bignumber.js' import { useRouter } from 'next/router' import { useEffect, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' import { SolendStrategy } from 'Strategies/types/types' import AdditionalProposalOptions from '@components/AdditionalProposalOptions' import { validateInstruction } from '@utils/instructionTools' @@ -32,7 +30,19 @@ import { getReserveData, SolendSubStrategy, } from 'Strategies/protocols/solend' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' +import { PublicKey } from '@solana/web3.js' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { useRealmProposalsQuery } from '@hooks/queries/proposal' +import { useLegacyVoterWeight } from '@hooks/queries/governancePower' +import {useVotingClients} from "@hooks/useVotingClients"; +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; const SOL_BUFFER = 0.02 @@ -49,27 +59,23 @@ const SolendDeposit = ({ }) => { const router = useRouter() const { fmtUrlWithCluster } = useQueryContext() - const { - proposals, - realmInfo, - realm, - ownVoterWeight, - mint, - councilMint, - symbol, - config, - } = useRealm() + const realm = useRealmQuery().data?.result + const { symbol } = router.query + const config = useRealmConfigQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const { result: ownVoterWeight } = useLegacyVoterWeight() + const { realmInfo } = useRealm() + const proposals = useRealmProposalsQuery().data const [isDepositing, setIsDepositing] = useState(false) const [deposits, setDeposits] = useState<{ [reserveAddress: string]: number }>({}) - const [voteByCouncil, setVoteByCouncil] = useState(false) - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const tokenInfo = tokenService.getTokenInfo(handledMint) + const { voteByCouncil, setVoteByCouncil } = useVoteByCouncilToggle(); + const votingClients = useVotingClients(); + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const tokenInfo = tokenPriceService.getTokenInfo(handledMint) const { governedTokenAccountsWithoutNfts, auxiliaryTokenAccounts, @@ -82,7 +88,7 @@ const SolendDeposit = ({ : governedTokenAccount.extensions.token!.account.amount ) const mintInfo = governedTokenAccount.extensions?.mint?.account - const tokenSymbol = tokenService.getTokenInfo( + const tokenSymbol = tokenPriceService.getTokenInfo( governedTokenAccount.extensions.mint!.publicKey.toBase58() )?.symbol const [form, setForm] = useState<{ @@ -137,6 +143,20 @@ const SolendDeposit = ({ ] const relevantAccs = accounts + .filter((acc) => { + if (governedTokenAccount.isSol) { + return ( + acc.extensions.token?.account.owner.toBase58() === + governedTokenAccount.pubkey.toBase58() + ) + } else { + return ( + acc.extensions.token?.account.owner.toBase58() && + acc.extensions.token.account.owner.toBase58() === + governedTokenAccount.extensions.token?.account.owner.toBase58() + ) + } + }) .map((acc) => { const reserve = (proposedInvestment as SolendStrategy)?.reserves.find( (reserve) => @@ -177,9 +197,12 @@ const SolendDeposit = ({ setDeposits(results) } getSlndCTokens() + // 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 }, []) const handleDeposit = async () => { + if (ownVoterWeight === undefined) throw new Error() + if (proposals === undefined) throw new Error() const isValid = await validateInstruction({ schema, form, setFormErrors }) if (!isValid) { return @@ -215,7 +238,7 @@ const SolendDeposit = ({ form.amount as number, governedTokenAccount.extensions.mint!.account.decimals ), - proposalCount: Object.keys(proposals).length, + proposalCount: proposals.length, action: 'Deposit', }, realm!, @@ -225,7 +248,7 @@ const SolendDeposit = ({ governedTokenAccount!.governance!.account!.proposalCount, false, connection, - client + votingClients(voteByCouncil? 'council' : 'community') ) const url = fmtUrlWithCluster( `/dao/${symbol}/proposal/${proposalAddress}` @@ -281,9 +304,6 @@ const SolendDeposit = ({
))} - -
Create new account
-
Amount diff --git a/Strategies/components/solend/SolendWithdraw.tsx b/Strategies/components/solend/SolendWithdraw.tsx index 4ad4f87234..8733c75ead 100644 --- a/Strategies/components/solend/SolendWithdraw.tsx +++ b/Strategies/components/solend/SolendWithdraw.tsx @@ -1,4 +1,3 @@ -import { PublicKey } from '@blockworks-foundation/mango-client' import Button, { LinkButton } from '@components/Button' import Input from '@components/inputs/Input' import Loading from '@components/Loading' @@ -7,20 +6,18 @@ import useGovernanceAssets from '@hooks/useGovernanceAssets' import useQueryContext from '@hooks/useQueryContext' import useRealm from '@hooks/useRealm' import { getProgramVersionForRealm } from '@models/registry/api' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { RpcContext } from '@solana/spl-governance' import { getMintMinAmountAsDecimal, - getMintNaturalAmountFromDecimalAsBN, + getMintNaturalAmountFromDecimal, } from '@tools/sdk/units' import { precision } from '@utils/formatting' -import tokenService from '@utils/services/token' +import tokenPriceService from '@utils/services/tokenPrice' import BigNumber from 'bignumber.js' import { useRouter } from 'next/router' import { useEffect, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' import { SolendStrategy } from 'Strategies/types/types' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' import AdditionalProposalOptions from '@components/AdditionalProposalOptions' import { validateInstruction } from '@utils/instructionTools' import * as yup from 'yup' @@ -32,6 +29,19 @@ import { getReserveData, SolendSubStrategy, } from 'Strategies/protocols/solend' +import { PublicKey } from '@solana/web3.js' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { useRealmProposalsQuery } from '@hooks/queries/proposal' +import { useLegacyVoterWeight } from '@hooks/queries/governancePower' +import {useVotingClients} from "@hooks/useVotingClients"; +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; const SolendWithdraw = ({ proposedInvestment, @@ -51,29 +61,25 @@ const SolendWithdraw = ({ } = useGovernanceAssets() const router = useRouter() const { fmtUrlWithCluster } = useQueryContext() - const { - proposals, - realmInfo, - realm, - ownVoterWeight, - mint, - councilMint, - symbol, - config, - } = useRealm() + const realm = useRealmQuery().data?.result + const { symbol } = router.query + const config = useRealmConfigQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const { result: ownVoterWeight } = useLegacyVoterWeight() + const { realmInfo } = useRealm() const [isWithdrawing, setIsWithdrawing] = useState(false) - const [voteByCouncil, setVoteByCouncil] = useState(false) + const { voteByCouncil, setVoteByCouncil } = useVoteByCouncilToggle(); const [deposits, setDeposits] = useState<{ [reserveAddress: string]: { amount: number; amountExact: number } }>({}) - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const tokenInfo = tokenService.getTokenInfo(handledMint) + const votingClients = useVotingClients(); + const proposals = useRealmProposalsQuery().data + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const tokenInfo = tokenPriceService.getTokenInfo(handledMint) const mintInfo = governedTokenAccount.extensions?.mint?.account - const tokenSymbol = tokenService.getTokenInfo( + const tokenSymbol = tokenPriceService.getTokenInfo( governedTokenAccount.extensions.mint!.publicKey.toBase58() )?.symbol const [form, setForm] = useState<{ @@ -119,6 +125,20 @@ const SolendWithdraw = ({ ] const relevantAccs = accounts + .filter((acc) => { + if (governedTokenAccount.isSol) { + return ( + acc.extensions.token?.account.owner.toBase58() === + governedTokenAccount.pubkey.toBase58() + ) + } else { + return ( + acc.extensions.token?.account.owner.toBase58() && + acc.extensions.token.account.owner.toBase58() === + governedTokenAccount.extensions.token?.account.owner.toBase58() + ) + } + }) .map((acc) => { const reserve = (proposedInvestment as SolendStrategy)?.reserves.find( (reserve) => @@ -164,6 +184,7 @@ const SolendWithdraw = ({ ) } getSlndCTokens() + // 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 }, []) const validateAmountOnBlur = () => { @@ -179,6 +200,8 @@ const SolendWithdraw = ({ } const handleWithdraw = async () => { + if (ownVoterWeight === undefined) throw new Error() + if (proposals === undefined) throw new Error() const isValid = await validateInstruction({ schema, form, setFormErrors }) if (!isValid) { return @@ -213,14 +236,19 @@ const SolendWithdraw = ({ ...form, bnAmount: form.max ? new BN(deposits[form.reserve.reserveAddress].amountExact) - : getMintNaturalAmountFromDecimalAsBN( - (form.amount as number) / cTokenExchangeRate(reserveStat[0]), - governedTokenAccount.extensions.mint!.account.decimals + : new BN( + Math.floor( + getMintNaturalAmountFromDecimal( + (form.amount as number) / + cTokenExchangeRate(reserveStat[0]), + governedTokenAccount.extensions.mint!.account.decimals + ) + ).toString() ), amountFmt: ( (form.amount as number) / cTokenExchangeRate(reserveStat[0]) ).toFixed(4), - proposalCount: Object.keys(proposals).length, + proposalCount: proposals.length, action: 'Withdraw', }, realm!, @@ -230,7 +258,7 @@ const SolendWithdraw = ({ governedTokenAccount!.governance!.account!.proposalCount, false, connection, - client + votingClients(voteByCouncil? 'council' : 'community'), ) const url = fmtUrlWithCluster( `/dao/${symbol}/proposal/${proposalAddress}` @@ -285,9 +313,6 @@ const SolendWithdraw = ({
))} - -
Create new account
-
Amount diff --git a/Strategies/protocols/everlend/constants.ts b/Strategies/protocols/everlend/constants.ts deleted file mode 100644 index 22b37b2a85..0000000000 --- a/Strategies/protocols/everlend/constants.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { PublicKey } from '@solana/web3.js' - -export const MARKET_MAIN = 'DzGDoJHdzUANM7P7V25t5nxqbvzRcHDmdhY51V6WNiXC' -export const MARKET_DEV = '4yC3cUWXQmoyyybfnENpxo33hiNxUNa1YAmmuxz93WAJ' -export const REGISTRY_DEV = '6KCHtgSGR2WDE3aqrqSJppHRGVPgy9fHDX5XD8VZgb61' -export const REGISTRY_MAIN = 'UaqUGgMvVzUZLthLHC9uuuBzgw5Ldesich94Wu5pMJg' -export const ENDPOINT_MAIN = 'https://api.everlend.finance/api/v1/' -export const ENDPOINT_DEV = 'https://dev-api.everlend.finance/api/v1/' - -export const REWARD_PROGRAM_ID = new PublicKey( - 'ELDR7M6m1ysPXks53T7da6zkhnhJV44twXLiAgTf2VpM' -) -export const CONFIG_MAINNET = '69C4Ba9LyQvWHPSSqXWXHnaedrLEuY49rSj23nJdrkkn' -export const CONFIG_DEVNET = 'Hjm8ZVys6828sY9BxzuQhVwdsX1N28dqh3fKqbpGWu25' - -export const EVERLEND = 'Everlend' diff --git a/Strategies/protocols/everlend/depositTools.ts b/Strategies/protocols/everlend/depositTools.ts deleted file mode 100644 index 9b789add57..0000000000 --- a/Strategies/protocols/everlend/depositTools.ts +++ /dev/null @@ -1,426 +0,0 @@ -import { - Connection, - Keypair, - PublicKey, - SystemProgram, - Transaction, - TransactionInstruction, -} from '@solana/web3.js' -import BN from 'bn.js' -import { - DepositTx, - Pool, - prepareDepositTx, - prepareWithdrawalRequestTx, -} from '@everlend/general-pool' -import { GeneralPoolsProgram } from '@everlend/general-pool' -import { - CreateAssociatedTokenAccount, - findAssociatedTokenAccount, - findRegistryPoolConfigAccount, -} from '@everlend/common' -import { - ASSOCIATED_TOKEN_PROGRAM_ID, - Token, - TOKEN_PROGRAM_ID, -} from '@solana/spl-token' -import { - getInstructionDataFromBase64, - ProgramAccount, - Realm, - RpcContext, - serializeInstructionToBase64, - TokenOwnerRecord, -} from '@solana/spl-governance' -import { AssetAccount } from '@utils/uiTypes/assets' -import { ConnectionContext } from '@utils/connection' -import { VotingClient } from '@utils/uiTypes/VotePlugin' -import { - createProposal, - InstructionDataWithHoldUpTime, -} from '../../../actions/createProposal' -import { - CONFIG_DEVNET, - CONFIG_MAINNET, - REGISTRY_DEV, - REGISTRY_MAIN, - REWARD_PROGRAM_ID, -} from './constants' -import { getInitMiningTx } from './useRewardProgram' -import { SignerWalletAdapter } from '@solana/wallet-adapter-base' -import { syncNative } from '@solendprotocol/solend-sdk' - -export type ActionOptions = { - /** the JSON RPC connection instance. */ - connection: Connection - /** the fee payer public key, can be user's SOL address (owner address). */ - payerPublicKey: PublicKey -} - -export type ActionResult = { - /** the prepared transaction, ready for signing and sending. */ - tx: Transaction - setupTx: Transaction - /** the additional key pairs which may be needed for signing and sending transactions. */ - keypairs?: Record -} - -export const prepareSolDepositTx = async ( - { connection, payerPublicKey }: ActionOptions, - pool: PublicKey, - registry: PublicKey, - amount: BN, - rewardPool: PublicKey, - rewardAccount: PublicKey, - config: PublicKey, - rewardProgramId: PublicKey, - source: PublicKey, - destination: PublicKey -): Promise => { - const { - data: { poolMarket, tokenAccount, poolMint, tokenMint }, - } = await Pool.load(connection, pool) - - const poolMarketAuthority = await GeneralPoolsProgram.findProgramAddress([ - poolMarket.toBuffer(), - ]) - - const tx = new Transaction() - const setupTx = new Transaction() - const registryPoolConfig = await findRegistryPoolConfigAccount(registry, pool) - - // Wrapping SOL - const depositAccountInfo = await connection.getAccountInfo(source) - if (!depositAccountInfo) { - // generate the instruction for creating the ATA - const createAtaInst = Token.createAssociatedTokenAccountInstruction( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - new PublicKey(tokenMint), - source, - payerPublicKey, - payerPublicKey - ) - setupTx.add(createAtaInst) - } - - const userWSOLAccountInfo = await connection.getAccountInfo(destination) - - const rentExempt = await Token.getMinBalanceRentForExemptAccount(connection) - - const transferLamportsIx = SystemProgram.transfer({ - fromPubkey: payerPublicKey, - toPubkey: source, - lamports: (userWSOLAccountInfo ? 0 : rentExempt) + amount.toNumber(), - }) - - setupTx.add(transferLamportsIx) - - const syncIx = syncNative(source) - tx.add(syncIx) - - // Create destination account for pool mint if doesn't exist - destination = - destination ?? (await findAssociatedTokenAccount(payerPublicKey, poolMint)) - !(await connection.getAccountInfo(destination)) && - setupTx.add( - new CreateAssociatedTokenAccount( - { feePayer: payerPublicKey }, - { - associatedTokenAddress: destination, - tokenMint: poolMint, - } - ) - ) - - tx.add( - new DepositTx( - { feePayer: payerPublicKey }, - { - poolConfig: registryPoolConfig, - poolMarket, - pool, - source, - destination, - tokenAccount, - poolMint, - rewardPool, - rewardAccount, - config, - rewardProgramId, - poolMarketAuthority, - amount, - } - ) - ) - - return { tx, setupTx } -} - -export async function handleEverlendAction( - rpcContext: RpcContext, - form: { - action: 'Deposit' | 'Withdraw' - title: string - description: string - bnAmount: BN - poolPubKey: string - tokenMint: string - poolMint: string - }, - realm: ProgramAccount, - matchedTreasury: AssetAccount, - tokenOwnerRecord: ProgramAccount, - governingTokenMint: PublicKey, - proposalIndex: number, - isDraft: boolean, - connection: ConnectionContext, - wallet: SignerWalletAdapter, - client?: VotingClient -) { - const isSol = matchedTreasury.isSol - const insts: InstructionDataWithHoldUpTime[] = [] - const owner = isSol - ? matchedTreasury!.pubkey - : matchedTreasury!.extensions!.token!.account.owner - const isMainnet = connection.cluster === 'mainnet' - const REGISTRY = new PublicKey(isMainnet ? REGISTRY_MAIN : REGISTRY_DEV) - const CONFIG = new PublicKey(isMainnet ? CONFIG_MAINNET : CONFIG_DEVNET) - - const ctokenATA = isSol - ? await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - new PublicKey(form.tokenMint), - owner, - true - ) - : matchedTreasury.pubkey - - const liquidityATA = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - new PublicKey(form.poolMint), - owner, - true - ) - - const [rewardPool] = PublicKey.findProgramAddressSync( - [ - Buffer.from('reward_pool'), - CONFIG.toBuffer(), - new PublicKey(form.tokenMint).toBuffer(), - ], - REWARD_PROGRAM_ID - ) - const [rewardAccount] = PublicKey.findProgramAddressSync( - [Buffer.from('mining'), owner.toBuffer(), rewardPool.toBuffer()], - REWARD_PROGRAM_ID - ) - - const setupInsts: InstructionDataWithHoldUpTime[] = [] - const cleanupInsts: InstructionDataWithHoldUpTime[] = [] - - if (form.action === 'Deposit') { - const { actionTx, initMiningTx } = await handleEverlendDeposit( - wallet!, - Boolean(isSol), - connection, - owner, - REGISTRY, - CONFIG, - rewardPool, - rewardAccount, - form.poolPubKey, - form.bnAmount, - ctokenATA, - liquidityATA - ) - actionTx.instructions.map((instruction) => { - insts.push({ - data: getInstructionDataFromBase64( - serializeInstructionToBase64(instruction) - ), - holdUpTime: matchedTreasury.governance!.account!.config - .minInstructionHoldUpTime, - prerequisiteInstructions: [], - chunkSplitByDefault: true, - }) - }) - - if (initMiningTx.instructions.length) { - initMiningTx.instructions.map((instruction) => { - setupInsts.push({ - data: getInstructionDataFromBase64( - serializeInstructionToBase64(instruction) - ), - holdUpTime: matchedTreasury.governance!.account!.config - .minInstructionHoldUpTime, - prerequisiteInstructions: [], - chunkSplitByDefault: true, - }) - }) - } - } else if (form.action === 'Withdraw') { - const { withdrawTx } = await handleEverlendWithdraw( - Boolean(isSol), - connection, - owner, - REGISTRY, - CONFIG, - rewardPool, - rewardAccount, - form.poolPubKey, - form.bnAmount, - liquidityATA, - ctokenATA - ) - - withdrawTx.instructions.map((instruction) => { - insts.push({ - data: getInstructionDataFromBase64( - serializeInstructionToBase64(instruction) - ), - holdUpTime: matchedTreasury.governance!.account!.config - .minInstructionHoldUpTime, - prerequisiteInstructions: [], - chunkSplitByDefault: true, - }) - }) - } - - const proposalsAdresses: PublicKey[] = [] - - // eslint-disable-next-line no-debugger - debugger - - const proposalAddress = await createProposal( - rpcContext, - realm, - matchedTreasury.governance!.pubkey, - tokenOwnerRecord, - form.title, - form.description, - governingTokenMint, - proposalIndex, - [...setupInsts, ...insts, ...cleanupInsts], - isDraft, - client - ) - proposalsAdresses.push(proposalAddress) - - return proposalsAdresses -} - -export async function handleEverlendDeposit( - wallet: SignerWalletAdapter, - isSol: boolean, - connection: ConnectionContext, - owner: PublicKey, - REGISTRY: PublicKey, - CONFIG: PublicKey, - rewardPool: PublicKey, - rewardAccount: PublicKey, - poolPubKey: string, - amount: BN, - source: PublicKey, - destination: PublicKey -) { - const actionTx = new Transaction() - const initMiningTx = new Transaction() - - const rewardPoolInfo = await connection.current.getAccountInfo(rewardPool) - const rewardAccountInfo = await connection.current.getAccountInfo( - rewardAccount - ) - - if (!rewardAccountInfo && rewardPoolInfo?.data) { - const initTx = await getInitMiningTx( - rewardPool, - rewardAccount, - wallet.publicKey!, - owner, - connection, - wallet, - CONFIG - ) - - initMiningTx.add(initTx) - } - if (isSol) { - const { tx: depositTx, setupTx } = await prepareSolDepositTx( - { connection: connection.current, payerPublicKey: owner }, - new PublicKey(poolPubKey), - REGISTRY, - amount, - rewardPool, - rewardAccount, - CONFIG, - REWARD_PROGRAM_ID, - source, - destination - ) - actionTx.add(depositTx) - initMiningTx.add(setupTx) - } else { - const { tx: depositTx } = await prepareDepositTx( - { connection: connection.current, payerPublicKey: owner }, - new PublicKey(poolPubKey), - amount, - REWARD_PROGRAM_ID, - CONFIG, - rewardPool, - rewardAccount, - source - ) - actionTx.add(depositTx) - } - - return { actionTx, initMiningTx } -} - -export async function handleEverlendWithdraw( - isSol: boolean, - connection: ConnectionContext, - owner: PublicKey, - REGISTRY: PublicKey, - CONFIG: PublicKey, - rewardPool: PublicKey, - rewardAccount: PublicKey, - poolPubKey: string, - amount: BN, - source: PublicKey, - destination: PublicKey -) { - const { tx: withdrawslTx } = await prepareWithdrawalRequestTx( - { - connection: connection.current, - payerPublicKey: owner, - }, - new PublicKey(poolPubKey), - amount, - REWARD_PROGRAM_ID, - CONFIG, - rewardPool, - rewardAccount, - source, - isSol ? owner : undefined - ) - const withdrawTx = withdrawslTx - let closeIx: TransactionInstruction | undefined - if (isSol) { - const closeWSOLAccountIx = Token.createCloseAccountInstruction( - TOKEN_PROGRAM_ID, - destination, - owner, - owner, - [] - ) - closeIx = closeWSOLAccountIx - } - - return { - withdrawTx, - closeIx: closeIx ?? null, - } -} diff --git a/Strategies/protocols/everlend/tools.ts b/Strategies/protocols/everlend/tools.ts deleted file mode 100644 index 7633155981..0000000000 --- a/Strategies/protocols/everlend/tools.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js' -import { - ProgramAccount, - Realm, - RpcContext, - TokenOwnerRecord, -} from '@solana/spl-governance' -import { BN } from '@project-serum/anchor' -import { AssetAccount } from '@utils/uiTypes/assets' -import { ConnectionContext } from '@utils/connection' -import { VotingClient } from '@utils/uiTypes/VotePlugin' -import numbro from 'numbro' -import tokenService from '@utils/services/token' -import { Pool } from '@everlend/general-pool' -import axios from 'axios' - -import { - MARKET_MAIN, - MARKET_DEV, - ENDPOINT_MAIN, - ENDPOINT_DEV, -} from './constants' -import { handleEverlendAction } from './depositTools' -import { SignerWalletAdapter } from '@solana/wallet-adapter-base' -import { deserialize } from '@everlend/common' -export const EVERLEND = 'Everlend' - -async function getAPYs(isDev = false) { - const api = axios.create({ - baseURL: isDev ? ENDPOINT_DEV : ENDPOINT_MAIN, - timeout: 30000, - }) - - return api.get('apy') -} - -async function getStrategies(connection: ConnectionContext) { - const isDev = connection.cluster === 'devnet' - const POOL_MARKET_PUBKEY = new PublicKey(isDev ? MARKET_DEV : MARKET_MAIN) - - try { - const response = await Pool.findMany(connection.current, { - poolMarket: POOL_MARKET_PUBKEY, - }) - - const apys = await getAPYs(isDev) - - const strategies = await Promise.all( - response.map(async (pool) => { - const { - tokenMint, - poolMint, - tokenAccount, - totalAmountBorrowed, - } = pool.data - const tokenInfo = tokenService.getTokenInfo(tokenMint.toString()) - const apy = - apys.data.find((apy) => apy.token === tokenInfo?.symbol)?.supply_apy * - 100 ?? 0 - - const tokenAccountBalance = await connection.current.getTokenAccountBalance( - tokenAccount - ) - const poolMintInfoRaw = await connection.current.getAccountInfo( - poolMint - ) - - let poolMintInfoBuffer - let poolMintInfo - if (poolMintInfoRaw) { - poolMintInfoBuffer = Buffer.from(poolMintInfoRaw?.data) - poolMintInfo = deserialize(poolMintInfoBuffer) - } - - const rateEToken = calcETokenRate( - poolMintInfo.supply.toNumber(), - Number(tokenAccountBalance.value.amount) + - totalAmountBorrowed.toNumber() - ) - - return { - handledMint: tokenMint.toString(), - createProposalFcn: handleEverlendAction, - protocolLogoSrc: '/realms/Everlend/img/logo.png', - protocolName: 'Everlend', - protocolSymbol: 'evd', - isGenericItem: false, - poolMint: poolMint.toString(), - poolPubKey: pool.publicKey.toString(), - strategyDescription: '', - strategyName: 'Deposit', - handledTokenSymbol: tokenInfo?.symbol, - handledTokenImgSrc: tokenInfo?.logoURI, - apy: apy.toFixed(2).concat('%'), - rateEToken, - decimals: poolMintInfo.decimals, - } - }) - ) - - return strategies - } catch (e) { - console.error(e) - } -} - -export async function getEverlendStrategies( - connection: ConnectionContext -): Promise { - const strategies = await getStrategies(connection) - - return strategies -} - -export const lamportsToSol = (value: number): number => { - return value / LAMPORTS_PER_SOL -} - -export type CreateEverlendProposal = ( - rpcContext: RpcContext, - form: { - action: 'Deposit' | 'Withdraw' - title: string - description: string - bnAmount: BN - amountFmt: string - poolPubKey: string - tokenMint: string - poolMint: string - }, - realm: ProgramAccount, - matchedTreasury: AssetAccount, - tokenOwnerRecord: ProgramAccount, - governingTokenMint: PublicKey, - proposalIndex: number, - isDraft: boolean, - connection: ConnectionContext, - wallet: SignerWalletAdapter, - client?: VotingClient -) => Promise - -export const calcETokenRate = ( - collateralTotalMintSupply: number, - totalPoolSize: number -): number => { - const rate = collateralTotalMintSupply / totalPoolSize - - return Number.isNaN(rate) || !Number.isFinite(rate) ? 1 : rate -} - -export const calcUserTokenBalanceByPoolToken = ( - poolTokenAmount: number, - tokenDecimals = 9, - eTokenRate: number, - ceil = true -): number => { - const tokenBalanceRaw = poolTokenAmount / eTokenRate - const decimalMultiplier = 10 ** tokenDecimals - const tokenBalanceByDecimalMultiplier = tokenBalanceRaw * decimalMultiplier - - return ( - (ceil - ? Math.ceil(tokenBalanceByDecimalMultiplier) - : 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 -} diff --git a/Strategies/protocols/everlend/useRewardProgram.ts b/Strategies/protocols/everlend/useRewardProgram.ts deleted file mode 100644 index a87f546c86..0000000000 --- a/Strategies/protocols/everlend/useRewardProgram.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Wallet } from '@project-serum/anchor' -import { EldRewards, IDL } from '@everlend/core/dist/idl/eld_rewards' -import * as anchor from '@project-serum/anchor' -import { - PublicKey, - SystemProgram, - SYSVAR_RENT_PUBKEY, - Transaction, -} from '@solana/web3.js' -import { REWARD_PROGRAM_ID } from './constants' -import { ConnectionContext } from '@utils/connection' -import { SignerWalletAdapter } from '@solana/wallet-adapter-base' - -const getInitMiningTx = async ( - rewardPool: PublicKey, - rewardAccount: PublicKey, - walletPubKey: PublicKey, - owner: PublicKey, - connection: ConnectionContext, - wallet: SignerWalletAdapter, - CONFIG: PublicKey -): Promise => { - const provider = new anchor.AnchorProvider( - connection.current, - (wallet as unknown) as Wallet, - { - commitment: 'processed', - } - ) - const rewardProgram = new anchor.Program( - IDL, - REWARD_PROGRAM_ID, - provider - ) as anchor.Program - const tx = new Transaction() - if (!walletPubKey) return tx - - tx.add( - rewardProgram.transaction.initializeMining({ - accounts: { - config: CONFIG, - rewardPool, - mining: rewardAccount, - user: owner, - payer: owner, - systemProgram: SystemProgram.programId, - rent: SYSVAR_RENT_PUBKEY, - }, - signers: [], - }) - ) - - tx.feePayer = walletPubKey - tx.recentBlockhash = (await connection.current.getLatestBlockhash()).blockhash - - return tx -} - -export { getInitMiningTx } diff --git a/Strategies/protocols/foresight/tools.ts b/Strategies/protocols/foresight/tools.ts deleted file mode 100644 index db42d1ef84..0000000000 --- a/Strategies/protocols/foresight/tools.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const FORESIGHT_MINT_DEVNET = - 'H7uqouPsJkeEiLpCEoC1qYVVquDrZan6ZfdPK2gS44zm' diff --git a/Strategies/protocols/mango/tools.ts b/Strategies/protocols/mango/tools.ts deleted file mode 100644 index 219a166d3d..0000000000 --- a/Strategies/protocols/mango/tools.ts +++ /dev/null @@ -1,436 +0,0 @@ -import { - makeCreateMangoAccountInstruction, - makeDepositInstruction, - PublicKey, - BN, - makeSetDelegateInstruction, - MangoAccount, -} from '@blockworks-foundation/mango-client' -import { - closeAccount, - initializeAccount, - WRAPPED_SOL_MINT, -} from '@project-serum/serum/lib/token-instructions' -import { - getInstructionDataFromBase64, - getNativeTreasuryAddress, - serializeInstructionToBase64, - TOKEN_PROGRAM_ID, -} from '@solana/spl-governance' -import { - Keypair, - LAMPORTS_PER_SOL, - SystemProgram, - TransactionInstruction, -} from '@solana/web3.js' -import { syncNative } from '@solendprotocol/solend-sdk' -import { fmtMintAmount } from '@tools/sdk/units' -import { ConnectionContext } from '@utils/connection' -import tokenService from '@utils/services/token' -import { - createProposal, - InstructionDataWithHoldUpTime, -} from 'actions/createProposal' -import axios from 'axios' -import BigNumber from 'bignumber.js' -import { MarketStore } from 'Strategies/store/marketStore' -import { - TreasuryStrategy, - HandleCreateProposalWithStrategy, -} from 'Strategies/types/types' - -//Symbol, coingeckoId -export const tokenList = { - ETH: 'ethereum', - BTC: 'bitcoin', - SOL: 'solana', - SRM: 'serum', - USDC: 'usd-coin', - USDT: 'tether', - MNGO: 'mango-markets', - RAY: 'raydium', - COPE: 'cope', - FTT: 'ftx-token', - MSOL: 'msol', - BNB: 'binance-coin', - AVAX: 'avalanche', - LUNA: 'terra-luna', -} -export const MANGO = 'Mango' -export const MANGO_MINT = 'MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac' -export const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' -export const MANGO_MINT_DEVNET = 'Bb9bsTQa1bGEtQ5KagGkvSHyuLqDWumFUcRqFusFNJWC' -export const MANGO_USDC_MINT_DEVNET = - '8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN' -export const tokenListFilter = Object.keys(tokenList).map((x) => { - return { - name: x, - val: x, - } -}) - -const endpoint = - 'https://mango-stats-v3.herokuapp.com/spot?mangoGroup=mainnet.1' - -// Very inefficient -function findClosestToDate(values, date) { - let min = values[0] - for (const val of values) { - const valDate = new Date(val.time).getTime() - const minDate = new Date(min.time).getTime() - if (Math.abs(valDate - date) < Math.abs(minDate - date)) { - min = val - } - } - if (Math.abs(new Date(min.time).getTime() - date) > 24 * 3600 * 1000) { - return { - totalDeposits: 0, - totalBorrows: 0, - } - } - return min -} - -//method to fetch mango strategies -export async function tvl(timestamp, connection: ConnectionContext) { - const protocolInfo = await tokenService.getTokenInfo(MANGO_MINT) - const balances: TreasuryStrategy[] = [] - const stats = await axios.get(endpoint) - const date = new Date(timestamp * 1000).getTime() - for (const [mangoId, mangoTokens] of Object.entries(tokenList)) { - const assetDeposits = stats.data.filter((s) => s.name === mangoId) - - if (assetDeposits.length > 0) { - const info = tokenService.getTokenInfoFromCoingeckoId(mangoTokens) - const handledMint = - (info?.address === MANGO_MINT && connection.cluster === 'devnet' - ? MANGO_MINT_DEVNET - : info?.address === USDC_MINT && connection.cluster === 'devnet' - ? MANGO_USDC_MINT_DEVNET - : info?.address) || '' - const closestVal = findClosestToDate(assetDeposits, date) - balances.push({ - liquidity: - (closestVal.totalDeposits - closestVal.totalBorrows) * - closestVal.baseOraclePrice, - handledTokenSymbol: info?.symbol || mangoId, - apy: `${( - (Math.pow(1 + closestVal.depositRate / 128, 128) - 1) * - 100 - ).toFixed(2)}%`, - protocolName: MANGO, - protocolSymbol: protocolInfo?.symbol || '', - handledMint: handledMint, - handledTokenImgSrc: info?.logoURI || '', - protocolLogoSrc: protocolInfo?.logoURI || '', - strategyName: 'Deposit', - strategyDescription: 'Description', - isGenericItem: false, - createProposalFcn: HandleMangoDeposit, - }) - } - } - - return balances -} - -export const calculateAllDepositsInMangoAccountsForMint = ( - accounts: MangoAccount[], - mint: PublicKey, - market: MarketStore -) => { - let deposited = 0 - const group = market!.group - const depositIndex = - mint && - group?.tokens.findIndex((x) => x.mint.toBase58() === mint.toBase58()) - if (accounts?.length && typeof depositIndex !== 'undefined' && group) { - const depositsWithAmountHiherThenZero = accounts - .map((x) => x.deposits[depositIndex]) - .filter((x) => !x?.isZero()) - if (depositsWithAmountHiherThenZero.length) { - const currentDepositAmount = accounts - .map((x) => - x - ?.getUiDeposit( - market.cache!.rootBankCache[depositIndex], - group, - depositIndex - ) - .toNumber() - ) - .reduce((prev, next) => (prev += next), 0) - deposited += currentDepositAmount ? currentDepositAmount : 0 - } - } - return deposited -} - -const HandleMangoDeposit: HandleCreateProposalWithStrategy = async ( - rpcContext, - handledMint, - form, - realm, - matchedTreasury, - tokenOwnerRecord, - governingTokenMint, - proposalIndex, - prerequisiteInstructions, - isDraft, - market, - client -) => { - const fmtAmount = fmtMintAmount( - matchedTreasury.extensions.mint?.account, - new BN(form.mintAmount) - ) - const decimalAmount = new BigNumber(form.mintAmount) - .shiftedBy(-matchedTreasury.extensions.mint!.account.decimals) - .toNumber() - const group = market!.group! - const groupConfig = market!.groupConfig! - const rootBank = group.tokens.find( - (x) => - x.mint.toBase58() === - matchedTreasury.extensions.mint?.publicKey.toBase58() - )?.rootBank - const quoteRootBank = - group.rootBankAccounts[group.getRootBankIndex(rootBank!)] - const quoteNodeBank = quoteRootBank?.nodeBankAccounts[0] - const nextAccNumb = new BN(form.proposalCount) - const mangoAccountPk = - form.mangoAccountPk || - ( - await PublicKey.findProgramAddress( - [ - group.publicKey.toBytes(), - matchedTreasury.governance!.pubkey.toBytes(), - nextAccNumb.toArrayLike(Buffer, 'le', 8), - ], - groupConfig.mangoProgramId - ) - )[0] - const solAddress = await getNativeTreasuryAddress( - realm!.owner, - matchedTreasury!.governance!.pubkey - ) - let wrappedSolAccount: null | Keypair = null - const insts: InstructionDataWithHoldUpTime[] = [] - const localPrequisteInstructions: TransactionInstruction[] = [] - if (matchedTreasury.isSol) { - wrappedSolAccount = new Keypair() - const lamports = decimalAmount * LAMPORTS_PER_SOL - const space = 165 - const rent = await rpcContext.connection.getMinimumBalanceForRentExemption( - space, - 'processed' - ) - localPrequisteInstructions.push( - SystemProgram.createAccount({ - fromPubkey: rpcContext.wallet.publicKey!, - newAccountPubkey: wrappedSolAccount?.publicKey, - lamports: rent, - space: space, - programId: TOKEN_PROGRAM_ID, - }), - initializeAccount({ - account: wrappedSolAccount?.publicKey, - mint: WRAPPED_SOL_MINT, - owner: matchedTreasury.governance.pubkey!, - }) - ) - const transferIx = SystemProgram.transfer({ - fromPubkey: matchedTreasury.extensions.transferAddress!, - toPubkey: wrappedSolAccount!.publicKey!, - lamports: lamports, - }) - const instructionData = { - data: getInstructionDataFromBase64( - serializeInstructionToBase64(transferIx) - ), - holdUpTime: matchedTreasury.governance!.account!.config - .minInstructionHoldUpTime, - prerequisiteInstructions: [...localPrequisteInstructions], - prerequisiteInstructionsSigners: [wrappedSolAccount], - } - insts.push(instructionData) - const syncIx = syncNative(wrappedSolAccount.publicKey!) - const syncInst = { - data: getInstructionDataFromBase64(serializeInstructionToBase64(syncIx)), - holdUpTime: matchedTreasury.governance!.account!.config - .minInstructionHoldUpTime, - prerequisiteInstructions: [], - } - insts.push(syncInst) - } - const depositMangoAccountInsObj = { - data: getInstructionDataFromBase64( - serializeInstructionToBase64( - makeDepositInstruction( - groupConfig.mangoProgramId, - groupConfig.publicKey, - matchedTreasury.isSol - ? matchedTreasury.governance.pubkey! - : matchedTreasury.extensions.token!.account.owner!, - group.mangoCache, - mangoAccountPk, - quoteRootBank!.publicKey, - quoteNodeBank!.publicKey, - quoteNodeBank!.vault, - wrappedSolAccount?.publicKey ?? - matchedTreasury.extensions.transferAddress!, - new BN(form.mintAmount) - ) - ) - ), - holdUpTime: matchedTreasury.governance!.account!.config - .minInstructionHoldUpTime, - prerequisiteInstructions: [], - chunkSplitByDefault: true, - } - if (!form.mangoAccountPk) { - const createMangoAccountIns = makeCreateMangoAccountInstruction( - groupConfig.mangoProgramId, - groupConfig.publicKey, - mangoAccountPk, - matchedTreasury.governance!.pubkey, - nextAccNumb, - solAddress - ) - const instructionData = { - data: getInstructionDataFromBase64( - serializeInstructionToBase64(createMangoAccountIns) - ), - holdUpTime: matchedTreasury.governance!.account!.config - .minInstructionHoldUpTime, - prerequisiteInstructions: [...prerequisiteInstructions], - splitToChunkByDefault: true, - } - insts.push(instructionData) - } - if (form.delegateAddress && form.delegateDeposit) { - const delegateMangoAccount = makeSetDelegateInstruction( - groupConfig.mangoProgramId, - groupConfig.publicKey, - mangoAccountPk, - matchedTreasury.governance!.pubkey, - new PublicKey(form.delegateAddress) - ) - const instructionData = { - data: getInstructionDataFromBase64( - serializeInstructionToBase64(delegateMangoAccount) - ), - holdUpTime: matchedTreasury.governance!.account!.config - .minInstructionHoldUpTime, - prerequisiteInstructions: [], - splitToChunkByDefault: true, - } - insts.push(instructionData) - } - insts.push(depositMangoAccountInsObj) - if (wrappedSolAccount) { - const instructionData = { - data: getInstructionDataFromBase64( - serializeInstructionToBase64( - closeAccount({ - source: wrappedSolAccount.publicKey, - destination: matchedTreasury.extensions.transferAddress, - owner: matchedTreasury.governance.pubkey, - }) - ) - ), - holdUpTime: matchedTreasury.governance!.account!.config - .minInstructionHoldUpTime, - prerequisiteInstructions: [], - splitToChunkByDefault: true, - } - insts.push(instructionData) - } - const proposalAddress = await createProposal( - rpcContext, - realm, - matchedTreasury.governance!.pubkey, - tokenOwnerRecord, - form.title || - `Deposit ${fmtAmount} ${ - tokenService.getTokenInfo( - matchedTreasury.extensions.mint!.publicKey.toBase58() - )?.symbol || 'tokens' - } to Mango account`, - form.description, - governingTokenMint, - proposalIndex, - insts, - isDraft, - client - ) - return proposalAddress -} - -export const tryGetMangoAccount = async ( - market: MarketStore, - mangoAccountPk: PublicKey -) => { - try { - const account = await market.client?.getMangoAccount( - mangoAccountPk, - market.group!.dexProgramId - ) - return account - } catch (e) { - return null - } -} - -export const tryGetMangoAccountsForOwner = async ( - market: MarketStore, - ownerPk: PublicKey -) => { - try { - const accounts = await market.client?.getMangoAccountsForOwner( - market.group!, - ownerPk - ) - return accounts - } catch (e) { - return null - } -} - -export const ASSET_TYPE = [ - { - name: 'Token', - value: 0, - }, - { - name: 'Perp', - value: 1, - }, -] - -export const MARKET_MODE = [ - { - name: 'Default', - value: 0, - }, - { - name: 'Active', - value: 1, - }, - { - name: 'Close Only', - value: 2, - }, - { - name: 'Force Close Only', - value: 3, - }, - { - name: 'Inactive', - value: 4, - }, - { - name: 'Swapping Spot Market', - value: 5, - }, -] diff --git a/Strategies/protocols/psyfi/actions/deposit.ts b/Strategies/protocols/psyfi/actions/deposit.ts new file mode 100644 index 0000000000..826df3e4a8 --- /dev/null +++ b/Strategies/protocols/psyfi/actions/deposit.ts @@ -0,0 +1,179 @@ +import { Program } from '@coral-xyz/anchor' +import { + RpcContext, + serializeInstructionToBase64, +} from '@solana/spl-governance' +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + NATIVE_MINT, + Token, + TOKEN_PROGRAM_ID, +} from '@solana/spl-token' +import { + PublicKey, + SystemProgram, + TransactionInstruction, + LAMPORTS_PER_SOL, +} from '@solana/web3.js' +import { AssetAccount } from '@utils/uiTypes/assets' +import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes' +import { InstructionDataWithHoldUpTime } from 'actions/createProposal' +import { instructions as psyFiInstructions, PsyFiEuros } from 'psyfi-euros-test' +import { PsyFiActionForm, PsyFiStrategyInfo } from '../types' +import { syncNative } from '@solendprotocol/solend-sdk' + +export const deposit = async ( + rpcContext: RpcContext, + treasuryAssetAccount: AssetAccount, + psyFiProgram: Program, + psyFiStrategyInfo: PsyFiStrategyInfo, + form: PsyFiActionForm, + owner: PublicKey, + transferAddress: PublicKey +) => { + const instructions: InstructionDataWithHoldUpTime[] = [] + + let vaultOwnershipAccount: PublicKey | undefined = + psyFiStrategyInfo.ownedStrategyTokenAccount?.pubkey + const prerequisiteInstructions: TransactionInstruction[] = [] + + let coreDepositIx: TransactionInstruction + const serializedTransferToReceiptIxs: string[] = [] + + // If the lp token account does not exist, add it to the pre-requisite instructions + if (!vaultOwnershipAccount) { + const address = await Token.getAssociatedTokenAddress( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + form.strategy.vaultAccounts.lpTokenMint, + owner, + true + ) + const createAtaIx = Token.createAssociatedTokenAccountInstruction( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + form.strategy.vaultAccounts.lpTokenMint, + address, + owner, + rpcContext.walletPubkey + ) + prerequisiteInstructions.push(createAtaIx) + vaultOwnershipAccount = address + } + + let poolMintATA + + // If the pool mint associated token account does not exist, add it to the pre-requisite instructions + + if (form.amount && treasuryAssetAccount.isSol) { + poolMintATA = await Token.getAssociatedTokenAddress( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + NATIVE_MINT, + owner, + true + ) + + if ( + (await psyFiProgram.provider.connection.getAccountInfo(poolMintATA)) === + null + ) { + prerequisiteInstructions.push( + Token.createAssociatedTokenAccountInstruction( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + NATIVE_MINT, + poolMintATA, + owner, + rpcContext.walletPubkey + ) + ) + } + + const wsolTransferIx = SystemProgram.transfer({ + fromPubkey: owner, + toPubkey: poolMintATA, + lamports: form.amount * LAMPORTS_PER_SOL, + }) + + serializedTransferToReceiptIxs.push( + serializeInstructionToBase64(wsolTransferIx) + ) + serializedTransferToReceiptIxs.push( + serializeInstructionToBase64(syncNative(poolMintATA)) + ) + } + + // Check if the vault requires a deposit receipt + if (form.strategy.vaultInfo.status.optionsActive) { + if (!psyFiStrategyInfo.depositReceipt) { + // Add init deposit receipt instruction + const initReceiptIx = await psyFiInstructions.initializeDepositReceiptInstruction( + // @ts-ignore: Anchor version differences. + psyFiProgram, + form.strategy.vaultInfo.status.currentEpoch, + owner, + form.strategy.vaultAccounts.pubkey + ) + const uiInstruction: UiInstruction = { + governance: treasuryAssetAccount.governance, + serializedInstruction: serializeInstructionToBase64(initReceiptIx), + prerequisiteInstructions: [], + isValid: true, + customHoldUpTime: + treasuryAssetAccount.governance.account.config + .minInstructionHoldUpTime, + } + const initReceiptFullPropIx = new InstructionDataWithHoldUpTime({ + instruction: uiInstruction, + }) + instructions.push(initReceiptFullPropIx) + } + + // Create transfer to deposit receipt instruction + coreDepositIx = await psyFiInstructions.transferToDepositReceiptInstruction( + // @ts-ignore: Anchor version differences. + psyFiProgram, + form.bnAmount, + form.strategy.vaultInfo.status.currentEpoch, + owner, + form.strategy.vaultAccounts.pubkey, + treasuryAssetAccount.isSol ? poolMintATA : transferAddress + ) + + serializedTransferToReceiptIxs.push( + serializeInstructionToBase64(coreDepositIx) + ) + } else { + // Create the actual deposit instruction + coreDepositIx = await psyFiInstructions.depositInstruction( + // @ts-ignore: Anchor version differences. + psyFiProgram, + form.bnAmount, + owner, + form.strategy.vaultAccounts.pubkey, + transferAddress, + vaultOwnershipAccount + ) + serializedTransferToReceiptIxs.push( + serializeInstructionToBase64(coreDepositIx) + ) + } + + // Create the InstructionDataWithHoldUpTime + const uiInstruction: UiInstruction = { + governance: treasuryAssetAccount.governance, + serializedInstruction: serializedTransferToReceiptIxs[0], + additionalSerializedInstructions: + serializedTransferToReceiptIxs.slice(1) || [], + prerequisiteInstructions, + isValid: true, + customHoldUpTime: + treasuryAssetAccount.governance.account.config.minInstructionHoldUpTime, + } + const fullPropInstruction = new InstructionDataWithHoldUpTime({ + instruction: uiInstruction, + }) + instructions.push(fullPropInstruction) + return instructions +} diff --git a/Strategies/protocols/psyfi/index.ts b/Strategies/protocols/psyfi/index.ts new file mode 100644 index 0000000000..59ab191f22 --- /dev/null +++ b/Strategies/protocols/psyfi/index.ts @@ -0,0 +1,203 @@ +import { ConnectionContext } from '@utils/connection' +import { PsyFiStrategy } from 'Strategies/types/types' +import axios from 'axios' + +import { + Action, + CreatePsyFiStrategy, + PsyFiActionForm, + PsyFiStrategyInfo, + Strategy, + TokenGroupedVaults, + VaultInfo, +} from './types' +import tokenPriceService from '@utils/services/tokenPrice' +import { + ProgramAccount, + Realm, + RpcContext, + TokenOwnerRecord, +} from '@solana/spl-governance' +import { Program } from '@coral-xyz/anchor' +import { AssetAccount } from '@utils/uiTypes/assets' +import { PublicKey } from '@solana/web3.js' +import { VotingClient } from '@utils/uiTypes/VotePlugin' +import { + createProposal, + InstructionDataWithHoldUpTime, +} from 'actions/createProposal' +import { deriveVaultCollateralAccount } from 'Strategies/components/psyfi/pdas' +import { MAINNET_PROGRAM_KEYS } from 'Strategies/components/psyfi/programIds' + +import { PsyFiEuros } from 'psyfi-euros-test' +import { deposit } from './actions/deposit' + +export const getVaultInfos = async (): Promise => { + const res = await axios.get( + `https://us-central1-psyfi-api.cloudfunctions.net/vaults?env=mainnet` + ) + const vaultInfos = Object.values(res.data.vaults as any) as VaultInfo[] + return vaultInfos +} + +const handleVaultAction: CreatePsyFiStrategy = async ( + rpcContext: RpcContext, + form: PsyFiActionForm, + psyFiProgram: Program, + psyFiStrategyInfo: PsyFiStrategyInfo, + realm: ProgramAccount, + treasuryAssetAccount: AssetAccount, + tokenOwnerRecord: ProgramAccount, + governingTokenMint: PublicKey, + proposalIndex: number, + isDraft: boolean, + connection: ConnectionContext, + client?: VotingClient +) => { + const owner = treasuryAssetAccount.isSol + ? treasuryAssetAccount!.pubkey + : treasuryAssetAccount!.extensions!.token!.account.owner + const transferAddress = treasuryAssetAccount.extensions.transferAddress! + + let instructions: InstructionDataWithHoldUpTime[] = [] + + if (form.action === Action.Deposit) { + instructions = await deposit( + rpcContext, + treasuryAssetAccount, + psyFiProgram, + psyFiStrategyInfo, + form, + owner, + transferAddress + ) + } + + console.log('*** instructions', instructions) + + const proposalAddress = await createProposal( + rpcContext, + realm, + treasuryAssetAccount.governance!.pubkey, + tokenOwnerRecord, + form.title, + form.description, + governingTokenMint, + proposalIndex, + instructions, + isDraft, + ["Approve"], + client + ) + return proposalAddress +} + +export const convertVaultInfoToStrategy = async ( + vaultInfo: VaultInfo, + otherStrategies: PsyFiStrategy[] | undefined +): Promise => { + let strategyName = '' + if (vaultInfo.strategyType === Strategy.Call) { + strategyName = vaultInfo.name + } else if (vaultInfo.strategyType === Strategy.Put) { + strategyName = vaultInfo.name + } + const handledMint = vaultInfo.accounts.collateralAssetMint + const tokenInfo = await tokenPriceService.getTokenInfo(handledMint) + if (!tokenInfo) { + return + } + const apyPercentage = vaultInfo.apy.movingAverageApy.apyAfterFees.toFixed(2) + const vaultPubkey = new PublicKey(vaultInfo.accounts.vaultAddress) + const [collateralAccountKey] = await deriveVaultCollateralAccount( + MAINNET_PROGRAM_KEYS.PSYFI_V2, + vaultPubkey + ) + const strategy: PsyFiStrategy = { + liquidity: vaultInfo.deposits.current, + protocolSymbol: 'PSY', + apy: `Estimated ${apyPercentage}%`, + apyHeader: `Projected Yield`, + protocolName: 'PsyFi', + handledMint, + handledTokenSymbol: tokenInfo.symbol, + handledTokenImgSrc: tokenInfo.logoURI || '', + protocolLogoSrc: + 'https://user-images.githubusercontent.com/32071703/149460918-3694084f-2a37-4c95-93d3-b5aaf078d444.png', + strategyName, + strategyDescription: 'Description', + isGenericItem: false, + createProposalFcn: handleVaultAction, + otherStrategies: otherStrategies ?? [], + vaultInfo: vaultInfo, + vaultAccounts: { + pubkey: vaultPubkey, + lpTokenMint: new PublicKey(vaultInfo.accounts.vaultOwnershipTokenMint), + collateralAccountKey, + }, + } + return strategy +} + +export const getPsyFiStrategies = async (): Promise => { + const vaultInfos = await getVaultInfos() + + // group strategies by token + const groupedVaults = groupVaultsByToken(vaultInfos) + + // Change how strategies are created using a custom type that has all token strategies + // as additionalStrategies. + return psyFiVestingStrategies(groupedVaults) +} + +const psyFiVestingStrategies = async ( + groupedVaults: TokenGroupedVaults +): Promise => { + const res = await Promise.all( + Object.keys(groupedVaults).map(async (collateralTokenAddress) => { + const strategies = groupedVaults[collateralTokenAddress] + const topVault = strategies[0] + if (!topVault) { + // This should be unreachable + throw new Error(`No vault found for ${collateralTokenAddress}`) + } + const otherStrategies = await Promise.all( + strategies.map( + async (x) => await convertVaultInfoToStrategy(x, undefined) + ) + ) + return convertVaultInfoToStrategy( + topVault, + // @ts-ignore: + otherStrategies.filter((x) => !!x) + ) + }) + ) + + // @ts-ignore + return res.filter((x) => !!x) +} + +/** + * Given an array for VaultInfos, group by collateral token and sort the groups by APY + */ +const groupVaultsByToken = (vaultInfos: VaultInfo[]) => { + const res: TokenGroupedVaults = {} + vaultInfos.forEach((vaultInfo) => { + if (res[vaultInfo.accounts.collateralAssetMint]) { + const strategies = res[vaultInfo.accounts.collateralAssetMint] + strategies.push(vaultInfo) + strategies.sort((a, b) => { + return ( + b.apy.movingAverageApy.apyAfterFees - + a.apy.movingAverageApy.apyAfterFees + ) + }) + res[vaultInfo.accounts.collateralAssetMint] = strategies + } else { + res[vaultInfo.accounts.collateralAssetMint] = [vaultInfo] + } + }) + + return res +} diff --git a/Strategies/protocols/psyfi/types.ts b/Strategies/protocols/psyfi/types.ts new file mode 100644 index 0000000000..3fb986460b --- /dev/null +++ b/Strategies/protocols/psyfi/types.ts @@ -0,0 +1,174 @@ +import { BN, Program } from '@coral-xyz/anchor' +import { + ProgramAccount, + Realm, + RpcContext, + TokenOwnerRecord, +} from '@solana/spl-governance' +import { PublicKey } from '@solana/web3.js' +import { ConnectionContext } from '@utils/connection' +import { AssetAccount } from '@utils/uiTypes/assets' +import { VotingClient } from '@utils/uiTypes/VotePlugin' +import { PsyFiEuros } from 'psyfi-euros-test' +import { PsyFiStrategy } from 'Strategies/types/types' + +export type PsyFiStrategyForm = { + strategy: PsyFiStrategy + title: string + description: string + amount?: number +} + +export type PsyFiActionForm = PsyFiStrategyForm & { + action: Action + bnAmount: BN +} + +export type CreatePsyFiStrategy = ( + rpcContext: RpcContext, + form: { + title: string + description: string + action: Action + bnAmount: BN + strategy: PsyFiStrategy + }, + psyFiProgram: Program, + psyFiStrategyInfo: PsyFiStrategyInfo, + realm: ProgramAccount, + treasuaryAccount: AssetAccount, + tokenOwnerRecord: ProgramAccount, + governingTokenMint: PublicKey, + proposalIndex: number, + isDraft: boolean, + connection: ConnectionContext, + client?: VotingClient +) => Promise + +export type PsyFiStrategyInfo = { + depositReceipt: DepositReceipt | undefined + depositReceiptPubkey: PublicKey + ownedStrategyTokenAccount: AssetAccount | undefined +} + +export type DepositReceipt = { + vaultAccount: PublicKey + epochHistory: PublicKey + receiptOwner: PublicKey // Owner of funds deposited. + depositAmount: BN // In collateral asset + bump: number + lockupPeriod: number // Lockup period if vault tokens are staked. + forStaking: boolean // If vault tokens should be staked. + stakingRecord: PublicKey // Destination of vault tokens, if staking. +} + +export enum Strategy { + Call = 0, + Put = 1, +} + +export type StrategyInfo = { + currentDeposits: number +} + +export enum Action { + Deposit = 0, + Withdraw = 1, +} + +export enum VaultVisibility { + Development, + Staging, + Production, +} + +export type PoolReward = { + metadata?: { + rewardPoolApr?: number[] + rewardInUsdPerYearPerRewardUnit?: number + usdValuePerRewardToken?: number + } + tokenSymbol: string + rewardPoolKey: string + rewardTokensPerWeek: number + rewardMintAddress: string + multiplier: number + poolId: number +} + +export type VaultInfo = { + id: string + name: string + version: number + strategyType: Strategy + visibility: VaultVisibility + accounts: { + vaultAddress: string + collateralAssetMint: string + vaultOwnershipTokenMint: string + optionsUnderlyingMint: string + pythPriceOracle: string + feeTokenAccount: string + } + deposits: { + current: number + max: number + } + fees: { + performance: number + withdrawal: number + } + status: { + currentEpoch: number + optionsActive: boolean + nextEpochStartTime: number + nextOptionMintTime: number + isDeprecated: boolean + } + stakingProviderUrl?: string + selectedStrike?: number + apy: { + currentEpochApy: number + stakingApy: number + movingAverageApy: { + apyBeforeFees: number + apyAfterFees: number + epochsCounted: number + averageEpochYield: number // Value before fees. + } + weightedApy: { + targetDelta: number + averageHistoricalLoss: number + epochsCounted: number + averageSaleYield: number + apyBeforeFees: number + apyAfterFees: number + } + } + vaultHistory: VaultHistory[] + valuePerVaultToken: number + staking?: { + metadata?: { + usdValuePerVaultToken?: number + } + stakePoolKey: string + stakingApr: number[] + poolRewards: PoolReward[] + } +} + +export type VaultHistory = { + saleAmount: number + saleYield: number + priceAtExpiry: number + endingValuePerVaultToken: number + strikePrice: number + overallYield: number + percentageLossOnCollateral: number + epoch: number + optionMinted: string + startDate: number + epochHistoryKey: string +} + +export type TokenGroupedVaults = Record diff --git a/Strategies/protocols/solend/index.ts b/Strategies/protocols/solend/index.ts index 3289dd0e29..a62b6664d7 100644 --- a/Strategies/protocols/solend/index.ts +++ b/Strategies/protocols/solend/index.ts @@ -1,4 +1,4 @@ -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { ProgramAccount, Realm, @@ -19,7 +19,7 @@ import { redeemReserveCollateralInstruction, syncNative, } from '@solendprotocol/solend-sdk' -import tokenService from '@utils/services/token' +import tokenPriceService from '@utils/services/tokenPrice' import { createProposal, InstructionDataWithHoldUpTime, @@ -141,15 +141,23 @@ export async function getReserveData( reserveIds: Array ): Promise> { if (!reserveIds.length) return [] - const stats = ( - await ( - await axios.get( - `${SOLEND_ENDPOINT}/v1/reserves?ids=${reserveIds.join(',')}` - ) - ).data - ).results as Array - return stats + const res = reserveIds.flat().reduce((acc, _curr, i) => { + if (!(i % 50)) { + acc.push(reserveIds.flat().slice(i, i + 50)) + } + return acc + }, [] as string[][]) + + const stats = await Promise.all( + res.map((reserveIds) => + axios.get(`${SOLEND_ENDPOINT}/v1/reserves?ids=${reserveIds.join(',')}`) + ) + ) + + return (await Promise.all(stats.map((stat) => stat.data))).flatMap( + (stat) => stat.results + ) } export function cTokenExchangeRate(reserve: ReserveStat) { @@ -163,18 +171,12 @@ export function cTokenExchangeRate(reserve: ReserveStat) { export async function getReserve(): Promise { return await ( - await axios.get(`${SOLEND_ENDPOINT}/v1/markets/configs?scope=solend`) - ).data -} - -export async function getConfig(): Promise { - return await ( - await axios.get(`${SOLEND_ENDPOINT}/v1/markets/configs?scope=solend`) + await axios.get(`${SOLEND_ENDPOINT}/v1/markets/configs?scope=all`) ).data } export async function getReserves(): Promise { - const config = await getConfig() + const config = await getReserve() const reserves = config.flatMap((market) => market.reserves.map((reserve) => ({ marketName: market.name, @@ -193,7 +195,7 @@ export async function getSolendStrategies() { const strats: SolendStrategy[] = [] // method to fetch solend strategies - const config = await getConfig() + const config = await getReserve() const reserves = config.flatMap((market) => market.reserves.map((reserve) => ({ marketName: market.name, @@ -334,7 +336,7 @@ async function handleSolendAction( const withdrawAccountInfo = await connection.current.getAccountInfo( liquidityATA ) - if (!withdrawAccountInfo) { + if (!withdrawAccountInfo && !isSol) { // generate the instruction for creating the ATA createAtaInst = Token.createAssociatedTokenAccountInstruction( ASSOCIATED_TOKEN_PROGRAM_ID, @@ -355,7 +357,6 @@ async function handleSolendAction( holdUpTime: matchedTreasury.governance!.account!.config .minInstructionHoldUpTime, prerequisiteInstructions: [], - chunkSplitByDefault: true, } insts.push(createAtaInstObj) } @@ -389,7 +390,6 @@ async function handleSolendAction( holdUpTime: matchedTreasury.governance!.account!.config .minInstructionHoldUpTime, prerequisiteInstructions: [], - chunkSplitByDefault: true, } setupInsts.push(transferLamportInst) @@ -409,7 +409,6 @@ async function handleSolendAction( holdUpTime: matchedTreasury.governance!.account!.config .minInstructionHoldUpTime, prerequisiteInstructions: [], - chunkSplitByDefault: true, } if (userWSOLAccountInfo) { @@ -421,7 +420,6 @@ async function handleSolendAction( holdUpTime: matchedTreasury.governance!.account!.config .minInstructionHoldUpTime, prerequisiteInstructions: [], - chunkSplitByDefault: true, } if (sendAction) { setupInsts.push(syncInst) @@ -444,7 +442,6 @@ async function handleSolendAction( holdUpTime: matchedTreasury.governance!.account!.config .minInstructionHoldUpTime, prerequisiteInstructions: [], - chunkSplitByDefault: true, } setupInsts.push(createUserWSOLAccountInst) cleanupInsts.push(closeWSOLInst) @@ -483,7 +480,6 @@ async function handleSolendAction( holdUpTime: matchedTreasury.governance!.account!.config .minInstructionHoldUpTime, prerequisiteInstructions: [], - chunkSplitByDefault: true, } insts.push(depositSolendInsObj) @@ -494,7 +490,7 @@ async function handleSolendAction( tokenOwnerRecord, form.title || `${form.action} ${form.amountFmt} ${ - tokenService.getTokenInfo( + tokenPriceService.getTokenInfo( matchedTreasury.extensions.mint!.publicKey.toBase58() )?.symbol || 'tokens' } ${form.action === 'Deposit' ? 'into' : 'from'} the Solend ${ @@ -505,6 +501,7 @@ async function handleSolendAction( proposalIndex, [...setupInsts, ...insts, ...cleanupInsts], isDraft, + ["Approve"], client ) return proposalAddress diff --git a/Strategies/store/marketStore.tsx b/Strategies/store/marketStore.tsx deleted file mode 100644 index 759abd8330..0000000000 --- a/Strategies/store/marketStore.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import create, { State } from 'zustand' -import { - Config, - getMarketIndexBySymbol, - GroupConfig, - MangoCache, - MangoClient, - MangoGroup, - PerpMarket, - PerpMarketConfig, - PerpMarketInfo, - RootBank, - TokenInfo, -} from '@blockworks-foundation/mango-client' -import { ConnectionContext } from '@utils/connection' -import { Connection } from '@solana/web3.js' - -export interface MarketStore extends State { - groupConfig?: GroupConfig - marketConfig?: PerpMarketConfig - cache?: MangoCache - client?: MangoClient - group?: MangoGroup - info?: PerpMarketInfo - market?: PerpMarket - indexPrice?: number - quoteCurrency?: TokenInfo - quoteRootBank?: RootBank - loadMarket: (connection: ConnectionContext, cluster: string) => void -} -const useMarketStore = create((set, _get) => ({ - loadMarket: async (connection: ConnectionContext, cluster: string) => { - const GROUP = cluster === 'devnet' ? 'devnet.2' : 'mainnet.1' - const mangoConnection = - cluster === 'localnet' - ? new Connection(Config.ids().cluster_urls.mainnet) - : connection.current - const groupConfig = Config.ids().getGroupWithName(GROUP)! - const DEFAULT_MARKET = 'SOL' - const DEFAULT_MARKET_INDEX = getMarketIndexBySymbol( - groupConfig, - DEFAULT_MARKET - ) - const marketConfig = groupConfig?.perpMarkets[DEFAULT_MARKET_INDEX] - const client = new MangoClient(mangoConnection, groupConfig.mangoProgramId) - const group = await client.getMangoGroup(groupConfig.publicKey) - - const [perpMarket] = await Promise.all([ - group.loadPerpMarket( - mangoConnection, - marketConfig.marketIndex, - marketConfig.baseDecimals, - marketConfig.quoteDecimals - ), - group.loadRootBanks(mangoConnection), - ]) - - const cache = await group.loadCache(mangoConnection) - const indexPrice = group.getPriceUi(marketConfig.marketIndex, cache) - set((s: MarketStore) => { - s.groupConfig = groupConfig - s.marketConfig = marketConfig - s.market = perpMarket - s.client = client - s.group = group - s.info = group.perpMarkets[marketConfig.marketIndex] - s.cache = cache - s.indexPrice = indexPrice - }) - }, -})) - -export default useMarketStore diff --git a/Strategies/store/useStrategiesStore.tsx b/Strategies/store/useStrategiesStore.tsx index 3e39e96c22..4a736a3033 100644 --- a/Strategies/store/useStrategiesStore.tsx +++ b/Strategies/store/useStrategiesStore.tsx @@ -1,31 +1,30 @@ -import { ConnectionContext } from '@utils/connection' import { notify } from '@utils/notifications' -import { tvl } from 'Strategies/protocols/mango/tools' +import { getPsyFiStrategies } from 'Strategies/protocols/psyfi' import { getSolendStrategies } from 'Strategies/protocols/solend' import { TreasuryStrategy } from 'Strategies/types/types' import create, { State } from 'zustand' -import { getEverlendStrategies } from '../protocols/everlend/tools' interface StrategiesStore extends State { strategies: TreasuryStrategy[] strategiesLoading: boolean - getStrategies: (connection: ConnectionContext) => void + getStrategies: () => void } const useStrategiesStore = create((set, _get) => ({ strategies: [], strategiesLoading: false, - getStrategies: async (connection: ConnectionContext) => { + getStrategies: async () => { set((s) => { s.strategiesLoading = true }) try { - const mango = await tvl(Date.now() / 1000, connection) - const solend = await getSolendStrategies() - const everlend = await getEverlendStrategies(connection) + const [solend, psyfi] = await Promise.all([ + getSolendStrategies(), + getPsyFiStrategies(), + ]) //add fetch functions for your protocol in promise.all - const strategies: TreasuryStrategy[] = [...solend, ...mango, ...everlend] + const strategies: TreasuryStrategy[] = [...solend, ...psyfi] set((s) => { s.strategies = strategies diff --git a/Strategies/types/types.ts b/Strategies/types/types.ts index 51b1f7c0a1..49f1e1cabd 100644 --- a/Strategies/types/types.ts +++ b/Strategies/types/types.ts @@ -1,24 +1,16 @@ -import { MangoAccount } from '@blockworks-foundation/mango-client' -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 { MarketStore } from 'Strategies/store/marketStore' +import { PublicKey } from '@solana/web3.js' import { CreateSolendStrategyParams, SolendSubStrategy, } from 'Strategies/protocols/solend' +import { VaultInfo } from 'Strategies/protocols/psyfi/types' export interface TreasuryStrategy { //liquidity in $ liquidity: number protocolSymbol: string apy: string + apyHeader?: string protocolName: string strategySubtext?: string handledMint: string @@ -31,26 +23,33 @@ export interface TreasuryStrategy { //item and modal to strategywrapper component based on generic components isGenericItem?: boolean createProposalFcn: any + /** 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 createProposalFcn: CreateSolendStrategyParams } -export type EverlendStrategy = TreasuryStrategy & { - poolMint: string - decimals: number - rateEToken: number +export type PsyFiStrategy = TreasuryStrategy & { + vaultAccounts: { + pubkey: PublicKey + lpTokenMint: PublicKey + collateralAccountKey: PublicKey + } + vaultInfo: VaultInfo + otherStrategies: Array } -export type HandleCreateProposalWithStrategy = ( +/* +type HandleCreateProposalWithStrategy = ( { connection, wallet, programId, programVersion, walletPubkey }: RpcContext, handledMint: string, form: MNGODepositForm, @@ -61,22 +60,16 @@ export type HandleCreateProposalWithStrategy = ( proposalIndex: number, prerequisiteInstructions: TransactionInstruction[], isDraft: boolean, - market?: MarketStore, client?: VotingClient -) => Promise - -export interface NameVal { - name: string - val: string | null -} - -export type MNGODepositForm = { +) => Promise */ +/* +type MNGODepositForm = { mintAmount: number delegateDeposit: boolean delegateAddress: string mangoAccountPk: PublicKey | null - mangoAccounts: MangoAccount[] title: string description: string proposalCount: number } + */ diff --git a/SwitchboardVotePlugin/SwitchboardIdl.ts b/SwitchboardVotePlugin/SwitchboardIdl.ts deleted file mode 100644 index 4e1eac7ded..0000000000 --- a/SwitchboardVotePlugin/SwitchboardIdl.ts +++ /dev/null @@ -1,9714 +0,0 @@ -export type Switchboard = { - version: '0.1.0' - name: 'switchboard_v2' - instructions: [ - { - name: 'aggregatorAddJob' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - }, - { - name: 'job' - isMut: true - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorAddJobParams' - } - } - ] - }, - { - name: 'aggregatorInit' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: false - }, - { - name: 'queue' - isMut: false - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorInitParams' - } - } - ] - }, - { - name: 'aggregatorLock' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: true - isSigner: true - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorLockParams' - } - } - ] - }, - { - name: 'aggregatorOpenRound' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'lease' - isMut: true - isSigner: false - }, - { - name: 'oracleQueue' - isMut: true - isSigner: false - }, - { - name: 'queueAuthority' - isMut: false - isSigner: false - }, - { - name: 'permission' - isMut: true - isSigner: false - }, - { - name: 'escrow' - isMut: true - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'payoutWallet' - isMut: true - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - }, - { - name: 'dataBuffer' - isMut: false - isSigner: false - }, - { - name: 'mint' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorOpenRoundParams' - } - } - ] - }, - { - name: 'aggregatorRemoveJob' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - }, - { - name: 'job' - isMut: true - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorRemoveJobParams' - } - } - ] - }, - { - name: 'aggregatorSaveResult' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'oracle' - isMut: true - isSigner: false - }, - { - name: 'oracleAuthority' - isMut: false - isSigner: true - }, - { - name: 'oracleQueue' - isMut: false - isSigner: false - }, - { - name: 'queueAuthority' - isMut: false - isSigner: false - }, - { - name: 'feedPermission' - isMut: true - isSigner: false - }, - { - name: 'oraclePermission' - isMut: false - isSigner: false - }, - { - name: 'lease' - isMut: true - isSigner: false - }, - { - name: 'escrow' - isMut: true - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'historyBuffer' - isMut: true - isSigner: false - }, - { - name: 'mint' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorSaveResultParams' - } - } - ] - }, - { - name: 'aggregatorSetAuthority' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - }, - { - name: 'newAuthority' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorSetAuthorityParams' - } - } - ] - }, - { - name: 'aggregatorSetBatchSize' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorSetBatchSizeParams' - } - } - ] - }, - { - name: 'aggregatorSetHistoryBuffer' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - }, - { - name: 'buffer' - isMut: true - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorSetHistoryBufferParams' - } - } - ] - }, - { - name: 'aggregatorSetMinJobs' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorSetMinJobsParams' - } - } - ] - }, - { - name: 'aggregatorSetMinOracles' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorSetMinOraclesParams' - } - } - ] - }, - { - name: 'aggregatorSetQueue' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - }, - { - name: 'queue' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorSetQueueParams' - } - } - ] - }, - { - name: 'aggregatorSetUpdateInterval' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorSetUpdateIntervalParams' - } - } - ] - }, - { - name: 'aggregatorSetVarianceThreshold' - accounts: [ - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - } - ] - args: [ - { - name: 'params' - type: { - defined: 'AggregatorSetVarianceThresholdParams' - } - } - ] - }, - { - name: 'crankInit' - accounts: [ - { - name: 'crank' - isMut: true - isSigner: true - }, - { - name: 'queue' - isMut: false - isSigner: false - }, - { - name: 'buffer' - isMut: true - isSigner: false - }, - { - name: 'payer' - isMut: true - isSigner: false - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'CrankInitParams' - } - } - ] - }, - { - name: 'crankPop' - accounts: [ - { - name: 'crank' - isMut: true - isSigner: false - }, - { - name: 'oracleQueue' - isMut: true - isSigner: false - }, - { - name: 'queueAuthority' - isMut: false - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'payoutWallet' - isMut: true - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - }, - { - name: 'crankDataBuffer' - isMut: true - isSigner: false - }, - { - name: 'queueDataBuffer' - isMut: false - isSigner: false - }, - { - name: 'mint' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'CrankPopParams' - } - } - ] - }, - { - name: 'crankPush' - accounts: [ - { - name: 'crank' - isMut: true - isSigner: false - }, - { - name: 'aggregator' - isMut: true - isSigner: false - }, - { - name: 'oracleQueue' - isMut: true - isSigner: false - }, - { - name: 'queueAuthority' - isMut: false - isSigner: false - }, - { - name: 'permission' - isMut: false - isSigner: false - }, - { - name: 'lease' - isMut: true - isSigner: false - }, - { - name: 'escrow' - isMut: true - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'dataBuffer' - isMut: true - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'CrankPushParams' - } - } - ] - }, - { - name: 'jobInit' - accounts: [ - { - name: 'job' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'JobInitParams' - } - } - ] - }, - { - name: 'leaseExtend' - accounts: [ - { - name: 'lease' - isMut: true - isSigner: false - }, - { - name: 'aggregator' - isMut: false - isSigner: false - }, - { - name: 'queue' - isMut: false - isSigner: false - }, - { - name: 'funder' - isMut: true - isSigner: false - }, - { - name: 'owner' - isMut: true - isSigner: true - }, - { - name: 'escrow' - isMut: true - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'mint' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'LeaseExtendParams' - } - } - ] - }, - { - name: 'leaseInit' - accounts: [ - { - name: 'lease' - isMut: true - isSigner: false - }, - { - name: 'queue' - isMut: true - isSigner: false - }, - { - name: 'aggregator' - isMut: false - isSigner: false - }, - { - name: 'funder' - isMut: true - isSigner: false - }, - { - name: 'payer' - isMut: true - isSigner: true - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - }, - { - name: 'owner' - isMut: true - isSigner: true - }, - { - name: 'escrow' - isMut: true - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'mint' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'LeaseInitParams' - } - } - ] - }, - { - name: 'leaseSetAuthority' - accounts: [ - { - name: 'lease' - isMut: true - isSigner: false - }, - { - name: 'withdrawAuthority' - isMut: false - isSigner: true - }, - { - name: 'newAuthority' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'LeaseSetAuthorityParams' - } - } - ] - }, - { - name: 'leaseWithdraw' - accounts: [ - { - name: 'lease' - isMut: true - isSigner: false - }, - { - name: 'escrow' - isMut: true - isSigner: false - }, - { - name: 'aggregator' - isMut: false - isSigner: false - }, - { - name: 'queue' - isMut: false - isSigner: false - }, - { - name: 'withdrawAuthority' - isMut: false - isSigner: true - }, - { - name: 'withdrawAccount' - isMut: true - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'mint' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'LeaseWithdrawParams' - } - } - ] - }, - { - name: 'oracleHeartbeat' - accounts: [ - { - name: 'oracle' - isMut: true - isSigner: false - }, - { - name: 'oracleAuthority' - isMut: false - isSigner: true - }, - { - name: 'tokenAccount' - isMut: false - isSigner: false - }, - { - name: 'gcOracle' - isMut: true - isSigner: false - }, - { - name: 'oracleQueue' - isMut: true - isSigner: false - }, - { - name: 'permission' - isMut: false - isSigner: false - }, - { - name: 'dataBuffer' - isMut: true - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'OracleHeartbeatParams' - } - } - ] - }, - { - name: 'oracleInit' - accounts: [ - { - name: 'oracle' - isMut: true - isSigner: false - }, - { - name: 'oracleAuthority' - isMut: false - isSigner: false - }, - { - name: 'wallet' - isMut: false - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'queue' - isMut: false - isSigner: false - }, - { - name: 'payer' - isMut: true - isSigner: false - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'OracleInitParams' - } - } - ] - }, - { - name: 'oracleQueueInit' - accounts: [ - { - name: 'oracleQueue' - isMut: true - isSigner: true - }, - { - name: 'authority' - isMut: false - isSigner: false - }, - { - name: 'buffer' - isMut: true - isSigner: false - }, - { - name: 'payer' - isMut: true - isSigner: false - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - }, - { - name: 'mint' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'OracleQueueInitParams' - } - } - ] - }, - { - name: 'oracleQueueSetRewards' - accounts: [ - { - name: 'queue' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - } - ] - args: [ - { - name: 'params' - type: { - defined: 'OracleQueueSetRewardsParams' - } - } - ] - }, - { - name: 'oracleQueueVrfConfig' - accounts: [ - { - name: 'queue' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - } - ] - args: [ - { - name: 'params' - type: { - defined: 'OracleQueueVrfConfigParams' - } - } - ] - }, - { - name: 'oracleWithdraw' - accounts: [ - { - name: 'oracle' - isMut: true - isSigner: false - }, - { - name: 'oracleAuthority' - isMut: false - isSigner: true - }, - { - name: 'tokenAccount' - isMut: true - isSigner: false - }, - { - name: 'withdrawAccount' - isMut: true - isSigner: false - }, - { - name: 'oracleQueue' - isMut: true - isSigner: false - }, - { - name: 'permission' - isMut: true - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'payer' - isMut: true - isSigner: true - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'OracleWithdrawParams' - } - } - ] - }, - { - name: 'permissionInit' - accounts: [ - { - name: 'permission' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: false - }, - { - name: 'granter' - isMut: false - isSigner: false - }, - { - name: 'grantee' - isMut: false - isSigner: false - }, - { - name: 'payer' - isMut: true - isSigner: true - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'PermissionInitParams' - } - } - ] - }, - { - name: 'permissionSet' - accounts: [ - { - name: 'permission' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - } - ] - args: [ - { - name: 'params' - type: { - defined: 'PermissionSetParams' - } - } - ] - }, - { - name: 'permissionSetVoterWeight' - accounts: [ - { - name: 'permission' - isMut: false - isSigner: false - }, - { - name: 'permissionAuthority' - isMut: false - isSigner: false - }, - { - name: 'oracle' - isMut: false - isSigner: false - }, - { - name: 'oracleAuthority' - isMut: false - isSigner: false - }, - { - name: 'payer' - isMut: true - isSigner: true - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'govProgram' - isMut: false - isSigner: false - }, - { - name: 'daoMint' - isMut: false - isSigner: false - }, - { - name: 'spawnRecord' - isMut: true - isSigner: false - }, - { - name: 'voterWeight' - isMut: true - isSigner: false - }, - { - name: 'tokenOwnerRecord' - isMut: true - isSigner: false - }, - { - name: 'realm' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'PermissionSetVoterWeightParams' - } - } - ] - }, - { - name: 'programConfig' - accounts: [ - { - name: 'authority' - isMut: false - isSigner: true - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'daoMint' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'ProgramConfigParams' - } - } - ] - }, - { - name: 'programInit' - accounts: [ - { - name: 'state' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: false - }, - { - name: 'tokenMint' - isMut: true - isSigner: false - }, - { - name: 'vault' - isMut: true - isSigner: false - }, - { - name: 'payer' - isMut: true - isSigner: false - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - }, - { - name: 'daoMint' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'ProgramInitParams' - } - } - ] - }, - { - name: 'vaultTransfer' - accounts: [ - { - name: 'state' - isMut: false - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: true - }, - { - name: 'to' - isMut: true - isSigner: false - }, - { - name: 'vault' - isMut: true - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'VaultTransferParams' - } - } - ] - }, - { - name: 'vrfInit' - accounts: [ - { - name: 'vrf' - isMut: true - isSigner: false - }, - { - name: 'authority' - isMut: false - isSigner: false - }, - { - name: 'oracleQueue' - isMut: false - isSigner: false - }, - { - name: 'escrow' - isMut: true - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'VrfInitParams' - } - } - ] - }, - { - name: 'vrfProve' - accounts: [ - { - name: 'vrf' - isMut: true - isSigner: false - }, - { - name: 'oracle' - isMut: false - isSigner: false - }, - { - name: 'randomnessProducer' - isMut: false - isSigner: true - } - ] - args: [ - { - name: 'params' - type: { - defined: 'VrfProveParams' - } - } - ] - }, - { - name: 'vrfProveAndVerify' - accounts: [ - { - name: 'vrf' - isMut: true - isSigner: false - }, - { - name: 'callbackPid' - isMut: false - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - }, - { - name: 'escrow' - isMut: true - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'oracle' - isMut: false - isSigner: false - }, - { - name: 'oracleAuthority' - isMut: false - isSigner: true - }, - { - name: 'oracleWallet' - isMut: true - isSigner: false - }, - { - name: 'instructionsSysvar' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'VrfProveAndVerifyParams' - } - } - ] - }, - { - name: 'vrfRequestRandomness' - accounts: [ - { - name: 'authority' - isMut: false - isSigner: true - }, - { - name: 'vrf' - isMut: true - isSigner: false - }, - { - name: 'oracleQueue' - isMut: true - isSigner: false - }, - { - name: 'queueAuthority' - isMut: false - isSigner: false - }, - { - name: 'dataBuffer' - isMut: false - isSigner: false - }, - { - name: 'permission' - isMut: true - isSigner: false - }, - { - name: 'escrow' - isMut: true - isSigner: false - }, - { - name: 'payerWallet' - isMut: true - isSigner: false - }, - { - name: 'payerAuthority' - isMut: false - isSigner: true - }, - { - name: 'recentBlockhashes' - isMut: false - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'VrfRequestRandomnessParams' - } - } - ] - }, - { - name: 'vrfVerify' - accounts: [ - { - name: 'vrf' - isMut: true - isSigner: false - }, - { - name: 'callbackPid' - isMut: false - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - }, - { - name: 'escrow' - isMut: true - isSigner: false - }, - { - name: 'programState' - isMut: false - isSigner: false - }, - { - name: 'oracle' - isMut: false - isSigner: false - }, - { - name: 'oracleAuthority' - isMut: false - isSigner: false - }, - { - name: 'oracleWallet' - isMut: true - isSigner: false - }, - { - name: 'instructionsSysvar' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'params' - type: { - defined: 'VrfVerifyParams' - } - } - ] - } - ] - accounts: [ - { - name: 'SbState' - type: { - kind: 'struct' - fields: [ - { - name: 'authority' - type: 'publicKey' - }, - { - name: 'tokenMint' - type: 'publicKey' - }, - { - name: 'tokenVault' - type: 'publicKey' - }, - { - name: 'daoMint' - type: 'publicKey' - }, - { - name: 'ebuf' - type: { - array: ['u8', 992] - } - } - ] - } - }, - { - name: 'AggregatorAccountData' - type: { - kind: 'struct' - fields: [ - { - name: 'name' - type: { - array: ['u8', 32] - } - }, - { - name: 'metadata' - type: { - array: ['u8', 128] - } - }, - { - name: 'reserved1' - type: { - array: ['u8', 32] - } - }, - { - name: 'queuePubkey' - type: 'publicKey' - }, - { - name: 'oracleRequestBatchSize' - type: 'u32' - }, - { - name: 'minOracleResults' - type: 'u32' - }, - { - name: 'minJobResults' - type: 'u32' - }, - { - name: 'minUpdateDelaySeconds' - type: 'u32' - }, - { - name: 'startAfter' - type: 'i64' - }, - { - name: 'varianceThreshold' - type: { - defined: 'SwitchboardDecimal' - } - }, - { - name: 'forceReportPeriod' - type: 'i64' - }, - { - name: 'expiration' - type: 'i64' - }, - { - name: 'consecutiveFailureCount' - type: 'u64' - }, - { - name: 'nextAllowedUpdateTime' - type: 'i64' - }, - { - name: 'isLocked' - type: 'bool' - }, - { - name: 'crankPubkey' - type: 'publicKey' - }, - { - name: 'latestConfirmedRound' - type: { - defined: 'AggregatorRound' - } - }, - { - name: 'currentRound' - type: { - defined: 'AggregatorRound' - } - }, - { - name: 'jobPubkeysData' - type: { - array: ['publicKey', 16] - } - }, - { - name: 'jobHashes' - type: { - array: [ - { - defined: 'Hash' - }, - 16 - ] - } - }, - { - name: 'jobPubkeysSize' - type: 'u32' - }, - { - name: 'jobsChecksum' - type: { - array: ['u8', 32] - } - }, - { - name: 'authority' - type: 'publicKey' - }, - { - name: 'historyBuffer' - type: 'publicKey' - }, - { - name: 'previousConfirmedRoundResult' - type: { - defined: 'SwitchboardDecimal' - } - }, - { - name: 'previousConfirmedRoundSlot' - type: 'u64' - }, - { - name: 'disableCrank' - type: 'bool' - }, - { - name: 'jobWeights' - type: { - array: ['u8', 16] - } - }, - { - name: 'ebuf' - type: { - array: ['u8', 147] - } - } - ] - } - }, - { - name: 'PermissionAccountData' - type: { - kind: 'struct' - fields: [ - { - name: 'authority' - type: 'publicKey' - }, - { - name: 'permissions' - type: 'u32' - }, - { - name: 'granter' - type: 'publicKey' - }, - { - name: 'grantee' - type: 'publicKey' - }, - { - name: 'expiration' - type: 'i64' - }, - { - name: 'ebuf' - type: { - array: ['u8', 256] - } - } - ] - } - }, - { - name: 'RealmSpawnRecordAccountData' - type: { - kind: 'struct' - fields: [ - { - name: 'ebuf' - type: { - array: ['u8', 256] - } - } - ] - } - }, - { - name: 'LeaseAccountData' - type: { - kind: 'struct' - fields: [ - { - name: 'escrow' - type: 'publicKey' - }, - { - name: 'queue' - type: 'publicKey' - }, - { - name: 'aggregator' - type: 'publicKey' - }, - { - name: 'tokenProgram' - type: 'publicKey' - }, - { - name: 'isActive' - type: 'bool' - }, - { - name: 'crankRowCount' - type: 'u32' - }, - { - name: 'createdAt' - type: 'i64' - }, - { - name: 'updateCount' - type: 'u128' - }, - { - name: 'withdrawAuthority' - type: 'publicKey' - }, - { - name: 'ebuf' - type: { - array: ['u8', 256] - } - } - ] - } - }, - { - name: 'OracleQueueAccountData' - type: { - kind: 'struct' - fields: [ - { - name: 'name' - type: { - array: ['u8', 32] - } - }, - { - name: 'metadata' - type: { - array: ['u8', 64] - } - }, - { - name: 'authority' - type: 'publicKey' - }, - { - name: 'oracleTimeout' - type: 'u32' - }, - { - name: 'reward' - type: 'u64' - }, - { - name: 'minStake' - type: 'u64' - }, - { - name: 'slashingEnabled' - type: 'bool' - }, - { - name: 'varianceToleranceMultiplier' - type: { - defined: 'SwitchboardDecimal' - } - }, - { - name: 'feedProbationPeriod' - type: 'u32' - }, - { - name: 'currIdx' - type: 'u32' - }, - { - name: 'size' - type: 'u32' - }, - { - name: 'gcIdx' - type: 'u32' - }, - { - name: 'consecutiveFeedFailureLimit' - type: 'u64' - }, - { - name: 'consecutiveOracleFailureLimit' - type: 'u64' - }, - { - name: 'unpermissionedFeedsEnabled' - type: 'bool' - }, - { - name: 'unpermissionedVrfEnabled' - type: 'bool' - }, - { - name: 'curatorRewardCut' - type: { - defined: 'SwitchboardDecimal' - } - }, - { - name: 'lockLeaseFunding' - type: 'bool' - }, - { - name: 'mint' - type: 'publicKey' - }, - { - name: 'ebuf' - type: { - array: ['u8', 969] - } - }, - { - name: 'maxSize' - type: 'u32' - }, - { - name: 'dataBuffer' - type: 'publicKey' - } - ] - } - }, - { - name: 'CrankAccountData' - type: { - kind: 'struct' - fields: [ - { - name: 'name' - type: { - array: ['u8', 32] - } - }, - { - name: 'metadata' - type: { - array: ['u8', 64] - } - }, - { - name: 'queuePubkey' - type: 'publicKey' - }, - { - name: 'pqSize' - type: 'u32' - }, - { - name: 'maxRows' - type: 'u32' - }, - { - name: 'jitterModifier' - type: 'u8' - }, - { - name: 'ebuf' - type: { - array: ['u8', 255] - } - }, - { - name: 'dataBuffer' - type: 'publicKey' - } - ] - } - }, - { - name: 'OracleAccountData' - type: { - kind: 'struct' - fields: [ - { - name: 'name' - type: { - array: ['u8', 32] - } - }, - { - name: 'metadata' - type: { - array: ['u8', 128] - } - }, - { - name: 'oracleAuthority' - type: 'publicKey' - }, - { - name: 'lastHeartbeat' - type: 'i64' - }, - { - name: 'numInUse' - type: 'u32' - }, - { - name: 'tokenAccount' - type: 'publicKey' - }, - { - name: 'queuePubkey' - type: 'publicKey' - }, - { - name: 'metrics' - type: { - defined: 'OracleMetrics' - } - }, - { - name: 'ebuf' - type: { - array: ['u8', 256] - } - } - ] - } - }, - { - name: 'JobAccountData' - type: { - kind: 'struct' - fields: [ - { - name: 'name' - type: { - array: ['u8', 32] - } - }, - { - name: 'metadata' - type: { - array: ['u8', 64] - } - }, - { - name: 'authority' - type: 'publicKey' - }, - { - name: 'expiration' - type: 'i64' - }, - { - name: 'hash' - type: { - array: ['u8', 32] - } - }, - { - name: 'data' - type: 'bytes' - }, - { - name: 'referenceCount' - type: 'u32' - }, - { - name: 'totalSpent' - type: 'u64' - }, - { - name: 'createdAt' - type: 'i64' - } - ] - } - }, - { - name: 'VrfAccountData' - type: { - kind: 'struct' - fields: [ - { - name: 'status' - type: { - defined: 'VrfStatus' - } - }, - { - name: 'counter' - type: 'u128' - }, - { - name: 'authority' - type: 'publicKey' - }, - { - name: 'oracleQueue' - type: 'publicKey' - }, - { - name: 'escrow' - type: 'publicKey' - }, - { - name: 'callback' - type: { - defined: 'CallbackZC' - } - }, - { - name: 'batchSize' - type: 'u32' - }, - { - name: 'builders' - type: { - array: [ - { - defined: 'VrfBuilder' - }, - 8 - ] - } - }, - { - name: 'buildersLen' - type: 'u32' - }, - { - name: 'testMode' - type: 'bool' - }, - { - name: 'currentRound' - type: { - defined: 'VrfRound' - } - }, - { - name: 'ebuf' - type: { - array: ['u8', 1024] - } - } - ] - } - } - ] - types: [ - { - name: 'AggregatorAddJobParams' - type: { - kind: 'struct' - fields: [ - { - name: 'weight' - type: { - option: 'u8' - } - } - ] - } - }, - { - name: 'AggregatorInitParams' - type: { - kind: 'struct' - fields: [ - { - name: 'name' - type: { - array: ['u8', 32] - } - }, - { - name: 'metadata' - type: { - array: ['u8', 128] - } - }, - { - name: 'batchSize' - type: 'u32' - }, - { - name: 'minOracleResults' - type: 'u32' - }, - { - name: 'minJobResults' - type: 'u32' - }, - { - name: 'minUpdateDelaySeconds' - type: 'u32' - }, - { - name: 'startAfter' - type: 'i64' - }, - { - name: 'varianceThreshold' - type: { - defined: 'BorshDecimal' - } - }, - { - name: 'forceReportPeriod' - type: 'i64' - }, - { - name: 'expiration' - type: 'i64' - }, - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'disableCrank' - type: 'bool' - } - ] - } - }, - { - name: 'AggregatorLockParams' - type: { - kind: 'struct' - fields: [] - } - }, - { - name: 'AggregatorOpenRoundParams' - type: { - kind: 'struct' - fields: [ - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'leaseBump' - type: 'u8' - }, - { - name: 'permissionBump' - type: 'u8' - }, - { - name: 'jitter' - type: 'u8' - } - ] - } - }, - { - name: 'AggregatorRemoveJobParams' - type: { - kind: 'struct' - fields: [ - { - name: 'jobIdx' - type: 'u32' - } - ] - } - }, - { - name: 'AggregatorSaveResultParams' - type: { - kind: 'struct' - fields: [ - { - name: 'oracleIdx' - type: 'u32' - }, - { - name: 'error' - type: 'bool' - }, - { - name: 'value' - type: { - defined: 'BorshDecimal' - } - }, - { - name: 'jobsChecksum' - type: { - array: ['u8', 32] - } - }, - { - name: 'minResponse' - type: { - defined: 'BorshDecimal' - } - }, - { - name: 'maxResponse' - type: { - defined: 'BorshDecimal' - } - }, - { - name: 'feedPermissionBump' - type: 'u8' - }, - { - name: 'oraclePermissionBump' - type: 'u8' - }, - { - name: 'leaseBump' - type: 'u8' - }, - { - name: 'stateBump' - type: 'u8' - } - ] - } - }, - { - name: 'AggregatorSetAuthorityParams' - type: { - kind: 'struct' - fields: [] - } - }, - { - name: 'AggregatorSetBatchSizeParams' - type: { - kind: 'struct' - fields: [ - { - name: 'batchSize' - type: 'u32' - } - ] - } - }, - { - name: 'AggregatorSetHistoryBufferParams' - type: { - kind: 'struct' - fields: [] - } - }, - { - name: 'AggregatorSetMinJobsParams' - type: { - kind: 'struct' - fields: [ - { - name: 'minJobResults' - type: 'u32' - } - ] - } - }, - { - name: 'AggregatorSetMinOraclesParams' - type: { - kind: 'struct' - fields: [ - { - name: 'minOracleResults' - type: 'u32' - } - ] - } - }, - { - name: 'AggregatorSetQueueParams' - type: { - kind: 'struct' - fields: [] - } - }, - { - name: 'AggregatorSetUpdateIntervalParams' - type: { - kind: 'struct' - fields: [ - { - name: 'newInterval' - type: 'u32' - } - ] - } - }, - { - name: 'AggregatorSetVarianceThresholdParams' - type: { - kind: 'struct' - fields: [ - { - name: 'varianceThreshold' - type: { - defined: 'BorshDecimal' - } - } - ] - } - }, - { - name: 'CrankInitParams' - type: { - kind: 'struct' - fields: [ - { - name: 'name' - type: 'bytes' - }, - { - name: 'metadata' - type: 'bytes' - }, - { - name: 'crankSize' - type: 'u32' - } - ] - } - }, - { - name: 'CrankPopParams' - type: { - kind: 'struct' - fields: [ - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'leaseBumps' - type: 'bytes' - }, - { - name: 'permissionBumps' - type: 'bytes' - }, - { - name: 'nonce' - type: { - option: 'u32' - } - }, - { - name: 'failOpenOnAccountMismatch' - type: { - option: 'bool' - } - } - ] - } - }, - { - name: 'CrankPushParams' - type: { - kind: 'struct' - fields: [ - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'permissionBump' - type: 'u8' - } - ] - } - }, - { - name: 'JobInitParams' - type: { - kind: 'struct' - fields: [ - { - name: 'name' - type: { - array: ['u8', 32] - } - }, - { - name: 'expiration' - type: 'i64' - }, - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'data' - type: 'bytes' - } - ] - } - }, - { - name: 'LeaseExtendParams' - type: { - kind: 'struct' - fields: [ - { - name: 'loadAmount' - type: 'u64' - }, - { - name: 'leaseBump' - type: 'u8' - }, - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'walletBumps' - type: 'bytes' - } - ] - } - }, - { - name: 'LeaseInitParams' - type: { - kind: 'struct' - fields: [ - { - name: 'loadAmount' - type: 'u64' - }, - { - name: 'withdrawAuthority' - type: 'publicKey' - }, - { - name: 'leaseBump' - type: 'u8' - }, - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'walletBumps' - type: 'bytes' - } - ] - } - }, - { - name: 'LeaseSetAuthorityParams' - type: { - kind: 'struct' - fields: [] - } - }, - { - name: 'LeaseWithdrawParams' - type: { - kind: 'struct' - fields: [ - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'leaseBump' - type: 'u8' - }, - { - name: 'amount' - type: 'u64' - } - ] - } - }, - { - name: 'OracleHeartbeatParams' - type: { - kind: 'struct' - fields: [ - { - name: 'permissionBump' - type: 'u8' - } - ] - } - }, - { - name: 'OracleInitParams' - type: { - kind: 'struct' - fields: [ - { - name: 'name' - type: 'bytes' - }, - { - name: 'metadata' - type: 'bytes' - }, - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'oracleBump' - type: 'u8' - } - ] - } - }, - { - name: 'OracleQueueInitParams' - type: { - kind: 'struct' - fields: [ - { - name: 'name' - type: { - array: ['u8', 32] - } - }, - { - name: 'metadata' - type: { - array: ['u8', 64] - } - }, - { - name: 'reward' - type: 'u64' - }, - { - name: 'minStake' - type: 'u64' - }, - { - name: 'feedProbationPeriod' - type: 'u32' - }, - { - name: 'oracleTimeout' - type: 'u32' - }, - { - name: 'slashingEnabled' - type: 'bool' - }, - { - name: 'varianceToleranceMultiplier' - type: { - defined: 'BorshDecimal' - } - }, - { - name: 'consecutiveFeedFailureLimit' - type: 'u64' - }, - { - name: 'consecutiveOracleFailureLimit' - type: 'u64' - }, - { - name: 'queueSize' - type: 'u32' - }, - { - name: 'unpermissionedFeeds' - type: 'bool' - }, - { - name: 'unpermissionedVrf' - type: 'bool' - } - ] - } - }, - { - name: 'OracleQueueSetRewardsParams' - type: { - kind: 'struct' - fields: [ - { - name: 'rewards' - type: 'u64' - } - ] - } - }, - { - name: 'OracleQueueVrfConfigParams' - type: { - kind: 'struct' - fields: [ - { - name: 'unpermissionedVrfEnabled' - type: 'bool' - } - ] - } - }, - { - name: 'OracleWithdrawParams' - type: { - kind: 'struct' - fields: [ - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'permissionBump' - type: 'u8' - }, - { - name: 'amount' - type: 'u64' - } - ] - } - }, - { - name: 'PermissionInitParams' - type: { - kind: 'struct' - fields: [] - } - }, - { - name: 'PermissionSetParams' - type: { - kind: 'struct' - fields: [ - { - name: 'permission' - type: { - defined: 'SwitchboardPermission' - } - }, - { - name: 'enable' - type: 'bool' - } - ] - } - }, - { - name: 'PermissionSetVoterWeightParams' - type: { - kind: 'struct' - fields: [ - { - name: 'stateBump' - type: 'u8' - } - ] - } - }, - { - name: 'ProgramConfigParams' - type: { - kind: 'struct' - fields: [ - { - name: 'token' - type: 'publicKey' - }, - { - name: 'bump' - type: 'u8' - }, - { - name: 'daoMint' - type: 'publicKey' - } - ] - } - }, - { - name: 'ProgramInitParams' - type: { - kind: 'struct' - fields: [ - { - name: 'stateBump' - type: 'u8' - } - ] - } - }, - { - name: 'VaultTransferParams' - type: { - kind: 'struct' - fields: [ - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'amount' - type: 'u64' - } - ] - } - }, - { - name: 'VrfInitParams' - type: { - kind: 'struct' - fields: [ - { - name: 'callback' - type: { - defined: 'Callback' - } - }, - { - name: 'stateBump' - type: 'u8' - } - ] - } - }, - { - name: 'VrfProveParams' - type: { - kind: 'struct' - fields: [ - { - name: 'proof' - type: 'bytes' - }, - { - name: 'idx' - type: 'u32' - } - ] - } - }, - { - name: 'VrfProveAndVerifyParams' - type: { - kind: 'struct' - fields: [ - { - name: 'nonce' - type: { - option: 'u32' - } - }, - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'idx' - type: 'u32' - }, - { - name: 'proof' - type: 'bytes' - } - ] - } - }, - { - name: 'VrfRequestRandomnessParams' - type: { - kind: 'struct' - fields: [ - { - name: 'permissionBump' - type: 'u8' - }, - { - name: 'stateBump' - type: 'u8' - } - ] - } - }, - { - name: 'VrfVerifyParams' - type: { - kind: 'struct' - fields: [ - { - name: 'nonce' - type: { - option: 'u32' - } - }, - { - name: 'stateBump' - type: 'u8' - }, - { - name: 'idx' - type: 'u32' - } - ] - } - }, - { - name: 'Hash' - type: { - kind: 'struct' - fields: [ - { - name: 'data' - type: { - array: ['u8', 32] - } - } - ] - } - }, - { - name: 'AggregatorRound' - type: { - kind: 'struct' - fields: [ - { - name: 'numSuccess' - type: 'u32' - }, - { - name: 'numError' - type: 'u32' - }, - { - name: 'isClosed' - type: 'bool' - }, - { - name: 'roundOpenSlot' - type: 'u64' - }, - { - name: 'roundOpenTimestamp' - type: 'i64' - }, - { - name: 'result' - type: { - defined: 'SwitchboardDecimal' - } - }, - { - name: 'stdDeviation' - type: { - defined: 'SwitchboardDecimal' - } - }, - { - name: 'minResponse' - type: { - defined: 'SwitchboardDecimal' - } - }, - { - name: 'maxResponse' - type: { - defined: 'SwitchboardDecimal' - } - }, - { - name: 'oraclePubkeysData' - type: { - array: ['publicKey', 16] - } - }, - { - name: 'mediansData' - type: { - array: [ - { - defined: 'SwitchboardDecimal' - }, - 16 - ] - } - }, - { - name: 'currentPayout' - type: { - array: ['i64', 16] - } - }, - { - name: 'mediansFulfilled' - type: { - array: ['bool', 16] - } - }, - { - name: 'errorsFulfilled' - type: { - array: ['bool', 16] - } - } - ] - } - }, - { - name: 'AggregatorHistoryRow' - type: { - kind: 'struct' - fields: [ - { - name: 'timestamp' - type: 'i64' - }, - { - name: 'value' - type: { - defined: 'SwitchboardDecimal' - } - } - ] - } - }, - { - name: 'SwitchboardDecimal' - type: { - kind: 'struct' - fields: [ - { - name: 'mantissa' - type: 'i128' - }, - { - name: 'scale' - type: 'u32' - } - ] - } - }, - { - name: 'CrankRow' - type: { - kind: 'struct' - fields: [ - { - name: 'pubkey' - type: 'publicKey' - }, - { - name: 'nextTimestamp' - type: 'i64' - } - ] - } - }, - { - name: 'OracleMetrics' - type: { - kind: 'struct' - fields: [ - { - name: 'consecutiveSuccess' - type: 'u64' - }, - { - name: 'consecutiveError' - type: 'u64' - }, - { - name: 'consecutiveDisagreement' - type: 'u64' - }, - { - name: 'consecutiveLateResponse' - type: 'u64' - }, - { - name: 'consecutiveFailure' - type: 'u64' - }, - { - name: 'totalSuccess' - type: 'u128' - }, - { - name: 'totalError' - type: 'u128' - }, - { - name: 'totalDisagreement' - type: 'u128' - }, - { - name: 'totalLateResponse' - type: 'u128' - } - ] - } - }, - { - name: 'BorshDecimal' - type: { - kind: 'struct' - fields: [ - { - name: 'mantissa' - type: 'i128' - }, - { - name: 'scale' - type: 'u32' - } - ] - } - }, - { - name: 'EcvrfProofZC' - type: { - kind: 'struct' - fields: [ - { - name: 'gamma' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'c' - type: { - defined: 'Scalar' - } - }, - { - name: 's' - type: { - defined: 'Scalar' - } - } - ] - } - }, - { - name: 'Scalar' - type: { - kind: 'struct' - fields: [ - { - name: 'bytes' - type: { - array: ['u8', 32] - } - } - ] - } - }, - { - name: 'FieldElementZC' - type: { - kind: 'struct' - fields: [ - { - name: 'bytes' - type: { - array: ['u64', 5] - } - } - ] - } - }, - { - name: 'CompletedPointZC' - type: { - kind: 'struct' - fields: [ - { - name: 'x' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'y' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'z' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 't' - type: { - defined: 'FieldElementZC' - } - } - ] - } - }, - { - name: 'EdwardsPointZC' - type: { - kind: 'struct' - fields: [ - { - name: 'x' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'y' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'z' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 't' - type: { - defined: 'FieldElementZC' - } - } - ] - } - }, - { - name: 'ProjectivePointZC' - type: { - kind: 'struct' - fields: [ - { - name: 'x' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'y' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'z' - type: { - defined: 'FieldElementZC' - } - } - ] - } - }, - { - name: 'EcvrfIntermediate' - type: { - kind: 'struct' - fields: [ - { - name: 'r' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'nS' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'd' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 't13' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 't15' - type: { - defined: 'FieldElementZC' - } - } - ] - } - }, - { - name: 'VrfBuilder' - type: { - kind: 'struct' - fields: [ - { - name: 'producer' - type: 'publicKey' - }, - { - name: 'status' - type: { - defined: 'VrfStatus' - } - }, - { - name: 'reprProof' - type: { - array: ['u8', 80] - } - }, - { - name: 'proof' - type: { - defined: 'EcvrfProofZC' - } - }, - { - name: 'yPoint' - type: 'publicKey' - }, - { - name: 'stage' - type: 'u32' - }, - { - name: 'stage1Out' - type: { - defined: 'EcvrfIntermediate' - } - }, - { - name: 'r1' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'r2' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'stage3Out' - type: { - defined: 'EcvrfIntermediate' - } - }, - { - name: 'hPoint' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'sReduced' - type: { - defined: 'Scalar' - } - }, - { - name: 'yPointBuilder' - type: { - array: [ - { - defined: 'FieldElementZC' - }, - 3 - ] - } - }, - { - name: 'yRistrettoPoint' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'mulRound' - type: 'u8' - }, - { - name: 'hashPointsRound' - type: 'u8' - }, - { - name: 'mulTmp1' - type: { - defined: 'CompletedPointZC' - } - }, - { - name: 'uPoint1' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'uPoint2' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'vPoint1' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'vPoint2' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'uPoint' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'vPoint' - type: { - defined: 'EdwardsPointZC' - } - }, - { - name: 'u1' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'u2' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'invertee' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'y' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'z' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'p1Bytes' - type: { - array: ['u8', 32] - } - }, - { - name: 'p2Bytes' - type: { - array: ['u8', 32] - } - }, - { - name: 'p3Bytes' - type: { - array: ['u8', 32] - } - }, - { - name: 'p4Bytes' - type: { - array: ['u8', 32] - } - }, - { - name: 'cPrimeHashbuf' - type: { - array: ['u8', 16] - } - }, - { - name: 'm1' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'm2' - type: { - defined: 'FieldElementZC' - } - }, - { - name: 'txRemaining' - type: 'u32' - }, - { - name: 'verified' - type: 'bool' - }, - { - name: 'result' - type: { - array: ['u8', 32] - } - } - ] - } - }, - { - name: 'AccountMetaZC' - type: { - kind: 'struct' - fields: [ - { - name: 'pubkey' - type: 'publicKey' - }, - { - name: 'isSigner' - type: 'bool' - }, - { - name: 'isWritable' - type: 'bool' - } - ] - } - }, - { - name: 'AccountMetaBorsh' - type: { - kind: 'struct' - fields: [ - { - name: 'pubkey' - type: 'publicKey' - }, - { - name: 'isSigner' - type: 'bool' - }, - { - name: 'isWritable' - type: 'bool' - } - ] - } - }, - { - name: 'CallbackZC' - type: { - kind: 'struct' - fields: [ - { - name: 'programId' - type: 'publicKey' - }, - { - name: 'accounts' - type: { - array: [ - { - defined: 'AccountMetaZC' - }, - 32 - ] - } - }, - { - name: 'accountsLen' - type: 'u32' - }, - { - name: 'ixData' - type: { - array: ['u8', 1024] - } - }, - { - name: 'ixDataLen' - type: 'u32' - } - ] - } - }, - { - name: 'Callback' - type: { - kind: 'struct' - fields: [ - { - name: 'programId' - type: 'publicKey' - }, - { - name: 'accounts' - type: { - vec: { - defined: 'AccountMetaBorsh' - } - } - }, - { - name: 'ixData' - type: 'bytes' - } - ] - } - }, - { - name: 'VrfRound' - type: { - kind: 'struct' - fields: [ - { - name: 'alpha' - type: { - array: ['u8', 256] - } - }, - { - name: 'alphaLen' - type: 'u32' - }, - { - name: 'requestSlot' - type: 'u64' - }, - { - name: 'requestTimestamp' - type: 'i64' - }, - { - name: 'result' - type: { - array: ['u8', 32] - } - }, - { - name: 'numVerified' - type: 'u32' - }, - { - name: 'ebuf' - type: { - array: ['u8', 256] - } - } - ] - } - }, - { - name: 'Lanes' - type: { - kind: 'enum' - variants: [ - { - name: 'C' - }, - { - name: 'D' - }, - { - name: 'AB' - }, - { - name: 'AC' - }, - { - name: 'CD' - }, - { - name: 'AD' - }, - { - name: 'BC' - }, - { - name: 'ABCD' - } - ] - } - }, - { - name: 'Shuffle' - type: { - kind: 'enum' - variants: [ - { - name: 'AAAA' - }, - { - name: 'BBBB' - }, - { - name: 'CACA' - }, - { - name: 'DBBD' - }, - { - name: 'ADDA' - }, - { - name: 'CBCB' - }, - { - name: 'ABAB' - }, - { - name: 'BADC' - }, - { - name: 'BACD' - }, - { - name: 'ABDC' - } - ] - } - }, - { - name: 'Shuffle' - type: { - kind: 'enum' - variants: [ - { - name: 'AAAA' - }, - { - name: 'BBBB' - }, - { - name: 'BADC' - }, - { - name: 'BACD' - }, - { - name: 'ADDA' - }, - { - name: 'CBCB' - }, - { - name: 'ABDC' - }, - { - name: 'ABAB' - }, - { - name: 'DBBD' - }, - { - name: 'CACA' - } - ] - } - }, - { - name: 'Lanes' - type: { - kind: 'enum' - variants: [ - { - name: 'D' - }, - { - name: 'C' - }, - { - name: 'AB' - }, - { - name: 'AC' - }, - { - name: 'AD' - }, - { - name: 'BCD' - } - ] - } - }, - { - name: 'Error' - type: { - kind: 'enum' - variants: [ - { - name: 'InvalidPublicKey' - }, - { - name: 'SerializationError' - fields: [ - { - defined: 'bincode::Error' - } - ] - }, - { - name: 'DeserializationError' - fields: [ - { - defined: 'bincode::Error' - } - ] - }, - { - name: 'InvalidDataError' - } - ] - } - }, - { - name: 'SwitchboardPermission' - type: { - kind: 'enum' - variants: [ - { - name: 'PermitOracleHeartbeat' - }, - { - name: 'PermitOracleQueueUsage' - }, - { - name: 'PermitVrfRequests' - } - ] - } - }, - { - name: 'OracleResponseType' - type: { - kind: 'enum' - variants: [ - { - name: 'TypeSuccess' - }, - { - name: 'TypeError' - }, - { - name: 'TypeDisagreement' - }, - { - name: 'TypeNoResponse' - } - ] - } - }, - { - name: 'VrfStatus' - type: { - kind: 'enum' - variants: [ - { - name: 'StatusNone' - }, - { - name: 'StatusRequesting' - }, - { - name: 'StatusVerifying' - }, - { - name: 'StatusVerified' - }, - { - name: 'StatusCallbackSuccess' - }, - { - name: 'StatusVerifyFailure' - } - ] - } - } - ] - events: [ - { - name: 'AggregatorInitEvent' - fields: [ - { - name: 'feedPubkey' - type: 'publicKey' - index: false - } - ] - }, - { - name: 'VrfRequestRandomnessEvent' - fields: [ - { - name: 'vrfPubkey' - type: 'publicKey' - index: true - }, - { - name: 'oraclePubkeys' - type: { - vec: 'publicKey' - } - index: false - }, - { - name: 'loadAmount' - type: 'u64' - index: false - }, - { - name: 'existingAmount' - type: 'u64' - index: false - } - ] - }, - { - name: 'VrfRequestEvent' - fields: [ - { - name: 'vrfPubkey' - type: 'publicKey' - index: true - }, - { - name: 'oraclePubkeys' - type: { - vec: 'publicKey' - } - index: false - } - ] - }, - { - name: 'VrfProveEvent' - fields: [ - { - name: 'vrfPubkey' - type: 'publicKey' - index: true - }, - { - name: 'oraclePubkey' - type: 'publicKey' - index: true - }, - { - name: 'authorityPubkey' - type: 'publicKey' - index: false - } - ] - }, - { - name: 'VrfVerifyEvent' - fields: [ - { - name: 'vrfPubkey' - type: 'publicKey' - index: true - }, - { - name: 'oraclePubkey' - type: 'publicKey' - index: true - }, - { - name: 'authorityPubkey' - type: 'publicKey' - index: false - }, - { - name: 'amount' - type: 'u64' - index: false - } - ] - }, - { - name: 'VrfCallbackPerformedEvent' - fields: [ - { - name: 'vrfPubkey' - type: 'publicKey' - index: true - }, - { - name: 'oraclePubkey' - type: 'publicKey' - index: true - }, - { - name: 'amount' - type: 'u64' - index: false - } - ] - }, - { - name: 'AggregatorOpenRoundEvent' - fields: [ - { - name: 'feedPubkey' - type: 'publicKey' - index: false - }, - { - name: 'oraclePubkeys' - type: { - vec: 'publicKey' - } - index: false - }, - { - name: 'jobPubkeys' - type: { - vec: 'publicKey' - } - index: false - }, - { - name: 'remainingFunds' - type: 'u64' - index: false - }, - { - name: 'queueAuthority' - type: 'publicKey' - index: false - } - ] - }, - { - name: 'AggregatorValueUpdateEvent' - fields: [ - { - name: 'feedPubkey' - type: 'publicKey' - index: false - }, - { - name: 'value' - type: { - defined: 'BorshDecimal' - } - index: false - }, - { - name: 'slot' - type: 'u64' - index: false - }, - { - name: 'timestamp' - type: 'i64' - index: false - }, - { - name: 'oraclePubkeys' - type: { - vec: 'publicKey' - } - index: false - }, - { - name: 'oracleValues' - type: { - vec: { - defined: 'BorshDecimal' - } - } - index: false - } - ] - }, - { - name: 'OracleRewardEvent' - fields: [ - { - name: 'feedPubkey' - type: 'publicKey' - index: false - }, - { - name: 'leasePubkey' - type: 'publicKey' - index: false - }, - { - name: 'oraclePubkey' - type: 'publicKey' - index: false - }, - { - name: 'walletPubkey' - type: 'publicKey' - index: false - }, - { - name: 'amount' - type: 'u64' - index: false - }, - { - name: 'roundSlot' - type: 'u64' - index: false - }, - { - name: 'timestamp' - type: 'i64' - index: false - } - ] - }, - { - name: 'OracleWithdrawEvent' - fields: [ - { - name: 'oraclePubkey' - type: 'publicKey' - index: false - }, - { - name: 'walletPubkey' - type: 'publicKey' - index: false - }, - { - name: 'destinationWallet' - type: 'publicKey' - index: false - }, - { - name: 'previousAmount' - type: 'u64' - index: false - }, - { - name: 'newAmount' - type: 'u64' - index: false - }, - { - name: 'timestamp' - type: 'i64' - index: false - } - ] - }, - { - name: 'LeaseWithdrawEvent' - fields: [ - { - name: 'leasePubkey' - type: 'publicKey' - index: false - }, - { - name: 'walletPubkey' - type: 'publicKey' - index: false - }, - { - name: 'previousAmount' - type: 'u64' - index: false - }, - { - name: 'newAmount' - type: 'u64' - index: false - }, - { - name: 'timestamp' - type: 'i64' - index: false - } - ] - }, - { - name: 'OracleSlashEvent' - fields: [ - { - name: 'feedPubkey' - type: 'publicKey' - index: false - }, - { - name: 'leasePubkey' - type: 'publicKey' - index: false - }, - { - name: 'oraclePubkey' - type: 'publicKey' - index: false - }, - { - name: 'walletPubkey' - type: 'publicKey' - index: false - }, - { - name: 'amount' - type: 'u64' - index: false - }, - { - name: 'roundSlot' - type: 'u64' - index: false - }, - { - name: 'timestamp' - type: 'i64' - index: false - } - ] - }, - { - name: 'LeaseFundEvent' - fields: [ - { - name: 'leasePubkey' - type: 'publicKey' - index: false - }, - { - name: 'funder' - type: 'publicKey' - index: false - }, - { - name: 'amount' - type: 'u64' - index: false - }, - { - name: 'timestamp' - type: 'i64' - index: false - } - ] - }, - { - name: 'ProbationBrokenEvent' - fields: [ - { - name: 'feedPubkey' - type: 'publicKey' - index: false - }, - { - name: 'queuePubkey' - type: 'publicKey' - index: false - }, - { - name: 'timestamp' - type: 'i64' - index: false - } - ] - }, - { - name: 'FeedPermissionRevokedEvent' - fields: [ - { - name: 'feedPubkey' - type: 'publicKey' - index: false - }, - { - name: 'timestamp' - type: 'i64' - index: false - } - ] - }, - { - name: 'GarbageCollectFailureEvent' - fields: [ - { - name: 'queuePubkey' - type: 'publicKey' - index: false - } - ] - }, - { - name: 'OracleBootedEvent' - fields: [ - { - name: 'queuePubkey' - type: 'publicKey' - index: false - }, - { - name: 'oraclePubkey' - type: 'publicKey' - index: false - } - ] - }, - { - name: 'CrankLeaseInsufficientFundsEvent' - fields: [ - { - name: 'feedPubkey' - type: 'publicKey' - index: false - }, - { - name: 'leasePubkey' - type: 'publicKey' - index: false - } - ] - }, - { - name: 'CrankPopExpectedFailureEvent' - fields: [ - { - name: 'feedPubkey' - type: 'publicKey' - index: false - }, - { - name: 'leasePubkey' - type: 'publicKey' - index: false - } - ] - } - ] - errors: [ - { - code: 6000 - name: 'ArrayOperationError' - msg: 'Illegal operation on a Switchboard array.' - }, - { - code: 6001 - name: 'QueueOperationError' - msg: 'Illegal operation on a Switchboard queue.' - }, - { - code: 6002 - name: 'IncorrectProgramOwnerError' - msg: 'An account required to be owned by the program has a different owner.' - }, - { - code: 6003 - name: 'InvalidAggregatorRound' - msg: 'Aggregator is not currently populated with a valid round.' - }, - { - code: 6004 - name: 'TooManyAggregatorJobs' - msg: 'Aggregator cannot fit any more jobs.' - }, - { - code: 6005 - name: 'AggregatorCurrentRoundClosed' - msg: "Aggregator's current round is closed. No results are being accepted." - }, - { - code: 6006 - name: 'AggregatorInvalidSaveResult' - msg: 'Aggregator received an invalid save result instruction.' - }, - { - code: 6007 - name: 'InvalidStrDecimalConversion' - msg: 'Failed to convert string to decimal format.' - }, - { - code: 6008 - name: 'AccountLoaderMissingSignature' - msg: 'AccountLoader account is missing a required signature.' - }, - { - code: 6009 - name: 'MissingRequiredSignature' - msg: 'Account is missing a required signature.' - }, - { - code: 6010 - name: 'ArrayOverflowError' - msg: 'The attempted action will overflow a zero-copy account array.' - }, - { - code: 6011 - name: 'ArrayUnderflowError' - msg: 'The attempted action will underflow a zero-copy account array.' - }, - { - code: 6012 - name: 'PubkeyNotFoundError' - msg: 'The queried public key was not found.' - }, - { - code: 6013 - name: 'AggregatorIllegalRoundOpenCall' - msg: 'Aggregator round open called too early.' - }, - { - code: 6014 - name: 'AggregatorIllegalRoundCloseCall' - msg: 'Aggregator round close called too early.' - }, - { - code: 6015 - name: 'AggregatorClosedError' - msg: 'Aggregator is closed. Illegal action.' - }, - { - code: 6016 - name: 'IllegalOracleIdxError' - msg: 'Illegal oracle index.' - }, - { - code: 6017 - name: 'OracleAlreadyRespondedError' - msg: 'The provided oracle has already responded this round.' - }, - { - code: 6018 - name: 'ProtoDeserializeError' - msg: 'Failed to deserialize protocol buffer.' - }, - { - code: 6019 - name: 'UnauthorizedStateUpdateError' - msg: 'Unauthorized program state modification attempted.' - }, - { - code: 6020 - name: 'MissingOracleAccountsError' - msg: 'Not enough oracle accounts provided to closeRounds.' - }, - { - code: 6021 - name: 'OracleMismatchError' - msg: 'An unexpected oracle account was provided for the transaction.' - }, - { - code: 6022 - name: 'CrankMaxCapacityError' - msg: "Attempted to push to a Crank that's at capacity" - }, - { - code: 6023 - name: 'AggregatorLeaseInsufficientFunds' - msg: 'Aggregator update call attempted but attached lease has insufficient funds.' - }, - { - code: 6024 - name: 'IncorrectTokenAccountMint' - msg: 'The provided token account does not point to the Switchboard token mint.' - }, - { - code: 6025 - name: 'InvalidEscrowAccount' - msg: 'An invalid escrow account was provided.' - }, - { - code: 6026 - name: 'CrankEmptyError' - msg: 'Crank empty. Pop failed.' - }, - { - code: 6027 - name: 'PdaDeriveError' - msg: 'Failed to derive a PDA from the provided seed.' - }, - { - code: 6028 - name: 'AggregatorAccountNotFound' - msg: 'Aggregator account missing from provided account list.' - }, - { - code: 6029 - name: 'PermissionAccountNotFound' - msg: 'Permission account missing from provided account list.' - }, - { - code: 6030 - name: 'LeaseAccountDeriveFailure' - msg: 'Failed to derive a lease account.' - }, - { - code: 6031 - name: 'PermissionAccountDeriveFailure' - msg: 'Failed to derive a permission account.' - }, - { - code: 6032 - name: 'EscrowAccountNotFound' - msg: 'Escrow account missing from provided account list.' - }, - { - code: 6033 - name: 'LeaseAccountNotFound' - msg: 'Lease account missing from provided account list.' - }, - { - code: 6034 - name: 'DecimalConversionError' - msg: 'Decimal conversion method failed.' - }, - { - code: 6035 - name: 'PermissionDenied' - msg: 'Permission account is missing required flags for the given action.' - }, - { - code: 6036 - name: 'QueueAtCapacity' - msg: 'Oracle queue is at lease capacity.' - }, - { - code: 6037 - name: 'ExcessiveCrankRowsError' - msg: 'Data feed is already pushed on a crank.' - }, - { - code: 6038 - name: 'AggregatorLockedError' - msg: 'Aggregator is locked, no setting modifications or job additions allowed.' - }, - { - code: 6039 - name: 'AggregatorInvalidBatchSizeError' - msg: 'Aggregator invalid batch size.' - }, - { - code: 6040 - name: 'AggregatorJobChecksumMismatch' - msg: 'Oracle provided an incorrect aggregator job checksum.' - }, - { - code: 6041 - name: 'IntegerOverflowError' - msg: 'An integer overflow occurred.' - }, - { - code: 6042 - name: 'InvalidUpdatePeriodError' - msg: 'Minimum update period is 5 seconds.' - }, - { - code: 6043 - name: 'NoResultsError' - msg: 'Aggregator round evaluation attempted with no results.' - }, - { - code: 6044 - name: 'InvalidExpirationError' - msg: 'An expiration constraint was broken.' - }, - { - code: 6045 - name: 'InsufficientStakeError' - msg: 'An account provided insufficient stake for action.' - }, - { - code: 6046 - name: 'LeaseInactiveError' - msg: 'The provided lease account is not active.' - }, - { - code: 6047 - name: 'NoAggregatorJobsFound' - msg: 'No jobs are currently included in the aggregator.' - }, - { - code: 6048 - name: 'IntegerUnderflowError' - msg: 'An integer underflow occurred.' - }, - { - code: 6049 - name: 'OracleQueueMismatch' - msg: 'An invalid oracle queue account was provided.' - }, - { - code: 6050 - name: 'OracleWalletMismatchError' - msg: 'An unexpected oracle wallet account was provided for the transaction.' - }, - { - code: 6051 - name: 'InvalidBufferAccountError' - msg: 'An invalid buffer account was provided.' - }, - { - code: 6052 - name: 'InsufficientOracleQueueError' - msg: 'Insufficient oracle queue size.' - }, - { - code: 6053 - name: 'InvalidAuthorityError' - msg: 'Invalid authority account provided.' - }, - { - code: 6054 - name: 'InvalidTokenAccountMintError' - msg: 'A provided token wallet is associated with an incorrect mint.' - }, - { - code: 6055 - name: 'ExcessiveLeaseWithdrawlError' - msg: 'You must leave enough funds to perform at least 1 update in the lease.' - }, - { - code: 6056 - name: 'InvalideHistoryAccountError' - msg: 'Invalid history account provided.' - }, - { - code: 6057 - name: 'InvalidLeaseAccountEscrowError' - msg: 'Invalid lease account escrow.' - }, - { - code: 6058 - name: 'InvalidCrankAccountError' - msg: 'Invalid crank provided.' - }, - { - code: 6059 - name: 'CrankNoElementsReadyError' - msg: 'No elements ready to be popped.' - }, - { - code: 6060 - name: 'IndexOutOfBoundsError' - msg: 'Index out of bounds' - }, - { - code: 6061 - name: 'VrfInvalidRequestError' - msg: 'Invalid vrf request params' - }, - { - code: 6062 - name: 'VrfInvalidProofSubmissionError' - msg: 'Vrf proof failed to verify' - }, - { - code: 6063 - name: 'VrfVerifyError' - msg: 'Error in verifying vrf proof.' - }, - { - code: 6064 - name: 'VrfCallbackError' - msg: 'Vrf callback function failed.' - }, - { - code: 6065 - name: 'VrfCallbackParamsError' - msg: 'Invalid vrf callback params provided.' - }, - { - code: 6066 - name: 'VrfCallbackAlreadyCalledError' - msg: 'Vrf callback has already been triggered.' - }, - { - code: 6067 - name: 'VrfInvalidPubkeyError' - msg: 'The provided pubkey is invalid to use in ecvrf proofs' - }, - { - code: 6068 - name: 'VrfTooManyVerifyCallsError' - msg: 'Number of required verify calls exceeded' - }, - { - code: 6069 - name: 'VrfRequestAlreadyLaunchedError' - msg: 'Vrf request is already pending' - }, - { - code: 6070 - name: 'VrfInsufficientVerificationError' - msg: 'Insufficient amount of proofs collected for VRF callback' - }, - { - code: 6071 - name: 'InvalidVrfProducerError' - msg: 'An incorrect oracle attempted to submit a proof' - }, - { - code: 6072 - name: 'InvalidGovernancePidError' - msg: 'Invalid SPLGovernance Account Supplied' - }, - { - code: 6073 - name: 'InvalidGovernanceAccountError' - msg: 'An Invalid Governance Account was supplied' - }, - { - code: 6074 - name: 'MissingOptionalAccount' - msg: 'Expected an optional account' - }, - { - code: 6075 - name: 'InvalidSpawnRecordOwner' - msg: 'Invalid Owner for Spawn Record' - }, - { - code: 6076 - name: 'NoopError' - msg: 'Noop error' - }, - { - code: 6077 - name: 'MissingRequiredAccountsError' - msg: 'A required instruction account was not included' - }, - { - code: 6078 - name: 'InvalidMintError' - msg: 'Invalid mint account passed for instruction' - }, - { - code: 6079 - name: 'InvalidTokenAccountKeyError' - msg: 'An invalid token account was passed into the instruction' - }, - { - code: 6080 - name: 'InvalidJobAccountError' - msg: '' - } - ] -} - -export const IDL: Switchboard = { - version: '0.1.0', - name: 'switchboard_v2', - instructions: [ - { - name: 'aggregatorAddJob', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'job', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorAddJobParams', - }, - }, - ], - }, - { - name: 'aggregatorInit', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: false, - }, - { - name: 'queue', - isMut: false, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorInitParams', - }, - }, - ], - }, - { - name: 'aggregatorLock', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: true, - isSigner: true, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorLockParams', - }, - }, - ], - }, - { - name: 'aggregatorOpenRound', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'lease', - isMut: true, - isSigner: false, - }, - { - name: 'oracleQueue', - isMut: true, - isSigner: false, - }, - { - name: 'queueAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'permission', - isMut: true, - isSigner: false, - }, - { - name: 'escrow', - isMut: true, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'payoutWallet', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'dataBuffer', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorOpenRoundParams', - }, - }, - ], - }, - { - name: 'aggregatorRemoveJob', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'job', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorRemoveJobParams', - }, - }, - ], - }, - { - name: 'aggregatorSaveResult', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'oracle', - isMut: true, - isSigner: false, - }, - { - name: 'oracleAuthority', - isMut: false, - isSigner: true, - }, - { - name: 'oracleQueue', - isMut: false, - isSigner: false, - }, - { - name: 'queueAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'feedPermission', - isMut: true, - isSigner: false, - }, - { - name: 'oraclePermission', - isMut: false, - isSigner: false, - }, - { - name: 'lease', - isMut: true, - isSigner: false, - }, - { - name: 'escrow', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'historyBuffer', - isMut: true, - isSigner: false, - }, - { - name: 'mint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorSaveResultParams', - }, - }, - ], - }, - { - name: 'aggregatorSetAuthority', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'newAuthority', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorSetAuthorityParams', - }, - }, - ], - }, - { - name: 'aggregatorSetBatchSize', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorSetBatchSizeParams', - }, - }, - ], - }, - { - name: 'aggregatorSetHistoryBuffer', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'buffer', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorSetHistoryBufferParams', - }, - }, - ], - }, - { - name: 'aggregatorSetMinJobs', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorSetMinJobsParams', - }, - }, - ], - }, - { - name: 'aggregatorSetMinOracles', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorSetMinOraclesParams', - }, - }, - ], - }, - { - name: 'aggregatorSetQueue', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'queue', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorSetQueueParams', - }, - }, - ], - }, - { - name: 'aggregatorSetUpdateInterval', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorSetUpdateIntervalParams', - }, - }, - ], - }, - { - name: 'aggregatorSetVarianceThreshold', - accounts: [ - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'AggregatorSetVarianceThresholdParams', - }, - }, - ], - }, - { - name: 'crankInit', - accounts: [ - { - name: 'crank', - isMut: true, - isSigner: true, - }, - { - name: 'queue', - isMut: false, - isSigner: false, - }, - { - name: 'buffer', - isMut: true, - isSigner: false, - }, - { - name: 'payer', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'CrankInitParams', - }, - }, - ], - }, - { - name: 'crankPop', - accounts: [ - { - name: 'crank', - isMut: true, - isSigner: false, - }, - { - name: 'oracleQueue', - isMut: true, - isSigner: false, - }, - { - name: 'queueAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'payoutWallet', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'crankDataBuffer', - isMut: true, - isSigner: false, - }, - { - name: 'queueDataBuffer', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'CrankPopParams', - }, - }, - ], - }, - { - name: 'crankPush', - accounts: [ - { - name: 'crank', - isMut: true, - isSigner: false, - }, - { - name: 'aggregator', - isMut: true, - isSigner: false, - }, - { - name: 'oracleQueue', - isMut: true, - isSigner: false, - }, - { - name: 'queueAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'permission', - isMut: false, - isSigner: false, - }, - { - name: 'lease', - isMut: true, - isSigner: false, - }, - { - name: 'escrow', - isMut: true, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'dataBuffer', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'CrankPushParams', - }, - }, - ], - }, - { - name: 'jobInit', - accounts: [ - { - name: 'job', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'JobInitParams', - }, - }, - ], - }, - { - name: 'leaseExtend', - accounts: [ - { - name: 'lease', - isMut: true, - isSigner: false, - }, - { - name: 'aggregator', - isMut: false, - isSigner: false, - }, - { - name: 'queue', - isMut: false, - isSigner: false, - }, - { - name: 'funder', - isMut: true, - isSigner: false, - }, - { - name: 'owner', - isMut: true, - isSigner: true, - }, - { - name: 'escrow', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'LeaseExtendParams', - }, - }, - ], - }, - { - name: 'leaseInit', - accounts: [ - { - name: 'lease', - isMut: true, - isSigner: false, - }, - { - name: 'queue', - isMut: true, - isSigner: false, - }, - { - name: 'aggregator', - isMut: false, - isSigner: false, - }, - { - name: 'funder', - isMut: true, - isSigner: false, - }, - { - name: 'payer', - isMut: true, - isSigner: true, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'owner', - isMut: true, - isSigner: true, - }, - { - name: 'escrow', - isMut: true, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'LeaseInitParams', - }, - }, - ], - }, - { - name: 'leaseSetAuthority', - accounts: [ - { - name: 'lease', - isMut: true, - isSigner: false, - }, - { - name: 'withdrawAuthority', - isMut: false, - isSigner: true, - }, - { - name: 'newAuthority', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'LeaseSetAuthorityParams', - }, - }, - ], - }, - { - name: 'leaseWithdraw', - accounts: [ - { - name: 'lease', - isMut: true, - isSigner: false, - }, - { - name: 'escrow', - isMut: true, - isSigner: false, - }, - { - name: 'aggregator', - isMut: false, - isSigner: false, - }, - { - name: 'queue', - isMut: false, - isSigner: false, - }, - { - name: 'withdrawAuthority', - isMut: false, - isSigner: true, - }, - { - name: 'withdrawAccount', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'LeaseWithdrawParams', - }, - }, - ], - }, - { - name: 'oracleHeartbeat', - accounts: [ - { - name: 'oracle', - isMut: true, - isSigner: false, - }, - { - name: 'oracleAuthority', - isMut: false, - isSigner: true, - }, - { - name: 'tokenAccount', - isMut: false, - isSigner: false, - }, - { - name: 'gcOracle', - isMut: true, - isSigner: false, - }, - { - name: 'oracleQueue', - isMut: true, - isSigner: false, - }, - { - name: 'permission', - isMut: false, - isSigner: false, - }, - { - name: 'dataBuffer', - isMut: true, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'OracleHeartbeatParams', - }, - }, - ], - }, - { - name: 'oracleInit', - accounts: [ - { - name: 'oracle', - isMut: true, - isSigner: false, - }, - { - name: 'oracleAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'wallet', - isMut: false, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'queue', - isMut: false, - isSigner: false, - }, - { - name: 'payer', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'OracleInitParams', - }, - }, - ], - }, - { - name: 'oracleQueueInit', - accounts: [ - { - name: 'oracleQueue', - isMut: true, - isSigner: true, - }, - { - name: 'authority', - isMut: false, - isSigner: false, - }, - { - name: 'buffer', - isMut: true, - isSigner: false, - }, - { - name: 'payer', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'mint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'OracleQueueInitParams', - }, - }, - ], - }, - { - name: 'oracleQueueSetRewards', - accounts: [ - { - name: 'queue', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'OracleQueueSetRewardsParams', - }, - }, - ], - }, - { - name: 'oracleQueueVrfConfig', - accounts: [ - { - name: 'queue', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'OracleQueueVrfConfigParams', - }, - }, - ], - }, - { - name: 'oracleWithdraw', - accounts: [ - { - name: 'oracle', - isMut: true, - isSigner: false, - }, - { - name: 'oracleAuthority', - isMut: false, - isSigner: true, - }, - { - name: 'tokenAccount', - isMut: true, - isSigner: false, - }, - { - name: 'withdrawAccount', - isMut: true, - isSigner: false, - }, - { - name: 'oracleQueue', - isMut: true, - isSigner: false, - }, - { - name: 'permission', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'payer', - isMut: true, - isSigner: true, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'OracleWithdrawParams', - }, - }, - ], - }, - { - name: 'permissionInit', - accounts: [ - { - name: 'permission', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: false, - }, - { - name: 'granter', - isMut: false, - isSigner: false, - }, - { - name: 'grantee', - isMut: false, - isSigner: false, - }, - { - name: 'payer', - isMut: true, - isSigner: true, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'PermissionInitParams', - }, - }, - ], - }, - { - name: 'permissionSet', - accounts: [ - { - name: 'permission', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'PermissionSetParams', - }, - }, - ], - }, - { - name: 'permissionSetVoterWeight', - accounts: [ - { - name: 'permission', - isMut: false, - isSigner: false, - }, - { - name: 'permissionAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'oracle', - isMut: false, - isSigner: false, - }, - { - name: 'oracleAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'payer', - isMut: true, - isSigner: true, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'govProgram', - isMut: false, - isSigner: false, - }, - { - name: 'daoMint', - isMut: false, - isSigner: false, - }, - { - name: 'spawnRecord', - isMut: true, - isSigner: false, - }, - { - name: 'voterWeight', - isMut: true, - isSigner: false, - }, - { - name: 'tokenOwnerRecord', - isMut: true, - isSigner: false, - }, - { - name: 'realm', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'PermissionSetVoterWeightParams', - }, - }, - ], - }, - { - name: 'programConfig', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'daoMint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'ProgramConfigParams', - }, - }, - ], - }, - { - name: 'programInit', - accounts: [ - { - name: 'state', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: false, - }, - { - name: 'tokenMint', - isMut: true, - isSigner: false, - }, - { - name: 'vault', - isMut: true, - isSigner: false, - }, - { - name: 'payer', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'daoMint', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'ProgramInitParams', - }, - }, - ], - }, - { - name: 'vaultTransfer', - accounts: [ - { - name: 'state', - isMut: false, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'to', - isMut: true, - isSigner: false, - }, - { - name: 'vault', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'VaultTransferParams', - }, - }, - ], - }, - { - name: 'vrfInit', - accounts: [ - { - name: 'vrf', - isMut: true, - isSigner: false, - }, - { - name: 'authority', - isMut: false, - isSigner: false, - }, - { - name: 'oracleQueue', - isMut: false, - isSigner: false, - }, - { - name: 'escrow', - isMut: true, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'VrfInitParams', - }, - }, - ], - }, - { - name: 'vrfProve', - accounts: [ - { - name: 'vrf', - isMut: true, - isSigner: false, - }, - { - name: 'oracle', - isMut: false, - isSigner: false, - }, - { - name: 'randomnessProducer', - isMut: false, - isSigner: true, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'VrfProveParams', - }, - }, - ], - }, - { - name: 'vrfProveAndVerify', - accounts: [ - { - name: 'vrf', - isMut: true, - isSigner: false, - }, - { - name: 'callbackPid', - isMut: false, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'escrow', - isMut: true, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'oracle', - isMut: false, - isSigner: false, - }, - { - name: 'oracleAuthority', - isMut: false, - isSigner: true, - }, - { - name: 'oracleWallet', - isMut: true, - isSigner: false, - }, - { - name: 'instructionsSysvar', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'VrfProveAndVerifyParams', - }, - }, - ], - }, - { - name: 'vrfRequestRandomness', - accounts: [ - { - name: 'authority', - isMut: false, - isSigner: true, - }, - { - name: 'vrf', - isMut: true, - isSigner: false, - }, - { - name: 'oracleQueue', - isMut: true, - isSigner: false, - }, - { - name: 'queueAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'dataBuffer', - isMut: false, - isSigner: false, - }, - { - name: 'permission', - isMut: true, - isSigner: false, - }, - { - name: 'escrow', - isMut: true, - isSigner: false, - }, - { - name: 'payerWallet', - isMut: true, - isSigner: false, - }, - { - name: 'payerAuthority', - isMut: false, - isSigner: true, - }, - { - name: 'recentBlockhashes', - isMut: false, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'VrfRequestRandomnessParams', - }, - }, - ], - }, - { - name: 'vrfVerify', - accounts: [ - { - name: 'vrf', - isMut: true, - isSigner: false, - }, - { - name: 'callbackPid', - isMut: false, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - { - name: 'escrow', - isMut: true, - isSigner: false, - }, - { - name: 'programState', - isMut: false, - isSigner: false, - }, - { - name: 'oracle', - isMut: false, - isSigner: false, - }, - { - name: 'oracleAuthority', - isMut: false, - isSigner: false, - }, - { - name: 'oracleWallet', - isMut: true, - isSigner: false, - }, - { - name: 'instructionsSysvar', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'params', - type: { - defined: 'VrfVerifyParams', - }, - }, - ], - }, - ], - accounts: [ - { - name: 'SbState', - type: { - kind: 'struct', - fields: [ - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'tokenMint', - type: 'publicKey', - }, - { - name: 'tokenVault', - type: 'publicKey', - }, - { - name: 'daoMint', - type: 'publicKey', - }, - { - name: 'ebuf', - type: { - array: ['u8', 992], - }, - }, - ], - }, - }, - { - name: 'AggregatorAccountData', - type: { - kind: 'struct', - fields: [ - { - name: 'name', - type: { - array: ['u8', 32], - }, - }, - { - name: 'metadata', - type: { - array: ['u8', 128], - }, - }, - { - name: 'reserved1', - type: { - array: ['u8', 32], - }, - }, - { - name: 'queuePubkey', - type: 'publicKey', - }, - { - name: 'oracleRequestBatchSize', - type: 'u32', - }, - { - name: 'minOracleResults', - type: 'u32', - }, - { - name: 'minJobResults', - type: 'u32', - }, - { - name: 'minUpdateDelaySeconds', - type: 'u32', - }, - { - name: 'startAfter', - type: 'i64', - }, - { - name: 'varianceThreshold', - type: { - defined: 'SwitchboardDecimal', - }, - }, - { - name: 'forceReportPeriod', - type: 'i64', - }, - { - name: 'expiration', - type: 'i64', - }, - { - name: 'consecutiveFailureCount', - type: 'u64', - }, - { - name: 'nextAllowedUpdateTime', - type: 'i64', - }, - { - name: 'isLocked', - type: 'bool', - }, - { - name: 'crankPubkey', - type: 'publicKey', - }, - { - name: 'latestConfirmedRound', - type: { - defined: 'AggregatorRound', - }, - }, - { - name: 'currentRound', - type: { - defined: 'AggregatorRound', - }, - }, - { - name: 'jobPubkeysData', - type: { - array: ['publicKey', 16], - }, - }, - { - name: 'jobHashes', - type: { - array: [ - { - defined: 'Hash', - }, - 16, - ], - }, - }, - { - name: 'jobPubkeysSize', - type: 'u32', - }, - { - name: 'jobsChecksum', - type: { - array: ['u8', 32], - }, - }, - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'historyBuffer', - type: 'publicKey', - }, - { - name: 'previousConfirmedRoundResult', - type: { - defined: 'SwitchboardDecimal', - }, - }, - { - name: 'previousConfirmedRoundSlot', - type: 'u64', - }, - { - name: 'disableCrank', - type: 'bool', - }, - { - name: 'jobWeights', - type: { - array: ['u8', 16], - }, - }, - { - name: 'ebuf', - type: { - array: ['u8', 147], - }, - }, - ], - }, - }, - { - name: 'PermissionAccountData', - type: { - kind: 'struct', - fields: [ - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'permissions', - type: 'u32', - }, - { - name: 'granter', - type: 'publicKey', - }, - { - name: 'grantee', - type: 'publicKey', - }, - { - name: 'expiration', - type: 'i64', - }, - { - name: 'ebuf', - type: { - array: ['u8', 256], - }, - }, - ], - }, - }, - { - name: 'RealmSpawnRecordAccountData', - type: { - kind: 'struct', - fields: [ - { - name: 'ebuf', - type: { - array: ['u8', 256], - }, - }, - ], - }, - }, - { - name: 'LeaseAccountData', - type: { - kind: 'struct', - fields: [ - { - name: 'escrow', - type: 'publicKey', - }, - { - name: 'queue', - type: 'publicKey', - }, - { - name: 'aggregator', - type: 'publicKey', - }, - { - name: 'tokenProgram', - type: 'publicKey', - }, - { - name: 'isActive', - type: 'bool', - }, - { - name: 'crankRowCount', - type: 'u32', - }, - { - name: 'createdAt', - type: 'i64', - }, - { - name: 'updateCount', - type: 'u128', - }, - { - name: 'withdrawAuthority', - type: 'publicKey', - }, - { - name: 'ebuf', - type: { - array: ['u8', 256], - }, - }, - ], - }, - }, - { - name: 'OracleQueueAccountData', - type: { - kind: 'struct', - fields: [ - { - name: 'name', - type: { - array: ['u8', 32], - }, - }, - { - name: 'metadata', - type: { - array: ['u8', 64], - }, - }, - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'oracleTimeout', - type: 'u32', - }, - { - name: 'reward', - type: 'u64', - }, - { - name: 'minStake', - type: 'u64', - }, - { - name: 'slashingEnabled', - type: 'bool', - }, - { - name: 'varianceToleranceMultiplier', - type: { - defined: 'SwitchboardDecimal', - }, - }, - { - name: 'feedProbationPeriod', - type: 'u32', - }, - { - name: 'currIdx', - type: 'u32', - }, - { - name: 'size', - type: 'u32', - }, - { - name: 'gcIdx', - type: 'u32', - }, - { - name: 'consecutiveFeedFailureLimit', - type: 'u64', - }, - { - name: 'consecutiveOracleFailureLimit', - type: 'u64', - }, - { - name: 'unpermissionedFeedsEnabled', - type: 'bool', - }, - { - name: 'unpermissionedVrfEnabled', - type: 'bool', - }, - { - name: 'curatorRewardCut', - type: { - defined: 'SwitchboardDecimal', - }, - }, - { - name: 'lockLeaseFunding', - type: 'bool', - }, - { - name: 'mint', - type: 'publicKey', - }, - { - name: 'ebuf', - type: { - array: ['u8', 969], - }, - }, - { - name: 'maxSize', - type: 'u32', - }, - { - name: 'dataBuffer', - type: 'publicKey', - }, - ], - }, - }, - { - name: 'CrankAccountData', - type: { - kind: 'struct', - fields: [ - { - name: 'name', - type: { - array: ['u8', 32], - }, - }, - { - name: 'metadata', - type: { - array: ['u8', 64], - }, - }, - { - name: 'queuePubkey', - type: 'publicKey', - }, - { - name: 'pqSize', - type: 'u32', - }, - { - name: 'maxRows', - type: 'u32', - }, - { - name: 'jitterModifier', - type: 'u8', - }, - { - name: 'ebuf', - type: { - array: ['u8', 255], - }, - }, - { - name: 'dataBuffer', - type: 'publicKey', - }, - ], - }, - }, - { - name: 'OracleAccountData', - type: { - kind: 'struct', - fields: [ - { - name: 'name', - type: { - array: ['u8', 32], - }, - }, - { - name: 'metadata', - type: { - array: ['u8', 128], - }, - }, - { - name: 'oracleAuthority', - type: 'publicKey', - }, - { - name: 'lastHeartbeat', - type: 'i64', - }, - { - name: 'numInUse', - type: 'u32', - }, - { - name: 'tokenAccount', - type: 'publicKey', - }, - { - name: 'queuePubkey', - type: 'publicKey', - }, - { - name: 'metrics', - type: { - defined: 'OracleMetrics', - }, - }, - { - name: 'ebuf', - type: { - array: ['u8', 256], - }, - }, - ], - }, - }, - { - name: 'JobAccountData', - type: { - kind: 'struct', - fields: [ - { - name: 'name', - type: { - array: ['u8', 32], - }, - }, - { - name: 'metadata', - type: { - array: ['u8', 64], - }, - }, - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'expiration', - type: 'i64', - }, - { - name: 'hash', - type: { - array: ['u8', 32], - }, - }, - { - name: 'data', - type: 'bytes', - }, - { - name: 'referenceCount', - type: 'u32', - }, - { - name: 'totalSpent', - type: 'u64', - }, - { - name: 'createdAt', - type: 'i64', - }, - ], - }, - }, - { - name: 'VrfAccountData', - type: { - kind: 'struct', - fields: [ - { - name: 'status', - type: { - defined: 'VrfStatus', - }, - }, - { - name: 'counter', - type: 'u128', - }, - { - name: 'authority', - type: 'publicKey', - }, - { - name: 'oracleQueue', - type: 'publicKey', - }, - { - name: 'escrow', - type: 'publicKey', - }, - { - name: 'callback', - type: { - defined: 'CallbackZC', - }, - }, - { - name: 'batchSize', - type: 'u32', - }, - { - name: 'builders', - type: { - array: [ - { - defined: 'VrfBuilder', - }, - 8, - ], - }, - }, - { - name: 'buildersLen', - type: 'u32', - }, - { - name: 'testMode', - type: 'bool', - }, - { - name: 'currentRound', - type: { - defined: 'VrfRound', - }, - }, - { - name: 'ebuf', - type: { - array: ['u8', 1024], - }, - }, - ], - }, - }, - ], - types: [ - { - name: 'AggregatorAddJobParams', - type: { - kind: 'struct', - fields: [ - { - name: 'weight', - type: { - option: 'u8', - }, - }, - ], - }, - }, - { - name: 'AggregatorInitParams', - type: { - kind: 'struct', - fields: [ - { - name: 'name', - type: { - array: ['u8', 32], - }, - }, - { - name: 'metadata', - type: { - array: ['u8', 128], - }, - }, - { - name: 'batchSize', - type: 'u32', - }, - { - name: 'minOracleResults', - type: 'u32', - }, - { - name: 'minJobResults', - type: 'u32', - }, - { - name: 'minUpdateDelaySeconds', - type: 'u32', - }, - { - name: 'startAfter', - type: 'i64', - }, - { - name: 'varianceThreshold', - type: { - defined: 'BorshDecimal', - }, - }, - { - name: 'forceReportPeriod', - type: 'i64', - }, - { - name: 'expiration', - type: 'i64', - }, - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'disableCrank', - type: 'bool', - }, - ], - }, - }, - { - name: 'AggregatorLockParams', - type: { - kind: 'struct', - fields: [], - }, - }, - { - name: 'AggregatorOpenRoundParams', - type: { - kind: 'struct', - fields: [ - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'leaseBump', - type: 'u8', - }, - { - name: 'permissionBump', - type: 'u8', - }, - { - name: 'jitter', - type: 'u8', - }, - ], - }, - }, - { - name: 'AggregatorRemoveJobParams', - type: { - kind: 'struct', - fields: [ - { - name: 'jobIdx', - type: 'u32', - }, - ], - }, - }, - { - name: 'AggregatorSaveResultParams', - type: { - kind: 'struct', - fields: [ - { - name: 'oracleIdx', - type: 'u32', - }, - { - name: 'error', - type: 'bool', - }, - { - name: 'value', - type: { - defined: 'BorshDecimal', - }, - }, - { - name: 'jobsChecksum', - type: { - array: ['u8', 32], - }, - }, - { - name: 'minResponse', - type: { - defined: 'BorshDecimal', - }, - }, - { - name: 'maxResponse', - type: { - defined: 'BorshDecimal', - }, - }, - { - name: 'feedPermissionBump', - type: 'u8', - }, - { - name: 'oraclePermissionBump', - type: 'u8', - }, - { - name: 'leaseBump', - type: 'u8', - }, - { - name: 'stateBump', - type: 'u8', - }, - ], - }, - }, - { - name: 'AggregatorSetAuthorityParams', - type: { - kind: 'struct', - fields: [], - }, - }, - { - name: 'AggregatorSetBatchSizeParams', - type: { - kind: 'struct', - fields: [ - { - name: 'batchSize', - type: 'u32', - }, - ], - }, - }, - { - name: 'AggregatorSetHistoryBufferParams', - type: { - kind: 'struct', - fields: [], - }, - }, - { - name: 'AggregatorSetMinJobsParams', - type: { - kind: 'struct', - fields: [ - { - name: 'minJobResults', - type: 'u32', - }, - ], - }, - }, - { - name: 'AggregatorSetMinOraclesParams', - type: { - kind: 'struct', - fields: [ - { - name: 'minOracleResults', - type: 'u32', - }, - ], - }, - }, - { - name: 'AggregatorSetQueueParams', - type: { - kind: 'struct', - fields: [], - }, - }, - { - name: 'AggregatorSetUpdateIntervalParams', - type: { - kind: 'struct', - fields: [ - { - name: 'newInterval', - type: 'u32', - }, - ], - }, - }, - { - name: 'AggregatorSetVarianceThresholdParams', - type: { - kind: 'struct', - fields: [ - { - name: 'varianceThreshold', - type: { - defined: 'BorshDecimal', - }, - }, - ], - }, - }, - { - name: 'CrankInitParams', - type: { - kind: 'struct', - fields: [ - { - name: 'name', - type: 'bytes', - }, - { - name: 'metadata', - type: 'bytes', - }, - { - name: 'crankSize', - type: 'u32', - }, - ], - }, - }, - { - name: 'CrankPopParams', - type: { - kind: 'struct', - fields: [ - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'leaseBumps', - type: 'bytes', - }, - { - name: 'permissionBumps', - type: 'bytes', - }, - { - name: 'nonce', - type: { - option: 'u32', - }, - }, - { - name: 'failOpenOnAccountMismatch', - type: { - option: 'bool', - }, - }, - ], - }, - }, - { - name: 'CrankPushParams', - type: { - kind: 'struct', - fields: [ - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'permissionBump', - type: 'u8', - }, - ], - }, - }, - { - name: 'JobInitParams', - type: { - kind: 'struct', - fields: [ - { - name: 'name', - type: { - array: ['u8', 32], - }, - }, - { - name: 'expiration', - type: 'i64', - }, - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'data', - type: 'bytes', - }, - ], - }, - }, - { - name: 'LeaseExtendParams', - type: { - kind: 'struct', - fields: [ - { - name: 'loadAmount', - type: 'u64', - }, - { - name: 'leaseBump', - type: 'u8', - }, - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'walletBumps', - type: 'bytes', - }, - ], - }, - }, - { - name: 'LeaseInitParams', - type: { - kind: 'struct', - fields: [ - { - name: 'loadAmount', - type: 'u64', - }, - { - name: 'withdrawAuthority', - type: 'publicKey', - }, - { - name: 'leaseBump', - type: 'u8', - }, - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'walletBumps', - type: 'bytes', - }, - ], - }, - }, - { - name: 'LeaseSetAuthorityParams', - type: { - kind: 'struct', - fields: [], - }, - }, - { - name: 'LeaseWithdrawParams', - type: { - kind: 'struct', - fields: [ - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'leaseBump', - type: 'u8', - }, - { - name: 'amount', - type: 'u64', - }, - ], - }, - }, - { - name: 'OracleHeartbeatParams', - type: { - kind: 'struct', - fields: [ - { - name: 'permissionBump', - type: 'u8', - }, - ], - }, - }, - { - name: 'OracleInitParams', - type: { - kind: 'struct', - fields: [ - { - name: 'name', - type: 'bytes', - }, - { - name: 'metadata', - type: 'bytes', - }, - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'oracleBump', - type: 'u8', - }, - ], - }, - }, - { - name: 'OracleQueueInitParams', - type: { - kind: 'struct', - fields: [ - { - name: 'name', - type: { - array: ['u8', 32], - }, - }, - { - name: 'metadata', - type: { - array: ['u8', 64], - }, - }, - { - name: 'reward', - type: 'u64', - }, - { - name: 'minStake', - type: 'u64', - }, - { - name: 'feedProbationPeriod', - type: 'u32', - }, - { - name: 'oracleTimeout', - type: 'u32', - }, - { - name: 'slashingEnabled', - type: 'bool', - }, - { - name: 'varianceToleranceMultiplier', - type: { - defined: 'BorshDecimal', - }, - }, - { - name: 'consecutiveFeedFailureLimit', - type: 'u64', - }, - { - name: 'consecutiveOracleFailureLimit', - type: 'u64', - }, - { - name: 'queueSize', - type: 'u32', - }, - { - name: 'unpermissionedFeeds', - type: 'bool', - }, - { - name: 'unpermissionedVrf', - type: 'bool', - }, - ], - }, - }, - { - name: 'OracleQueueSetRewardsParams', - type: { - kind: 'struct', - fields: [ - { - name: 'rewards', - type: 'u64', - }, - ], - }, - }, - { - name: 'OracleQueueVrfConfigParams', - type: { - kind: 'struct', - fields: [ - { - name: 'unpermissionedVrfEnabled', - type: 'bool', - }, - ], - }, - }, - { - name: 'OracleWithdrawParams', - type: { - kind: 'struct', - fields: [ - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'permissionBump', - type: 'u8', - }, - { - name: 'amount', - type: 'u64', - }, - ], - }, - }, - { - name: 'PermissionInitParams', - type: { - kind: 'struct', - fields: [], - }, - }, - { - name: 'PermissionSetParams', - type: { - kind: 'struct', - fields: [ - { - name: 'permission', - type: { - defined: 'SwitchboardPermission', - }, - }, - { - name: 'enable', - type: 'bool', - }, - ], - }, - }, - { - name: 'PermissionSetVoterWeightParams', - type: { - kind: 'struct', - fields: [ - { - name: 'stateBump', - type: 'u8', - }, - ], - }, - }, - { - name: 'ProgramConfigParams', - type: { - kind: 'struct', - fields: [ - { - name: 'token', - type: 'publicKey', - }, - { - name: 'bump', - type: 'u8', - }, - { - name: 'daoMint', - type: 'publicKey', - }, - ], - }, - }, - { - name: 'ProgramInitParams', - type: { - kind: 'struct', - fields: [ - { - name: 'stateBump', - type: 'u8', - }, - ], - }, - }, - { - name: 'VaultTransferParams', - type: { - kind: 'struct', - fields: [ - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'amount', - type: 'u64', - }, - ], - }, - }, - { - name: 'VrfInitParams', - type: { - kind: 'struct', - fields: [ - { - name: 'callback', - type: { - defined: 'Callback', - }, - }, - { - name: 'stateBump', - type: 'u8', - }, - ], - }, - }, - { - name: 'VrfProveParams', - type: { - kind: 'struct', - fields: [ - { - name: 'proof', - type: 'bytes', - }, - { - name: 'idx', - type: 'u32', - }, - ], - }, - }, - { - name: 'VrfProveAndVerifyParams', - type: { - kind: 'struct', - fields: [ - { - name: 'nonce', - type: { - option: 'u32', - }, - }, - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'idx', - type: 'u32', - }, - { - name: 'proof', - type: 'bytes', - }, - ], - }, - }, - { - name: 'VrfRequestRandomnessParams', - type: { - kind: 'struct', - fields: [ - { - name: 'permissionBump', - type: 'u8', - }, - { - name: 'stateBump', - type: 'u8', - }, - ], - }, - }, - { - name: 'VrfVerifyParams', - type: { - kind: 'struct', - fields: [ - { - name: 'nonce', - type: { - option: 'u32', - }, - }, - { - name: 'stateBump', - type: 'u8', - }, - { - name: 'idx', - type: 'u32', - }, - ], - }, - }, - { - name: 'Hash', - type: { - kind: 'struct', - fields: [ - { - name: 'data', - type: { - array: ['u8', 32], - }, - }, - ], - }, - }, - { - name: 'AggregatorRound', - type: { - kind: 'struct', - fields: [ - { - name: 'numSuccess', - type: 'u32', - }, - { - name: 'numError', - type: 'u32', - }, - { - name: 'isClosed', - type: 'bool', - }, - { - name: 'roundOpenSlot', - type: 'u64', - }, - { - name: 'roundOpenTimestamp', - type: 'i64', - }, - { - name: 'result', - type: { - defined: 'SwitchboardDecimal', - }, - }, - { - name: 'stdDeviation', - type: { - defined: 'SwitchboardDecimal', - }, - }, - { - name: 'minResponse', - type: { - defined: 'SwitchboardDecimal', - }, - }, - { - name: 'maxResponse', - type: { - defined: 'SwitchboardDecimal', - }, - }, - { - name: 'oraclePubkeysData', - type: { - array: ['publicKey', 16], - }, - }, - { - name: 'mediansData', - type: { - array: [ - { - defined: 'SwitchboardDecimal', - }, - 16, - ], - }, - }, - { - name: 'currentPayout', - type: { - array: ['i64', 16], - }, - }, - { - name: 'mediansFulfilled', - type: { - array: ['bool', 16], - }, - }, - { - name: 'errorsFulfilled', - type: { - array: ['bool', 16], - }, - }, - ], - }, - }, - { - name: 'AggregatorHistoryRow', - type: { - kind: 'struct', - fields: [ - { - name: 'timestamp', - type: 'i64', - }, - { - name: 'value', - type: { - defined: 'SwitchboardDecimal', - }, - }, - ], - }, - }, - { - name: 'SwitchboardDecimal', - type: { - kind: 'struct', - fields: [ - { - name: 'mantissa', - type: 'i128', - }, - { - name: 'scale', - type: 'u32', - }, - ], - }, - }, - { - name: 'CrankRow', - type: { - kind: 'struct', - fields: [ - { - name: 'pubkey', - type: 'publicKey', - }, - { - name: 'nextTimestamp', - type: 'i64', - }, - ], - }, - }, - { - name: 'OracleMetrics', - type: { - kind: 'struct', - fields: [ - { - name: 'consecutiveSuccess', - type: 'u64', - }, - { - name: 'consecutiveError', - type: 'u64', - }, - { - name: 'consecutiveDisagreement', - type: 'u64', - }, - { - name: 'consecutiveLateResponse', - type: 'u64', - }, - { - name: 'consecutiveFailure', - type: 'u64', - }, - { - name: 'totalSuccess', - type: 'u128', - }, - { - name: 'totalError', - type: 'u128', - }, - { - name: 'totalDisagreement', - type: 'u128', - }, - { - name: 'totalLateResponse', - type: 'u128', - }, - ], - }, - }, - { - name: 'BorshDecimal', - type: { - kind: 'struct', - fields: [ - { - name: 'mantissa', - type: 'i128', - }, - { - name: 'scale', - type: 'u32', - }, - ], - }, - }, - { - name: 'EcvrfProofZC', - type: { - kind: 'struct', - fields: [ - { - name: 'gamma', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'c', - type: { - defined: 'Scalar', - }, - }, - { - name: 's', - type: { - defined: 'Scalar', - }, - }, - ], - }, - }, - { - name: 'Scalar', - type: { - kind: 'struct', - fields: [ - { - name: 'bytes', - type: { - array: ['u8', 32], - }, - }, - ], - }, - }, - { - name: 'FieldElementZC', - type: { - kind: 'struct', - fields: [ - { - name: 'bytes', - type: { - array: ['u64', 5], - }, - }, - ], - }, - }, - { - name: 'CompletedPointZC', - type: { - kind: 'struct', - fields: [ - { - name: 'x', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'y', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'z', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 't', - type: { - defined: 'FieldElementZC', - }, - }, - ], - }, - }, - { - name: 'EdwardsPointZC', - type: { - kind: 'struct', - fields: [ - { - name: 'x', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'y', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'z', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 't', - type: { - defined: 'FieldElementZC', - }, - }, - ], - }, - }, - { - name: 'ProjectivePointZC', - type: { - kind: 'struct', - fields: [ - { - name: 'x', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'y', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'z', - type: { - defined: 'FieldElementZC', - }, - }, - ], - }, - }, - { - name: 'EcvrfIntermediate', - type: { - kind: 'struct', - fields: [ - { - name: 'r', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'nS', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'd', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 't13', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 't15', - type: { - defined: 'FieldElementZC', - }, - }, - ], - }, - }, - { - name: 'VrfBuilder', - type: { - kind: 'struct', - fields: [ - { - name: 'producer', - type: 'publicKey', - }, - { - name: 'status', - type: { - defined: 'VrfStatus', - }, - }, - { - name: 'reprProof', - type: { - array: ['u8', 80], - }, - }, - { - name: 'proof', - type: { - defined: 'EcvrfProofZC', - }, - }, - { - name: 'yPoint', - type: 'publicKey', - }, - { - name: 'stage', - type: 'u32', - }, - { - name: 'stage1Out', - type: { - defined: 'EcvrfIntermediate', - }, - }, - { - name: 'r1', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'r2', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'stage3Out', - type: { - defined: 'EcvrfIntermediate', - }, - }, - { - name: 'hPoint', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'sReduced', - type: { - defined: 'Scalar', - }, - }, - { - name: 'yPointBuilder', - type: { - array: [ - { - defined: 'FieldElementZC', - }, - 3, - ], - }, - }, - { - name: 'yRistrettoPoint', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'mulRound', - type: 'u8', - }, - { - name: 'hashPointsRound', - type: 'u8', - }, - { - name: 'mulTmp1', - type: { - defined: 'CompletedPointZC', - }, - }, - { - name: 'uPoint1', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'uPoint2', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'vPoint1', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'vPoint2', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'uPoint', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'vPoint', - type: { - defined: 'EdwardsPointZC', - }, - }, - { - name: 'u1', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'u2', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'invertee', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'y', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'z', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'p1Bytes', - type: { - array: ['u8', 32], - }, - }, - { - name: 'p2Bytes', - type: { - array: ['u8', 32], - }, - }, - { - name: 'p3Bytes', - type: { - array: ['u8', 32], - }, - }, - { - name: 'p4Bytes', - type: { - array: ['u8', 32], - }, - }, - { - name: 'cPrimeHashbuf', - type: { - array: ['u8', 16], - }, - }, - { - name: 'm1', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'm2', - type: { - defined: 'FieldElementZC', - }, - }, - { - name: 'txRemaining', - type: 'u32', - }, - { - name: 'verified', - type: 'bool', - }, - { - name: 'result', - type: { - array: ['u8', 32], - }, - }, - ], - }, - }, - { - name: 'AccountMetaZC', - type: { - kind: 'struct', - fields: [ - { - name: 'pubkey', - type: 'publicKey', - }, - { - name: 'isSigner', - type: 'bool', - }, - { - name: 'isWritable', - type: 'bool', - }, - ], - }, - }, - { - name: 'AccountMetaBorsh', - type: { - kind: 'struct', - fields: [ - { - name: 'pubkey', - type: 'publicKey', - }, - { - name: 'isSigner', - type: 'bool', - }, - { - name: 'isWritable', - type: 'bool', - }, - ], - }, - }, - { - name: 'CallbackZC', - type: { - kind: 'struct', - fields: [ - { - name: 'programId', - type: 'publicKey', - }, - { - name: 'accounts', - type: { - array: [ - { - defined: 'AccountMetaZC', - }, - 32, - ], - }, - }, - { - name: 'accountsLen', - type: 'u32', - }, - { - name: 'ixData', - type: { - array: ['u8', 1024], - }, - }, - { - name: 'ixDataLen', - type: 'u32', - }, - ], - }, - }, - { - name: 'Callback', - type: { - kind: 'struct', - fields: [ - { - name: 'programId', - type: 'publicKey', - }, - { - name: 'accounts', - type: { - vec: { - defined: 'AccountMetaBorsh', - }, - }, - }, - { - name: 'ixData', - type: 'bytes', - }, - ], - }, - }, - { - name: 'VrfRound', - type: { - kind: 'struct', - fields: [ - { - name: 'alpha', - type: { - array: ['u8', 256], - }, - }, - { - name: 'alphaLen', - type: 'u32', - }, - { - name: 'requestSlot', - type: 'u64', - }, - { - name: 'requestTimestamp', - type: 'i64', - }, - { - name: 'result', - type: { - array: ['u8', 32], - }, - }, - { - name: 'numVerified', - type: 'u32', - }, - { - name: 'ebuf', - type: { - array: ['u8', 256], - }, - }, - ], - }, - }, - { - name: 'Lanes', - type: { - kind: 'enum', - variants: [ - { - name: 'C', - }, - { - name: 'D', - }, - { - name: 'AB', - }, - { - name: 'AC', - }, - { - name: 'CD', - }, - { - name: 'AD', - }, - { - name: 'BC', - }, - { - name: 'ABCD', - }, - ], - }, - }, - { - name: 'Shuffle', - type: { - kind: 'enum', - variants: [ - { - name: 'AAAA', - }, - { - name: 'BBBB', - }, - { - name: 'CACA', - }, - { - name: 'DBBD', - }, - { - name: 'ADDA', - }, - { - name: 'CBCB', - }, - { - name: 'ABAB', - }, - { - name: 'BADC', - }, - { - name: 'BACD', - }, - { - name: 'ABDC', - }, - ], - }, - }, - { - name: 'Shuffle', - type: { - kind: 'enum', - variants: [ - { - name: 'AAAA', - }, - { - name: 'BBBB', - }, - { - name: 'BADC', - }, - { - name: 'BACD', - }, - { - name: 'ADDA', - }, - { - name: 'CBCB', - }, - { - name: 'ABDC', - }, - { - name: 'ABAB', - }, - { - name: 'DBBD', - }, - { - name: 'CACA', - }, - ], - }, - }, - { - name: 'Lanes', - type: { - kind: 'enum', - variants: [ - { - name: 'D', - }, - { - name: 'C', - }, - { - name: 'AB', - }, - { - name: 'AC', - }, - { - name: 'AD', - }, - { - name: 'BCD', - }, - ], - }, - }, - { - name: 'Error', - type: { - kind: 'enum', - variants: [ - { - name: 'InvalidPublicKey', - }, - { - name: 'SerializationError', - fields: [ - { - defined: 'bincode::Error', - }, - ], - }, - { - name: 'DeserializationError', - fields: [ - { - defined: 'bincode::Error', - }, - ], - }, - { - name: 'InvalidDataError', - }, - ], - }, - }, - { - name: 'SwitchboardPermission', - type: { - kind: 'enum', - variants: [ - { - name: 'PermitOracleHeartbeat', - }, - { - name: 'PermitOracleQueueUsage', - }, - { - name: 'PermitVrfRequests', - }, - ], - }, - }, - { - name: 'OracleResponseType', - type: { - kind: 'enum', - variants: [ - { - name: 'TypeSuccess', - }, - { - name: 'TypeError', - }, - { - name: 'TypeDisagreement', - }, - { - name: 'TypeNoResponse', - }, - ], - }, - }, - { - name: 'VrfStatus', - type: { - kind: 'enum', - variants: [ - { - name: 'StatusNone', - }, - { - name: 'StatusRequesting', - }, - { - name: 'StatusVerifying', - }, - { - name: 'StatusVerified', - }, - { - name: 'StatusCallbackSuccess', - }, - { - name: 'StatusVerifyFailure', - }, - ], - }, - }, - ], - events: [ - { - name: 'AggregatorInitEvent', - fields: [ - { - name: 'feedPubkey', - type: 'publicKey', - index: false, - }, - ], - }, - { - name: 'VrfRequestRandomnessEvent', - fields: [ - { - name: 'vrfPubkey', - type: 'publicKey', - index: true, - }, - { - name: 'oraclePubkeys', - type: { - vec: 'publicKey', - }, - index: false, - }, - { - name: 'loadAmount', - type: 'u64', - index: false, - }, - { - name: 'existingAmount', - type: 'u64', - index: false, - }, - ], - }, - { - name: 'VrfRequestEvent', - fields: [ - { - name: 'vrfPubkey', - type: 'publicKey', - index: true, - }, - { - name: 'oraclePubkeys', - type: { - vec: 'publicKey', - }, - index: false, - }, - ], - }, - { - name: 'VrfProveEvent', - fields: [ - { - name: 'vrfPubkey', - type: 'publicKey', - index: true, - }, - { - name: 'oraclePubkey', - type: 'publicKey', - index: true, - }, - { - name: 'authorityPubkey', - type: 'publicKey', - index: false, - }, - ], - }, - { - name: 'VrfVerifyEvent', - fields: [ - { - name: 'vrfPubkey', - type: 'publicKey', - index: true, - }, - { - name: 'oraclePubkey', - type: 'publicKey', - index: true, - }, - { - name: 'authorityPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'amount', - type: 'u64', - index: false, - }, - ], - }, - { - name: 'VrfCallbackPerformedEvent', - fields: [ - { - name: 'vrfPubkey', - type: 'publicKey', - index: true, - }, - { - name: 'oraclePubkey', - type: 'publicKey', - index: true, - }, - { - name: 'amount', - type: 'u64', - index: false, - }, - ], - }, - { - name: 'AggregatorOpenRoundEvent', - fields: [ - { - name: 'feedPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'oraclePubkeys', - type: { - vec: 'publicKey', - }, - index: false, - }, - { - name: 'jobPubkeys', - type: { - vec: 'publicKey', - }, - index: false, - }, - { - name: 'remainingFunds', - type: 'u64', - index: false, - }, - { - name: 'queueAuthority', - type: 'publicKey', - index: false, - }, - ], - }, - { - name: 'AggregatorValueUpdateEvent', - fields: [ - { - name: 'feedPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'value', - type: { - defined: 'BorshDecimal', - }, - index: false, - }, - { - name: 'slot', - type: 'u64', - index: false, - }, - { - name: 'timestamp', - type: 'i64', - index: false, - }, - { - name: 'oraclePubkeys', - type: { - vec: 'publicKey', - }, - index: false, - }, - { - name: 'oracleValues', - type: { - vec: { - defined: 'BorshDecimal', - }, - }, - index: false, - }, - ], - }, - { - name: 'OracleRewardEvent', - fields: [ - { - name: 'feedPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'leasePubkey', - type: 'publicKey', - index: false, - }, - { - name: 'oraclePubkey', - type: 'publicKey', - index: false, - }, - { - name: 'walletPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'amount', - type: 'u64', - index: false, - }, - { - name: 'roundSlot', - type: 'u64', - index: false, - }, - { - name: 'timestamp', - type: 'i64', - index: false, - }, - ], - }, - { - name: 'OracleWithdrawEvent', - fields: [ - { - name: 'oraclePubkey', - type: 'publicKey', - index: false, - }, - { - name: 'walletPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'destinationWallet', - type: 'publicKey', - index: false, - }, - { - name: 'previousAmount', - type: 'u64', - index: false, - }, - { - name: 'newAmount', - type: 'u64', - index: false, - }, - { - name: 'timestamp', - type: 'i64', - index: false, - }, - ], - }, - { - name: 'LeaseWithdrawEvent', - fields: [ - { - name: 'leasePubkey', - type: 'publicKey', - index: false, - }, - { - name: 'walletPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'previousAmount', - type: 'u64', - index: false, - }, - { - name: 'newAmount', - type: 'u64', - index: false, - }, - { - name: 'timestamp', - type: 'i64', - index: false, - }, - ], - }, - { - name: 'OracleSlashEvent', - fields: [ - { - name: 'feedPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'leasePubkey', - type: 'publicKey', - index: false, - }, - { - name: 'oraclePubkey', - type: 'publicKey', - index: false, - }, - { - name: 'walletPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'amount', - type: 'u64', - index: false, - }, - { - name: 'roundSlot', - type: 'u64', - index: false, - }, - { - name: 'timestamp', - type: 'i64', - index: false, - }, - ], - }, - { - name: 'LeaseFundEvent', - fields: [ - { - name: 'leasePubkey', - type: 'publicKey', - index: false, - }, - { - name: 'funder', - type: 'publicKey', - index: false, - }, - { - name: 'amount', - type: 'u64', - index: false, - }, - { - name: 'timestamp', - type: 'i64', - index: false, - }, - ], - }, - { - name: 'ProbationBrokenEvent', - fields: [ - { - name: 'feedPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'queuePubkey', - type: 'publicKey', - index: false, - }, - { - name: 'timestamp', - type: 'i64', - index: false, - }, - ], - }, - { - name: 'FeedPermissionRevokedEvent', - fields: [ - { - name: 'feedPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'timestamp', - type: 'i64', - index: false, - }, - ], - }, - { - name: 'GarbageCollectFailureEvent', - fields: [ - { - name: 'queuePubkey', - type: 'publicKey', - index: false, - }, - ], - }, - { - name: 'OracleBootedEvent', - fields: [ - { - name: 'queuePubkey', - type: 'publicKey', - index: false, - }, - { - name: 'oraclePubkey', - type: 'publicKey', - index: false, - }, - ], - }, - { - name: 'CrankLeaseInsufficientFundsEvent', - fields: [ - { - name: 'feedPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'leasePubkey', - type: 'publicKey', - index: false, - }, - ], - }, - { - name: 'CrankPopExpectedFailureEvent', - fields: [ - { - name: 'feedPubkey', - type: 'publicKey', - index: false, - }, - { - name: 'leasePubkey', - type: 'publicKey', - index: false, - }, - ], - }, - ], - errors: [ - { - code: 6000, - name: 'ArrayOperationError', - msg: 'Illegal operation on a Switchboard array.', - }, - { - code: 6001, - name: 'QueueOperationError', - msg: 'Illegal operation on a Switchboard queue.', - }, - { - code: 6002, - name: 'IncorrectProgramOwnerError', - msg: - 'An account required to be owned by the program has a different owner.', - }, - { - code: 6003, - name: 'InvalidAggregatorRound', - msg: 'Aggregator is not currently populated with a valid round.', - }, - { - code: 6004, - name: 'TooManyAggregatorJobs', - msg: 'Aggregator cannot fit any more jobs.', - }, - { - code: 6005, - name: 'AggregatorCurrentRoundClosed', - msg: - "Aggregator's current round is closed. No results are being accepted.", - }, - { - code: 6006, - name: 'AggregatorInvalidSaveResult', - msg: 'Aggregator received an invalid save result instruction.', - }, - { - code: 6007, - name: 'InvalidStrDecimalConversion', - msg: 'Failed to convert string to decimal format.', - }, - { - code: 6008, - name: 'AccountLoaderMissingSignature', - msg: 'AccountLoader account is missing a required signature.', - }, - { - code: 6009, - name: 'MissingRequiredSignature', - msg: 'Account is missing a required signature.', - }, - { - code: 6010, - name: 'ArrayOverflowError', - msg: 'The attempted action will overflow a zero-copy account array.', - }, - { - code: 6011, - name: 'ArrayUnderflowError', - msg: 'The attempted action will underflow a zero-copy account array.', - }, - { - code: 6012, - name: 'PubkeyNotFoundError', - msg: 'The queried public key was not found.', - }, - { - code: 6013, - name: 'AggregatorIllegalRoundOpenCall', - msg: 'Aggregator round open called too early.', - }, - { - code: 6014, - name: 'AggregatorIllegalRoundCloseCall', - msg: 'Aggregator round close called too early.', - }, - { - code: 6015, - name: 'AggregatorClosedError', - msg: 'Aggregator is closed. Illegal action.', - }, - { - code: 6016, - name: 'IllegalOracleIdxError', - msg: 'Illegal oracle index.', - }, - { - code: 6017, - name: 'OracleAlreadyRespondedError', - msg: 'The provided oracle has already responded this round.', - }, - { - code: 6018, - name: 'ProtoDeserializeError', - msg: 'Failed to deserialize protocol buffer.', - }, - { - code: 6019, - name: 'UnauthorizedStateUpdateError', - msg: 'Unauthorized program state modification attempted.', - }, - { - code: 6020, - name: 'MissingOracleAccountsError', - msg: 'Not enough oracle accounts provided to closeRounds.', - }, - { - code: 6021, - name: 'OracleMismatchError', - msg: 'An unexpected oracle account was provided for the transaction.', - }, - { - code: 6022, - name: 'CrankMaxCapacityError', - msg: "Attempted to push to a Crank that's at capacity", - }, - { - code: 6023, - name: 'AggregatorLeaseInsufficientFunds', - msg: - 'Aggregator update call attempted but attached lease has insufficient funds.', - }, - { - code: 6024, - name: 'IncorrectTokenAccountMint', - msg: - 'The provided token account does not point to the Switchboard token mint.', - }, - { - code: 6025, - name: 'InvalidEscrowAccount', - msg: 'An invalid escrow account was provided.', - }, - { - code: 6026, - name: 'CrankEmptyError', - msg: 'Crank empty. Pop failed.', - }, - { - code: 6027, - name: 'PdaDeriveError', - msg: 'Failed to derive a PDA from the provided seed.', - }, - { - code: 6028, - name: 'AggregatorAccountNotFound', - msg: 'Aggregator account missing from provided account list.', - }, - { - code: 6029, - name: 'PermissionAccountNotFound', - msg: 'Permission account missing from provided account list.', - }, - { - code: 6030, - name: 'LeaseAccountDeriveFailure', - msg: 'Failed to derive a lease account.', - }, - { - code: 6031, - name: 'PermissionAccountDeriveFailure', - msg: 'Failed to derive a permission account.', - }, - { - code: 6032, - name: 'EscrowAccountNotFound', - msg: 'Escrow account missing from provided account list.', - }, - { - code: 6033, - name: 'LeaseAccountNotFound', - msg: 'Lease account missing from provided account list.', - }, - { - code: 6034, - name: 'DecimalConversionError', - msg: 'Decimal conversion method failed.', - }, - { - code: 6035, - name: 'PermissionDenied', - msg: 'Permission account is missing required flags for the given action.', - }, - { - code: 6036, - name: 'QueueAtCapacity', - msg: 'Oracle queue is at lease capacity.', - }, - { - code: 6037, - name: 'ExcessiveCrankRowsError', - msg: 'Data feed is already pushed on a crank.', - }, - { - code: 6038, - name: 'AggregatorLockedError', - msg: - 'Aggregator is locked, no setting modifications or job additions allowed.', - }, - { - code: 6039, - name: 'AggregatorInvalidBatchSizeError', - msg: 'Aggregator invalid batch size.', - }, - { - code: 6040, - name: 'AggregatorJobChecksumMismatch', - msg: 'Oracle provided an incorrect aggregator job checksum.', - }, - { - code: 6041, - name: 'IntegerOverflowError', - msg: 'An integer overflow occurred.', - }, - { - code: 6042, - name: 'InvalidUpdatePeriodError', - msg: 'Minimum update period is 5 seconds.', - }, - { - code: 6043, - name: 'NoResultsError', - msg: 'Aggregator round evaluation attempted with no results.', - }, - { - code: 6044, - name: 'InvalidExpirationError', - msg: 'An expiration constraint was broken.', - }, - { - code: 6045, - name: 'InsufficientStakeError', - msg: 'An account provided insufficient stake for action.', - }, - { - code: 6046, - name: 'LeaseInactiveError', - msg: 'The provided lease account is not active.', - }, - { - code: 6047, - name: 'NoAggregatorJobsFound', - msg: 'No jobs are currently included in the aggregator.', - }, - { - code: 6048, - name: 'IntegerUnderflowError', - msg: 'An integer underflow occurred.', - }, - { - code: 6049, - name: 'OracleQueueMismatch', - msg: 'An invalid oracle queue account was provided.', - }, - { - code: 6050, - name: 'OracleWalletMismatchError', - msg: - 'An unexpected oracle wallet account was provided for the transaction.', - }, - { - code: 6051, - name: 'InvalidBufferAccountError', - msg: 'An invalid buffer account was provided.', - }, - { - code: 6052, - name: 'InsufficientOracleQueueError', - msg: 'Insufficient oracle queue size.', - }, - { - code: 6053, - name: 'InvalidAuthorityError', - msg: 'Invalid authority account provided.', - }, - { - code: 6054, - name: 'InvalidTokenAccountMintError', - msg: 'A provided token wallet is associated with an incorrect mint.', - }, - { - code: 6055, - name: 'ExcessiveLeaseWithdrawlError', - msg: - 'You must leave enough funds to perform at least 1 update in the lease.', - }, - { - code: 6056, - name: 'InvalideHistoryAccountError', - msg: 'Invalid history account provided.', - }, - { - code: 6057, - name: 'InvalidLeaseAccountEscrowError', - msg: 'Invalid lease account escrow.', - }, - { - code: 6058, - name: 'InvalidCrankAccountError', - msg: 'Invalid crank provided.', - }, - { - code: 6059, - name: 'CrankNoElementsReadyError', - msg: 'No elements ready to be popped.', - }, - { - code: 6060, - name: 'IndexOutOfBoundsError', - msg: 'Index out of bounds', - }, - { - code: 6061, - name: 'VrfInvalidRequestError', - msg: 'Invalid vrf request params', - }, - { - code: 6062, - name: 'VrfInvalidProofSubmissionError', - msg: 'Vrf proof failed to verify', - }, - { - code: 6063, - name: 'VrfVerifyError', - msg: 'Error in verifying vrf proof.', - }, - { - code: 6064, - name: 'VrfCallbackError', - msg: 'Vrf callback function failed.', - }, - { - code: 6065, - name: 'VrfCallbackParamsError', - msg: 'Invalid vrf callback params provided.', - }, - { - code: 6066, - name: 'VrfCallbackAlreadyCalledError', - msg: 'Vrf callback has already been triggered.', - }, - { - code: 6067, - name: 'VrfInvalidPubkeyError', - msg: 'The provided pubkey is invalid to use in ecvrf proofs', - }, - { - code: 6068, - name: 'VrfTooManyVerifyCallsError', - msg: 'Number of required verify calls exceeded', - }, - { - code: 6069, - name: 'VrfRequestAlreadyLaunchedError', - msg: 'Vrf request is already pending', - }, - { - code: 6070, - name: 'VrfInsufficientVerificationError', - msg: 'Insufficient amount of proofs collected for VRF callback', - }, - { - code: 6071, - name: 'InvalidVrfProducerError', - msg: 'An incorrect oracle attempted to submit a proof', - }, - { - code: 6072, - name: 'InvalidGovernancePidError', - msg: 'Invalid SPLGovernance Account Supplied', - }, - { - code: 6073, - name: 'InvalidGovernanceAccountError', - msg: 'An Invalid Governance Account was supplied', - }, - { - code: 6074, - name: 'MissingOptionalAccount', - msg: 'Expected an optional account', - }, - { - code: 6075, - name: 'InvalidSpawnRecordOwner', - msg: 'Invalid Owner for Spawn Record', - }, - { - code: 6076, - name: 'NoopError', - msg: 'Noop error', - }, - { - code: 6077, - name: 'MissingRequiredAccountsError', - msg: 'A required instruction account was not included', - }, - { - code: 6078, - name: 'InvalidMintError', - msg: 'Invalid mint account passed for instruction', - }, - { - code: 6079, - name: 'InvalidTokenAccountKeyError', - msg: 'An invalid token account was passed into the instruction', - }, - { - code: 6080, - name: 'InvalidJobAccountError', - msg: '', - }, - ], -} diff --git a/SwitchboardVotePlugin/SwitchboardQueueVoterClient.ts b/SwitchboardVotePlugin/SwitchboardQueueVoterClient.ts deleted file mode 100644 index 706cd4a9af..0000000000 --- a/SwitchboardVotePlugin/SwitchboardQueueVoterClient.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Program, Provider } from '@project-serum/anchor' -import { PublicKey, Transaction } from '@solana/web3.js' -import { Switchboard, IDL } from './SwitchboardIdl' -//import { NftVoter, IDL } from './nft_voter'; - -export const SWITCHBOARD_ID = new PublicKey( - '7PMP6yE6qb3XzBQr5TK2GhuruYayZzBnT8U92ySaLESC' -) - -export const SWITCHBOARD_ADDIN_ID = new PublicKey( - 'B4EDDdMh5CmB6B9DeMmZmFvRzEgyHR5zWktf6httcMk6' -) - -export const SWITCHBOARD_GRANT_AUTHORITY = new PublicKey( - '5wD32vPTeBk3UJfTCQUpa4KbrHZ5xxc8f4eLnqTPNW8L' -) - -export const SWITCHBOARD_REVOKE_AUTHORITY = new PublicKey( - '9rkK8T8wnYXZ1SSC6g2ZhbnyL5K5v546XSbNJv7og87b' -) - -export const QUEUE_LIST: PublicKey[] = [ - new PublicKey('7QN4mJo9U58XMeHEyfY6ckKxAkVLkqVtcWjwgNU6xaE'), -] - -export class SwitchboardQueueVoterClient { - constructor(public program: Program, public devnet?: boolean) {} - - static async connect( - provider: Provider, - devnet?: boolean - ): Promise { - // alternatively we could fetch from chain - // const idl = await Program.fetchIdl(VSR_ID, provider); - const idl = IDL - - return new SwitchboardQueueVoterClient( - new Program(idl as Switchboard, SWITCHBOARD_ID, provider), - devnet - ) - } -} - -export async function grantPermissionTx( - program: Program, - grantAuthority: PublicKey, - switchboardProgram: PublicKey, - permission: PublicKey -): Promise { - const [addinState] = await PublicKey.findProgramAddress( - [Buffer.from('state')], - program.programId - ) - - return await program.methods - .grantPermission() - .accounts({ - state: addinState, - grantAuthority: grantAuthority, - switchboardProgram: switchboardProgram, - permission: permission, - }) - .transaction() -} - -export async function revokePermissionTx( - program: Program, - revokeAuthority: PublicKey, - switchboardProgram: PublicKey, - permission: PublicKey -): Promise { - const [addinState] = await PublicKey.findProgramAddress( - [Buffer.from('state')], - program.programId - ) - - return await program.methods - .revokePermission() - .accounts({ - state: addinState, - revokeAuthority: revokeAuthority, - switchboardProgram: switchboardProgram, - permission: permission, - }) - .transaction() -} diff --git a/SwitchboardVotePlugin/gameofnodes.json b/SwitchboardVotePlugin/gameofnodes.json deleted file mode 100644 index 4008bed3d8..0000000000 --- a/SwitchboardVotePlugin/gameofnodes.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "version": "0.1.0", - "name": "gameofnodes", - "instructions": [ - { - "name": "initialize", - "accounts": [ - { - "name": "state", - "isMut": true, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "grantAuthority", - "type": "publicKey" - }, - { - "name": "revokeAuthority", - "type": "publicKey" - } - ] - }, - { - "name": "grantPermission", - "accounts": [ - { - "name": "state", - "isMut": false, - "isSigner": false - }, - { - "name": "grantAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "switchboardProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "permission", - "isMut": true, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "revokePermission", - "accounts": [ - { - "name": "state", - "isMut": false, - "isSigner": false - }, - { - "name": "revokeAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "switchboardProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "permission", - "isMut": true, - "isSigner": false - } - ], - "args": [] - }, - { - "name": "permissionSetVoterWeight", - "accounts": [ - { - "name": "permission", - "isMut": false, - "isSigner": false - }, - { - "name": "permissionAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "oracle", - "isMut": false, - "isSigner": false - }, - { - "name": "oracleAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "sbState", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "govProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "daoMint", - "isMut": false, - "isSigner": false - }, - { - "name": "spawnRecord", - "isMut": true, - "isSigner": false - }, - { - "name": "voterWeight", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerRecord", - "isMut": true, - "isSigner": false - }, - { - "name": "realm", - "isMut": false, - "isSigner": false - } - ], - "args": [] - } - ], - "accounts": [ - { - "name": "State", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "grantAuthority", - "type": "publicKey" - }, - { - "name": "revokeAuthority", - "type": "publicKey" - } - ] - } - }, - { - "name": "RealmSpawnRecordAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "spawner", - "type": "publicKey" - }, - { - "name": "spawnerPrivilege", - "type": "bool" - }, - { - "name": "ebuf", - "type": { - "array": ["u8", 256] - } - } - ] - } - } - ], - "errors": [ - { - "code": 6000, - "name": "InvalidGovernanceAccountError", - "msg": "Invalid Governance Account" - } - ], - "metadata": { - "address": "B4EDDdMh5CmB6B9DeMmZmFvRzEgyHR5zWktf6httcMk6" - } -} diff --git a/SwitchboardVotePlugin/sdk/accounts.tsx b/SwitchboardVotePlugin/sdk/accounts.tsx deleted file mode 100644 index 93b610d766..0000000000 --- a/SwitchboardVotePlugin/sdk/accounts.tsx +++ /dev/null @@ -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, - } -} diff --git a/SwitchboardVotePlugin/store/switchboardStore.ts b/SwitchboardVotePlugin/store/switchboardStore.ts deleted file mode 100644 index 546114a91a..0000000000 --- a/SwitchboardVotePlugin/store/switchboardStore.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { BN } from '@project-serum/anchor' -import create, { State } from 'zustand' -import { PublicKey, TransactionInstruction } from '@solana/web3.js' -import { VotingClient } from '@utils/uiTypes/VotePlugin' - -interface SwitchboardPluginStore extends State { - state: { - votingPower: BN - isLoading: boolean - oracleKeys: Array - instructions: Array - } - setVotingPower: (votingPower: BN) => void - setIsLoading: (val: boolean) => void - setOracleKeys: (keys: Array, votingClient: VotingClient) => void - setInstructions: ( - instructions: Array, - votingClient: VotingClient - ) => void -} - -const defaultState = { - votingPower: new BN(0), - isLoading: false, - oracleKeys: [], - instructions: [], -} - -const useSwitchboardPluginStore = create( - (set, _get) => ({ - state: { - ...defaultState, - }, - setIsLoading: (val) => { - set((s) => { - s.state.isLoading = val - }) - }, - setVotingPower: (votingPower) => { - set((s) => { - s.state.votingPower = votingPower - }) - }, - setOracleKeys: (oracleKeys, votingClient) => { - votingClient._setOracles(oracleKeys) - set((s) => { - s.state.oracleKeys = oracleKeys - }) - }, - setInstructions: (instructions, votingClient) => { - votingClient._setInstructions(instructions) - set((s) => { - s.state.instructions = instructions - }) - }, - }) -) - -export default useSwitchboardPluginStore diff --git a/SwitchboardVotePlugin/switchboard_v2.json b/SwitchboardVotePlugin/switchboard_v2.json deleted file mode 100644 index 0809111d32..0000000000 --- a/SwitchboardVotePlugin/switchboard_v2.json +++ /dev/null @@ -1,5316 +0,0 @@ -{ - "version": "0.1.0", - "name": "switchboard_v2", - "instructions": [ - { - "name": "aggregatorAddJob", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - }, - { - "name": "job", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorAddJobParams" - } - } - ] - }, - { - "name": "aggregatorInit", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": false - }, - { - "name": "queue", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorInitParams" - } - } - ] - }, - { - "name": "aggregatorLock", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorLockParams" - } - } - ] - }, - { - "name": "aggregatorOpenRound", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "lease", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleQueue", - "isMut": true, - "isSigner": false - }, - { - "name": "queueAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "permission", - "isMut": true, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "payoutWallet", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "dataBuffer", - "isMut": false, - "isSigner": false - }, - { - "name": "mint", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorOpenRoundParams" - } - } - ] - }, - { - "name": "aggregatorRemoveJob", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - }, - { - "name": "job", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorRemoveJobParams" - } - } - ] - }, - { - "name": "aggregatorSaveResult", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "oracle", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "oracleQueue", - "isMut": false, - "isSigner": false - }, - { - "name": "queueAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "feedPermission", - "isMut": true, - "isSigner": false - }, - { - "name": "oraclePermission", - "isMut": false, - "isSigner": false - }, - { - "name": "lease", - "isMut": true, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "historyBuffer", - "isMut": true, - "isSigner": false - }, - { - "name": "mint", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorSaveResultParams" - } - } - ] - }, - { - "name": "aggregatorSetAuthority", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - }, - { - "name": "newAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorSetAuthorityParams" - } - } - ] - }, - { - "name": "aggregatorSetBatchSize", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorSetBatchSizeParams" - } - } - ] - }, - { - "name": "aggregatorSetForceReportPeriod", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorSetForceReportPeriodParams" - } - } - ] - }, - { - "name": "aggregatorSetHistoryBuffer", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - }, - { - "name": "buffer", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorSetHistoryBufferParams" - } - } - ] - }, - { - "name": "aggregatorSetMinJobs", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorSetMinJobsParams" - } - } - ] - }, - { - "name": "aggregatorSetMinOracles", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorSetMinOraclesParams" - } - } - ] - }, - { - "name": "aggregatorSetQueue", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - }, - { - "name": "queue", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorSetQueueParams" - } - } - ] - }, - { - "name": "aggregatorSetUpdateInterval", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorSetUpdateIntervalParams" - } - } - ] - }, - { - "name": "aggregatorSetVarianceThreshold", - "accounts": [ - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "AggregatorSetVarianceThresholdParams" - } - } - ] - }, - { - "name": "crankInit", - "accounts": [ - { - "name": "crank", - "isMut": true, - "isSigner": true - }, - { - "name": "queue", - "isMut": false, - "isSigner": false - }, - { - "name": "buffer", - "isMut": true, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "CrankInitParams" - } - } - ] - }, - { - "name": "bufferRelayerInit", - "accounts": [ - { - "name": "bufferRelayer", - "isMut": true, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": false - }, - { - "name": "queue", - "isMut": false, - "isSigner": false - }, - { - "name": "job", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "mint", - "isMut": false, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "associatedTokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "rent", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "BufferRelayerInitParams" - } - } - ] - }, - { - "name": "bufferRelayerOpenRound", - "accounts": [ - { - "name": "bufferRelayer", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleQueue", - "isMut": true, - "isSigner": false - }, - { - "name": "dataBuffer", - "isMut": true, - "isSigner": false - }, - { - "name": "permission", - "isMut": true, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "BufferRelayerOpenRoundParams" - } - } - ] - }, - { - "name": "bufferRelayerSaveResult", - "accounts": [ - { - "name": "bufferRelayer", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "oracle", - "isMut": false, - "isSigner": false - }, - { - "name": "oracleQueue", - "isMut": true, - "isSigner": false - }, - { - "name": "dataBuffer", - "isMut": true, - "isSigner": false - }, - { - "name": "queueAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "permission", - "isMut": true, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleWallet", - "isMut": true, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "BufferRelayerSaveResultParams" - } - } - ] - }, - { - "name": "crankPop", - "accounts": [ - { - "name": "crank", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleQueue", - "isMut": true, - "isSigner": false - }, - { - "name": "queueAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "payoutWallet", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "crankDataBuffer", - "isMut": true, - "isSigner": false - }, - { - "name": "queueDataBuffer", - "isMut": false, - "isSigner": false - }, - { - "name": "mint", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "CrankPopParams" - } - } - ] - }, - { - "name": "crankPush", - "accounts": [ - { - "name": "crank", - "isMut": true, - "isSigner": false - }, - { - "name": "aggregator", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleQueue", - "isMut": true, - "isSigner": false - }, - { - "name": "queueAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "permission", - "isMut": false, - "isSigner": false - }, - { - "name": "lease", - "isMut": true, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "dataBuffer", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "CrankPushParams" - } - } - ] - }, - { - "name": "jobInit", - "accounts": [ - { - "name": "job", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "JobInitParams" - } - } - ] - }, - { - "name": "leaseExtend", - "accounts": [ - { - "name": "lease", - "isMut": true, - "isSigner": false - }, - { - "name": "aggregator", - "isMut": false, - "isSigner": false - }, - { - "name": "queue", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": false - }, - { - "name": "owner", - "isMut": true, - "isSigner": true - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "mint", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "LeaseExtendParams" - } - } - ] - }, - { - "name": "leaseInit", - "accounts": [ - { - "name": "lease", - "isMut": true, - "isSigner": false - }, - { - "name": "queue", - "isMut": true, - "isSigner": false - }, - { - "name": "aggregator", - "isMut": false, - "isSigner": false - }, - { - "name": "funder", - "isMut": true, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "owner", - "isMut": true, - "isSigner": true - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "mint", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "LeaseInitParams" - } - } - ] - }, - { - "name": "leaseSetAuthority", - "accounts": [ - { - "name": "lease", - "isMut": true, - "isSigner": false - }, - { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "newAuthority", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "LeaseSetAuthorityParams" - } - } - ] - }, - { - "name": "leaseWithdraw", - "accounts": [ - { - "name": "lease", - "isMut": true, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "aggregator", - "isMut": false, - "isSigner": false - }, - { - "name": "queue", - "isMut": false, - "isSigner": false - }, - { - "name": "withdrawAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "withdrawAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "mint", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "LeaseWithdrawParams" - } - } - ] - }, - { - "name": "oracleHeartbeat", - "accounts": [ - { - "name": "oracle", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "tokenAccount", - "isMut": false, - "isSigner": false - }, - { - "name": "gcOracle", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleQueue", - "isMut": true, - "isSigner": false - }, - { - "name": "permission", - "isMut": false, - "isSigner": false - }, - { - "name": "dataBuffer", - "isMut": true, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "OracleHeartbeatParams" - } - } - ] - }, - { - "name": "oracleInit", - "accounts": [ - { - "name": "oracle", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "wallet", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "queue", - "isMut": false, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "OracleInitParams" - } - } - ] - }, - { - "name": "oracleQueueInit", - "accounts": [ - { - "name": "oracleQueue", - "isMut": true, - "isSigner": true - }, - { - "name": "authority", - "isMut": false, - "isSigner": false - }, - { - "name": "buffer", - "isMut": true, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "mint", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "OracleQueueInitParams" - } - } - ] - }, - { - "name": "oracleQueueSetRewards", - "accounts": [ - { - "name": "queue", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "OracleQueueSetRewardsParams" - } - } - ] - }, - { - "name": "oracleQueueVrfConfig", - "accounts": [ - { - "name": "queue", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "OracleQueueVrfConfigParams" - } - } - ] - }, - { - "name": "oracleWithdraw", - "accounts": [ - { - "name": "oracle", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "tokenAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "withdrawAccount", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleQueue", - "isMut": true, - "isSigner": false - }, - { - "name": "permission", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "OracleWithdrawParams" - } - } - ] - }, - { - "name": "permissionInit", - "accounts": [ - { - "name": "permission", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": false - }, - { - "name": "granter", - "isMut": false, - "isSigner": false - }, - { - "name": "grantee", - "isMut": false, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "PermissionInitParams" - } - } - ] - }, - { - "name": "permissionSet", - "accounts": [ - { - "name": "permission", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "PermissionSetParams" - } - } - ] - }, - { - "name": "permissionSetVoterWeight", - "accounts": [ - { - "name": "permission", - "isMut": true, - "isSigner": false - }, - { - "name": "permissionAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "oracle", - "isMut": false, - "isSigner": false - }, - { - "name": "oracleAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "govProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "daoMint", - "isMut": false, - "isSigner": false - }, - { - "name": "spawnRecord", - "isMut": true, - "isSigner": false - }, - { - "name": "voterWeight", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenOwnerRecord", - "isMut": true, - "isSigner": false - }, - { - "name": "realm", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "PermissionSetVoterWeightParams" - } - } - ] - }, - { - "name": "programConfig", - "accounts": [ - { - "name": "authority", - "isMut": false, - "isSigner": true - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "daoMint", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "ProgramConfigParams" - } - } - ] - }, - { - "name": "programInit", - "accounts": [ - { - "name": "state", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenMint", - "isMut": true, - "isSigner": false - }, - { - "name": "vault", - "isMut": true, - "isSigner": false - }, - { - "name": "payer", - "isMut": true, - "isSigner": true - }, - { - "name": "systemProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "daoMint", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "ProgramInitParams" - } - } - ] - }, - { - "name": "vaultTransfer", - "accounts": [ - { - "name": "state", - "isMut": false, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": true - }, - { - "name": "to", - "isMut": true, - "isSigner": false - }, - { - "name": "vault", - "isMut": true, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "VaultTransferParams" - } - } - ] - }, - { - "name": "vrfInit", - "accounts": [ - { - "name": "vrf", - "isMut": true, - "isSigner": false - }, - { - "name": "authority", - "isMut": false, - "isSigner": false - }, - { - "name": "oracleQueue", - "isMut": false, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "VrfInitParams" - } - } - ] - }, - { - "name": "vrfProve", - "accounts": [ - { - "name": "vrf", - "isMut": true, - "isSigner": false - }, - { - "name": "oracle", - "isMut": false, - "isSigner": false - }, - { - "name": "randomnessProducer", - "isMut": false, - "isSigner": true - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "VrfProveParams" - } - } - ] - }, - { - "name": "vrfProveAndVerify", - "accounts": [ - { - "name": "vrf", - "isMut": true, - "isSigner": false - }, - { - "name": "callbackPid", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "oracle", - "isMut": false, - "isSigner": false - }, - { - "name": "oracleAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "oracleWallet", - "isMut": true, - "isSigner": false - }, - { - "name": "instructionsSysvar", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "VrfProveAndVerifyParams" - } - } - ] - }, - { - "name": "vrfRequestRandomness", - "accounts": [ - { - "name": "authority", - "isMut": false, - "isSigner": true - }, - { - "name": "vrf", - "isMut": true, - "isSigner": false - }, - { - "name": "oracleQueue", - "isMut": true, - "isSigner": false - }, - { - "name": "queueAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "dataBuffer", - "isMut": false, - "isSigner": false - }, - { - "name": "permission", - "isMut": true, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "payerWallet", - "isMut": true, - "isSigner": false - }, - { - "name": "payerAuthority", - "isMut": false, - "isSigner": true - }, - { - "name": "recentBlockhashes", - "isMut": false, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "VrfRequestRandomnessParams" - } - } - ] - }, - { - "name": "vrfVerify", - "accounts": [ - { - "name": "vrf", - "isMut": true, - "isSigner": false - }, - { - "name": "callbackPid", - "isMut": false, - "isSigner": false - }, - { - "name": "tokenProgram", - "isMut": false, - "isSigner": false - }, - { - "name": "escrow", - "isMut": true, - "isSigner": false - }, - { - "name": "programState", - "isMut": false, - "isSigner": false - }, - { - "name": "oracle", - "isMut": false, - "isSigner": false - }, - { - "name": "oracleAuthority", - "isMut": false, - "isSigner": false - }, - { - "name": "oracleWallet", - "isMut": true, - "isSigner": false - }, - { - "name": "instructionsSysvar", - "isMut": false, - "isSigner": false - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": "VrfVerifyParams" - } - } - ] - } - ], - "accounts": [ - { - "name": "SbState", - "type": { - "kind": "struct", - "fields": [ - { - "name": "authority", - "type": "publicKey" - }, - { - "name": "tokenMint", - "type": "publicKey" - }, - { - "name": "tokenVault", - "type": "publicKey" - }, - { - "name": "daoMint", - "type": "publicKey" - }, - { - "name": "ebuf", - "type": { - "array": ["u8", 992] - } - } - ] - } - }, - { - "name": "TaskSpecRecord", - "type": { - "kind": "struct", - "fields": [ - { - "name": "hash", - "type": { - "defined": "Hash" - } - } - ] - } - }, - { - "name": "AggregatorAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "metadata", - "type": { - "array": ["u8", 128] - } - }, - { - "name": "reserved1", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "queuePubkey", - "type": "publicKey" - }, - { - "name": "oracleRequestBatchSize", - "type": "u32" - }, - { - "name": "minOracleResults", - "type": "u32" - }, - { - "name": "minJobResults", - "type": "u32" - }, - { - "name": "minUpdateDelaySeconds", - "type": "u32" - }, - { - "name": "startAfter", - "type": "i64" - }, - { - "name": "varianceThreshold", - "type": { - "defined": "SwitchboardDecimal" - } - }, - { - "name": "forceReportPeriod", - "type": "i64" - }, - { - "name": "expiration", - "type": "i64" - }, - { - "name": "consecutiveFailureCount", - "type": "u64" - }, - { - "name": "nextAllowedUpdateTime", - "type": "i64" - }, - { - "name": "isLocked", - "type": "bool" - }, - { - "name": "crankPubkey", - "type": "publicKey" - }, - { - "name": "latestConfirmedRound", - "type": { - "defined": "AggregatorRound" - } - }, - { - "name": "currentRound", - "type": { - "defined": "AggregatorRound" - } - }, - { - "name": "jobPubkeysData", - "type": { - "array": ["publicKey", 16] - } - }, - { - "name": "jobHashes", - "type": { - "array": [ - { - "defined": "Hash" - }, - 16 - ] - } - }, - { - "name": "jobPubkeysSize", - "type": "u32" - }, - { - "name": "jobsChecksum", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "authority", - "type": "publicKey" - }, - { - "name": "historyBuffer", - "type": "publicKey" - }, - { - "name": "previousConfirmedRoundResult", - "type": { - "defined": "SwitchboardDecimal" - } - }, - { - "name": "previousConfirmedRoundSlot", - "type": "u64" - }, - { - "name": "disableCrank", - "type": "bool" - }, - { - "name": "jobWeights", - "type": { - "array": ["u8", 16] - } - }, - { - "name": "ebuf", - "type": { - "array": ["u8", 147] - } - } - ] - } - }, - { - "name": "PermissionAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "authority", - "type": "publicKey" - }, - { - "name": "permissions", - "type": "u32" - }, - { - "name": "granter", - "type": "publicKey" - }, - { - "name": "grantee", - "type": "publicKey" - }, - { - "name": "expiration", - "type": "i64" - }, - { - "name": "ebuf", - "type": { - "array": ["u8", 256] - } - } - ] - } - }, - { - "name": "RealmSpawnRecordAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "ebuf", - "type": { - "array": ["u8", 256] - } - } - ] - } - }, - { - "name": "LeaseAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "escrow", - "type": "publicKey" - }, - { - "name": "queue", - "type": "publicKey" - }, - { - "name": "aggregator", - "type": "publicKey" - }, - { - "name": "tokenProgram", - "type": "publicKey" - }, - { - "name": "isActive", - "type": "bool" - }, - { - "name": "crankRowCount", - "type": "u32" - }, - { - "name": "createdAt", - "type": "i64" - }, - { - "name": "updateCount", - "type": "u128" - }, - { - "name": "withdrawAuthority", - "type": "publicKey" - }, - { - "name": "ebuf", - "type": { - "array": ["u8", 256] - } - } - ] - } - }, - { - "name": "OracleQueueAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "metadata", - "type": { - "array": ["u8", 64] - } - }, - { - "name": "authority", - "type": "publicKey" - }, - { - "name": "oracleTimeout", - "type": "u32" - }, - { - "name": "reward", - "type": "u64" - }, - { - "name": "minStake", - "type": "u64" - }, - { - "name": "slashingEnabled", - "type": "bool" - }, - { - "name": "varianceToleranceMultiplier", - "type": { - "defined": "SwitchboardDecimal" - } - }, - { - "name": "feedProbationPeriod", - "type": "u32" - }, - { - "name": "currIdx", - "type": "u32" - }, - { - "name": "size", - "type": "u32" - }, - { - "name": "gcIdx", - "type": "u32" - }, - { - "name": "consecutiveFeedFailureLimit", - "type": "u64" - }, - { - "name": "consecutiveOracleFailureLimit", - "type": "u64" - }, - { - "name": "unpermissionedFeedsEnabled", - "type": "bool" - }, - { - "name": "unpermissionedVrfEnabled", - "type": "bool" - }, - { - "name": "curatorRewardCut", - "type": { - "defined": "SwitchboardDecimal" - } - }, - { - "name": "lockLeaseFunding", - "type": "bool" - }, - { - "name": "mint", - "type": "publicKey" - }, - { - "name": "enableBufferRelayers", - "type": "bool" - }, - { - "name": "ebuf", - "type": { - "array": ["u8", 968] - } - }, - { - "name": "maxSize", - "type": "u32" - }, - { - "name": "dataBuffer", - "type": "publicKey" - } - ] - } - }, - { - "name": "CrankAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "metadata", - "type": { - "array": ["u8", 64] - } - }, - { - "name": "queuePubkey", - "type": "publicKey" - }, - { - "name": "pqSize", - "type": "u32" - }, - { - "name": "maxRows", - "type": "u32" - }, - { - "name": "jitterModifier", - "type": "u8" - }, - { - "name": "ebuf", - "type": { - "array": ["u8", 255] - } - }, - { - "name": "dataBuffer", - "type": "publicKey" - } - ] - } - }, - { - "name": "OracleAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "metadata", - "type": { - "array": ["u8", 128] - } - }, - { - "name": "oracleAuthority", - "type": "publicKey" - }, - { - "name": "lastHeartbeat", - "type": "i64" - }, - { - "name": "numInUse", - "type": "u32" - }, - { - "name": "tokenAccount", - "type": "publicKey" - }, - { - "name": "queuePubkey", - "type": "publicKey" - }, - { - "name": "metrics", - "type": { - "defined": "OracleMetrics" - } - }, - { - "name": "ebuf", - "type": { - "array": ["u8", 256] - } - } - ] - } - }, - { - "name": "JobAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "metadata", - "type": { - "array": ["u8", 64] - } - }, - { - "name": "authority", - "type": "publicKey" - }, - { - "name": "expiration", - "type": "i64" - }, - { - "name": "hash", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "data", - "type": "bytes" - }, - { - "name": "referenceCount", - "type": "u32" - }, - { - "name": "totalSpent", - "type": "u64" - }, - { - "name": "createdAt", - "type": "i64" - } - ] - } - }, - { - "name": "VrfAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "status", - "type": { - "defined": "VrfStatus" - } - }, - { - "name": "counter", - "type": "u128" - }, - { - "name": "authority", - "type": "publicKey" - }, - { - "name": "oracleQueue", - "type": "publicKey" - }, - { - "name": "escrow", - "type": "publicKey" - }, - { - "name": "callback", - "type": { - "defined": "CallbackZC" - } - }, - { - "name": "batchSize", - "type": "u32" - }, - { - "name": "builders", - "type": { - "array": [ - { - "defined": "VrfBuilder" - }, - 8 - ] - } - }, - { - "name": "buildersLen", - "type": "u32" - }, - { - "name": "testMode", - "type": "bool" - }, - { - "name": "currentRound", - "type": { - "defined": "VrfRound" - } - }, - { - "name": "ebuf", - "type": { - "array": ["u8", 1024] - } - } - ] - } - }, - { - "name": "BufferRelayerAccountData", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "queuePubkey", - "type": "publicKey" - }, - { - "name": "escrow", - "type": "publicKey" - }, - { - "name": "authority", - "type": "publicKey" - }, - { - "name": "jobPubkey", - "type": "publicKey" - }, - { - "name": "jobHash", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "minUpdateDelaySeconds", - "type": "u32" - }, - { - "name": "isLocked", - "type": "bool" - }, - { - "name": "currentRound", - "type": { - "defined": "BufferRelayerRound" - } - }, - { - "name": "latestConfirmedRound", - "type": { - "defined": "BufferRelayerRound" - } - }, - { - "name": "result", - "type": "bytes" - } - ] - } - } - ], - "types": [ - { - "name": "AggregatorAddJobParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "weight", - "type": { - "option": "u8" - } - } - ] - } - }, - { - "name": "AggregatorInitParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "metadata", - "type": { - "array": ["u8", 128] - } - }, - { - "name": "batchSize", - "type": "u32" - }, - { - "name": "minOracleResults", - "type": "u32" - }, - { - "name": "minJobResults", - "type": "u32" - }, - { - "name": "minUpdateDelaySeconds", - "type": "u32" - }, - { - "name": "startAfter", - "type": "i64" - }, - { - "name": "varianceThreshold", - "type": { - "defined": "BorshDecimal" - } - }, - { - "name": "forceReportPeriod", - "type": "i64" - }, - { - "name": "expiration", - "type": "i64" - }, - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "disableCrank", - "type": "bool" - } - ] - } - }, - { - "name": "AggregatorLockParams", - "type": { - "kind": "struct", - "fields": [] - } - }, - { - "name": "AggregatorOpenRoundParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "leaseBump", - "type": "u8" - }, - { - "name": "permissionBump", - "type": "u8" - }, - { - "name": "jitter", - "type": "u8" - } - ] - } - }, - { - "name": "AggregatorRemoveJobParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "jobIdx", - "type": "u32" - } - ] - } - }, - { - "name": "AggregatorSaveResultParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "oracleIdx", - "type": "u32" - }, - { - "name": "error", - "type": "bool" - }, - { - "name": "value", - "type": { - "defined": "BorshDecimal" - } - }, - { - "name": "jobsChecksum", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "minResponse", - "type": { - "defined": "BorshDecimal" - } - }, - { - "name": "maxResponse", - "type": { - "defined": "BorshDecimal" - } - }, - { - "name": "feedPermissionBump", - "type": "u8" - }, - { - "name": "oraclePermissionBump", - "type": "u8" - }, - { - "name": "leaseBump", - "type": "u8" - }, - { - "name": "stateBump", - "type": "u8" - } - ] - } - }, - { - "name": "AggregatorSetAuthorityParams", - "type": { - "kind": "struct", - "fields": [] - } - }, - { - "name": "AggregatorSetBatchSizeParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "batchSize", - "type": "u32" - } - ] - } - }, - { - "name": "AggregatorSetForceReportPeriodParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "forceReportPeriod", - "type": "u32" - } - ] - } - }, - { - "name": "AggregatorSetHistoryBufferParams", - "type": { - "kind": "struct", - "fields": [] - } - }, - { - "name": "AggregatorSetMinJobsParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "minJobResults", - "type": "u32" - } - ] - } - }, - { - "name": "AggregatorSetMinOraclesParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "minOracleResults", - "type": "u32" - } - ] - } - }, - { - "name": "AggregatorSetQueueParams", - "type": { - "kind": "struct", - "fields": [] - } - }, - { - "name": "AggregatorSetUpdateIntervalParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "newInterval", - "type": "u32" - } - ] - } - }, - { - "name": "AggregatorSetVarianceThresholdParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "varianceThreshold", - "type": { - "defined": "BorshDecimal" - } - } - ] - } - }, - { - "name": "BufferRelayerInitParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "minUpdateDelaySeconds", - "type": "u32" - }, - { - "name": "stateBump", - "type": "u8" - } - ] - } - }, - { - "name": "BufferRelayerOpenRoundParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "permissionBump", - "type": "u8" - } - ] - } - }, - { - "name": "BufferRelayerSaveResultParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "permissionBump", - "type": "u8" - }, - { - "name": "result", - "type": "bytes" - }, - { - "name": "success", - "type": "bool" - } - ] - } - }, - { - "name": "CrankInitParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": "bytes" - }, - { - "name": "metadata", - "type": "bytes" - }, - { - "name": "crankSize", - "type": "u32" - } - ] - } - }, - { - "name": "CrankPopParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "leaseBumps", - "type": "bytes" - }, - { - "name": "permissionBumps", - "type": "bytes" - }, - { - "name": "nonce", - "type": { - "option": "u32" - } - }, - { - "name": "failOpenOnAccountMismatch", - "type": { - "option": "bool" - } - } - ] - } - }, - { - "name": "CrankPushParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "permissionBump", - "type": "u8" - } - ] - } - }, - { - "name": "JobInitParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "expiration", - "type": "i64" - }, - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "data", - "type": "bytes" - } - ] - } - }, - { - "name": "LeaseExtendParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "loadAmount", - "type": "u64" - }, - { - "name": "leaseBump", - "type": "u8" - }, - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "walletBumps", - "type": "bytes" - } - ] - } - }, - { - "name": "LeaseInitParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "loadAmount", - "type": "u64" - }, - { - "name": "withdrawAuthority", - "type": "publicKey" - }, - { - "name": "leaseBump", - "type": "u8" - }, - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "walletBumps", - "type": "bytes" - } - ] - } - }, - { - "name": "LeaseSetAuthorityParams", - "type": { - "kind": "struct", - "fields": [] - } - }, - { - "name": "LeaseWithdrawParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "leaseBump", - "type": "u8" - }, - { - "name": "amount", - "type": "u64" - } - ] - } - }, - { - "name": "OracleHeartbeatParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "permissionBump", - "type": "u8" - } - ] - } - }, - { - "name": "OracleInitParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": "bytes" - }, - { - "name": "metadata", - "type": "bytes" - }, - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "oracleBump", - "type": "u8" - } - ] - } - }, - { - "name": "OracleQueueInitParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "name", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "metadata", - "type": { - "array": ["u8", 64] - } - }, - { - "name": "reward", - "type": "u64" - }, - { - "name": "minStake", - "type": "u64" - }, - { - "name": "feedProbationPeriod", - "type": "u32" - }, - { - "name": "oracleTimeout", - "type": "u32" - }, - { - "name": "slashingEnabled", - "type": "bool" - }, - { - "name": "varianceToleranceMultiplier", - "type": { - "defined": "BorshDecimal" - } - }, - { - "name": "consecutiveFeedFailureLimit", - "type": "u64" - }, - { - "name": "consecutiveOracleFailureLimit", - "type": "u64" - }, - { - "name": "queueSize", - "type": "u32" - }, - { - "name": "unpermissionedFeeds", - "type": "bool" - }, - { - "name": "unpermissionedVrf", - "type": "bool" - }, - { - "name": "enableBufferRelayers", - "type": "bool" - } - ] - } - }, - { - "name": "OracleQueueSetRewardsParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "rewards", - "type": "u64" - } - ] - } - }, - { - "name": "OracleQueueVrfConfigParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "unpermissionedVrfEnabled", - "type": "bool" - } - ] - } - }, - { - "name": "OracleWithdrawParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "permissionBump", - "type": "u8" - }, - { - "name": "amount", - "type": "u64" - } - ] - } - }, - { - "name": "PermissionInitParams", - "type": { - "kind": "struct", - "fields": [] - } - }, - { - "name": "PermissionSetParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "permission", - "type": { - "defined": "SwitchboardPermission" - } - }, - { - "name": "enable", - "type": "bool" - } - ] - } - }, - { - "name": "PermissionSetVoterWeightParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - } - ] - } - }, - { - "name": "ProgramConfigParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "token", - "type": "publicKey" - }, - { - "name": "bump", - "type": "u8" - }, - { - "name": "daoMint", - "type": "publicKey" - } - ] - } - }, - { - "name": "ProgramInitParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - } - ] - } - }, - { - "name": "VaultTransferParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "amount", - "type": "u64" - } - ] - } - }, - { - "name": "VrfInitParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "callback", - "type": { - "defined": "Callback" - } - }, - { - "name": "stateBump", - "type": "u8" - } - ] - } - }, - { - "name": "VrfProveParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "proof", - "type": "bytes" - }, - { - "name": "idx", - "type": "u32" - } - ] - } - }, - { - "name": "VrfProveAndVerifyParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "nonce", - "type": { - "option": "u32" - } - }, - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "idx", - "type": "u32" - }, - { - "name": "proof", - "type": "bytes" - } - ] - } - }, - { - "name": "VrfRequestRandomnessParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "permissionBump", - "type": "u8" - }, - { - "name": "stateBump", - "type": "u8" - } - ] - } - }, - { - "name": "VrfVerifyParams", - "type": { - "kind": "struct", - "fields": [ - { - "name": "nonce", - "type": { - "option": "u32" - } - }, - { - "name": "stateBump", - "type": "u8" - }, - { - "name": "idx", - "type": "u32" - } - ] - } - }, - { - "name": "Callback", - "type": { - "kind": "struct", - "fields": [ - { - "name": "programId", - "type": "publicKey" - }, - { - "name": "accounts", - "type": { - "vec": { - "defined": "AccountMetaBorsh" - } - } - }, - { - "name": "ixData", - "type": "bytes" - } - ] - } - }, - { - "name": "EcvrfProofZC", - "type": { - "kind": "struct", - "fields": [ - { - "name": "gamma", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "c", - "type": { - "defined": "Scalar" - } - }, - { - "name": "s", - "type": { - "defined": "Scalar" - } - } - ] - } - }, - { - "name": "Scalar", - "type": { - "kind": "struct", - "fields": [ - { - "name": "bytes", - "type": { - "array": ["u8", 32] - } - } - ] - } - }, - { - "name": "FieldElementZC", - "type": { - "kind": "struct", - "fields": [ - { - "name": "bytes", - "type": { - "array": ["u64", 5] - } - } - ] - } - }, - { - "name": "CompletedPointZC", - "type": { - "kind": "struct", - "fields": [ - { - "name": "x", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "y", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "z", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "t", - "type": { - "defined": "FieldElementZC" - } - } - ] - } - }, - { - "name": "EdwardsPointZC", - "type": { - "kind": "struct", - "fields": [ - { - "name": "x", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "y", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "z", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "t", - "type": { - "defined": "FieldElementZC" - } - } - ] - } - }, - { - "name": "ProjectivePointZC", - "type": { - "kind": "struct", - "fields": [ - { - "name": "x", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "y", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "z", - "type": { - "defined": "FieldElementZC" - } - } - ] - } - }, - { - "name": "EcvrfIntermediate", - "type": { - "kind": "struct", - "fields": [ - { - "name": "r", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "nS", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "d", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "t13", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "t15", - "type": { - "defined": "FieldElementZC" - } - } - ] - } - }, - { - "name": "Hash", - "type": { - "kind": "struct", - "fields": [ - { - "name": "data", - "type": { - "array": ["u8", 32] - } - } - ] - } - }, - { - "name": "AggregatorRound", - "type": { - "kind": "struct", - "fields": [ - { - "name": "numSuccess", - "type": "u32" - }, - { - "name": "numError", - "type": "u32" - }, - { - "name": "isClosed", - "type": "bool" - }, - { - "name": "roundOpenSlot", - "type": "u64" - }, - { - "name": "roundOpenTimestamp", - "type": "i64" - }, - { - "name": "result", - "type": { - "defined": "SwitchboardDecimal" - } - }, - { - "name": "stdDeviation", - "type": { - "defined": "SwitchboardDecimal" - } - }, - { - "name": "minResponse", - "type": { - "defined": "SwitchboardDecimal" - } - }, - { - "name": "maxResponse", - "type": { - "defined": "SwitchboardDecimal" - } - }, - { - "name": "oraclePubkeysData", - "type": { - "array": ["publicKey", 16] - } - }, - { - "name": "mediansData", - "type": { - "array": [ - { - "defined": "SwitchboardDecimal" - }, - 16 - ] - } - }, - { - "name": "currentPayout", - "type": { - "array": ["i64", 16] - } - }, - { - "name": "mediansFulfilled", - "type": { - "array": ["bool", 16] - } - }, - { - "name": "errorsFulfilled", - "type": { - "array": ["bool", 16] - } - } - ] - } - }, - { - "name": "AggregatorHistoryRow", - "type": { - "kind": "struct", - "fields": [ - { - "name": "timestamp", - "type": "i64" - }, - { - "name": "value", - "type": { - "defined": "SwitchboardDecimal" - } - } - ] - } - }, - { - "name": "SwitchboardDecimal", - "type": { - "kind": "struct", - "fields": [ - { - "name": "mantissa", - "type": "i128" - }, - { - "name": "scale", - "type": "u32" - } - ] - } - }, - { - "name": "CrankRow", - "type": { - "kind": "struct", - "fields": [ - { - "name": "pubkey", - "type": "publicKey" - }, - { - "name": "nextTimestamp", - "type": "i64" - } - ] - } - }, - { - "name": "OracleMetrics", - "type": { - "kind": "struct", - "fields": [ - { - "name": "consecutiveSuccess", - "type": "u64" - }, - { - "name": "consecutiveError", - "type": "u64" - }, - { - "name": "consecutiveDisagreement", - "type": "u64" - }, - { - "name": "consecutiveLateResponse", - "type": "u64" - }, - { - "name": "consecutiveFailure", - "type": "u64" - }, - { - "name": "totalSuccess", - "type": "u128" - }, - { - "name": "totalError", - "type": "u128" - }, - { - "name": "totalDisagreement", - "type": "u128" - }, - { - "name": "totalLateResponse", - "type": "u128" - } - ] - } - }, - { - "name": "VrfBuilder", - "type": { - "kind": "struct", - "fields": [ - { - "name": "producer", - "type": "publicKey" - }, - { - "name": "status", - "type": { - "defined": "VrfStatus" - } - }, - { - "name": "reprProof", - "type": { - "array": ["u8", 80] - } - }, - { - "name": "proof", - "type": { - "defined": "EcvrfProofZC" - } - }, - { - "name": "yPoint", - "type": "publicKey" - }, - { - "name": "stage", - "type": "u32" - }, - { - "name": "stage1Out", - "type": { - "defined": "EcvrfIntermediate" - } - }, - { - "name": "r1", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "r2", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "stage3Out", - "type": { - "defined": "EcvrfIntermediate" - } - }, - { - "name": "hPoint", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "sReduced", - "type": { - "defined": "Scalar" - } - }, - { - "name": "yPointBuilder", - "type": { - "array": [ - { - "defined": "FieldElementZC" - }, - 3 - ] - } - }, - { - "name": "yRistrettoPoint", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "mulRound", - "type": "u8" - }, - { - "name": "hashPointsRound", - "type": "u8" - }, - { - "name": "mulTmp1", - "type": { - "defined": "CompletedPointZC" - } - }, - { - "name": "uPoint1", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "uPoint2", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "vPoint1", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "vPoint2", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "uPoint", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "vPoint", - "type": { - "defined": "EdwardsPointZC" - } - }, - { - "name": "u1", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "u2", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "invertee", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "y", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "z", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "p1Bytes", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "p2Bytes", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "p3Bytes", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "p4Bytes", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "cPrimeHashbuf", - "type": { - "array": ["u8", 16] - } - }, - { - "name": "m1", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "m2", - "type": { - "defined": "FieldElementZC" - } - }, - { - "name": "txRemaining", - "type": "u32" - }, - { - "name": "verified", - "type": "bool" - }, - { - "name": "result", - "type": { - "array": ["u8", 32] - } - } - ] - } - }, - { - "name": "AccountMetaZC", - "type": { - "kind": "struct", - "fields": [ - { - "name": "pubkey", - "type": "publicKey" - }, - { - "name": "isSigner", - "type": "bool" - }, - { - "name": "isWritable", - "type": "bool" - } - ] - } - }, - { - "name": "AccountMetaBorsh", - "type": { - "kind": "struct", - "fields": [ - { - "name": "pubkey", - "type": "publicKey" - }, - { - "name": "isSigner", - "type": "bool" - }, - { - "name": "isWritable", - "type": "bool" - } - ] - } - }, - { - "name": "CallbackZC", - "type": { - "kind": "struct", - "fields": [ - { - "name": "programId", - "type": "publicKey" - }, - { - "name": "accounts", - "type": { - "array": [ - { - "defined": "AccountMetaZC" - }, - 32 - ] - } - }, - { - "name": "accountsLen", - "type": "u32" - }, - { - "name": "ixData", - "type": { - "array": ["u8", 1024] - } - }, - { - "name": "ixDataLen", - "type": "u32" - } - ] - } - }, - { - "name": "VrfRound", - "type": { - "kind": "struct", - "fields": [ - { - "name": "alpha", - "type": { - "array": ["u8", 256] - } - }, - { - "name": "alphaLen", - "type": "u32" - }, - { - "name": "requestSlot", - "type": "u64" - }, - { - "name": "requestTimestamp", - "type": "i64" - }, - { - "name": "result", - "type": { - "array": ["u8", 32] - } - }, - { - "name": "numVerified", - "type": "u32" - }, - { - "name": "ebuf", - "type": { - "array": ["u8", 256] - } - } - ] - } - }, - { - "name": "BufferRelayerRound", - "type": { - "kind": "struct", - "fields": [ - { - "name": "numSuccess", - "type": "u32" - }, - { - "name": "numError", - "type": "u32" - }, - { - "name": "roundOpenSlot", - "type": "u64" - }, - { - "name": "roundOpenTimestamp", - "type": "i64" - }, - { - "name": "oraclePubkey", - "type": "publicKey" - } - ] - } - }, - { - "name": "BorshDecimal", - "type": { - "kind": "struct", - "fields": [ - { - "name": "mantissa", - "type": "i128" - }, - { - "name": "scale", - "type": "u32" - } - ] - } - }, - { - "name": "Lanes", - "type": { - "kind": "enum", - "variants": [ - { - "name": "C" - }, - { - "name": "D" - }, - { - "name": "AB" - }, - { - "name": "AC" - }, - { - "name": "CD" - }, - { - "name": "AD" - }, - { - "name": "BC" - }, - { - "name": "ABCD" - } - ] - } - }, - { - "name": "Shuffle", - "type": { - "kind": "enum", - "variants": [ - { - "name": "AAAA" - }, - { - "name": "BBBB" - }, - { - "name": "CACA" - }, - { - "name": "DBBD" - }, - { - "name": "ADDA" - }, - { - "name": "CBCB" - }, - { - "name": "ABAB" - }, - { - "name": "BADC" - }, - { - "name": "BACD" - }, - { - "name": "ABDC" - } - ] - } - }, - { - "name": "Shuffle", - "type": { - "kind": "enum", - "variants": [ - { - "name": "AAAA" - }, - { - "name": "BBBB" - }, - { - "name": "BADC" - }, - { - "name": "BACD" - }, - { - "name": "ADDA" - }, - { - "name": "CBCB" - }, - { - "name": "ABDC" - }, - { - "name": "ABAB" - }, - { - "name": "DBBD" - }, - { - "name": "CACA" - } - ] - } - }, - { - "name": "Lanes", - "type": { - "kind": "enum", - "variants": [ - { - "name": "D" - }, - { - "name": "C" - }, - { - "name": "AB" - }, - { - "name": "AC" - }, - { - "name": "AD" - }, - { - "name": "BCD" - } - ] - } - }, - { - "name": "Error", - "type": { - "kind": "enum", - "variants": [ - { - "name": "InvalidPublicKey" - }, - { - "name": "SerializationError", - "fields": [ - { - "defined": "bincode::Error" - } - ] - }, - { - "name": "DeserializationError", - "fields": [ - { - "defined": "bincode::Error" - } - ] - }, - { - "name": "InvalidDataError" - } - ] - } - }, - { - "name": "SwitchboardPermission", - "type": { - "kind": "enum", - "variants": [ - { - "name": "PermitOracleHeartbeat" - }, - { - "name": "PermitOracleQueueUsage" - }, - { - "name": "PermitVrfRequests" - } - ] - } - }, - { - "name": "OracleResponseType", - "type": { - "kind": "enum", - "variants": [ - { - "name": "TypeSuccess" - }, - { - "name": "TypeError" - }, - { - "name": "TypeDisagreement" - }, - { - "name": "TypeNoResponse" - } - ] - } - }, - { - "name": "VrfStatus", - "type": { - "kind": "enum", - "variants": [ - { - "name": "StatusNone" - }, - { - "name": "StatusRequesting" - }, - { - "name": "StatusVerifying" - }, - { - "name": "StatusVerified" - }, - { - "name": "StatusCallbackSuccess" - }, - { - "name": "StatusVerifyFailure" - } - ] - } - } - ], - "events": [ - { - "name": "AggregatorInitEvent", - "fields": [ - { - "name": "feedPubkey", - "type": "publicKey", - "index": false - } - ] - }, - { - "name": "VrfRequestRandomnessEvent", - "fields": [ - { - "name": "vrfPubkey", - "type": "publicKey", - "index": true - }, - { - "name": "oraclePubkeys", - "type": { - "vec": "publicKey" - }, - "index": false - }, - { - "name": "loadAmount", - "type": "u64", - "index": false - }, - { - "name": "existingAmount", - "type": "u64", - "index": false - } - ] - }, - { - "name": "VrfRequestEvent", - "fields": [ - { - "name": "vrfPubkey", - "type": "publicKey", - "index": true - }, - { - "name": "oraclePubkeys", - "type": { - "vec": "publicKey" - }, - "index": false - } - ] - }, - { - "name": "VrfProveEvent", - "fields": [ - { - "name": "vrfPubkey", - "type": "publicKey", - "index": true - }, - { - "name": "oraclePubkey", - "type": "publicKey", - "index": true - }, - { - "name": "authorityPubkey", - "type": "publicKey", - "index": false - } - ] - }, - { - "name": "VrfVerifyEvent", - "fields": [ - { - "name": "vrfPubkey", - "type": "publicKey", - "index": true - }, - { - "name": "oraclePubkey", - "type": "publicKey", - "index": true - }, - { - "name": "authorityPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "amount", - "type": "u64", - "index": false - } - ] - }, - { - "name": "VrfCallbackPerformedEvent", - "fields": [ - { - "name": "vrfPubkey", - "type": "publicKey", - "index": true - }, - { - "name": "oraclePubkey", - "type": "publicKey", - "index": true - }, - { - "name": "amount", - "type": "u64", - "index": false - } - ] - }, - { - "name": "AggregatorOpenRoundEvent", - "fields": [ - { - "name": "feedPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "oraclePubkeys", - "type": { - "vec": "publicKey" - }, - "index": false - }, - { - "name": "jobPubkeys", - "type": { - "vec": "publicKey" - }, - "index": false - }, - { - "name": "remainingFunds", - "type": "u64", - "index": false - }, - { - "name": "queueAuthority", - "type": "publicKey", - "index": false - } - ] - }, - { - "name": "AggregatorValueUpdateEvent", - "fields": [ - { - "name": "feedPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "value", - "type": { - "defined": "BorshDecimal" - }, - "index": false - }, - { - "name": "slot", - "type": "u64", - "index": false - }, - { - "name": "timestamp", - "type": "i64", - "index": false - }, - { - "name": "oraclePubkeys", - "type": { - "vec": "publicKey" - }, - "index": false - }, - { - "name": "oracleValues", - "type": { - "vec": { - "defined": "BorshDecimal" - } - }, - "index": false - } - ] - }, - { - "name": "OracleRewardEvent", - "fields": [ - { - "name": "feedPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "leasePubkey", - "type": "publicKey", - "index": false - }, - { - "name": "oraclePubkey", - "type": "publicKey", - "index": false - }, - { - "name": "walletPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "amount", - "type": "u64", - "index": false - }, - { - "name": "roundSlot", - "type": "u64", - "index": false - }, - { - "name": "timestamp", - "type": "i64", - "index": false - } - ] - }, - { - "name": "OracleWithdrawEvent", - "fields": [ - { - "name": "oraclePubkey", - "type": "publicKey", - "index": false - }, - { - "name": "walletPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "destinationWallet", - "type": "publicKey", - "index": false - }, - { - "name": "previousAmount", - "type": "u64", - "index": false - }, - { - "name": "newAmount", - "type": "u64", - "index": false - }, - { - "name": "timestamp", - "type": "i64", - "index": false - } - ] - }, - { - "name": "LeaseWithdrawEvent", - "fields": [ - { - "name": "leasePubkey", - "type": "publicKey", - "index": false - }, - { - "name": "walletPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "previousAmount", - "type": "u64", - "index": false - }, - { - "name": "newAmount", - "type": "u64", - "index": false - }, - { - "name": "timestamp", - "type": "i64", - "index": false - } - ] - }, - { - "name": "OracleSlashEvent", - "fields": [ - { - "name": "feedPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "leasePubkey", - "type": "publicKey", - "index": false - }, - { - "name": "oraclePubkey", - "type": "publicKey", - "index": false - }, - { - "name": "walletPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "amount", - "type": "u64", - "index": false - }, - { - "name": "roundSlot", - "type": "u64", - "index": false - }, - { - "name": "timestamp", - "type": "i64", - "index": false - } - ] - }, - { - "name": "LeaseFundEvent", - "fields": [ - { - "name": "leasePubkey", - "type": "publicKey", - "index": false - }, - { - "name": "funder", - "type": "publicKey", - "index": false - }, - { - "name": "amount", - "type": "u64", - "index": false - }, - { - "name": "timestamp", - "type": "i64", - "index": false - } - ] - }, - { - "name": "ProbationBrokenEvent", - "fields": [ - { - "name": "feedPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "queuePubkey", - "type": "publicKey", - "index": false - }, - { - "name": "timestamp", - "type": "i64", - "index": false - } - ] - }, - { - "name": "FeedPermissionRevokedEvent", - "fields": [ - { - "name": "feedPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "timestamp", - "type": "i64", - "index": false - } - ] - }, - { - "name": "GarbageCollectFailureEvent", - "fields": [ - { - "name": "queuePubkey", - "type": "publicKey", - "index": false - } - ] - }, - { - "name": "OracleBootedEvent", - "fields": [ - { - "name": "queuePubkey", - "type": "publicKey", - "index": false - }, - { - "name": "oraclePubkey", - "type": "publicKey", - "index": false - } - ] - }, - { - "name": "AggregatorCrankEvictionEvent", - "fields": [ - { - "name": "crankPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "aggregatorPubkey", - "type": "publicKey", - "index": true - }, - { - "name": "reason", - "type": { - "option": "u32" - }, - "index": false - }, - { - "name": "timestamp", - "type": "i64", - "index": false - } - ] - }, - { - "name": "CrankLeaseInsufficientFundsEvent", - "fields": [ - { - "name": "feedPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "leasePubkey", - "type": "publicKey", - "index": false - } - ] - }, - { - "name": "CrankPopExpectedFailureEvent", - "fields": [ - { - "name": "feedPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "leasePubkey", - "type": "publicKey", - "index": false - } - ] - }, - { - "name": "BufferRelayerOpenRoundEvent", - "fields": [ - { - "name": "relayerPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "jobPubkey", - "type": "publicKey", - "index": false - }, - { - "name": "oraclePubkeys", - "type": { - "vec": "publicKey" - }, - "index": false - }, - { - "name": "remainingFunds", - "type": "u64", - "index": false - }, - { - "name": "queue", - "type": "publicKey", - "index": false - } - ] - } - ], - "errors": [ - { - "code": 6000, - "name": "ArrayOperationError", - "msg": "Illegal operation on a Switchboard array." - }, - { - "code": 6001, - "name": "QueueOperationError", - "msg": "Illegal operation on a Switchboard queue." - }, - { - "code": 6002, - "name": "IncorrectProgramOwnerError", - "msg": "An account required to be owned by the program has a different owner." - }, - { - "code": 6003, - "name": "InvalidAggregatorRound", - "msg": "Aggregator is not currently populated with a valid round." - }, - { - "code": 6004, - "name": "TooManyAggregatorJobs", - "msg": "Aggregator cannot fit any more jobs." - }, - { - "code": 6005, - "name": "AggregatorCurrentRoundClosed", - "msg": "Aggregator's current round is closed. No results are being accepted." - }, - { - "code": 6006, - "name": "AggregatorInvalidSaveResult", - "msg": "Aggregator received an invalid save result instruction." - }, - { - "code": 6007, - "name": "InvalidStrDecimalConversion", - "msg": "Failed to convert string to decimal format." - }, - { - "code": 6008, - "name": "AccountLoaderMissingSignature", - "msg": "AccountLoader account is missing a required signature." - }, - { - "code": 6009, - "name": "MissingRequiredSignature", - "msg": "Account is missing a required signature." - }, - { - "code": 6010, - "name": "ArrayOverflowError", - "msg": "The attempted action will overflow a zero-copy account array." - }, - { - "code": 6011, - "name": "ArrayUnderflowError", - "msg": "The attempted action will underflow a zero-copy account array." - }, - { - "code": 6012, - "name": "PubkeyNotFoundError", - "msg": "The queried public key was not found." - }, - { - "code": 6013, - "name": "AggregatorIllegalRoundOpenCall", - "msg": "Aggregator round open called too early." - }, - { - "code": 6014, - "name": "AggregatorIllegalRoundCloseCall", - "msg": "Aggregator round close called too early." - }, - { - "code": 6015, - "name": "AggregatorClosedError", - "msg": "Aggregator is closed. Illegal action." - }, - { - "code": 6016, - "name": "IllegalOracleIdxError", - "msg": "Illegal oracle index." - }, - { - "code": 6017, - "name": "OracleAlreadyRespondedError", - "msg": "The provided oracle has already responded this round." - }, - { - "code": 6018, - "name": "ProtoDeserializeError", - "msg": "Failed to deserialize protocol buffer." - }, - { - "code": 6019, - "name": "UnauthorizedStateUpdateError", - "msg": "Unauthorized program state modification attempted." - }, - { - "code": 6020, - "name": "MissingOracleAccountsError", - "msg": "Not enough oracle accounts provided to closeRounds." - }, - { - "code": 6021, - "name": "OracleMismatchError", - "msg": "An unexpected oracle account was provided for the transaction." - }, - { - "code": 6022, - "name": "CrankMaxCapacityError", - "msg": "Attempted to push to a Crank that's at capacity" - }, - { - "code": 6023, - "name": "AggregatorLeaseInsufficientFunds", - "msg": "Aggregator update call attempted but attached lease has insufficient funds." - }, - { - "code": 6024, - "name": "IncorrectTokenAccountMint", - "msg": "The provided token account does not point to the Switchboard token mint." - }, - { - "code": 6025, - "name": "InvalidEscrowAccount", - "msg": "An invalid escrow account was provided." - }, - { - "code": 6026, - "name": "CrankEmptyError", - "msg": "Crank empty. Pop failed." - }, - { - "code": 6027, - "name": "PdaDeriveError", - "msg": "Failed to derive a PDA from the provided seed." - }, - { - "code": 6028, - "name": "AggregatorAccountNotFound", - "msg": "Aggregator account missing from provided account list." - }, - { - "code": 6029, - "name": "PermissionAccountNotFound", - "msg": "Permission account missing from provided account list." - }, - { - "code": 6030, - "name": "LeaseAccountDeriveFailure", - "msg": "Failed to derive a lease account." - }, - { - "code": 6031, - "name": "PermissionAccountDeriveFailure", - "msg": "Failed to derive a permission account." - }, - { - "code": 6032, - "name": "EscrowAccountNotFound", - "msg": "Escrow account missing from provided account list." - }, - { - "code": 6033, - "name": "LeaseAccountNotFound", - "msg": "Lease account missing from provided account list." - }, - { - "code": 6034, - "name": "DecimalConversionError", - "msg": "Decimal conversion method failed." - }, - { - "code": 6035, - "name": "PermissionDenied", - "msg": "Permission account is missing required flags for the given action." - }, - { - "code": 6036, - "name": "QueueAtCapacity", - "msg": "Oracle queue is at lease capacity." - }, - { - "code": 6037, - "name": "ExcessiveCrankRowsError", - "msg": "Data feed is already pushed on a crank." - }, - { - "code": 6038, - "name": "AggregatorLockedError", - "msg": "Aggregator is locked, no setting modifications or job additions allowed." - }, - { - "code": 6039, - "name": "AggregatorInvalidBatchSizeError", - "msg": "Aggregator invalid batch size." - }, - { - "code": 6040, - "name": "AggregatorJobChecksumMismatch", - "msg": "Oracle provided an incorrect aggregator job checksum." - }, - { - "code": 6041, - "name": "IntegerOverflowError", - "msg": "An integer overflow occurred." - }, - { - "code": 6042, - "name": "InvalidUpdatePeriodError", - "msg": "Minimum update period is 5 seconds." - }, - { - "code": 6043, - "name": "NoResultsError", - "msg": "Aggregator round evaluation attempted with no results." - }, - { - "code": 6044, - "name": "InvalidExpirationError", - "msg": "An expiration constraint was broken." - }, - { - "code": 6045, - "name": "InsufficientStakeError", - "msg": "An account provided insufficient stake for action." - }, - { - "code": 6046, - "name": "LeaseInactiveError", - "msg": "The provided lease account is not active." - }, - { - "code": 6047, - "name": "NoAggregatorJobsFound", - "msg": "No jobs are currently included in the aggregator." - }, - { - "code": 6048, - "name": "IntegerUnderflowError", - "msg": "An integer underflow occurred." - }, - { - "code": 6049, - "name": "OracleQueueMismatch", - "msg": "An invalid oracle queue account was provided." - }, - { - "code": 6050, - "name": "OracleWalletMismatchError", - "msg": "An unexpected oracle wallet account was provided for the transaction." - }, - { - "code": 6051, - "name": "InvalidBufferAccountError", - "msg": "An invalid buffer account was provided." - }, - { - "code": 6052, - "name": "InsufficientOracleQueueError", - "msg": "Insufficient oracle queue size." - }, - { - "code": 6053, - "name": "InvalidAuthorityError", - "msg": "Invalid authority account provided." - }, - { - "code": 6054, - "name": "InvalidTokenAccountMintError", - "msg": "A provided token wallet is associated with an incorrect mint." - }, - { - "code": 6055, - "name": "ExcessiveLeaseWithdrawlError", - "msg": "You must leave enough funds to perform at least 1 update in the lease." - }, - { - "code": 6056, - "name": "InvalideHistoryAccountError", - "msg": "Invalid history account provided." - }, - { - "code": 6057, - "name": "InvalidLeaseAccountEscrowError", - "msg": "Invalid lease account escrow." - }, - { - "code": 6058, - "name": "InvalidCrankAccountError", - "msg": "Invalid crank provided." - }, - { - "code": 6059, - "name": "CrankNoElementsReadyError", - "msg": "No elements ready to be popped." - }, - { - "code": 6060, - "name": "IndexOutOfBoundsError", - "msg": "Index out of bounds" - }, - { - "code": 6061, - "name": "VrfInvalidRequestError", - "msg": "Invalid vrf request params" - }, - { - "code": 6062, - "name": "VrfInvalidProofSubmissionError", - "msg": "Vrf proof failed to verify" - }, - { - "code": 6063, - "name": "VrfVerifyError", - "msg": "Error in verifying vrf proof." - }, - { - "code": 6064, - "name": "VrfCallbackError", - "msg": "Vrf callback function failed." - }, - { - "code": 6065, - "name": "VrfCallbackParamsError", - "msg": "Invalid vrf callback params provided." - }, - { - "code": 6066, - "name": "VrfCallbackAlreadyCalledError", - "msg": "Vrf callback has already been triggered." - }, - { - "code": 6067, - "name": "VrfInvalidPubkeyError", - "msg": "The provided pubkey is invalid to use in ecvrf proofs" - }, - { - "code": 6068, - "name": "VrfTooManyVerifyCallsError", - "msg": "Number of required verify calls exceeded" - }, - { - "code": 6069, - "name": "VrfRequestAlreadyLaunchedError", - "msg": "Vrf request is already pending" - }, - { - "code": 6070, - "name": "VrfInsufficientVerificationError", - "msg": "Insufficient amount of proofs collected for VRF callback" - }, - { - "code": 6071, - "name": "InvalidVrfProducerError", - "msg": "An incorrect oracle attempted to submit a proof" - }, - { - "code": 6072, - "name": "InvalidGovernancePidError", - "msg": "Invalid SPLGovernance Account Supplied" - }, - { - "code": 6073, - "name": "InvalidGovernanceAccountError", - "msg": "An Invalid Governance Account was supplied" - }, - { - "code": 6074, - "name": "MissingOptionalAccount", - "msg": "Expected an optional account" - }, - { - "code": 6075, - "name": "InvalidSpawnRecordOwner", - "msg": "Invalid Owner for Spawn Record" - }, - { - "code": 6076, - "name": "NoopError", - "msg": "Noop error" - }, - { - "code": 6077, - "name": "MissingRequiredAccountsError", - "msg": "A required instruction account was not included" - }, - { - "code": 6078, - "name": "InvalidMintError", - "msg": "Invalid mint account passed for instruction" - }, - { - "code": 6079, - "name": "InvalidTokenAccountKeyError", - "msg": "An invalid token account was passed into the instruction" - }, - { - "code": 6080, - "name": "InvalidJobAccountError", - "msg": "" - }, - { - "code": 6081, - "name": "VoterStakeRegistryError", - "msg": "" - }, - { - "code": 6082, - "name": "AccountDiscriminatorMismatch", - "msg": "Account discriminator did not match." - } - ], - "metadata": { - "address": "7PMP6yE6qb3XzBQr5TK2GhuruYayZzBnT8U92ySaLESC" - } -} diff --git a/TokenHaverPlugin/TokenHaverClient.ts b/TokenHaverPlugin/TokenHaverClient.ts new file mode 100644 index 0000000000..7b575a6c8e --- /dev/null +++ b/TokenHaverPlugin/TokenHaverClient.ts @@ -0,0 +1,151 @@ +import { BN, Program, Provider } from '@coral-xyz/anchor' +import { Client } from '@solana/governance-program-library' +import { SYSTEM_PROGRAM_ID } from '@solana/spl-governance' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' + +import { fetchTokenAccountByPubkey } from '@hooks/queries/tokenAccount' +import { fetchRealmByPubkey } from '@hooks/queries/realm' +import { IDL, TokenHaver } from './idl/token_haver' +import { getAssociatedTokenAddress } from '@blockworks-foundation/mango-v4' +import { TOKEN_HAVER_PLUGIN } from './constants' + +export class TokenHaverClient extends Client { + readonly requiresInputVoterWeight = true + + constructor(public program: Program, public devnet: boolean) { + super(program, devnet) + } + + async calculateMaxVoterWeight( + _realm: PublicKey, + _mint: PublicKey + ): Promise { + const { result: realm } = await fetchRealmByPubkey( + this.program.provider.connection, + _realm + ) + return realm?.account.config?.communityMintMaxVoteWeightSource.value ?? null // TODO this code should not actually be called because this is not a max voter weight plugin + } + + async calculateVoterWeight( + voter: PublicKey, + realm: PublicKey, + mint: PublicKey + ): Promise { + const { registrar: registrarPk } = this.getRegistrarPDA(realm, mint) + const registrar = await this.program.account.registrar.fetch(registrarPk) + const countOfTokensUserHas = ( + await Promise.all( + registrar.mints.map(async (mint) => { + const tokenAccountPk = await getAssociatedTokenAddress(mint, voter) + const tokenAccount = await fetchTokenAccountByPubkey( + this.program.provider.connection, + tokenAccountPk + ) + return (tokenAccount.result?.amount ?? new BN(0)).gt(new BN(0)) + ? 1 + : 0 + }) + ) + ).reduce((acc, curr) => acc + curr, 0) + return new BN(countOfTokensUserHas).muln(10 ** 6) + } + + async updateVoterWeightRecord( + voter: PublicKey, + realm: PublicKey, + mint: PublicKey + //action?: VoterWeightAction | undefined, + //inputRecordCallback?: (() => Promise) | undefined + ): Promise<{ + pre: TransactionInstruction[] + post?: TransactionInstruction[] | undefined + }> { + const connection = this.program.provider.connection + const { result: realmAccount } = await fetchRealmByPubkey(connection, realm) + if (!realmAccount) throw new Error('Realm not found') + + const { voterWeightPk } = await this.getVoterWeightRecordPDA( + realm, + mint, + voter + ) + const { registrar: registrarPk } = this.getRegistrarPDA(realm, mint) + const registrar = await this.program.account.registrar.fetch(registrarPk) + + const tokenAccounts = ( + await Promise.all( + registrar.mints.map(async (mint) => { + const tokenAccountPk = await getAssociatedTokenAddress(mint, voter) + // filter out empty accounts + const account = await fetchTokenAccountByPubkey( + this.program.provider.connection, + tokenAccountPk + ) + return account.found ? tokenAccountPk : null + }) + ) + ).filter((x) => x !== null) as PublicKey[] + + const ix = await this.program.methods + .updateVoterWeightRecord() + .accountsStrict({ + voterWeightRecord: voterWeightPk, + registrar: registrarPk, + }) + .remainingAccounts( + tokenAccounts.map((pubkey) => ({ + pubkey, + isSigner: false, + isWritable: false, + })) + ) + .instruction() + + return { pre: [ix] } + } + + // NO-OP + async createMaxVoterWeightRecord(): Promise { + return null + } + + // NO-OP + async updateMaxVoterWeightRecord(): Promise { + return null + } + + static async connect( + provider: Provider, + programId = new PublicKey(TOKEN_HAVER_PLUGIN), + devnet = false + ) { + return new TokenHaverClient( + new Program(IDL, programId, provider), + devnet + ) + } + + async createVoterWeightRecord( + voter: PublicKey, + realm: PublicKey, + mint: PublicKey + ): Promise { + const { voterWeightPk } = await this.getVoterWeightRecordPDA( + realm, + mint, + voter + ) + const { registrar } = this.getRegistrarPDA(realm, mint) + + return this.program.methods + .createVoterWeightRecord(voter) + .accounts({ + voterWeightRecord: voterWeightPk, + registrar, + payer: voter, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .instruction() + } +} diff --git a/TokenHaverPlugin/constants.ts b/TokenHaverPlugin/constants.ts new file mode 100644 index 0000000000..2969211106 --- /dev/null +++ b/TokenHaverPlugin/constants.ts @@ -0,0 +1,5 @@ +import { PublicKey } from '@solana/web3.js' + +export const TOKEN_HAVER_PLUGIN = new PublicKey( + '7gobfUihgoxA14RUnVaseoah89ggCgYAzgz1JoaPAXam' +) diff --git a/TokenHaverPlugin/idl/token_haver.ts b/TokenHaverPlugin/idl/token_haver.ts new file mode 100644 index 0000000000..3cefd2367e --- /dev/null +++ b/TokenHaverPlugin/idl/token_haver.ts @@ -0,0 +1,867 @@ +export type TokenHaver = { + version: '0.0.1' + name: 'token_haver' + instructions: [ + { + name: 'createRegistrar' + accounts: [ + { + name: 'registrar' + isMut: true + isSigner: false + docs: [ + 'The Realm Voter Registrar', + 'There can only be a single registrar per governance Realm and governing mint of the Realm' + ] + }, + { + name: 'governanceProgramId' + isMut: false + isSigner: false + docs: [ + 'The program id of the spl-governance program the realm belongs to' + ] + }, + { + name: 'realm' + isMut: false + isSigner: false + docs: [ + 'An spl-governance Realm', + '', + 'Realm is validated in the instruction:', + '- Realm is owned by the governance_program_id', + '- governing_token_mint must be the community or council mint', + '- realm_authority is realm.authority' + ] + }, + { + name: 'governingTokenMint' + isMut: false + isSigner: false + docs: [ + 'Either the realm community mint or the council mint.', + 'It must match Realm.community_mint or Realm.config.council_mint', + '', + 'Note: Once the Realm voter plugin is enabled the governing_token_mint is used only as identity', + 'for the voting population and the tokens of that are no longer used' + ] + }, + { + name: 'realmAuthority' + isMut: false + isSigner: true + docs: ['realm_authority must sign and match Realm.authority'] + }, + { + name: 'payer' + isMut: true + isSigner: true + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'mints' + type: { + vec: 'publicKey' + } + } + ] + }, + { + name: 'createVoterWeightRecord' + accounts: [ + { + name: 'registrar' + isMut: false + isSigner: false + }, + { + name: 'voterWeightRecord' + isMut: true + isSigner: false + }, + { + name: 'payer' + isMut: true + isSigner: true + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'governingTokenOwner' + type: 'publicKey' + } + ] + }, + { + name: 'updateVoterWeightRecord' + accounts: [ + { + name: 'registrar' + isMut: false + isSigner: false + docs: ['The RealmVoter voting Registrar'] + }, + { + name: 'voterWeightRecord' + isMut: true + isSigner: false + } + ] + args: [] + }, + { + name: 'configureMints' + accounts: [ + { + name: 'registrar' + isMut: true + isSigner: false + docs: ['The Registrar for the given realm and governing_token_mint'] + }, + { + name: 'realm' + isMut: false + isSigner: false + }, + { + name: 'payer' + isMut: false + isSigner: true + }, + { + name: 'realmAuthority' + isMut: false + isSigner: true + docs: ['Authority of the Realm must sign and match realm.authority'] + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'mints' + type: { + vec: 'publicKey' + } + } + ] + } + ] + accounts: [ + { + name: 'maxVoterWeightRecord' + docs: [ + 'MaxVoterWeightRecord account as defined in spl-governance-addin-api', + "It's redefined here without account_discriminator for Anchor to treat it as native account", + '', + 'The account is used as an api interface to provide max voting power to the governance program from external addin contracts' + ] + type: { + kind: 'struct' + fields: [ + { + name: 'realm' + docs: ['The Realm the MaxVoterWeightRecord belongs to'] + type: 'publicKey' + }, + { + name: 'governingTokenMint' + docs: [ + 'Governing Token Mint the MaxVoterWeightRecord is associated with', + 'Note: The addin can take deposits of any tokens and is not restricted to the community or council tokens only' + ] + type: 'publicKey' + }, + { + name: 'maxVoterWeight' + docs: [ + 'Max voter weight', + 'The max voter weight provided by the addin for the given realm and governing_token_mint' + ] + type: 'u64' + }, + { + name: 'maxVoterWeightExpiry' + docs: [ + 'The slot when the max voting weight expires', + 'It should be set to None if the weight never expires', + 'If the max vote weight decays with time, for example for time locked based weights, then the expiry must be set', + 'As a pattern Revise instruction to update the max weight should be invoked before governance instruction within the same transaction', + 'and the expiry set to the current slot to provide up to date weight' + ] + type: { + option: 'u64' + } + }, + { + name: 'reserved' + docs: ['Reserved space for future versions'] + type: { + array: ['u8', 8] + } + } + ] + } + }, + { + name: 'registrar' + docs: [ + 'Registrar which stores spl-governance configurations for the given Realm' + ] + type: { + kind: 'struct' + fields: [ + { + name: 'governanceProgramId' + docs: ['spl-governance program the Realm belongs to'] + type: 'publicKey' + }, + { + name: 'realm' + docs: ['Realm of the Registrar'] + type: 'publicKey' + }, + { + name: 'governingTokenMint' + docs: [ + 'Governing token mint the Registrar is for', + 'It can either be the Community or the Council mint of the Realm', + 'When the plugin is enabled the mint is only used as the identity of the governing power (voting population)', + 'and the actual token of the mint is not used' + ] + type: 'publicKey' + }, + { + name: 'mints' + type: { + vec: 'publicKey' + } + } + ] + } + }, + { + name: 'voterWeightRecord' + docs: [ + 'VoterWeightRecord account as defined in spl-governance-addin-api', + "It's redefined here without account_discriminator for Anchor to treat it as native account", + '', + 'The account is used as an api interface to provide voting power to the governance program from external addin contracts' + ] + type: { + kind: 'struct' + fields: [ + { + name: 'realm' + docs: ['The Realm the VoterWeightRecord belongs to'] + type: 'publicKey' + }, + { + name: 'governingTokenMint' + docs: [ + 'Governing Token Mint the VoterWeightRecord is associated with', + 'Note: The addin can take deposits of any tokens and is not restricted to the community or council tokens only' + ] + type: 'publicKey' + }, + { + name: 'governingTokenOwner' + docs: [ + 'The owner of the governing token and voter', + 'This is the actual owner (voter) and corresponds to TokenOwnerRecord.governing_token_owner' + ] + type: 'publicKey' + }, + { + name: 'voterWeight' + docs: [ + "Voter's weight", + 'The weight of the voter provided by the addin for the given realm, governing_token_mint and governing_token_owner (voter)' + ] + type: 'u64' + }, + { + name: 'voterWeightExpiry' + docs: [ + 'The slot when the voting weight expires', + 'It should be set to None if the weight never expires', + 'If the voter weight decays with time, for example for time locked based weights, then the expiry must be set', + 'As a common pattern Revise instruction to update the weight should be invoked before governance instruction within the same transaction', + 'and the expiry set to the current slot to provide up to date weight' + ] + type: { + option: 'u64' + } + }, + { + name: 'weightAction' + docs: [ + "The governance action the voter's weight pertains to", + "It allows to provided voter's weight specific to the particular action the weight is evaluated for", + 'When the action is provided then the governance program asserts the executing action is the same as specified by the addin' + ] + type: { + option: { + defined: 'VoterWeightAction' + } + } + }, + { + name: 'weightActionTarget' + docs: [ + "The target the voter's weight action pertains to", + "It allows to provided voter's weight specific to the target the weight is evaluated for", + 'For example when addin supplies weight to vote on a particular proposal then it must specify the proposal as the action target', + 'When the target is provided then the governance program asserts the target is the same as specified by the addin' + ] + type: { + option: 'publicKey' + } + }, + { + name: 'reserved' + docs: ['Reserved space for future versions'] + type: { + array: ['u8', 8] + } + } + ] + } + } + ] + types: [ + { + name: 'CollectionItemChangeType' + docs: ['Enum defining collection item change type'] + type: { + kind: 'enum' + variants: [ + { + name: 'Upsert' + }, + { + name: 'Remove' + } + ] + } + }, + { + name: 'VoterWeightAction' + docs: [ + 'VoterWeightAction enum as defined in spl-governance-addin-api', + "It's redefined here for Anchor to export it to IDL" + ] + type: { + kind: 'enum' + variants: [ + { + name: 'CastVote' + }, + { + name: 'CommentProposal' + }, + { + name: 'CreateGovernance' + }, + { + name: 'CreateProposal' + }, + { + name: 'SignOffProposal' + } + ] + } + } + ] + errors: [ + { + code: 6000 + name: 'InvalidRealmAuthority' + msg: 'Invalid Realm Authority' + }, + { + code: 6001 + name: 'InvalidRealmForRegistrar' + msg: 'Invalid Realm for Registrar' + }, + { + code: 6002 + name: 'InvalidVoterWeightRecordRealm' + msg: 'Invalid VoterWeightRecord Realm' + }, + { + code: 6003 + name: 'InvalidVoterWeightRecordMint' + msg: 'Invalid VoterWeightRecord Mint' + }, + { + code: 6004 + name: 'GoverningTokenOwnerMustMatch' + msg: 'Governing TokenOwner must match' + }, + { + code: 6005 + name: 'TokenAccountWrongOwner' + msg: 'All token accounts must be owned by the governing token owner' + }, + { + code: 6006 + name: 'TokenAccountWrongMint' + msg: "All token accounts' mints must be included in the registrar" + }, + { + code: 6007 + name: 'TokenAccountNotLocked' + msg: "All token accounts' mints must be included in the registrar" + } + ] +} + +export const IDL: TokenHaver = { + version: '0.0.1', + name: 'token_haver', + instructions: [ + { + name: 'createRegistrar', + accounts: [ + { + name: 'registrar', + isMut: true, + isSigner: false, + docs: [ + 'The Realm Voter Registrar', + 'There can only be a single registrar per governance Realm and governing mint of the Realm', + ], + }, + { + name: 'governanceProgramId', + isMut: false, + isSigner: false, + docs: [ + 'The program id of the spl-governance program the realm belongs to', + ], + }, + { + name: 'realm', + isMut: false, + isSigner: false, + docs: [ + 'An spl-governance Realm', + '', + 'Realm is validated in the instruction:', + '- Realm is owned by the governance_program_id', + '- governing_token_mint must be the community or council mint', + '- realm_authority is realm.authority', + ], + }, + { + name: 'governingTokenMint', + isMut: false, + isSigner: false, + docs: [ + 'Either the realm community mint or the council mint.', + 'It must match Realm.community_mint or Realm.config.council_mint', + '', + 'Note: Once the Realm voter plugin is enabled the governing_token_mint is used only as identity', + 'for the voting population and the tokens of that are no longer used', + ], + }, + { + name: 'realmAuthority', + isMut: false, + isSigner: true, + docs: ['realm_authority must sign and match Realm.authority'], + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'mints', + type: { + vec: 'publicKey', + }, + }, + ], + }, + { + name: 'createVoterWeightRecord', + accounts: [ + { + name: 'registrar', + isMut: false, + isSigner: false, + }, + { + name: 'voterWeightRecord', + isMut: true, + isSigner: false, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'governingTokenOwner', + type: 'publicKey', + }, + ], + }, + { + name: 'updateVoterWeightRecord', + accounts: [ + { + name: 'registrar', + isMut: false, + isSigner: false, + docs: ['The RealmVoter voting Registrar'], + }, + { + name: 'voterWeightRecord', + isMut: true, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'configureMints', + accounts: [ + { + name: 'registrar', + isMut: true, + isSigner: false, + docs: ['The Registrar for the given realm and governing_token_mint'], + }, + { + name: 'realm', + isMut: false, + isSigner: false, + }, + { + name: 'payer', + isMut: false, + isSigner: true, + }, + { + name: 'realmAuthority', + isMut: false, + isSigner: true, + docs: ['Authority of the Realm must sign and match realm.authority'], + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'mints', + type: { + vec: 'publicKey', + }, + }, + ], + }, + ], + accounts: [ + { + name: 'maxVoterWeightRecord', + docs: [ + 'MaxVoterWeightRecord account as defined in spl-governance-addin-api', + "It's redefined here without account_discriminator for Anchor to treat it as native account", + '', + 'The account is used as an api interface to provide max voting power to the governance program from external addin contracts', + ], + type: { + kind: 'struct', + fields: [ + { + name: 'realm', + docs: ['The Realm the MaxVoterWeightRecord belongs to'], + type: 'publicKey', + }, + { + name: 'governingTokenMint', + docs: [ + 'Governing Token Mint the MaxVoterWeightRecord is associated with', + 'Note: The addin can take deposits of any tokens and is not restricted to the community or council tokens only', + ], + type: 'publicKey', + }, + { + name: 'maxVoterWeight', + docs: [ + 'Max voter weight', + 'The max voter weight provided by the addin for the given realm and governing_token_mint', + ], + type: 'u64', + }, + { + name: 'maxVoterWeightExpiry', + docs: [ + 'The slot when the max voting weight expires', + 'It should be set to None if the weight never expires', + 'If the max vote weight decays with time, for example for time locked based weights, then the expiry must be set', + 'As a pattern Revise instruction to update the max weight should be invoked before governance instruction within the same transaction', + 'and the expiry set to the current slot to provide up to date weight', + ], + type: { + option: 'u64', + }, + }, + { + name: 'reserved', + docs: ['Reserved space for future versions'], + type: { + array: ['u8', 8], + }, + }, + ], + }, + }, + { + name: 'registrar', + docs: [ + 'Registrar which stores spl-governance configurations for the given Realm', + ], + type: { + kind: 'struct', + fields: [ + { + name: 'governanceProgramId', + docs: ['spl-governance program the Realm belongs to'], + type: 'publicKey', + }, + { + name: 'realm', + docs: ['Realm of the Registrar'], + type: 'publicKey', + }, + { + name: 'governingTokenMint', + docs: [ + 'Governing token mint the Registrar is for', + 'It can either be the Community or the Council mint of the Realm', + 'When the plugin is enabled the mint is only used as the identity of the governing power (voting population)', + 'and the actual token of the mint is not used', + ], + type: 'publicKey', + }, + { + name: 'mints', + type: { + vec: 'publicKey', + }, + }, + ], + }, + }, + { + name: 'voterWeightRecord', + docs: [ + 'VoterWeightRecord account as defined in spl-governance-addin-api', + "It's redefined here without account_discriminator for Anchor to treat it as native account", + '', + 'The account is used as an api interface to provide voting power to the governance program from external addin contracts', + ], + type: { + kind: 'struct', + fields: [ + { + name: 'realm', + docs: ['The Realm the VoterWeightRecord belongs to'], + type: 'publicKey', + }, + { + name: 'governingTokenMint', + docs: [ + 'Governing Token Mint the VoterWeightRecord is associated with', + 'Note: The addin can take deposits of any tokens and is not restricted to the community or council tokens only', + ], + type: 'publicKey', + }, + { + name: 'governingTokenOwner', + docs: [ + 'The owner of the governing token and voter', + 'This is the actual owner (voter) and corresponds to TokenOwnerRecord.governing_token_owner', + ], + type: 'publicKey', + }, + { + name: 'voterWeight', + docs: [ + "Voter's weight", + 'The weight of the voter provided by the addin for the given realm, governing_token_mint and governing_token_owner (voter)', + ], + type: 'u64', + }, + { + name: 'voterWeightExpiry', + docs: [ + 'The slot when the voting weight expires', + 'It should be set to None if the weight never expires', + 'If the voter weight decays with time, for example for time locked based weights, then the expiry must be set', + 'As a common pattern Revise instruction to update the weight should be invoked before governance instruction within the same transaction', + 'and the expiry set to the current slot to provide up to date weight', + ], + type: { + option: 'u64', + }, + }, + { + name: 'weightAction', + docs: [ + "The governance action the voter's weight pertains to", + "It allows to provided voter's weight specific to the particular action the weight is evaluated for", + 'When the action is provided then the governance program asserts the executing action is the same as specified by the addin', + ], + type: { + option: { + defined: 'VoterWeightAction', + }, + }, + }, + { + name: 'weightActionTarget', + docs: [ + "The target the voter's weight action pertains to", + "It allows to provided voter's weight specific to the target the weight is evaluated for", + 'For example when addin supplies weight to vote on a particular proposal then it must specify the proposal as the action target', + 'When the target is provided then the governance program asserts the target is the same as specified by the addin', + ], + type: { + option: 'publicKey', + }, + }, + { + name: 'reserved', + docs: ['Reserved space for future versions'], + type: { + array: ['u8', 8], + }, + }, + ], + }, + }, + ], + types: [ + { + name: 'CollectionItemChangeType', + docs: ['Enum defining collection item change type'], + type: { + kind: 'enum', + variants: [ + { + name: 'Upsert', + }, + { + name: 'Remove', + }, + ], + }, + }, + { + name: 'VoterWeightAction', + docs: [ + 'VoterWeightAction enum as defined in spl-governance-addin-api', + "It's redefined here for Anchor to export it to IDL", + ], + type: { + kind: 'enum', + variants: [ + { + name: 'CastVote', + }, + { + name: 'CommentProposal', + }, + { + name: 'CreateGovernance', + }, + { + name: 'CreateProposal', + }, + { + name: 'SignOffProposal', + }, + ], + }, + }, + ], + errors: [ + { + code: 6000, + name: 'InvalidRealmAuthority', + msg: 'Invalid Realm Authority', + }, + { + code: 6001, + name: 'InvalidRealmForRegistrar', + msg: 'Invalid Realm for Registrar', + }, + { + code: 6002, + name: 'InvalidVoterWeightRecordRealm', + msg: 'Invalid VoterWeightRecord Realm', + }, + { + code: 6003, + name: 'InvalidVoterWeightRecordMint', + msg: 'Invalid VoterWeightRecord Mint', + }, + { + code: 6004, + name: 'GoverningTokenOwnerMustMatch', + msg: 'Governing TokenOwner must match', + }, + { + code: 6005, + name: 'TokenAccountWrongOwner', + msg: 'All token accounts must be owned by the governing token owner', + }, + { + code: 6006, + name: 'TokenAccountWrongMint', + msg: "All token accounts' mints must be included in the registrar", + }, + { + code: 6007, + name: 'TokenAccountNotLocked', + msg: "All token accounts' mints must be included in the registrar", + }, + ], +} diff --git a/TokenHaverPlugin/readme.md b/TokenHaverPlugin/readme.md new file mode 100644 index 0000000000..bb8a3c0fbc --- /dev/null +++ b/TokenHaverPlugin/readme.md @@ -0,0 +1 @@ +This plugin simply detects if token accounts for a list of mints are present and nonzero. It was used for Voshy's "Greed Experiment" DAO. The contract can be found on the governance-program-library. \ No newline at end of file diff --git a/VoteStakeRegistry/actions/closeDeposit.ts b/VoteStakeRegistry/actions/closeDeposit.ts index 6305ba16d4..77158520a4 100644 --- a/VoteStakeRegistry/actions/closeDeposit.ts +++ b/VoteStakeRegistry/actions/closeDeposit.ts @@ -27,12 +27,12 @@ export const closeDeposit = async ({ const instructions: TransactionInstruction[] = [] const clientProgramId = client!.program.programId - const { registrar } = await getRegistrarPDA( + const { registrar } = getRegistrarPDA( realmPk, communityMintPk, client!.program.programId ) - const { voter } = await getVoterPDA( + const { voter } = getVoterPDA( registrar, wallet!.publicKey!, clientProgramId diff --git a/VoteStakeRegistry/actions/getClawbackInstruction.ts b/VoteStakeRegistry/actions/getClawbackInstruction.ts index f73ec97f6e..c468363c83 100644 --- a/VoteStakeRegistry/actions/getClawbackInstruction.ts +++ b/VoteStakeRegistry/actions/getClawbackInstruction.ts @@ -29,12 +29,12 @@ export const getClawbackInstruction = async ({ }) => { const clientProgramId = client!.program.programId - const { registrar } = await getRegistrarPDA( + const { registrar } = getRegistrarPDA( realmPk, realmCommunityMintPk, clientProgramId ) - const { voter } = await getVoterPDA( + const { voter } = getVoterPDA( registrar, voterWalletAddress, clientProgramId diff --git a/VoteStakeRegistry/actions/getGrantInstruction.ts b/VoteStakeRegistry/actions/getGrantInstruction.ts index e36045e846..ed37997754 100644 --- a/VoteStakeRegistry/actions/getGrantInstruction.ts +++ b/VoteStakeRegistry/actions/getGrantInstruction.ts @@ -1,6 +1,6 @@ import { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY } from '@solana/web3.js' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { getRegistrarPDA, getVoterPDA, @@ -46,17 +46,17 @@ export const getGrantInstruction = async ({ const systemProgram = SystemProgram.programId const clientProgramId = client!.program.programId - const { registrar } = await getRegistrarPDA( + const { registrar } = getRegistrarPDA( realmPk, communityMintPk, clientProgramId ) - const { voter, voterBump } = await getVoterPDA( + const { voter, voterBump } = getVoterPDA( registrar, toPk, clientProgramId ) - const { voterWeightPk, voterWeightBump } = await getVoterWeightPDA( + const { voterWeightPk, voterWeightBump } = getVoterWeightPDA( registrar, toPk, clientProgramId @@ -73,7 +73,7 @@ export const getGrantInstruction = async ({ .grant( voterBump, voterWeightBump, - { [lockupKind]: {} }, + { [lockupKind]: {} } as any, // The cast to any works around an anchor issue with interpreting enums new BN(startTime), lockupPeriod, allowClawback, diff --git a/VoteStakeRegistry/actions/voteRegistryDepositWithoutLockup.ts b/VoteStakeRegistry/actions/voteRegistryDepositWithoutLockup.ts index acc7fd4e39..d357eeda98 100644 --- a/VoteStakeRegistry/actions/voteRegistryDepositWithoutLockup.ts +++ b/VoteStakeRegistry/actions/voteRegistryDepositWithoutLockup.ts @@ -7,7 +7,7 @@ import { import { RpcContext } from '@solana/spl-governance' import { sendTransaction } from 'utils/send' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { withVoteRegistryDeposit } from '../sdk/withVoteRegistryDeposit' import { VsrClient } from 'VoteStakeRegistry/sdk/client' diff --git a/VoteStakeRegistry/actions/voteRegistryLockDeposit.ts b/VoteStakeRegistry/actions/voteRegistryLockDeposit.ts index 7776ac05b6..0488cbb34d 100644 --- a/VoteStakeRegistry/actions/voteRegistryLockDeposit.ts +++ b/VoteStakeRegistry/actions/voteRegistryLockDeposit.ts @@ -7,7 +7,7 @@ import { import { RpcContext, TOKEN_PROGRAM_ID } from '@solana/spl-governance' import { sendTransaction } from 'utils/send' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { LockupType } from 'VoteStakeRegistry/sdk/accounts' import { withCreateNewDeposit } from '../sdk/withCreateNewDeposit' import { getPeriod } from 'VoteStakeRegistry/tools/deposits' @@ -114,7 +114,8 @@ export const voteRegistryLockDeposit = async ({ if (!amountFromVoteRegistryDeposit.isZero()) { const period = getPeriod(lockUpPeriodInDays, lockupKind) const resetLockup = await client?.program.methods - .resetLockup(depositIdx, { [lockupKind]: {} }, period) + // The cast to any works around an anchor issue with interpreting enums + .resetLockup(depositIdx, { [lockupKind]: {} } as any, period) .accounts({ registrar: registrar, voter: voter, diff --git a/VoteStakeRegistry/actions/voteRegistryStartUnlock.ts b/VoteStakeRegistry/actions/voteRegistryStartUnlock.ts index 4cca4527b6..3bdeac51a4 100644 --- a/VoteStakeRegistry/actions/voteRegistryStartUnlock.ts +++ b/VoteStakeRegistry/actions/voteRegistryStartUnlock.ts @@ -7,7 +7,7 @@ import { import { RpcContext } from '@solana/spl-governance' import { sendTransaction } from 'utils/send' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { withCreateNewDeposit } from '../sdk/withCreateNewDeposit' import { VsrClient } from 'VoteStakeRegistry/sdk/client' diff --git a/VoteStakeRegistry/actions/voteRegistryWithdraw.ts b/VoteStakeRegistry/actions/voteRegistryWithdraw.ts index 9af97a29e6..ca21918710 100644 --- a/VoteStakeRegistry/actions/voteRegistryWithdraw.ts +++ b/VoteStakeRegistry/actions/voteRegistryWithdraw.ts @@ -1,14 +1,9 @@ -import { - Keypair, - PublicKey, - Transaction, - TransactionInstruction, -} from '@solana/web3.js' -import { BN } from '@project-serum/anchor' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { BN } from '@coral-xyz/anchor' import { withVoteRegistryWithdraw } from '../sdk/withVoteRegistryWithdraw' import { RpcContext } from '@solana/spl-governance' -import { sendTransaction } from '@utils/send' import { VsrClient } from 'VoteStakeRegistry/sdk/client' +import { sendTransactionsV3, SequenceType } from '@utils/sendTransactions' export const voteRegistryWithdraw = async ({ rpcContext, @@ -18,6 +13,8 @@ export const voteRegistryWithdraw = async ({ tokenOwnerRecordPubKey, depositIndex, closeDepositAfterOperation, + splProgramId, + splProgramVersion, communityMintPk, client, }: { @@ -26,15 +23,17 @@ export const voteRegistryWithdraw = async ({ realmPk: PublicKey communityMintPk: PublicKey amount: BN - tokenOwnerRecordPubKey: PublicKey + tokenOwnerRecordPubKey: PublicKey | undefined depositIndex: number + splProgramId: PublicKey + splProgramVersion: number //if we want to close deposit after doing operation we need to fill this because we can close only deposits that have 0 tokens inside closeDepositAfterOperation?: boolean client?: VsrClient }) => { - const signers: Keypair[] = [] const { wallet, connection } = rpcContext const instructions: TransactionInstruction[] = [] + //spl governance tokenownerrecord pubkey await withVoteRegistryWithdraw({ instructions, walletPk: wallet!.publicKey!, @@ -47,17 +46,23 @@ export const voteRegistryWithdraw = async ({ communityMintPk, connection, client, + splProgramId, + splProgramVersion, + }) + const txes = [instructions].map((txBatch) => { + return { + instructionsSet: txBatch.map((x) => { + return { + transactionInstruction: x, + } + }), + sequenceType: SequenceType.Sequential, + } }) - const transaction = new Transaction() - transaction.add(...instructions) - - await sendTransaction({ - transaction, - wallet, + await sendTransactionsV3({ connection, - signers, - sendingMessage: `Withdrawing`, - successMessage: `Withdraw successful`, + wallet, + transactionInstructions: txes, }) } diff --git a/VoteStakeRegistry/components/Account/Account.tsx b/VoteStakeRegistry/components/Account/Account.tsx deleted file mode 100644 index 0c90ad9f92..0000000000 --- a/VoteStakeRegistry/components/Account/Account.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import PreviousRouteBtn from '@components/PreviousRouteBtn' -import { LinkIcon } from '@heroicons/react/outline' -import MyProposalsBtn from 'pages/dao/[symbol]/proposal/components/MyProposalsBtn' -import useWalletStore from 'stores/useWalletStore' -import DelegateCard from '@components/DelegateCard' - -const AccountInner = ({ withHeader = true }: { withHeader?: boolean }) => { - const connected = useWalletStore((s) => s.connected) - return ( -
- {withHeader && ( - <> -
- -
-
-

Account

-
- - )} - -
- {connected ? ( - - ) : ( -
- - Connect your wallet -
- )} -
-
- ) -} - -const Account = ({ withHeader = true }: { withHeader?: boolean }) => { - if (withHeader) { - return ( -
- -
- -
-
- ) - } else { - return ( - <> - -
- -
- - ) - } -} - -export default Account diff --git a/VoteStakeRegistry/components/Account/DepositCard.tsx b/VoteStakeRegistry/components/Account/DepositCard.tsx index dafc9d9205..5ccf139dd5 100644 --- a/VoteStakeRegistry/components/Account/DepositCard.tsx +++ b/VoteStakeRegistry/components/Account/DepositCard.tsx @@ -3,45 +3,61 @@ import useRealm from '@hooks/useRealm' import { getProgramVersionForRealm } from '@models/registry/api' import { RpcContext } from '@solana/spl-governance' import { fmtMintAmount, getMintDecimalAmount } from '@tools/sdk/units' -import useWalletStore from 'stores/useWalletStore' import { voteRegistryWithdraw } from 'VoteStakeRegistry/actions/voteRegistryWithdraw' import { DepositWithMintAccount, LockupType, + Registrar, } from 'VoteStakeRegistry/sdk/accounts' import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' -import tokenService from '@utils/services/token' +import tokenPriceService from '@utils/services/tokenPrice' import LockTokensModal from './LockTokensModal' import { useState } from 'react' -import { - getFormattedStringFromDays, - getMinDurationFmt, - getTimeLeftFromNowFmt, - SECS_PER_DAY, -} from 'VoteStakeRegistry/tools/dateTools' import { closeDeposit } from 'VoteStakeRegistry/actions/closeDeposit' import { abbreviateAddress } from '@utils/formatting' import { notify } from '@utils/notifications' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' import dayjs from 'dayjs' -import { BN } from '@project-serum/anchor' +import { + getMinDurationFmt, + getTimeLeftFromNowFmt, + getFormattedStringFromDays, + SECS_PER_DAY, +} from '@utils/dateTools' +import { BN } from '@coral-xyz/anchor' +import { VsrClient } from 'VoteStakeRegistry/sdk/client' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { useConnection } from '@solana/wallet-adapter-react' +import queryClient from '@hooks/queries/queryClient' +import { tokenAccountQueryKeys } from '@hooks/queries/tokenAccount' +import {useVsrClient} from "../../../VoterWeightPlugins/useVsrClient"; -const DepositCard = ({ deposit }: { deposit: DepositWithMintAccount }) => { +const DepositCard = ({ + deposit, + vsrClient, + registrar +}: { + deposit: DepositWithMintAccount + vsrClient?: VsrClient | undefined, + registrar?: Registrar | undefined +}) => { const { getOwnedDeposits } = useDepositStore() - const { realm, realmInfo, tokenRecords, ownTokenRecord } = useRealm() - const client = useVotePluginsClientStore((s) => s.state.vsrClient) - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection.current) - const endpoint = useWalletStore((s) => s.connection.endpoint) + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const realm = useRealmQuery().data?.result + + const { realmInfo } = useRealm() + const { vsrClient: client } = useVsrClient() + const actualClient = vsrClient || client + const wallet = useWalletOnePointOh() + const { connection } = useConnection() + const endpoint = connection.rpcEndpoint const [isUnlockModalOpen, setIsUnlockModalOpen] = useState(false) - const { fetchRealm, fetchWalletTokenAccounts } = useWalletStore( - (s) => s.actions - ) const handleWithDrawFromDeposit = async ( depositEntry: DepositWithMintAccount ) => { if ( - ownTokenRecord!.account!.unrelinquishedVotesCount && + ownTokenRecord?.account?.unrelinquishedVotesCount && realm!.account.communityMint.toBase58() === deposit.mint.publicKey.toBase58() ) { @@ -66,20 +82,23 @@ const DepositCard = ({ deposit }: { deposit: DepositWithMintAccount }) => { amount: depositEntry.available, communityMintPk: realm!.account.communityMint, closeDepositAfterOperation: depositEntry.currentlyLocked.isZero(), - tokenOwnerRecordPubKey: tokenRecords[wallet!.publicKey!.toBase58()] - .pubkey!, + tokenOwnerRecordPubKey: ownTokenRecord?.pubkey, depositIndex: depositEntry.index, - client: client, + client: actualClient, + splProgramId: realm!.owner!, + splProgramVersion: getProgramVersionForRealm(realmInfo!), }) await getOwnedDeposits({ realmPk: realm!.pubkey, communityMintPk: realm!.account.communityMint, walletPk: wallet!.publicKey!, - client: client!, + client: actualClient!, connection, }) - await fetchWalletTokenAccounts() - await fetchRealm(realmInfo!.programId, realmInfo!.realmId) + queryClient.invalidateQueries( + tokenAccountQueryKeys.byOwner(connection.rpcEndpoint, wallet!.publicKey!) + ) + queryClient.invalidateQueries(['VoteRecord']) } const handleStartUnlock = () => { setIsUnlockModalOpen(true) @@ -97,13 +116,13 @@ const DepositCard = ({ deposit }: { deposit: DepositWithMintAccount }) => { realmPk: realm!.pubkey!, depositIndex: deposit.index, communityMintPk: realm!.account.communityMint, - client, + client: actualClient, }) await getOwnedDeposits({ realmPk: realm!.pubkey, communityMintPk: realm!.account.communityMint, walletPk: wallet!.publicKey!, - client: client!, + client: actualClient!, connection, }) } @@ -113,8 +132,8 @@ const DepositCard = ({ deposit }: { deposit: DepositWithMintAccount }) => { deposit.currentlyLocked.add(deposit.available) ) const type = Object.keys(deposit.lockup.kind)[0] as LockupType - const typeName = type !== 'monthly' ? type : 'Vested' - const isVest = type === 'monthly' + const isVest = type === 'monthly' || type === 'daily' + const typeName = !isVest ? type : 'Vested' const isRealmCommunityMint = deposit.mint.publicKey.toBase58() === realm?.account.communityMint.toBase58() @@ -127,7 +146,10 @@ const DepositCard = ({ deposit }: { deposit: DepositWithMintAccount }) => {
) } - const tokenInfo = tokenService.getTokenInfo(deposit.mint.publicKey.toBase58()) + const tokenInfo = tokenPriceService.getTokenInfo( + deposit.mint.publicKey.toBase58() + ) + return (
@@ -146,10 +168,12 @@ const DepositCard = ({ deposit }: { deposit: DepositWithMintAccount }) => { className="p-4 rounded-lg flex flex-col h-full" style={{ minHeight: '290px' }} > -
+
{ `${getMintDecimalAmount( deposit.mint.account, deposit.vestingRate - ).toFormat(0)} p/mo` + ).toFormat(0)} ${ + typeof deposit.lockup.kind.monthly !== 'undefined' + ? 'p/mo' + : 'p/d' + }` } /> )} {isVest && deposit.nextVestingTimestamp !== null && ( )} {isRealmCommunityMint && ( )} @@ -199,8 +239,11 @@ const DepositCard = ({ deposit }: { deposit: DepositWithMintAccount }) => { label={isConstant ? 'Min. Duration' : 'Time left'} value={ isConstant - ? getMinDurationFmt(deposit) - : getTimeLeftFromNowFmt(deposit) + ? getMinDurationFmt( + deposit.lockup.startTs, + deposit.lockup.endTs + ) + : getTimeLeftFromNowFmt(deposit.lockup.endTs) } /> { - const { - realm, - realmInfo, - mint, - tokenRecords, - councilMint, - config, - } = useRealm() +const LockTokensAccount: React.FC<{ + tokenOwnerRecordPk: PublicKey + children: React.ReactNode +}> = ({ tokenOwnerRecordPk, children }) => { + const realm = useRealmQuery().data?.result + const config = useRealmConfigQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const { realmInfo } = useRealm() const [isLockModalOpen, setIsLockModalOpen] = useState(false) - const client = useVotePluginsClientStore((s) => s.state.vsrClient) + const { vsrClient: client, plugin } = useVsrClient(); + const registrar = plugin?.params as Registrar | undefined; + + const isZeroMultiplierConfig = !registrar?.votingMints.filter( + (x) => !x.maxExtraLockupVoteWeightScaledFactor.isZero() + ).length + const [reducedDeposits, setReducedDeposits] = useState([]) const ownDeposits = useDepositStore((s) => s.state.deposits) const [deposits, setDeposits] = useState([]) - const [votingPower, setVotingPower] = useState(new BN(0)) + const votingPower = useVsrGovpower().data?.result ?? new BN(0) const [votingPowerFromDeposits, setVotingPowerFromDeposits] = useState( new BN(0) ) const [isOwnerOfDeposits, setIsOwnerOfDeposits] = useState(true) - const tokenOwnerRecordWalletPk = Object.keys(tokenRecords)?.find( - (key) => tokenRecords[key]?.pubkey?.toBase58() === tokenOwnerRecordPk + + const { data: tokenOwnerRecord } = useTokenOwnerRecordByPubkeyQuery( + tokenOwnerRecordPk ) + const tokenOwnerRecordWalletPk = + tokenOwnerRecord?.result?.account.governingTokenOwner + const [isLoading, setIsLoading] = useState(false) - const connection = useWalletStore((s) => s.connection.current) - const wallet = useWalletStore((s) => s.current) - const connected = useWalletStore((s) => s.connected) + const { connection } = useConnection() + const wallet = useWalletOnePointOh() + const publicKey = wallet?.publicKey ?? null + const connected = wallet?.connected const mainBoxesClasses = 'bg-bkg-1 col-span-1 p-4 rounded-md' const isNextSameRecord = (x, next) => { const nextType = Object.keys(next.lockup.kind)[0] @@ -77,26 +101,22 @@ const LockTokensAccount = ({ tokenOwnerRecordPk }) => { unlockedTypes.includes(nextType))) ) } - const handleGetDeposits = async () => { + const handleGetDeposits = useCallback(async () => { setIsLoading(true) try { if ( config?.account.communityTokenConfig.voterWeightAddin && - realm!.pubkey && - wallet?.publicKey && + realm?.pubkey && + publicKey && client ) { - const { - deposits, - votingPower, - votingPowerFromDeposits, - } = await getDeposits({ - realmPk: realm!.pubkey, - communityMintPk: realm!.account.communityMint, + const { deposits, votingPowerFromDeposits } = await getDeposits({ + realmPk: realm.pubkey, + communityMintPk: realm.account.communityMint, walletPk: tokenOwnerRecordWalletPk ? new PublicKey(tokenOwnerRecordWalletPk) - : wallet.publicKey, - client: client!, + : publicKey, + client: client, connection: connection, }) const reducedDeposits = deposits.reduce((curr, next) => { @@ -129,12 +149,10 @@ const LockTokensAccount = ({ tokenOwnerRecordPk }) => { return curr }, [] as DepositBox[]) setVotingPowerFromDeposits(votingPowerFromDeposits) - setVotingPower(votingPower) setDeposits(deposits) setReducedDeposits(reducedDeposits) } else if (!wallet?.connected) { setVotingPowerFromDeposits(new BN(0)) - setVotingPower(new BN(0)) setDeposits([]) setReducedDeposits([]) } @@ -146,41 +164,49 @@ const LockTokensAccount = ({ tokenOwnerRecordPk }) => { }) } setIsLoading(false) - } - useEffect(() => { - if ( - JSON.stringify(ownDeposits) !== JSON.stringify(deposits) && - isOwnerOfDeposits - ) { - handleGetDeposits() - } - }, [JSON.stringify(ownDeposits), ownDeposits.length]) + }, [ + client, + config?.account.communityTokenConfig.voterWeightAddin, + connection, + publicKey, + realm?.account.communityMint, + realm?.pubkey, + tokenOwnerRecordWalletPk, + wallet?.connected, + ]) + useEffect(() => { handleGetDeposits() - }, [isOwnerOfDeposits, client]) + }, [ + isOwnerOfDeposits, + client, + handleGetDeposits, + ownDeposits, //side effect + ]) + + const depositMint = + !mint?.supply.isZero() || + config?.account.communityTokenConfig.maxVoterWeightAddin || + realm?.account.communityMint + ? realm?.account.communityMint + : !councilMint?.supply.isZero() + ? realm?.account.config.councilMint + : undefined + 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! - ) - setIsOwnerOfDeposits( - tokenOwnerRecordAddress.toBase58() === tokenOwnerRecordPk - ) - } - if (realm && wallet?.connected) { + if (realm?.owner && realm.pubkey && publicKey !== null && depositMint) { + const getTokenOwnerRecord = async () => { + const tokenOwnerRecordAddress = await getTokenOwnerRecordAddress( + realm.owner, + realm.pubkey, + depositMint, + publicKey + ) + setIsOwnerOfDeposits(tokenOwnerRecordAddress.equals(tokenOwnerRecordPk)) + } getTokenOwnerRecord() } - }, [realm?.pubkey.toBase58(), wallet?.connected, tokenOwnerRecordPk]) + }, [tokenOwnerRecordPk, depositMint, realm, publicKey]) const hasLockedTokens = useMemo(() => { return reducedDeposits.find((d) => d.lockUpKind !== 'none') @@ -204,7 +230,7 @@ const LockTokensAccount = ({ tokenOwnerRecordPk }) => { )?.index ) ) - }, [deposits]) + }, [deposits, realm?.account.communityMint]) return (
@@ -213,15 +239,24 @@ const LockTokensAccount = ({ tokenOwnerRecordPk }) => {
-

- Your Account{' '} - - ({realmInfo?.displayName}) + {realmInfo?.ogImage && ( + + )} +

+ + {realmInfo?.displayName} + My governance power{' '}

- +

@@ -264,10 +299,11 @@ const LockTokensAccount = ({ tokenOwnerRecordPk }) => { x.mint, x.currentAmount ).toNumber() * - tokenService.getUSDTokenPrice(x.mintPk.toBase58()) + tokenPriceService.getUSDTokenPrice(x.mintPk.toBase58()) const tokenName = getMintMetadata(x.mintPk)?.name || - tokenService.getTokenInfo(x.mintPk.toBase58())?.name || + tokenPriceService.getTokenInfo(x.mintPk.toBase58()) + ?.name || abbreviateAddress(x.mintPk) const formatter = Intl.NumberFormat('en', { notation: 'compact', @@ -329,22 +365,25 @@ const LockTokensAccount = ({ tokenOwnerRecordPk }) => { )?.index ) ?.map((x, idx) => ( - + ))} -
- -

- Increase your voting power by

locking your tokens. -

- -
+ {!isZeroMultiplierConfig && ( +
+ +

+ Increase your voting power by

locking your + tokens. +

+ +
+ )}
- ) : ( + ) : !isZeroMultiplierConfig ? (

@@ -357,7 +396,7 @@ const LockTokensAccount = ({ tokenOwnerRecordPk }) => {

- )} + ) : null}
) : (
@@ -371,8 +410,15 @@ const LockTokensAccount = ({ tokenOwnerRecordPk }) => { onClose={() => setIsLockModalOpen(false)} > )} +
+ +
- {connected && } + {connected && children}
) } diff --git a/VoteStakeRegistry/components/Account/LockTokensAccountWithdraw.tsx b/VoteStakeRegistry/components/Account/LockTokensAccountWithdraw.tsx new file mode 100644 index 0000000000..c0a4c58665 --- /dev/null +++ b/VoteStakeRegistry/components/Account/LockTokensAccountWithdraw.tsx @@ -0,0 +1,450 @@ +import Button from '@components/Button' +import useRealm from '@hooks/useRealm' +import { + fmtMintAmount, + getMintDecimalAmountFromNatural, +} from '@tools/sdk/units' +import { useCallback, useEffect, useMemo, useState } from 'react' +import LockTokensModal from './LockTokensModal' +import DepositCard from './DepositCard' +import PreviousRouteBtn from '@components/PreviousRouteBtn' +import VotingPowerBox from '../TokenBalance/VotingPowerBox' +import { PublicKey } from '@solana/web3.js' +import { MintInfo } from '@solana/spl-token' +import { AnchorProvider, BN, Wallet } from '@coral-xyz/anchor' +import tokenPriceService from '@utils/services/tokenPrice' +import { getDeposits } from 'VoteStakeRegistry/tools/deposits' +import { DepositWithMintAccount } from 'VoteStakeRegistry/sdk/accounts' +import { notify } from '@utils/notifications' +import { + getTokenOwnerRecordAddress, + GoverningTokenRole, +} from '@solana/spl-governance' +import InlineNotification from '@components/InlineNotification' +import { + LightningBoltIcon, + LinkIcon, + LockClosedIcon, +} from '@heroicons/react/outline' +import { getMintMetadata } from '@components/instructions/programs/splToken' +import Account from '../../../pages/dao/[symbol]/account/Account' +import { abbreviateAddress } from '@utils/formatting' +import { TokenDeposit } from '@components/TokenBalance/TokenDeposit' +import { VsrClient } from 'VoteStakeRegistry/sdk/client' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { useTokenOwnerRecordByPubkeyQuery } from '@hooks/queries/tokenOwnerRecord' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' +import { useConnection } from '@solana/wallet-adapter-react' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { useVsrGovpower } from '@hooks/queries/plugins/vsr' + +interface DepositBox { + mintPk: PublicKey + mint: MintInfo + currentAmount: BN + lockUpKind: string +} +const unlockedTypes: string[] = [] + +const LockTokensAccount = ({ tokenOwnerRecordPk }) => { + const realm = useRealmQuery().data?.result + const config = useRealmConfigQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const { realmInfo } = useRealm() + const [isLockModalOpen, setIsLockModalOpen] = useState(false) + const [client, setClient] = useState(undefined) + const [reducedDeposits, setReducedDeposits] = useState([]) + const [ownDeposits, setOwnDeposits] = useState([]) + const [deposits, setDeposits] = useState([]) + const votingPower = useVsrGovpower().data?.result ?? new BN(0) + const [votingPowerFromDeposits, setVotingPowerFromDeposits] = useState( + new BN(0) + ) + const [isOwnerOfDeposits, setIsOwnerOfDeposits] = useState(true) + + const lol = useMemo(() => new PublicKey(tokenOwnerRecordPk), [ + tokenOwnerRecordPk, + ]) + const { data: tokenOwnerRecord } = useTokenOwnerRecordByPubkeyQuery(lol) + + const tokenOwnerRecordWalletPk = + tokenOwnerRecord?.result?.account.governingTokenOwner + const [isLoading, setIsLoading] = useState(false) + const { connection } = useConnection() + const connnectionContext = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const mainBoxesClasses = 'bg-bkg-1 col-span-1 p-4 rounded-md' + const isNextSameRecord = (x, next) => { + const nextType = Object.keys(next.lockup.kind)[0] + return ( + x.mintPk.toBase58() === next.mint.publicKey.toBase58() && + ((!unlockedTypes.includes(x.lockUpKind) && + !unlockedTypes.includes(nextType)) || + (unlockedTypes.includes(x.lockUpKind) && + unlockedTypes.includes(nextType))) + ) + } + + const handleSetVsrClient = useCallback( + async (wallet, connection, programId) => { + const options = AnchorProvider.defaultOptions() + const provider = new AnchorProvider( + connection.current, + (wallet as unknown) as Wallet, + options + ) + const vsrClient = await VsrClient.connect( + provider, + programId, + connection.cluster === 'devnet' + ) + const ownDeposits = await getOwnedDeposits({ + realmPk: realm!.pubkey, + communityMintPk: realm!.account.communityMint, + walletPk: new PublicKey(tokenOwnerRecordWalletPk!), + client: vsrClient!, + connection: connection.current, + }) + setClient(vsrClient) + setOwnDeposits(ownDeposits) + }, + [realm, tokenOwnerRecordWalletPk] + ) + + const getOwnedDeposits = async ({ + isUsed = true, + realmPk, + walletPk, + communityMintPk, + client, + connection, + }) => { + const { deposits } = await getDeposits({ + isUsed, + realmPk, + walletPk, + communityMintPk, + client, + connection, + }) + return deposits + } + const handleGetDeposits = useCallback(async () => { + setIsLoading(true) + try { + if (realm!.pubkey && wallet?.publicKey && client) { + const { deposits, votingPowerFromDeposits } = await getDeposits({ + realmPk: realm!.pubkey, + communityMintPk: realm!.account.communityMint, + walletPk: tokenOwnerRecordWalletPk + ? new PublicKey(tokenOwnerRecordWalletPk) + : wallet.publicKey, + client: client!, + connection: connection, + }) + const reducedDeposits = deposits.reduce((curr, next) => { + const nextType = Object.keys(next.lockup.kind)[0] + const isUnlockedType = unlockedTypes.includes(nextType) + const currentValue = curr.find((x) => { + return isNextSameRecord(x, next) + }) + if (typeof currentValue === 'undefined') { + curr.push({ + mintPk: next.mint.publicKey, + mint: next.mint.account, + currentAmount: isUnlockedType + ? next.available + : next.currentlyLocked, + lockUpKind: nextType, + }) + } else { + curr.map((x) => { + if (isNextSameRecord(x, next)) { + x.currentAmount = x.currentAmount.add( + unlockedTypes.includes(x.lockUpKind) + ? next.available + : next.currentlyLocked + ) + } + return x + }) + } + return curr + }, [] as DepositBox[]) + setVotingPowerFromDeposits(votingPowerFromDeposits) + setDeposits(deposits) + setReducedDeposits(reducedDeposits) + } else if (!wallet?.connected) { + setVotingPowerFromDeposits(new BN(0)) + setDeposits([]) + setReducedDeposits([]) + } + } catch (e) { + console.log(e) + notify({ + type: 'error', + message: "Can't fetch deposits", + }) + } + setIsLoading(false) + }, [ + client, + connection, + realm, + tokenOwnerRecordWalletPk, + wallet?.connected, + wallet?.publicKey, + ]) + + const areLoadedDepositsSameAsOwned = + JSON.stringify(ownDeposits) === JSON.stringify(deposits) + useEffect(() => { + if (!areLoadedDepositsSameAsOwned && isOwnerOfDeposits) { + handleGetDeposits() + } + }, [areLoadedDepositsSameAsOwned, isOwnerOfDeposits, handleGetDeposits]) + useEffect(() => { + handleGetDeposits() + }, [isOwnerOfDeposits, client, handleGetDeposits]) + + useEffect(() => { + if ( + wallet?.publicKey?.toBase58() && + connnectionContext && + realm?.pubkey.toBase58() + ) { + handleSetVsrClient( + wallet, + connnectionContext, + new PublicKey('4Q6WW2ouZ6V3iaNm56MTd5n2tnTm4C5fiH8miFHnAFHo') + ) + } + }, [connnectionContext, handleSetVsrClient, realm?.pubkey, wallet]) + + const defaultMintOwnerRecordMint = + !mint?.supply.isZero() || + config?.account.communityTokenConfig.maxVoterWeightAddin + ? realm?.account.communityMint + : !councilMint?.supply.isZero() + ? realm?.account.config.councilMint + : undefined + + useEffect(() => { + const walletPubkey = wallet?.publicKey + if ( + realm?.owner && + walletPubkey && + walletPubkey !== null && + realm.pubkey && + defaultMintOwnerRecordMint + ) { + const getTokenOwnerRecord = async () => { + const tokenOwnerRecordAddress = await getTokenOwnerRecordAddress( + realm.owner, + realm.pubkey, + defaultMintOwnerRecordMint, + walletPubkey + ) + setIsOwnerOfDeposits( + tokenOwnerRecordAddress.toBase58() === tokenOwnerRecordPk + ) + } + getTokenOwnerRecord() + } + }, [ + defaultMintOwnerRecordMint, + realm?.owner, + realm?.pubkey, + tokenOwnerRecordPk, + wallet?.publicKey, + ]) + + const hasLockedTokens = useMemo(() => { + return reducedDeposits.find((d) => d.lockUpKind !== 'none') + }, [reducedDeposits]) + + const lockedTokens = useMemo(() => { + return deposits + }, [deposits]) + + return ( +
+
+
+ +
+
+ {realmInfo?.ogImage && ( + + )} +

+ + {realmInfo?.displayName} + + My governance power{' '} +

+ +
+
+ {!isOwnerOfDeposits && connected && ( +
+ +
+ )} + {connected ? ( +
+
+ {isLoading ? ( + <> +
+
+
+ + ) : ( + <> +
+ {mint && ( + + )} +
+ {reducedDeposits?.map((x, idx) => { + const availableTokens = fmtMintAmount( + x.mint, + x.currentAmount + ) + const price = + getMintDecimalAmountFromNatural( + x.mint, + x.currentAmount + ).toNumber() * + tokenPriceService.getUSDTokenPrice(x.mintPk.toBase58()) + const tokenName = + getMintMetadata(x.mintPk)?.name || + tokenPriceService.getTokenInfo(x.mintPk.toBase58()) + ?.name || + abbreviateAddress(x.mintPk) + const formatter = Intl.NumberFormat('en', { + notation: 'compact', + }) + return ( +
+

+ {`${tokenName} ${ + x.lockUpKind === 'none' ? 'Deposited' : 'Locked' + }`} +

+ + {availableTokens} + {price ? ( + + $ + {formatter.format(price)} + + ) : null} + +
+ ) + })} + {reducedDeposits.length === 0 ? ( +
+

{`${realmInfo?.symbol} Deposited`}

+ 0 +
+ ) : null} + {!hasLockedTokens ? ( +
+

{`${realmInfo?.symbol} Locked`}

+ 0 +
+ ) : null} + + )} +
+

Locked Deposits

+ {lockedTokens?.length > 0 ? ( +
+ {deposits + //we filter out one deposits that is used to store none locked community tokens + ?.map((x, idx) => ( + + ))} +
+ +

+ Increase your voting power by

locking your tokens. +

+ +
+
+ ) : ( +
+ +

+ Increase your voting power by

locking your tokens. +

+ +
+ )} +
+ ) : ( +
+ + Connect your wallet +
+ )} + {isLockModalOpen && ( + setIsLockModalOpen(false)} + > + )} +
+ +
+
+ {connected && } +
+ ) +} + +export default LockTokensAccount diff --git a/VoteStakeRegistry/components/Account/LockTokensModal.tsx b/VoteStakeRegistry/components/Account/LockTokensModal.tsx index fd5ef86b89..7662e523a0 100644 --- a/VoteStakeRegistry/components/Account/LockTokensModal.tsx +++ b/VoteStakeRegistry/components/Account/LockTokensModal.tsx @@ -6,7 +6,7 @@ import Modal from '@components/Modal' import { QuestionMarkCircleIcon } from '@heroicons/react/outline' import useRealm from '@hooks/useRealm' import { getProgramVersionForRealm } from '@models/registry/api' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { RpcContext } from '@solana/spl-governance' import { fmtMintAmount, @@ -15,17 +15,19 @@ import { getMintNaturalAmountFromDecimalAsBN, } from '@tools/sdk/units' import { precision } from '@utils/formatting' -import { useEffect, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' +import { useCallback, useEffect, useMemo, useState } from 'react' import { voteRegistryLockDeposit } from 'VoteStakeRegistry/actions/voteRegistryLockDeposit' -import { DepositWithMintAccount } from 'VoteStakeRegistry/sdk/accounts' +import { DepositWithMintAccount, Registrar } from 'VoteStakeRegistry/sdk/accounts' import { yearsToDays, daysToMonths, getMinDurationInDays, SECS_PER_DAY, getFormattedStringFromDays, -} from 'VoteStakeRegistry/tools/dateTools' + secsToDays, + yearsToSecs, + daysToSecs, +} from '@utils/dateTools' import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' import { voteRegistryStartUnlock } from 'VoteStakeRegistry/actions/voteRegistryStartUnlock' import { @@ -38,13 +40,19 @@ import { vestingPeriods, } from 'VoteStakeRegistry/tools/types' import BigNumber from 'bignumber.js' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' import { calcMintMultiplier } from 'VoteStakeRegistry/tools/deposits' import ButtonGroup from '@components/ButtonGroup' import InlineNotification from '@components/InlineNotification' import Tooltip from '@components/Tooltip' -//import Switch from '@components/Switch' import { notify } from '@utils/notifications' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { useAddressQuery_CommunityTokenOwner } from '@hooks/queries/addresses/tokenOwnerRecord' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' +import { useConnection } from '@solana/wallet-adapter-react' +import { tokenAccountQueryKeys } from '@hooks/queries/tokenAccount' +import queryClient from '@hooks/queries/queryClient' +import {useVsrClient} from "../../../VoterWeightPlugins/useVsrClient"; const YES = 'Yes' const NO = 'No' @@ -59,50 +67,98 @@ const LockTokensModal = ({ depositToUnlock?: DepositWithMintAccount | null }) => { const { getOwnedDeposits } = useDepositStore() - const { mint, realm, realmTokenAccount, realmInfo, tokenRecords } = useRealm() - const client = useVotePluginsClientStore((s) => s.state.vsrClient) - const voteStakeRegistryRegistrar = useVotePluginsClientStore( - (s) => s.state.voteStakeRegistryRegistrar - ) - const connection = useWalletStore((s) => s.connection.current) - const endpoint = useWalletStore((s) => s.connection.endpoint) - const wallet = useWalletStore((s) => s.current) + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const { realmTokenAccount, realmInfo } = useRealm() + const { data: tokenOwnerRecordPk } = useAddressQuery_CommunityTokenOwner() + + const { vsrClient: client, plugin } = useVsrClient(); + const voteStakeRegistryRegistrar = plugin?.params as Registrar | undefined; + const saturationSecs = realm && voteStakeRegistryRegistrar ? + voteStakeRegistryRegistrar.votingMints.find(x => x.mint.equals( + realm.account.communityMint + ))?.lockupSaturationSecs : + undefined + + const { connection } = useConnection() + const endpoint = connection.rpcEndpoint + const wallet = useWalletOnePointOh() const deposits = useDepositStore((s) => s.state.deposits) - const { fetchRealm, fetchWalletTokenAccounts } = useWalletStore( - (s) => s.actions - ) + const fiveYearsSecs = yearsToSecs(5) - const lockupPeriods: Period[] = [ - { - defaultValue: yearsToDays(1), - display: '1y', - }, - { - defaultValue: yearsToDays(2), - display: '2y', - }, - { - defaultValue: yearsToDays(3), - display: '3y', - }, - { - defaultValue: yearsToDays(4), - display: '4y', - }, - { - defaultValue: yearsToDays(5), - display: '5y', - }, - { - defaultValue: 1, - display: 'Custom', - }, - ].filter((x) => - depositToUnlock - ? getMinDurationInDays(depositToUnlock) <= x.defaultValue || - x.display === 'Custom' - : true - ) + const lockupPeriods: Period[] = useMemo(() => { + return [ + { + defaultValue: 30, + display: '30d', + }, + { + defaultValue: 60, + display: '60d', + }, + { + defaultValue: 90, + display: '90d', + }, + { + defaultValue: 120, + display: '120d', + }, + { + defaultValue: 180, + display: '180d', + }, + { + defaultValue: yearsToDays(1), + display: '1y', + }, + { + defaultValue: yearsToDays(2), + display: '2y', + }, + { + defaultValue: yearsToDays(3), + display: '3y', + }, + { + defaultValue: yearsToDays(4), + display: '4y', + }, + { + defaultValue: yearsToDays(5), + display: '5y', + }, + { + defaultValue: depositToUnlock + ? Math.ceil( + secsToDays( + depositToUnlock?.lockup.endTs.toNumber() - + depositToUnlock.lockup.startTs.toNumber() + ) + ) + : 1, + display: 'Custom', + }, + ] + .filter((x) => + depositToUnlock + ? getMinDurationInDays( + depositToUnlock.lockup.startTs, + depositToUnlock.lockup.endTs + ) <= x.defaultValue || x.display === 'Custom' + : true + ) + .filter((x) => { + return x.defaultValue <= secsToDays(fiveYearsSecs) + }) + }, [depositToUnlock, fiveYearsSecs]) + + const lockupLen = lockupPeriods.length + const fixedlockupPeriods = lockupPeriods.slice(0, lockupLen-1) + + const withinPeriod = saturationSecs ? + lockupPeriods.findIndex(p => daysToSecs(p.defaultValue) >= saturationSecs.toNumber()) : + 5 const maxNonCustomDaysLockup = lockupPeriods .map((x) => x.defaultValue) @@ -111,18 +167,18 @@ const LockTokensModal = ({ }) const maxMultiplier = calcMintMultiplier( maxNonCustomDaysLockup * SECS_PER_DAY, - voteStakeRegistryRegistrar, + voteStakeRegistryRegistrar ?? null, realm ) const depositRecord = deposits.find( (x) => - x.mint.publicKey.toBase58() === realm!.account.communityMint.toBase58() && + x.mint.publicKey.toBase58() === realm?.account.communityMint.toBase58() && x.lockup.kind.none ) const [lockupPeriodDays, setLockupPeriodDays] = useState(0) - const [allowClawback, setAllowClawback] = useState(false) - console.log(setAllowClawback) + + const allowClawback = false const [lockupPeriod, setLockupPeriod] = useState(lockupPeriods[0]) const [amount, setAmount] = useState() const [lockMoreThenDeposited, setLockMoreThenDeposited] = useState( @@ -149,6 +205,7 @@ const LockTokensModal = ({ depositToUnlock?.amountInitiallyLockedNative ) : 0 + const maxAmountToLock = depositRecord && mint ? wantToLockMoreThenDeposited @@ -187,8 +244,9 @@ const LockTokensModal = ({ : '' const currentMultiplier = calcMintMultiplier( lockupPeriodDays * SECS_PER_DAY, - voteStakeRegistryRegistrar, - realm + voteStakeRegistryRegistrar ?? null, + realm, + lockupType.value !== 'constant' ) const currentPercentOfMaxMultiplier = (100 * currentMultiplier) / maxMultiplier @@ -199,7 +257,7 @@ const LockTokensModal = ({ const goToStep = (val: number) => { setCurrentStep(val) } - const validateAmountOnBlur = () => { + const validateAmountOnBlur = useCallback(() => { const val = parseFloat( Math.max( Number(mintMinAmount), @@ -207,8 +265,11 @@ const LockTokensModal = ({ ).toFixed(currentPrecision) ) setAmount(val) - } + }, [amount, currentPrecision, maxAmount, mintMinAmount]) + const handleSaveLock = async () => { + if (!tokenOwnerRecordPk) throw new Error() + const rpcContext = new RpcContext( realm!.owner, getProgramVersionForRealm(realmInfo!), @@ -250,8 +311,7 @@ const LockTokensModal = ({ sourceDepositIdx: depositRecord!.index, sourceTokenAccount: realmTokenAccount!.publicKey, allowClawback: allowClawback, - tokenOwnerRecordPk: - tokenRecords[wallet!.publicKey!.toBase58()]?.pubkey || null, + tokenOwnerRecordPk, client: client, }) await getOwnedDeposits({ @@ -261,8 +321,9 @@ const LockTokensModal = ({ client: client!, connection, }) - fetchWalletTokenAccounts() - fetchRealm(realmInfo!.programId, realmInfo!.realmId) + queryClient.invalidateQueries( + tokenAccountQueryKeys.byOwner(connection.rpcEndpoint, wallet!.publicKey!) + ) onClose() } @@ -270,6 +331,7 @@ const LockTokensModal = ({ if (!depositToUnlock) { throw 'No deposit to unlock selected' } + if (!tokenOwnerRecordPk) throw new Error() const rpcContext = new RpcContext( realm!.owner, @@ -300,8 +362,7 @@ const LockTokensModal = ({ lockUpPeriodInDays: lockupPeriodDays, sourceDepositIdx: depositToUnlock!.index, communityMintPk: realm!.account.communityMint, - tokenOwnerRecordPk: - tokenRecords[wallet!.publicKey!.toBase58()]?.pubkey || null, + tokenOwnerRecordPk, client: client, }) await getOwnedDeposits({ @@ -352,14 +413,10 @@ const LockTokensModal = ({ onChange={(type) => setLockupType( //@ts-ignore - lockupTypes - .filter((x) => x.value !== MONTHLY) - .find((t) => t.displayName === type) + lockupTypes.find((t) => t.displayName === type) ) } - values={lockupTypes - .filter((x) => x.value !== MONTHLY) - .map((type) => type.displayName)} + values={lockupTypes.map((type) => type.displayName)} />
@@ -387,11 +444,12 @@ const LockTokensModal = ({
setAmount(e.target.value)} + onChange={(e) => setAmount(e.target.value as any)} step={mintMinAmount} onBlur={validateAmountOnBlur} /> @@ -407,10 +465,19 @@ const LockTokensModal = ({ lockupPeriods.find((p) => p.display === period) ) } - values={lockupPeriods.map((p) => p.display)} + values={ + withinPeriod === -1 ? + [...fixedlockupPeriods.filter((_, i) => i%2 === 0), lockupPeriods[lockupLen-1]] + .map((p) => p.display) : + [ + ...fixedlockupPeriods.slice(Math.floor(withinPeriod/2), Math.floor(withinPeriod/2)+6), + lockupPeriods[lockupLen-1] + ] + .map((p) => p.display) + } />
- {lockupPeriod.defaultValue === 1 && ( + {lockupPeriod.display === 'Custom' && ( <>
Number of days @@ -536,23 +603,27 @@ const LockTokensModal = ({ return 'Unknown step' } } + useEffect(() => { if (amount) { validateAmountOnBlur() } - }, [lockMoreThenDeposited]) + }, [lockMoreThenDeposited, amount, validateAmountOnBlur]) + useEffect(() => { setLockupPeriod(lockupPeriods[0]) - }, [voteStakeRegistryRegistrar]) + }, [voteStakeRegistryRegistrar, lockupPeriods]) + useEffect(() => { if (depositToUnlock) { goToStep(0) } }, [depositToUnlock]) + useEffect(() => { setLockupPeriodDays(lockupPeriod.defaultValue) }, [lockupPeriod.defaultValue]) - // const isMainBtnVisible = !hasMoreTokensInWallet || currentStep !== 0 + const isTitleVisible = currentStep !== 3 const getCurrentBtnForStep = () => { switch (currentStep) { diff --git a/VoteStakeRegistry/components/LockTokenStats/InfoBox.tsx b/VoteStakeRegistry/components/LockTokenStats/InfoBox.tsx index b787eae360..6be5974b20 100644 --- a/VoteStakeRegistry/components/LockTokenStats/InfoBox.tsx +++ b/VoteStakeRegistry/components/LockTokenStats/InfoBox.tsx @@ -1,25 +1,51 @@ import Tooltip from '@components/Tooltip' import { InformationCircleIcon } from '@heroicons/react/outline' -import useRealm from '@hooks/useRealm' +import { fetchJupiterPrice } from '@hooks/queries/jupiterPrice' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' +import { useRealmQuery } from '@hooks/queries/realm' import { getMintDecimalAmount } from '@tools/sdk/units' -import tokenService from '@utils/services/token' +import BN from 'bn.js' +import { useAsync } from 'react-async-hook' -const InfoBox = ({ title, val, tooltip = '', className = '' }) => { - const { mint, realm } = useRealm() +const InfoBox = ({ + title, + val, + tooltip = '', + className = '', +}: { + title: string + val: BN | undefined + tooltip?: string + className?: string +}) => { + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result const formatter = Intl.NumberFormat('en', { notation: 'compact', }) - const fmtAmount = (val) => { + const fmtAmount = (val: BN) => { return mint - ? formatter.format(getMintDecimalAmount(mint!, val).toNumber()) + ? formatter.format(getMintDecimalAmount(mint, val).toNumber()) : '0' } - const price = realm - ? tokenService.getUSDTokenPrice(realm!.account.communityMint.toBase58()) - : 0 - const totalPrice = mint - ? formatter.format(getMintDecimalAmount(mint!, val).toNumber() * price) - : '' + + const { result: price } = useAsync( + async () => + realm + ? await fetchJupiterPrice(realm.account.communityMint).then((x) => + x.found ? x.result.price : 0 + ) + : undefined, + [realm] + ) + + const totalPrice = + val !== undefined && price !== undefined + ? mint + ? formatter.format(getMintDecimalAmount(mint, val).toNumber() * price) + : '' + : '...' + return (
{ )}
- {fmtAmount(val)} - {totalPrice && ( - - {' '} - ≈ ${totalPrice} - - )} + + {val !== undefined ? fmtAmount(val) : '...'} + + ≈ ${totalPrice}
) diff --git a/VoteStakeRegistry/components/LockTokenStats/LockTokenRow.tsx b/VoteStakeRegistry/components/LockTokenStats/LockTokenRow.tsx deleted file mode 100644 index e4c31fb1e1..0000000000 --- a/VoteStakeRegistry/components/LockTokenStats/LockTokenRow.tsx +++ /dev/null @@ -1,80 +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 'VoteStakeRegistry/tools/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 renderAddressName = useMemo(() => { - return ( - - ) - }, [depositWithWallet.wallet.toBase58()]) - const renderAddressImage = useMemo( - () => ( - } - /> - ), - [depositWithWallet.wallet.toBase58()] - ) - 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 ( -
-
- {renderAddressImage} {renderAddressName} -
-
{typeName}
-
- {isConstant - ? getMinDurationFmt(depositWithWallet.deposit as any) - : getTimeLeftFromNowFmt(depositWithWallet.deposit as any)} -
-
{lockedTokens}
-
- ) -} - -export default LockTokenRow diff --git a/VoteStakeRegistry/components/LockTokenStats/tools.tsx b/VoteStakeRegistry/components/LockTokenStats/tools.tsx index daf3e43846..4d17febf24 100644 --- a/VoteStakeRegistry/components/LockTokenStats/tools.tsx +++ b/VoteStakeRegistry/components/LockTokenStats/tools.tsx @@ -1,5 +1,4 @@ -import { BN } from '@project-serum/anchor' -import { bs58 } from '@project-serum/anchor/dist/cjs/utils/bytes' +import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes' import { ProposalTransaction, getGovernanceSchemaForAccount, @@ -19,11 +18,6 @@ export interface DepositWithWallet { wallet: PublicKey deposit: Deposit } -export interface DepoistWithVoter { - amount: BN | undefined - voterPk: PublicKey - startTs: BN | undefined -} //TODO fcn specific to grant instruction => make it generic for all governanceAccounts and move to sdk export const getProposalsTransactions = async ( @@ -37,6 +31,7 @@ export const getProposalsTransactions = async ( headers: { 'Content-Type': 'application/json', }, + // TODO batch alert data: JSON.stringify([ ...pubkeys.map((x) => { return { diff --git a/VoteStakeRegistry/components/TokenBalance/DepositCommunityTokensBtn.tsx b/VoteStakeRegistry/components/TokenBalance/DepositCommunityTokensBtn.tsx index ae410eb1a6..d5faea2244 100644 --- a/VoteStakeRegistry/components/TokenBalance/DepositCommunityTokensBtn.tsx +++ b/VoteStakeRegistry/components/TokenBalance/DepositCommunityTokensBtn.tsx @@ -1,36 +1,41 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import Button from '@components/Button' +import { SecondaryButton } from '@components/Button' import Loading from '@components/Loading' import useRealm from '@hooks/useRealm' import { getProgramVersionForRealm } from '@models/registry/api' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { RpcContext } from '@solana/spl-governance' import { notify } from '@utils/notifications' import { useState } from 'react' -import useWalletStore from 'stores/useWalletStore' import { voteRegistryDepositWithoutLockup } from 'VoteStakeRegistry/actions/voteRegistryDepositWithoutLockup' import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord' +import { useConnection } from '@solana/wallet-adapter-react' +import queryClient from '@hooks/queries/queryClient' +import { tokenAccountQueryKeys } from '@hooks/queries/tokenAccount' +import {useVsrClient} from "../../../VoterWeightPlugins/useVsrClient"; -const DepositCommunityTokensBtn = ({ className = '' }) => { +const DepositCommunityTokensBtn = ({ className = '', inAccountDetails }) => { const { getOwnedDeposits } = useDepositStore() - const { realm, realmInfo, realmTokenAccount, tokenRecords } = useRealm() - const client = useVotePluginsClientStore((s) => s.state.vsrClient) + const realm = useRealmQuery().data?.result + + const { realmInfo, realmTokenAccount } = useRealm() const [isLoading, setIsLoading] = useState(false) - const wallet = useWalletStore((s) => s.current) - const connected = useWalletStore((s) => s.connected) - const connection = useWalletStore((s) => s.connection.current) - const endpoint = useWalletStore((s) => s.connection.endpoint) - const { fetchRealm, fetchWalletTokenAccounts } = useWalletStore( - (s) => s.actions - ) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const { connection } = useConnection() + const endpoint = connection.rpcEndpoint + const currentTokenOwnerRecord = useUserCommunityTokenOwnerRecord().data + ?.result + const {vsrClient} = useVsrClient(); const depositAllTokens = async function () { if (!realm) { throw 'No realm selected' } setIsLoading(true) - const currentTokenOwnerRecord = tokenRecords[wallet!.publicKey!.toBase58()] const tokenOwnerRecordPk = typeof currentTokenOwnerRecord !== 'undefined' ? currentTokenOwnerRecord.pubkey @@ -52,18 +57,22 @@ const DepositCommunityTokensBtn = ({ className = '' }) => { programVersion: realmInfo?.programVersion!, amount: realmTokenAccount!.account.amount, tokenOwnerRecordPk, - client: client, + client: vsrClient, communityMintPk: realm.account.communityMint, }) await getOwnedDeposits({ realmPk: realm!.pubkey, communityMintPk: realm!.account.communityMint, walletPk: wallet!.publicKey!, - client: client!, + client: vsrClient!, connection, }) - await fetchWalletTokenAccounts() - await fetchRealm(realmInfo!.programId, realmInfo!.realmId) + queryClient.invalidateQueries( + tokenAccountQueryKeys.byOwner( + connection.rpcEndpoint, + wallet!.publicKey! + ) + ) } catch (e) { console.log(e) notify({ message: `Something went wrong ${e}`, type: 'error' }) @@ -80,16 +89,16 @@ const DepositCommunityTokensBtn = ({ className = '' }) => { ? "You don't have any governance tokens in your wallet to deposit." : '' - return ( - - ) + + ) : null } export default DepositCommunityTokensBtn diff --git a/VoteStakeRegistry/components/TokenBalance/LockPluginTokenBalanceCard.tsx b/VoteStakeRegistry/components/TokenBalance/LockPluginTokenBalanceCard.tsx index d219991090..4435986393 100644 --- a/VoteStakeRegistry/components/TokenBalance/LockPluginTokenBalanceCard.tsx +++ b/VoteStakeRegistry/components/TokenBalance/LockPluginTokenBalanceCard.tsx @@ -3,7 +3,6 @@ import { PublicKey } from '@solana/web3.js' import BN from 'bn.js' import useRealm from '@hooks/useRealm' import { getTokenOwnerRecordAddress, Proposal } from '@solana/spl-governance' -import useWalletStore from '../../../stores/useWalletStore' import { Option } from '@tools/core/option' import { GoverningTokenRole } from '@solana/spl-governance' import { fmtMintAmount } from '@tools/sdk/units' @@ -17,19 +16,37 @@ import { useEffect, useState } from 'react' import { ChevronRightIcon } from '@heroicons/react/solid' import InlineNotification from '@components/InlineNotification' import Link from 'next/link' -import DelegateTokenBalanceCard from '@components/TokenBalance/DelegateTokenBalanceCard' -import { TokenDeposit } from '@components/TokenBalance/TokenBalanceCard' +import { TokenDeposit } from '@components/TokenBalance/TokenDeposit' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRouter } from 'next/router' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' +import { useVsrGovpower } from '@hooks/queries/plugins/vsr' +/** UNUSED */ const LockPluginTokenBalanceCard = ({ proposal, + inAccountDetails, }: { proposal?: Option + inAccountDetails?: boolean }) => { + const [hasGovPower, setHasGovPower] = useState(false) const { fmtUrlWithCluster } = useQueryContext() - const { councilMint, mint, realm, symbol, config } = useRealm() - const [tokenOwnerRecordPk, setTokenOwneRecordPk] = useState('') - const connected = useWalletStore((s) => s.connected) - const wallet = useWalletStore((s) => s.current) + const realm = useRealmQuery().data?.result + const { symbol } = useRouter().query + const config = useRealmConfigQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const [tokenOwnerRecordPk, setTokenOwnerRecordPk] = useState('') + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const walletPublicKey = wallet?.publicKey + const isDepositVisible = ( depositMint: MintInfo | undefined, realmMint: PublicKey | undefined @@ -49,38 +66,35 @@ const LockPluginTokenBalanceCard = ({ realm?.account.config.councilMint ) + const defaultMint = + !mint?.supply.isZero() || + config?.account.communityTokenConfig.maxVoterWeightAddin + ? realm?.account.communityMint + : !councilMint?.supply.isZero() + ? realm?.account.config.councilMint + : undefined + 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) { + if (realm?.owner && walletPublicKey && defaultMint) { + const getTokenOwnerRecord = async () => { + const tokenOwnerRecordAddress = await getTokenOwnerRecordAddress( + realm.owner, + realm.pubkey, + defaultMint, + walletPublicKey + ) + setTokenOwnerRecordPk(tokenOwnerRecordAddress.toBase58()) + } getTokenOwnerRecord() } - }, [realm?.pubkey.toBase58(), wallet?.connected]) + }, [defaultMint, realm, walletPublicKey]) const hasLoaded = mint || councilMint return ( -
+ <>
-

Your Account

- +

My governance power

+ {hasLoaded ? ( <> + {!hasGovPower && !inAccountDetails && connected && ( +
+ You do not have any governance power in this dao +
+ )} + {!connected && ( +
+ Connect your wallet to see governance power +
+ )} {communityDepositVisible && ( )} {councilDepositVisible && (
)} - ) : ( <> @@ -119,22 +144,29 @@ const LockPluginTokenBalanceCard = ({
)} -
+ ) } const TokenDepositLock = ({ mint, - tokenType, + tokenRole, + inAccountDetails, + setHasGovPower, }: { mint: MintInfo | undefined - tokenType: GoverningTokenRole + tokenRole: GoverningTokenRole councilVote?: boolean + inAccountDetails?: boolean + setHasGovPower: (hasGovPower: boolean) => void }) => { - const { realm, realmTokenAccount, councilTokenAccount } = useRealm() - const connected = useWalletStore((s) => s.connected) + const realm = useRealmQuery().data?.result + + const { realmTokenAccount, councilTokenAccount } = useRealm() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected const deposits = useDepositStore((s) => s.state.deposits) - const votingPower = useDepositStore((s) => s.state.votingPower) + const votingPower = useVsrGovpower().data?.result ?? new BN(0) const votingPowerFromDeposits = useDepositStore( (s) => s.state.votingPowerFromDeposits ) @@ -148,28 +180,24 @@ const TokenDepositLock = ({ const depositRecord = deposits.find( (x) => - x.mint.publicKey.toBase58() === realm!.account.communityMint.toBase58() && + x.mint.publicKey.toBase58() === realm?.account.communityMint.toBase58() && x.lockup.kind.none ) - // Do not show deposits for mints with zero supply because nobody can deposit anyway - if (!mint || mint.supply.isZero()) { - return null - } const depositTokenAccount = - tokenType === GoverningTokenRole.Community + tokenRole === GoverningTokenRole.Community ? realmTokenAccount : councilTokenAccount const depositMint = - tokenType === GoverningTokenRole.Community + tokenRole === GoverningTokenRole.Community ? realm?.account.communityMint : realm?.account.config.councilMint const tokenName = getMintMetadata(depositMint)?.name ?? realm?.account.name const depositTokenName = `${tokenName} ${ - tokenType === GoverningTokenRole.Community ? '' : 'Council' + tokenRole === GoverningTokenRole.Community ? '' : 'Council' }` const hasTokensInWallet = @@ -186,58 +214,73 @@ const TokenDepositLock = ({ ? fmtMintAmount(mint, depositRecord.amountDepositedNative) : '0' - const canShowAvailableTokensMessage = - !hasTokensDeposited && hasTokensInWallet && connected - const canExecuteAction = !hasTokensDeposited ? 'deposit' : 'withdraw' - const canDepositToken = !hasTokensDeposited && hasTokensInWallet + useEffect(() => { + if (availableTokens != '0' || hasTokensDeposited || hasTokensInWallet) { + setHasGovPower(true) + } + }, [availableTokens, hasTokensDeposited, hasTokensInWallet, setHasGovPower]) + + const canShowAvailableTokensMessage = hasTokensInWallet && connected const tokensToShow = - canDepositToken && depositTokenAccount + hasTokensInWallet && depositTokenAccount ? fmtMintAmount(mint, depositTokenAccount.account.amount) - : canDepositToken + : hasTokensInWallet ? availableTokens : 0 + // Do not show deposits for mints with zero supply because nobody can deposit anyway + if (!mint || mint.supply.isZero()) { + return null + } + return ( <> {canShowAvailableTokensMessage ? (
) : null} -
- -
-
-

- {depositTokenName} Deposited - - {availableTokens} - -

-

- {depositTokenName} Locked - {lockTokensFmt} -

-
- {/*

- You have {tokensToShow} tokens available to {canExecuteAction}. -

*/} + {!votingPower.isZero() && ( +
+ +
+ )} + {(availableTokens != '0' || lockTokensFmt != '0') && ( +
+ {availableTokens != '0' && ( +

+ {depositTokenName} Deposited + + {availableTokens} + +

+ )} + {availableTokens != '0' && ( +

+ {depositTokenName} Locked + + {lockTokensFmt} + +

+ )} +
+ )}
- - + + {inAccountDetails && ( + + )}
) diff --git a/VoteStakeRegistry/components/TokenBalance/VSRVotingPower.tsx b/VoteStakeRegistry/components/TokenBalance/VSRVotingPower.tsx new file mode 100644 index 0000000000..05c0be0f3b --- /dev/null +++ b/VoteStakeRegistry/components/TokenBalance/VSRVotingPower.tsx @@ -0,0 +1,147 @@ +import { BigNumber } from 'bignumber.js' +import classNames from 'classnames' + +import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' +import { getMintDecimalAmount } from '@tools/sdk/units' + +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' +import BN from 'bn.js' +import { useVsrGovpowerMulti } from '@hooks/queries/plugins/vsr' +import VotingPowerBox from 'VoteStakeRegistry/components/TokenBalance/VotingPowerBox' +import { getMintMetadata } from '@components/instructions/programs/splToken' +import { useTokenOwnerRecordsDelegatedToUser } from '@hooks/queries/tokenOwnerRecord' +import { useMemo } from 'react' +import { useSelectedDelegatorStore } from 'stores/useSelectedDelegatorStore' + +interface Props { + className?: string, + votingPower: BN | undefined, + votingPowerLoading: boolean + isLastPlugin: boolean +} + +export default function VSRCommunityVotingPower({ className, votingPower, votingPowerLoading, isLastPlugin }: Props) { + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + + const deposits = useDepositStore((s) => s.state.deposits) + + const votingPowerFromDeposits = useDepositStore( + (s) => s.state.votingPowerFromDeposits + ) + const isLoading = useDepositStore((s) => s.state.isLoading) + + const depositRecord = deposits.find( + (deposit) => + deposit.mint.publicKey.toBase58() === + realm?.account.communityMint.toBase58() && deposit.lockup.kind.none + ) + + const depositMint = realm?.account.communityMint + + const tokenName = + getMintMetadata(depositMint)?.name ?? realm?.account.name ?? '' + + const tokenAmount = + depositRecord && mint + ? new BigNumber( + getMintDecimalAmount(mint, depositRecord.amountDepositedNative) + ) + : new BigNumber('0') + + const lockedTokensAmount = mint + ? deposits + .filter( + (x) => + typeof x.lockup.kind['none'] === 'undefined' && + x.mint.publicKey.toBase58() === + realm?.account.communityMint.toBase58() + ) + .reduce( + (curr, next) => + curr.plus(new BigNumber(next.currentlyLocked.toString())), + new BigNumber(0) + ) + .shiftedBy(-mint.decimals) + : new BigNumber('0') + + const { data: delegatedTors } = useTokenOwnerRecordsDelegatedToUser() + const selectedDelegator = useSelectedDelegatorStore( + (s) => s.communityDelegator + ) + // memoize useAsync inputs to prevent constant refetch + const relevantDelegators = useMemo( + () => + selectedDelegator !== undefined // ignore delegators if any delegator is selected + ? [] + : delegatedTors + ?.filter( + (x) => + x.account.governingTokenMint.toString() === + realm?.account.communityMint.toString() + ) + .map((x) => x.account.governingTokenOwner), + [delegatedTors, realm?.account.communityMint, selectedDelegator] + ) + const { data: delegatorPowers } = useVsrGovpowerMulti(relevantDelegators) + const totalDelegatorPower = + delegatorPowers && + mint && + Object.values(delegatorPowers).reduce( + (sum, curr) => sum.add(curr), + new BN(0) + ) + const formattedDelegatorPower = + totalDelegatorPower && + new BigNumber(totalDelegatorPower.toString()).shiftedBy(-mint.decimals) + + //const totalPower = votingPower.add(totalDelegatorPower ?? new BN(0)) + + if (isLoading || mint === undefined || votingPowerLoading) { + return ( +
+ ) + } + + return ( +
+ +
+

+ {tokenName} Deposited + + {tokenAmount.isNaN() ? '0' : tokenAmount.toFormat()} + +

+

+ {tokenName} Locked + + {lockedTokensAmount.isNaN() ? '0' : lockedTokensAmount.toFormat()} + +

+ {formattedDelegatorPower?.gt(new BigNumber(0)) && ( +

+ Votes from delegators + + {formattedDelegatorPower.isNaN() + ? '0' + : formattedDelegatorPower.toFormat()} + +

+ )} +
+
+ ) +} diff --git a/VoteStakeRegistry/components/TokenBalance/VotingPowerBox.tsx b/VoteStakeRegistry/components/TokenBalance/VotingPowerBox.tsx index 4dcea3a375..4a4c38a995 100644 --- a/VoteStakeRegistry/components/TokenBalance/VotingPowerBox.tsx +++ b/VoteStakeRegistry/components/TokenBalance/VotingPowerBox.tsx @@ -1,44 +1,71 @@ -import { BN } from '@project-serum/anchor' +import BigNumber from 'bignumber.js' +import { BN } from '@coral-xyz/anchor' import { MintInfo } from '@solana/spl-token' import { getMintDecimalAmount } from '@tools/sdk/units' import { LightningBoltIcon } from '@heroicons/react/solid' import Tooltip from '@components/Tooltip' +import VotingPowerPct from '@components/ProposalVotingPower/VotingPowerPct' +import clsx from "clsx"; const VotingPowerBox = ({ votingPower, mint, votingPowerFromDeposits, + isLastPlugin = true, className = '', style, }: { votingPower: BN mint: MintInfo votingPowerFromDeposits: BN + isLastPlugin?: boolean className?: string style?: any }) => { - const votingPowerFmt = + const votingPowerBigNum = votingPower && mint - ? getMintDecimalAmount(mint, votingPower).toFormat(0) - : '0' + ? getMintDecimalAmount(mint, votingPower) + : new BigNumber(0) + + const votingPowerFromDepositsBigNum = + votingPowerFromDeposits && mint + ? getMintDecimalAmount(mint, votingPowerFromDeposits) + : new BigNumber(0) + + const max: BigNumber = new BigNumber(mint.supply.toString()) return ( -
-

Votes

- - {votingPowerFmt}{' '} - {!votingPowerFromDeposits.isZero() && !votingPower.isZero() && ( - -
- - {`${( - votingPower.toNumber() / votingPowerFromDeposits.toNumber() - ).toFixed(2)}x`} -
-
- )} -
-
+ <> +
+
+

{ isLastPlugin ? 'Votes' : 'Token Power via Locking'}

+ + {votingPowerBigNum.toFormat(2)}{' '} + {!votingPowerFromDeposits.isZero() && !votingPower.isZero() && ( + +
+ + {`${votingPowerBigNum + .div(votingPowerFromDepositsBigNum) + .toFixed(2)}x`} +
+
+ )} +
+
+
+ {votingPowerBigNum.gt(0) + ? max && + !max.isZero() && ( + + ) + : null} +
+
+ ) } diff --git a/VoteStakeRegistry/components/TokenBalance/WithdrawCommunityTokensBtn.tsx b/VoteStakeRegistry/components/TokenBalance/WithdrawCommunityTokensBtn.tsx index e74d3f0fa2..01112eff22 100644 --- a/VoteStakeRegistry/components/TokenBalance/WithdrawCommunityTokensBtn.tsx +++ b/VoteStakeRegistry/components/TokenBalance/WithdrawCommunityTokensBtn.tsx @@ -1,7 +1,7 @@ -import Button from '@components/Button' +import { SecondaryButton } from '@components/Button' import useRealm from '@hooks/useRealm' import { getUnrelinquishedVoteRecords } from '@models/api' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { getProposal, ProposalState, @@ -11,42 +11,45 @@ import { import { Transaction, TransactionInstruction } from '@solana/web3.js' import { chunks } from '@utils/helpers' import { sendTransaction } from '@utils/send' -import useWalletStore from 'stores/useWalletStore' import { withVoteRegistryWithdraw } from 'VoteStakeRegistry/sdk/withVoteRegistryWithdraw' import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' import { getProgramVersionForRealm } from '@models/registry/api' import { notify } from '@utils/notifications' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' import { useState } from 'react' import Loading from '@components/Loading' -import useNftPluginStore from 'NftVotePlugin/store/nftPluginStore' +import { useMaxVoteRecord } from '@hooks/useMaxVoteRecord' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { fetchGovernanceByPubkey } from '@hooks/queries/governance' +import { useConnection } from '@solana/wallet-adapter-react' +import { proposalQueryKeys } from '@hooks/queries/proposal' +import queryClient from '@hooks/queries/queryClient' +import asFindable from '@utils/queries/asFindable' +import { tokenAccountQueryKeys } from '@hooks/queries/tokenAccount' +import { useVsrClient } from '../../../VoterWeightPlugins/useVsrClient' const WithDrawCommunityTokens = () => { const { getOwnedDeposits } = useDepositStore() - const client = useVotePluginsClientStore((s) => s.state.vsrClient) + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const realm = useRealmQuery().data?.result + const { vsrClient } = useVsrClient() + const { - realm, realmInfo, - ownTokenRecord, - proposals, - governances, - tokenRecords, toManyCommunityOutstandingProposalsForUser, toManyCouncilOutstandingProposalsForUse, } = useRealm() + const [isLoading, setIsLoading] = useState(false) - const wallet = useWalletStore((s) => s.current) - const connected = useWalletStore((s) => s.connected) - const connection = useWalletStore((s) => s.connection.current) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const { connection } = useConnection() const deposits = useDepositStore((s) => s.state.deposits) - const { fetchRealm, fetchWalletTokenAccounts } = useWalletStore( - (s) => s.actions - ) - const maxVoterWeight = - useNftPluginStore((s) => s.state.maxVoteRecord)?.pubkey || undefined + const maxVoterWeight = useMaxVoteRecord()?.pubkey || undefined const depositRecord = deposits.find( (x) => - x.mint.publicKey.toBase58() === realm!.account.communityMint.toBase58() && + x.mint.publicKey.toBase58() === realm?.account.communityMint.toBase58() && x.lockup.kind.none ) const withdrawAllTokens = async function () { @@ -61,18 +64,37 @@ const WithDrawCommunityTokens = () => { ) for (const voteRecord of Object.values(voteRecords)) { - let proposal = proposals[voteRecord.account.proposal.toBase58()] + const proposalQuery = await queryClient.fetchQuery({ + queryKey: proposalQueryKeys.byPubkey( + connection.rpcEndpoint, + voteRecord.account.proposal + ), + staleTime: 0, + queryFn: () => + asFindable(() => + getProposal(connection, voteRecord.account.proposal) + )(), + }) + const proposal = proposalQuery.result + if (!proposal) { continue } if (proposal.account.state === ProposalState.Voting) { // If the Proposal is in Voting state refetch it to make sure we have the latest state to avoid false positives - proposal = await getProposal(connection, proposal.pubkey) if (proposal.account.state === ProposalState.Voting) { - const governance = - governances[proposal.account.governance.toBase58()] - if (proposal.account.getTimeToVoteEnd(governance.account) > 0) { + const governance = ( + await fetchGovernanceByPubkey( + connection, + proposal.account.governance + ) + ).result + if (!governance) throw new Error('failed to fetch governance') + if ( + proposal.account.getTimeToVoteEnd(governance.account) > 0 && + governance.account.realm.equals(realm!.pubkey) + ) { setIsLoading(false) // Note: It's technically possible to withdraw the vote here but I think it would be confusing and people would end up unconsciously withdrawing their votes notify({ @@ -125,11 +147,12 @@ const WithDrawCommunityTokens = () => { realmPk: realm!.pubkey!, amount: depositRecord!.amountDepositedNative, communityMintPk: realm!.account.communityMint, - tokenOwnerRecordPubKey: tokenRecords[wallet!.publicKey!.toBase58()] - .pubkey!, + tokenOwnerRecordPubKey: ownTokenRecord!.pubkey, depositIndex: depositRecord!.index, connection, - client: client, + client: vsrClient, + splProgramId: realm!.owner, + splProgramVersion: realmInfo!.programVersion, }) try { @@ -152,15 +175,19 @@ const WithDrawCommunityTokens = () => { : `Released tokens (${index}/${ixChunks.length - 2})`, }) } - await fetchRealm(realmInfo!.programId, realmInfo!.realmId) - await fetchWalletTokenAccounts() await getOwnedDeposits({ realmPk: realm!.pubkey, communityMintPk: realm!.account.communityMint, walletPk: wallet!.publicKey!, - client: client!, + client: vsrClient!, connection, }) + queryClient.invalidateQueries( + tokenAccountQueryKeys.byOwner( + connection.rpcEndpoint, + wallet!.publicKey! + ) + ) } catch (ex) { console.error( "Can't withdraw tokens, go to my proposals in account view to check outstanding proposals", @@ -180,7 +207,7 @@ const WithDrawCommunityTokens = () => { ? "You don't have any governance tokens to withdraw." : '' return ( - + ) } diff --git a/VoteStakeRegistry/components/instructions/Clawback.tsx b/VoteStakeRegistry/components/instructions/Clawback.tsx index 1c67762f70..dbfd23c180 100644 --- a/VoteStakeRegistry/components/instructions/Clawback.tsx +++ b/VoteStakeRegistry/components/instructions/Clawback.tsx @@ -1,7 +1,11 @@ -import React, { useContext, useEffect, useState } from 'react' -import useRealm from '@hooks/useRealm' -import { TransactionInstruction } from '@solana/web3.js' -import useWalletStore from 'stores/useWalletStore' +import React, { + useCallback, + useContext, + useEffect, + useMemo, + useState, +} from 'react' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' import { tryGetMint } from '@utils/tokens' import { ClawbackForm, @@ -18,7 +22,6 @@ import { NewProposalContext } from 'pages/dao/[symbol]/proposal/new' import GovernedAccountSelect from 'pages/dao/[symbol]/proposal/components/GovernedAccountSelect' import * as yup from 'yup' import { - Deposit, DepositWithMintAccount, getRegistrarPDA, emptyPk, @@ -27,11 +30,14 @@ import { import Select from '@components/inputs/Select' import { tryGetRegistrar } from 'VoteStakeRegistry/sdk/api' import { fmtMintAmount } from '@tools/sdk/units' -import tokenService from '@utils/services/token' +import tokenPriceService from '@utils/services/tokenPrice' import { getClawbackInstruction } from 'VoteStakeRegistry/actions/getClawbackInstruction' import { abbreviateAddress } from '@utils/formatting' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' import { AssetAccount } from '@utils/uiTypes/assets' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import Input from '@components/inputs/Input' +import {useVsrClient} from "VoterWeightPlugins/useVsrClient"; const Clawback = ({ index, @@ -40,21 +46,38 @@ const Clawback = ({ index: number governance: ProgramAccount | null }) => { - const client = useVotePluginsClientStore((s) => s.state.vsrClient) - const connection = useWalletStore((s) => s.connection) - const { realm } = useRealm() + const { vsrClient } = useVsrClient(); + const connection = useLegacyConnectionContext() + const realm = useRealmQuery().data?.result + const { governedTokenAccountsWithoutNfts, governancesArray, } = useGovernanceAssets() - const shouldBeGoverned = index !== 0 && governance const [voters, setVoters] = useState([]) const [deposits, setDeposits] = useState([]) const [form, setForm] = useState({ governedTokenAccount: undefined, voter: null, deposit: null, + holdupTime: 0, }) + const formDeposits = form.deposit + const schema = useMemo( + () => + yup.object().shape({ + governedTokenAccount: yup + .object() + .required('Clawback destination required'), + voter: yup.object().nullable().required('Voter required'), + deposit: yup.object().nullable().required('Deposit required'), + }), + [] + ) + + const realmAuthorityGov = governancesArray.find( + (x) => x.pubkey.toBase58() === realm?.account.authority?.toBase58() + ) const [governedAccount, setGovernedAccount] = useState< ProgramAccount | undefined >(undefined) @@ -64,7 +87,7 @@ const Clawback = ({ setFormErrors({}) setForm({ ...form, [propertyName]: value }) } - async function getInstruction(): Promise { + const getInstruction = useCallback(async () => { const isValid = await validateInstruction({ schema, form, setFormErrors }) let serializedInstruction = '' const prerequisiteInstructions: TransactionInstruction[] = [] @@ -87,7 +110,7 @@ const Clawback = ({ voterDepositIndex: form.deposit.index, grantMintPk: form.deposit.mint.publicKey, realmCommunityMintPk: realm!.account.communityMint, - client, + client: vsrClient, }) serializedInstruction = serializeInstructionToBase64(clawbackIx!) } @@ -95,35 +118,35 @@ const Clawback = ({ const obj: UiInstruction = { serializedInstruction, isValid, - governance: governancesArray.find( - (x) => x.pubkey.toBase58() === realm?.account.authority?.toBase58() - ), + governance: realmAuthorityGov, prerequisiteInstructions: prerequisiteInstructions, - chunkSplitByDefault: true, + customHoldUpTime: form.holdupTime, } return obj - } + }, [vsrClient, form, realmAuthorityGov, realm, schema]) + useEffect(() => { handleSetInstructions( { governedAccount: governedAccount, getInstruction }, index ) - }, [form]) + }, [form, getInstruction, governedAccount, handleSetInstructions, index]) + useEffect(() => { setGovernedAccount( - governancesArray.find( + governancesArray?.find( (x) => x.pubkey.toBase58() === realm?.account.authority?.toBase58() ) ) - }, [form.governedTokenAccount]) + }, [form.governedTokenAccount, governancesArray, realm?.account.authority]) useEffect(() => { const getVoters = async () => { - const { registrar } = await getRegistrarPDA( - realm!.pubkey, - realm!.account.communityMint, - client!.program.programId + const { registrar } = getRegistrarPDA( + realm!.pubkey, + realm!.account.communityMint, + vsrClient!.program.programId ) - const resp = await client?.program.account.voter.all([ + const resp = await vsrClient?.program.account.voter.all([ { memcmp: { offset: 40, @@ -135,26 +158,27 @@ const Clawback = ({ resp ?.filter( (x) => - (x.account.deposits as Deposit[]).filter( + (x.account.deposits).filter( (depo) => depo.allowClawback ).length ) - .map((x) => x.account as Voter) || [] + // The cast works around an anchor issue with interpreting enums + .map((x) => x.account as unknown as Voter) || [] setVoters([...voters]) } - if (client) { + if (vsrClient) { getVoters() } - }, [client]) + }, [vsrClient, realm]) useEffect(() => { const getOwnedDepositsInfo = async () => { - const { registrar } = await getRegistrarPDA( - realm!.pubkey, - realm!.account.communityMint, - client!.program.programId + const { registrar } = getRegistrarPDA( + realm!.pubkey, + realm!.account.communityMint, + vsrClient!.program.programId ) - const existingRegistrar = await tryGetRegistrar(registrar, client!) + const existingRegistrar = await tryGetRegistrar(registrar, vsrClient!) const mintCfgs = existingRegistrar?.votingMints const mints = {} if (mintCfgs) { @@ -181,23 +205,22 @@ const Clawback = ({ } else { setDeposits([]) } - setForm({ ...form, deposit: null, governedTokenAccount: undefined }) - }, [form.voter]) + + setForm((prevForm) => ({ + ...prevForm, + deposit: null, + governedTokenAccount: undefined, + })) + }, [vsrClient, connection, form.voter, realm]) + useEffect(() => { - setForm({ ...form, governedTokenAccount: undefined }) - }, [form.deposit]) - const schema = yup.object().shape({ - governedTokenAccount: yup - .object() - .required('Clawback destination required'), - voter: yup.object().nullable().required('Voter required'), - deposit: yup.object().nullable().required('Deposit required'), - }) + setForm((prevForm) => ({ ...prevForm, governedTokenAccount: undefined })) + }, [formDeposits]) const getOwnedDepositsLabel = (deposit: DepositWithMintAccount | null) => { const symbol = deposit - ? tokenService.getTokenInfo(deposit.mint.publicKey.toBase58())?.symbol || - '' + ? tokenPriceService.getTokenInfo(deposit.mint.publicKey.toBase58()) + ?.symbol || '' : null return deposit ? `${fmtMintAmount( @@ -208,6 +231,23 @@ const Clawback = ({ } return ( <> +

+ Use only with realm authority governance cant be executed with other + governances +

+

governance: {realmAuthorityGov?.pubkey.toBase58()}

+

+ wallet:{' '} + {realmAuthorityGov + ? PublicKey.findProgramAddressSync( + [ + Buffer.from('native-treasury'), + realmAuthorityGov!.pubkey.toBuffer(), + ], + realm!.owner + )[0].toBase58() + : null} +

+ + handleSetForm({ + value: evt.target.value, + propertyName: 'holdupTime', + }) + } + > ) } diff --git a/VoteStakeRegistry/components/instructions/Grant.tsx b/VoteStakeRegistry/components/instructions/Grant.tsx index 869c44e518..77074b7a04 100644 --- a/VoteStakeRegistry/components/instructions/Grant.tsx +++ b/VoteStakeRegistry/components/instructions/Grant.tsx @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import React, { useContext, useEffect, useState } from 'react' +import { useCallback, useContext, useEffect, useMemo, useState } from 'react' import Input from '@components/inputs/Input' import useRealm from '@hooks/useRealm' import { AccountInfo } from '@solana/spl-token' @@ -10,7 +10,6 @@ import { import { PublicKey, TransactionInstruction } from '@solana/web3.js' import { precision } from '@utils/formatting' import { tryParseKey } from '@tools/validators/pubkey' -import useWalletStore from 'stores/useWalletStore' import { TokenProgramAccount, tryGetTokenAccount } from '@utils/tokens' import { GrantForm, UiInstruction } from '@utils/uiTypes/proposalCreationTypes' import { getAccountName } from '@components/instructions/tools' @@ -19,6 +18,8 @@ import { getTokenTransferSchema } from '@utils/validations' import useGovernanceAssets from '@hooks/useGovernanceAssets' import { Governance, + getTokenOwnerRecord, + getTokenOwnerRecordAddress, serializeInstructionToBase64, withCreateTokenOwnerRecord, } from '@solana/spl-governance' @@ -29,14 +30,20 @@ import GovernedAccountSelect from 'pages/dao/[symbol]/proposal/components/Govern import { lockupTypes } from 'VoteStakeRegistry/tools/types' import Select from '@components/inputs/Select' import Switch from '@components/Switch' -import { getFormattedStringFromDays } from 'VoteStakeRegistry/tools/dateTools' +import { getFormattedStringFromDays } from '@utils/dateTools' import * as yup from 'yup' import { getGrantInstruction } from 'VoteStakeRegistry/actions/getGrantInstruction' import { getRegistrarPDA } from 'VoteStakeRegistry/sdk/accounts' import { tryGetRegistrar } from 'VoteStakeRegistry/sdk/api' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' import dayjs from 'dayjs' import { AssetAccount } from '@utils/uiTypes/assets' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import queryClient from '@hooks/queries/queryClient' +import asFindable from '@utils/queries/asFindable' +import { tokenOwnerRecordQueryKeys } from '@hooks/queries/tokenOwnerRecord' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import {useVsrClient} from "../../../VoterWeightPlugins/useVsrClient"; const Grant = ({ index, @@ -45,13 +52,15 @@ const Grant = ({ index: number governance: ProgramAccount | null }) => { - const client = useVotePluginsClientStore((s) => s.state.vsrClient) + const { vsrClient } = useVsrClient(); const dateNow = dayjs().unix() - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const { realm, tokenRecords, realmInfo } = useRealm() + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const realm = useRealmQuery().data?.result + + const { realmInfo } = useRealm() const { governedTokenAccountsWithoutNfts } = useGovernanceAssets() - const shouldBeGoverned = index !== 0 && governance + const shouldBeGoverned = !!(index !== 0 && governance) const [startDate, setStartDate] = useState(dayjs().format('DD-MM-YYYY')) const [endDate, setEndDate] = useState('') const [useableGrantMints, setUseableGrantMints] = useState([]) @@ -66,6 +75,23 @@ const Grant = ({ allowClawback: true, lockupKind: lockupTypes[0], }) + const schema = useMemo( + () => + getTokenTransferSchema({ form, connection, ignoreAmount: true }).concat( + yup.object().shape({ + startDateUnixSeconds: yup + .number() + .required('Start date required') + .min(1, 'Start date required'), + periods: yup + .number() + .required('End date required') + .min(1, 'End date cannot be prior to start date'), + }) + ), + [form, connection] + ) + const [governedAccount, setGovernedAccount] = useState< ProgramAccount | undefined >(undefined) @@ -79,13 +105,16 @@ const Grant = ({ : 1 const currentPrecision = precision(mintMinAmount) const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { setFormErrors({}) - setForm({ ...form, [propertyName]: value }) + setForm((prevForm) => ({ ...prevForm, [propertyName]: value })) } + const setMintInfo = (value) => { - setForm({ ...form, mintInfo: value }) + setForm((prevForm) => ({ ...prevForm, mintInfo: value })) } + const setAmount = (event) => { const value = event.target.value handleSetForm({ @@ -106,7 +135,9 @@ const Grant = ({ propertyName: 'amount', }) } - async function getInstruction(): Promise { + const getInstruction = useCallback(async () => { + if (!realm) throw new Error() + const isValid = await validateInstruction({ schema, form, setFormErrors }) let serializedInstruction = '' const prerequisiteInstructions: TransactionInstruction[] = [] @@ -123,8 +154,26 @@ const Grant = ({ form.amount!, form.governedTokenAccount.extensions.mint.account.decimals ) - const currentTokenOwnerRecord = tokenRecords[form.destinationAccount] - if (!currentTokenOwnerRecord) { + + const destinationTokenOwnerRecordPk = await getTokenOwnerRecordAddress( + realm.owner, + realm.pubkey, + realm.account.communityMint, + destinationAccount + ) + const currentTokenOwnerRecord = await queryClient.fetchQuery({ + queryKey: tokenOwnerRecordQueryKeys.byPubkey( + connection.cluster, + destinationTokenOwnerRecordPk + ), + queryFn: () => + asFindable(getTokenOwnerRecord)( + connection.current, + destinationTokenOwnerRecordPk + ), + }) + + if (!currentTokenOwnerRecord.found) { await withCreateTokenOwnerRecord( prerequisiteInstructions, realm!.owner, @@ -149,7 +198,7 @@ const Grant = ({ startTime: form.startDateUnixSeconds, lockupKind: form.lockupKind.value, allowClawback: form.allowClawback, - client: client!, + client: vsrClient!, }) serializedInstruction = serializeInstructionToBase64(grantIx!) } @@ -159,10 +208,19 @@ const Grant = ({ isValid, governance: form.governedTokenAccount?.governance, prerequisiteInstructions: prerequisiteInstructions, - chunkSplitByDefault: true, + chunkBy: 1, } return obj - } + }, [ + vsrClient, + connection, + form, + realm, + realmInfo?.programVersion, + schema, + wallet, + ]) + const handleChangeStartDate = (e) => { const value = e.target.value setStartDate(value) @@ -194,6 +252,7 @@ const Grant = ({ }) } }, [startDate, endDate, form.lockupKind.value]) + useEffect(() => { if (form.destinationAccount) { debounce.debounceFcn(async () => { @@ -208,51 +267,46 @@ const Grant = ({ } else { setDestinationAccount(null) } - }, [form.destinationAccount]) + }, [form.destinationAccount, connection]) + useEffect(() => { handleSetInstructions( { governedAccount: governedAccount, getInstruction }, index ) - }, [form]) + }, [form, governedAccount, handleSetInstructions, index, getInstruction]) + useEffect(() => { setGovernedAccount(form.governedTokenAccount?.governance) setMintInfo(form.governedTokenAccount?.extensions.mint?.account) }, [form.governedTokenAccount]) + const destinationAccountName = destinationAccount?.publicKey && getAccountName(destinationAccount?.account.address) - const schema = getTokenTransferSchema({ form, connection }).concat( - yup.object().shape({ - startDateUnixSeconds: yup - .number() - .required('Start date required') - .min(1, 'Start date required'), - periods: yup - .number() - .required('End date required') - .min(1, 'End date cannot be prior to start date'), - }) - ) + useEffect(() => { const getGrantMints = async () => { - const clientProgramId = client!.program.programId - const { registrar } = await getRegistrarPDA( - realm!.pubkey, - realm!.account.communityMint, - clientProgramId + const clientProgramId = vsrClient!.program.programId + const { registrar } = getRegistrarPDA( + realm!.pubkey, + realm!.account.communityMint, + clientProgramId ) - const existingRegistrar = await tryGetRegistrar(registrar, client!) + const existingRegistrar = await tryGetRegistrar(registrar, vsrClient!) if (existingRegistrar) { setUseableGrantMints( existingRegistrar.votingMints.map((x) => x.mint.toBase58()) ) } } - if (client) { + if (vsrClient) { getGrantMints() } - }, [client]) + }, [vsrClient, realm]) + + const isNotVested = + form.lockupKind.value !== 'monthly' && form.lockupKind.value !== 'daily' return ( <> - ) : ( + )} + {form.lockupKind.value === 'monthly' && ( )} + {form.lockupKind.value === 'daily' && ( + { + handleSetForm({ + value: e.target.value, + propertyName: 'periods', + }) + }} + error={formErrors['periods']} + > + )} {form.periods !== 0 && (
Period
@@ -385,6 +456,13 @@ const Grant = ({ !isNaN(form.periods) && (
Vesting rate: {(form.amount / form.periods).toFixed(2)} p/m
)} + + {form.lockupKind.value === 'daily' && + form.amount && + !isNaN(form.amount) && + !isNaN(form.periods) && ( +
Vesting rate: {(form.amount / form.periods).toFixed(2)} p/d
+ )} ) } diff --git a/VoteStakeRegistry/sdk/accounts.tsx b/VoteStakeRegistry/sdk/accounts.tsx index a935073265..5306185fd5 100644 --- a/VoteStakeRegistry/sdk/accounts.tsx +++ b/VoteStakeRegistry/sdk/accounts.tsx @@ -1,4 +1,4 @@ -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { MintInfo } from '@solana/spl-token' import { PublicKey } from '@solana/web3.js' import { TokenProgramAccount } from '@utils/tokens' @@ -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 @@ -19,13 +19,13 @@ export interface votingMint { mint: PublicKey } -export type LockupType = 'none' | 'monthly' | 'cliff' | 'constant' | 'daily' //there is also daily type but not used on ui yet +export type LockupType = 'none' | 'monthly' | 'cliff' | 'constant' | 'daily' export interface Registrar { governanceProgramId: PublicKey realm: PublicKey realmAuthority: PublicKey realmGoverningTokenMint: PublicKey - votingMints: votingMint[] + votingMints: VotingMint[] //there are more fields but no use for them on ui yet } interface LockupKind { @@ -35,11 +35,13 @@ interface LockupKind { cliff: object constant: object } + interface Lockup { endTs: BN kind: LockupKind startTs: BN } + export interface Deposit { allowClawback: boolean amountDepositedNative: BN @@ -61,12 +63,12 @@ export interface DepositWithMintAccount extends Deposit { export const emptyPk = '11111111111111111111111111111111' -export const getRegistrarPDA = async ( +export const getRegistrarPDA = ( realmPk: PublicKey, mint: PublicKey, clientProgramId: PublicKey ) => { - const [registrar, registrarBump] = await PublicKey.findProgramAddress( + const [registrar, registrarBump] = PublicKey.findProgramAddressSync( [realmPk.toBuffer(), Buffer.from('registrar'), mint.toBuffer()], clientProgramId ) @@ -76,12 +78,12 @@ export const getRegistrarPDA = async ( } } -export const getVoterPDA = async ( +export const getVoterPDA = ( registrar: PublicKey, walletPk: PublicKey, clientProgramId: PublicKey ) => { - const [voter, voterBump] = await PublicKey.findProgramAddress( + const [voter, voterBump] = PublicKey.findProgramAddressSync( [registrar.toBuffer(), Buffer.from('voter'), walletPk.toBuffer()], clientProgramId ) @@ -92,12 +94,12 @@ export const getVoterPDA = async ( } } -export const getVoterWeightPDA = async ( +export const getVoterWeightPDA = ( registrar: PublicKey, walletPk: PublicKey, clientProgramId: PublicKey ) => { - const [voterWeightPk, voterWeightBump] = await PublicKey.findProgramAddress( + const [voterWeightPk, voterWeightBump] = PublicKey.findProgramAddressSync( [ registrar.toBuffer(), Buffer.from('voter-weight-record'), diff --git a/VoteStakeRegistry/sdk/api.ts b/VoteStakeRegistry/sdk/api.ts index f54c0cf7d3..7d265f8fa9 100644 --- a/VoteStakeRegistry/sdk/api.ts +++ b/VoteStakeRegistry/sdk/api.ts @@ -1,19 +1,25 @@ -import { NftVoterClient } from '@solana/governance-program-library' +import { NftVoterClient } from '@utils/uiTypes/NftVoterClient' import { PublicKey } from '@solana/web3.js' +import { HeliumVsrClient } from 'HeliumVotePlugin/sdk/client' import { Registrar, Voter } from './accounts' import { VsrClient } from './client' -export const tryGetVoter = async (voterPk: PublicKey, client: VsrClient) => { +export const tryGetVoter = async ( + voterPk: PublicKey, + client: Pick +) => { try { const voter = await client?.program.account.voter.fetch(voterPk) - return voter as Voter + // The cast to any works around an anchor issue with interpreting enums + return voter as unknown as Voter } catch (e) { return null } } + export const tryGetRegistrar = async ( registrarPk: PublicKey, - client: VsrClient + client: Pick ) => { try { const existingRegistrar = await client.program.account.registrar.fetch( @@ -25,6 +31,21 @@ export const tryGetRegistrar = async ( } } +export const tryGetHeliumRegistrar = async ( + registrarPk: PublicKey, + client: HeliumVsrClient +) => { + try { + const existingRegistrar = await client.program.account.registrar.fetch( + registrarPk + ) + + return existingRegistrar + } catch (e) { + return null + } +} + export const tryGetNftRegistrar = async ( registrarPk: PublicKey, client: NftVoterClient diff --git a/VoteStakeRegistry/sdk/client.ts b/VoteStakeRegistry/sdk/client.ts index 20f8aa96b9..016627cdf9 100644 --- a/VoteStakeRegistry/sdk/client.ts +++ b/VoteStakeRegistry/sdk/client.ts @@ -1,29 +1,159 @@ -import { Program, Provider, web3 } from '@project-serum/anchor' +import { Program, Provider, web3} from '@coral-xyz/anchor' import { IDL, VoterStakeRegistry } from './voter_stake_registry' +import {Client} from "@solana/governance-program-library"; +import {PublicKey, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RENT_PUBKEY, TransactionInstruction} from "@solana/web3.js"; +import {getVoterPDA} from "./accounts"; +import {SYSTEM_PROGRAM_ID} from "@solana/spl-governance"; +import BN from "bn.js"; +import {fetchVotingPower} from "@hooks/queries/plugins/vsr"; export const DEFAULT_VSR_ID = new web3.PublicKey( - '4Q6WW2ouZ6V3iaNm56MTd5n2tnTm4C5fiH8miFHnAFHo' + 'vsr2nfGVNHmSY8uxoBGqq8AQbwz3JwaEaHqGbsTPXqQ' ) -export class VsrClient { - constructor( - public program: Program, - public devnet?: boolean - ) {} +export class VsrClient extends Client { + readonly requiresInputVoterWeight = false; - static connect( + getRegistrarPDA(realm: PublicKey, mint: PublicKey) { + const [registrar, registrarBump] = PublicKey.findProgramAddressSync( + [realm.toBuffer(), Buffer.from('registrar'), mint.toBuffer()], + this.program.programId + ) + return { + registrar, + registrarBump, + } + } + + async getVoterWeightRecordPDA(realm: PublicKey, mint: PublicKey, walletPk: PublicKey) { + const {registrar} = this.getRegistrarPDA(realm, mint); + + const [voterWeightPk, voterWeightRecordBump] = PublicKey.findProgramAddressSync( + [ + registrar.toBuffer(), + Buffer.from('voter-weight-record'), + walletPk.toBuffer(), + ], + this.program.programId + ) + + return { + voterWeightPk, + voterWeightRecordBump, + } + } + + + /** + * Creates a voter weight record account and voter account for this VSR realm and user. + * Although the program creates both, this function keeps the 'createVoterWeightRecord' name to align with + * other plugins. The client code should not need to know the difference. + * @param voter + * @param realm + * @param mint + */ + async createVoterWeightRecord(voter: PublicKey, realm: PublicKey, mint: PublicKey): Promise { + const {registrar} = this.getRegistrarPDA(realm, mint); + const { voter: voterPDA, voterBump } = getVoterPDA( + registrar, + voter, + this.program.programId + ) + const { voterWeightPk, voterWeightRecordBump } = await this.getVoterWeightRecordPDA( + realm, + mint, + voter + ) + return this.program.methods + .createVoter(voterBump, voterWeightRecordBump) + .accounts({ + registrar: registrar, + voter: voterPDA, + voterAuthority: voter, + voterWeightRecord: voterWeightPk, + payer: voter, + systemProgram: SYSTEM_PROGRAM_ID, + rent: SYSVAR_RENT_PUBKEY, + instructions: SYSVAR_INSTRUCTIONS_PUBKEY, + }) + .instruction() + } + + async getVoterWeightRecord(realm: PublicKey, mint: PublicKey, voter: PublicKey) { + const {registrar} = this.getRegistrarPDA(realm, mint); + // This is a workaround for the fact that the VSR program IDL does not include the voterWeightRecord account + const votingPower = await fetchVotingPower( + this.program.provider.connection, + this.program.programId, + registrar, + voter + ) + + const power = votingPower.result ?? new BN(0); + + return { voterWeight: power }; + } + + // NO-OP + async createMaxVoterWeightRecord(): Promise { + return null; + } + + async updateVoterWeightRecord(voter: PublicKey, realm: PublicKey, mint: PublicKey) { + const pluginProgramId = this.program.programId; + const { registrar } = this.getRegistrarPDA(realm, mint) + const { voter: voterPDA } = getVoterPDA(registrar, voter, pluginProgramId) + const { voterWeightPk } = await this.getVoterWeightRecordPDA(realm, mint, voter); + const ix = await this.program.methods.updateVoterWeightRecord() + .accounts({ + registrar, + voter: voterPDA, + voterWeightRecord: voterWeightPk, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .instruction() + + return { pre: [ix] } + } + // NO-OP + async updateMaxVoterWeightRecord(): Promise { + return null; + } + async calculateVoterWeight(voter: PublicKey, realm: PublicKey, mint: PublicKey): Promise { + // TODO should use vsr govpower multi? see useVsrGovpowerMulti + const { registrar: registrarPk} = this.getRegistrarPDA(realm, mint) + const programId = this.program.programId; + if (registrarPk === undefined || programId === undefined) { + return null + } + + const { voter: voterPk } = getVoterPDA(registrarPk, voter, programId) + const votingPower = await fetchVotingPower( + this.program.provider.connection, + programId, + registrarPk, + voterPk + ) + + return votingPower.result ?? new BN(0); + } + constructor(program: Program, devnet:boolean) { + super(program, devnet); + } + + static async connect( provider: Provider, - programId?: web3.PublicKey, - devnet?: boolean - ): VsrClient { + programId: web3.PublicKey = DEFAULT_VSR_ID, + devnet = false + ): Promise { const idl = IDL return new VsrClient( new Program( - idl, - programId || DEFAULT_VSR_ID, + idl as VoterStakeRegistry, + programId, provider - ), + ) as Program, devnet ) } diff --git a/VoteStakeRegistry/sdk/withCreateNewDeposit.ts b/VoteStakeRegistry/sdk/withCreateNewDeposit.ts index ce7935fcec..e9f89d368d 100644 --- a/VoteStakeRegistry/sdk/withCreateNewDeposit.ts +++ b/VoteStakeRegistry/sdk/withCreateNewDeposit.ts @@ -1,7 +1,6 @@ import { PublicKey, SystemProgram, - SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RENT_PUBKEY, TransactionInstruction, } from '@solana/web3.js' @@ -55,17 +54,17 @@ export const withCreateNewDeposit = async ({ const clientProgramId = client!.program.programId let tokenOwnerRecordPubKey = tokenOwnerRecordPk - const { registrar } = await getRegistrarPDA( + const { registrar } = getRegistrarPDA( realmPk, communityMintPk, clientProgramId ) - const { voter, voterBump } = await getVoterPDA( + const { voter } = getVoterPDA( registrar, walletPk, clientProgramId ) - const { voterWeightPk, voterWeightBump } = await getVoterWeightPDA( + const { voterWeightPk } = getVoterWeightPDA( registrar, walletPk, clientProgramId @@ -88,24 +87,13 @@ export const withCreateNewDeposit = async ({ programVersion, realmPk, walletPk, - mintPk, + communityMintPk, walletPk ) } + if (!existingVoter) { - const createVoterIx = await client?.program.methods - .createVoter(voterBump, voterWeightBump) - .accounts({ - registrar: registrar, - voter: voter, - voterAuthority: walletPk, - voterWeightRecord: voterWeightPk, - payer: walletPk, - systemProgram: systemProgram, - rent: SYSVAR_RENT_PUBKEY, - instructions: SYSVAR_INSTRUCTIONS_PUBKEY, - }) - .instruction() + const createVoterIx = await client?.createVoterWeightRecord(walletPk, realmPk, communityMintPk) instructions.push(createVoterIx) } const mintCfgIdx = await getMintCfgIdx(registrar, mintPk, client) @@ -138,7 +126,7 @@ export const withCreateNewDeposit = async ({ const createDepositEntryInstruction = await client?.program.methods .createDepositEntry( firstFreeIdx, - { [lockupKind]: {} }, + { [lockupKind]: {} } as any, // The cast to any works around an anchor issue with interpreting enums //lockup starts now null, period, diff --git a/VoteStakeRegistry/sdk/withVoteRegistryDeposit.ts b/VoteStakeRegistry/sdk/withVoteRegistryDeposit.ts index 9a11687eea..e9d3be22d6 100644 --- a/VoteStakeRegistry/sdk/withVoteRegistryDeposit.ts +++ b/VoteStakeRegistry/sdk/withVoteRegistryDeposit.ts @@ -1,6 +1,6 @@ import { PublicKey, TransactionInstruction } from '@solana/web3.js' import { TOKEN_PROGRAM_ID } from '@solana/spl-token' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { LockupType } from 'VoteStakeRegistry/sdk/accounts' import { withCreateNewDeposit } from './withCreateNewDeposit' import { VsrClient } from './client' diff --git a/VoteStakeRegistry/sdk/withVoteRegistryWithdraw.ts b/VoteStakeRegistry/sdk/withVoteRegistryWithdraw.ts index b3f555f7c4..58b074c7fb 100644 --- a/VoteStakeRegistry/sdk/withVoteRegistryWithdraw.ts +++ b/VoteStakeRegistry/sdk/withVoteRegistryWithdraw.ts @@ -4,7 +4,7 @@ import { Token, TOKEN_PROGRAM_ID, } from '@solana/spl-token' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { getRegistrarPDA, getVoterPDA, @@ -12,6 +12,7 @@ import { } from 'VoteStakeRegistry/sdk/accounts' import { tryGetTokenAccount } from '@utils/tokens' import { VsrClient } from './client' +import { withCreateTokenOwnerRecord } from '@solana/spl-governance' export const withVoteRegistryWithdraw = async ({ instructions, @@ -23,6 +24,8 @@ export const withVoteRegistryWithdraw = async ({ depositIndex, communityMintPk, closeDepositAfterOperation, + splProgramId, + splProgramVersion, client, connection, }: { @@ -32,9 +35,11 @@ export const withVoteRegistryWithdraw = async ({ realmPk: PublicKey communityMintPk: PublicKey amount: BN - tokenOwnerRecordPubKey: PublicKey + tokenOwnerRecordPubKey: PublicKey | undefined depositIndex: number connection: Connection + splProgramId: PublicKey + splProgramVersion: number //if we want to close deposit after doing operation we need to fill this because we can close only deposits that have 0 tokens inside closeDepositAfterOperation?: boolean client?: VsrClient @@ -44,13 +49,13 @@ export const withVoteRegistryWithdraw = async ({ } const clientProgramId = client!.program.programId - const { registrar } = await getRegistrarPDA( + const { registrar } = getRegistrarPDA( realmPk, communityMintPk, client!.program.programId ) - const { voter } = await getVoterPDA(registrar, walletPk, clientProgramId) - const { voterWeightPk } = await getVoterWeightPDA( + const { voter } = getVoterPDA(registrar, walletPk, clientProgramId) + const { voterWeightPk } = getVoterWeightPDA( registrar, walletPk, clientProgramId @@ -84,6 +89,18 @@ export const withVoteRegistryWithdraw = async ({ ) ) } + //spl governance tokenownerrecord pubkey + if (!tokenOwnerRecordPubKey) { + tokenOwnerRecordPubKey = await withCreateTokenOwnerRecord( + instructions, + splProgramId, + splProgramVersion, + realmPk, + walletPk, + communityMintPk, + walletPk + ) + } const withdrawInstruction = await client?.program.methods .withdraw(depositIndex!, amount) .accounts({ diff --git a/VoteStakeRegistry/stores/useDepositStore.tsx b/VoteStakeRegistry/stores/useDepositStore.tsx index aac2fec63d..a3e2de40f4 100644 --- a/VoteStakeRegistry/stores/useDepositStore.tsx +++ b/VoteStakeRegistry/stores/useDepositStore.tsx @@ -1,14 +1,13 @@ import create, { State } from 'zustand' import { DepositWithMintAccount } from 'VoteStakeRegistry/sdk/accounts' import { Connection, PublicKey } from '@solana/web3.js' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { getDeposits } from 'VoteStakeRegistry/tools/deposits' import { VsrClient } from 'VoteStakeRegistry/sdk/client' interface DepositStore extends State { state: { deposits: DepositWithMintAccount[] - votingPower: BN votingPowerFromDeposits: BN isLoading: boolean } @@ -58,11 +57,7 @@ const useDepositStore = create((set, _get) => ({ s.state.isLoading = true }) - const { - votingPower, - deposits, - votingPowerFromDeposits, - } = await getDeposits({ + const { deposits, votingPowerFromDeposits } = await getDeposits({ isUsed, realmPk, walletPk, @@ -72,7 +67,6 @@ const useDepositStore = create((set, _get) => ({ }) set((s) => { - s.state.votingPower = votingPower s.state.deposits = deposits s.state.votingPowerFromDeposits = votingPowerFromDeposits s.state.isLoading = false diff --git a/VoteStakeRegistry/tools/dateTools.ts b/VoteStakeRegistry/tools/dateTools.ts deleted file mode 100644 index 8409bebcd8..0000000000 --- a/VoteStakeRegistry/tools/dateTools.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { BN } from '@project-serum/anchor' -import { DepositWithMintAccount } from 'VoteStakeRegistry/sdk/accounts' - -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 - -export function getFormattedStringFromDays( - numberOfDays: number, - fullFormat = false -) { - const years = Math.floor(numberOfDays / DAYS_PER_YEAR) - const months = Math.floor((numberOfDays % DAYS_PER_YEAR) / DAYS_PER_MONTH) - const days = Math.floor((numberOfDays % DAYS_PER_YEAR) % DAYS_PER_MONTH) - const hours = (numberOfDays - Math.floor(numberOfDays)) * HOURS_PER_DAY - const hoursInt = Math.floor(hours) - const minutes = Math.floor((hours - hoursInt) * MINS_PER_HOUR) - const yearSuffix = years > 1 ? ' years' : ' year' - const monthSuffix = months > 1 ? ' months' : ' month' - const daysSuffix = days > 1 ? ' days' : ' day' - const yearsDisplay = - years > 0 ? years + `${fullFormat ? yearSuffix : 'y'} ` : '' - const monthsDisplay = - months > 0 ? months + `${fullFormat ? monthSuffix : 'm'} ` : '' - const daysDisplay = days > 0 ? days + `${fullFormat ? daysSuffix : 'd'} ` : '' - const hoursDisplay = hours > 0 ? `${hoursInt}h ${minutes}min` : '' - const text = - !years && !months && days <= 1 - ? daysDisplay + hoursDisplay - : yearsDisplay + monthsDisplay + daysDisplay - return text ? text : 0 -} - -export const yearsToDays = (years: number) => { - return DAYS_PER_YEAR * years -} -export const daysToYear = (days: number) => { - return days / DAYS_PER_YEAR -} -export const yearsToSecs = (years: number) => { - return DAYS_PER_YEAR * years * SECS_PER_DAY -} - -export const secsToDays = (secs: number) => { - return secs / SECS_PER_DAY -} - -export const daysToMonths = (days: number) => { - return days / DAYS_PER_MONTH -} - -export const getMinDurationFmt = (deposit: DepositWithMintAccount) => { - return getFormattedStringFromDays(getMinDurationInDays(deposit)) -} -export const getTimeLeftFromNowFmt = (deposit: DepositWithMintAccount) => { - const dateNowSecTimeStampBN = new BN(new Date().getTime() / 1000) - return getFormattedStringFromDays( - deposit.lockup.endTs.sub(dateNowSecTimeStampBN).toNumber() / SECS_PER_DAY - ) -} - -export const getMinDurationInDays = (deposit: DepositWithMintAccount) => { - return ( - deposit.lockup.endTs.sub(deposit.lockup.startTs).toNumber() / SECS_PER_DAY - ) -} diff --git a/VoteStakeRegistry/tools/deposits.ts b/VoteStakeRegistry/tools/deposits.ts index d2927236c1..85dfe4e122 100644 --- a/VoteStakeRegistry/tools/deposits.ts +++ b/VoteStakeRegistry/tools/deposits.ts @@ -1,10 +1,14 @@ -import { BN, EventParser } from '@project-serum/anchor' +import { BN, EventParser, Idl, Program } from '@coral-xyz/anchor' +import { ProgramAccount, Realm } from '@solana/spl-governance' import { - ProgramAccount, - Realm, - simulateTransaction, -} from '@solana/spl-governance' -import { PublicKey, Transaction, Connection } from '@solana/web3.js' + PublicKey, + Transaction, + Connection, + ComputeBudgetProgram, +} from '@solana/web3.js' +import { SIMULATION_WALLET } from '@tools/constants' +import { DAYS_PER_MONTH, SECS_PER_DAY } from '@utils/dateTools' +import { chunks } from '@utils/helpers' import { tryGetMint } from '@utils/tokens' import { getRegistrarPDA, @@ -13,12 +17,32 @@ import { DepositWithMintAccount, LockupType, Registrar, + Voter, + Deposit, } from 'VoteStakeRegistry/sdk/accounts' import { tryGetVoter, tryGetRegistrar } from 'VoteStakeRegistry/sdk/api' import { VsrClient } from 'VoteStakeRegistry/sdk/client' -import { DAYS_PER_MONTH } from './dateTools' import { MONTHLY } from './types' +const VOTER_INFO_EVENT_NAME = 'VoterInfo' +const DEPOSIT_EVENT_NAME = 'DepositEntryInfo' +// The wallet can be any existing account for the simulation +// Note: when running a local validator ensure the account is copied from devnet: --clone ENmcpFCpxN1CqyUjuog9yyUVfdXBKF3LVCwLr7grJZpk -ud +const simulationWallet = new PublicKey(SIMULATION_WALLET) + +const logsToEvents = ( + program: Program, + logs: string[], + walletPk: string +): { + walletPk: string + event: any +}[] => { + const parser = new EventParser(program.programId, program.coder) + const errors = parser.parseLogs(logs) + return [...errors].map((event) => ({ event, walletPk })) +} + export const getDeposits = async ({ isUsed = true, realmPk, @@ -35,17 +59,16 @@ export const getDeposits = async ({ connection: Connection }) => { const clientProgramId = client.program.programId - const { registrar } = await getRegistrarPDA( + const { registrar } = getRegistrarPDA( realmPk, communityMintPk, clientProgramId ) - const { voter } = await getVoterPDA(registrar, walletPk, clientProgramId) + const { voter } = getVoterPDA(registrar, walletPk, clientProgramId) const existingVoter = await tryGetVoter(voter, client) const existingRegistrar = await tryGetRegistrar(registrar, client) const mintCfgs = existingRegistrar?.votingMints || [] const mints = {} - let votingPower = new BN(0) let votingPowerFromDeposits = new BN(0) let deposits: DepositWithMintAccount[] = [] for (const i of mintCfgs) { @@ -68,7 +91,6 @@ export const getDeposits = async ({ const usedDeposits = deposits.filter((x) => x.isUsed) const areThereAnyUsedDeposits = usedDeposits.length if (areThereAnyUsedDeposits) { - console.log({ client, usedDeposits, connection, registrar, voter }) const events = await getDepositsAdditionalInfoEvents( client, usedDeposits, @@ -76,8 +98,6 @@ export const getDeposits = async ({ registrar, voter ) - const DEPOSIT_EVENT_NAME = 'DepositEntryInfo' - const VOTER_INFO_EVENT_NAME = 'VoterInfo' const depositsInfo = events.filter((x) => x.name === DEPOSIT_EVENT_NAME) const votingPowerEntry = events.find( (x) => x.name === VOTER_INFO_EVENT_NAME @@ -103,13 +123,140 @@ export const getDeposits = async ({ ) { votingPowerFromDeposits = votingPowerEntry.data.votingPowerBaseline } - if (votingPowerEntry && !votingPowerEntry.data.votingPower.isZero()) { - votingPower = votingPowerEntry.data.votingPower + + return { deposits, votingPowerFromDeposits } + } + } + return { deposits, votingPowerFromDeposits } +} + +const getVotingPowersForWallets = async ({ + client, + registrarPk, + existingRegistrar, + walletPks, + connection, + latestBlockhash, +}: { + client: VsrClient + connection: Connection + registrarPk: PublicKey + existingRegistrar: Registrar + walletPks: PublicKey[] + latestBlockhash: Readonly<{ + blockhash: string + lastValidBlockHeight: number + }> +}) => { + const clientProgramId = client.program.programId + const voterPks: PublicKey[] = [] + const voters: (Voter | null)[] = [] + const encodedTransactionsParsedByWallets: { + walletPk: string + tx: string + }[] = [] + const mintCfgs = existingRegistrar.votingMints + const events: { + walletPk: string + event: any + }[] = [] + for (const walletPk of walletPks) { + const { voter } = getVoterPDA(registrarPk, walletPk, clientProgramId) + voterPks.push(voter) + } + + const voterAccsResponse = await client?.program.account.voter.fetchMultiple( + voterPks + ) + voters.push(...(voterAccsResponse as (Voter | null)[])) + + if (voters.length) { + for (const i in voters) { + const voter = voters[i] + const voterPk = voterPks[i] + if (voter) { + const hasDepositsWithCommunityMint = voter.deposits.find( + (x) => + x.isUsed && + mintCfgs[x.votingMintConfigIdx].baselineVoteWeightScaledFactor.gtn( + 0 + ) + ) + if (hasDepositsWithCommunityMint) { + const simulationWallet = new PublicKey(SIMULATION_WALLET) + + const originalTx = new Transaction({ feePayer: simulationWallet }) + const logVoterInfoIx = await client.program.methods + .logVoterInfo(1, 1) + .accounts({ registrar: registrarPk, voter: voterPk }) + .instruction() + originalTx.add(logVoterInfoIx) + + const transaction = originalTx + transaction.lastValidBlockHeight = + latestBlockhash.lastValidBlockHeight + transaction.recentBlockhash = latestBlockhash.blockhash + //@ts-ignore + const message = transaction._compile() + const signData = message.serialize() + //@ts-ignore + const wireTransaction = transaction._serialize(signData) + const encodedTransaction = wireTransaction.toString('base64') + encodedTransactionsParsedByWallets.push({ + walletPk: voter.voterAuthority.toBase58(), + tx: encodedTransaction, + }) + } } - return { votingPower, deposits, votingPowerFromDeposits } } + + const chunkedEncodedTransactionsParsed = chunks( + encodedTransactionsParsedByWallets, + 100 + ) + // TODO Batch alert + const simulations = await Promise.all( + chunkedEncodedTransactionsParsed.map((txChunk) => + fetch(connection.rpcEndpoint, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify([ + ...txChunk.map((encodedTransaction) => ({ + jsonrpc: '2.0', + id: encodedTransaction.walletPk, + method: 'simulateTransaction', + params: [ + encodedTransaction.tx, + { + commitment: 'recent', + encoding: 'base64', + }, + ], + })), + ]), + }) + ) + ) + const logsJsons = await Promise.all(simulations.map((x) => x.json())) + for (const logJson of logsJsons) { + for (const result of logJson) { + events.push( + ...logsToEvents(client.program, result.result.value.logs!, result.id) + ) + } + } + + const votingPowersPerWallet = events + .filter((x) => x.event.name === VOTER_INFO_EVENT_NAME) + .map((x) => ({ + walletPk: x.walletPk, + votingPower: (x.event?.data?.votingPower as BN) || new BN(0), + })) + return votingPowersPerWallet } - return { votingPower, deposits, votingPowerFromDeposits } + return null } export const calcMultiplier = ({ @@ -117,31 +264,33 @@ export const calcMultiplier = ({ maxExtraLockupVoteWeightScaledFactor, lockupSecs, lockupSaturationSecs, + isVested = false, }: { depositScaledFactor: number maxExtraLockupVoteWeightScaledFactor: number lockupSecs: number lockupSaturationSecs: number + isVested?: boolean }) => { - // if (isVested) { - // const onMonthSecs = SECS_PER_DAY * DAYS_PER_MONTH - // const n_periods_before_saturation = lockupSaturationSecs / onMonthSecs - // const n_periods = lockupSecs / onMonthSecs - // const n_unsaturated_periods = Math.min( - // n_periods, - // n_periods_before_saturation - // ) - // const n_saturated_periods = Math.max(0, n_periods - n_unsaturated_periods) - // const calc = - // (depositScaledFactor + - // (maxExtraLockupVoteWeightScaledFactor / n_periods) * - // (n_saturated_periods + - // ((n_unsaturated_periods + 1) * n_unsaturated_periods) / - // 2 / - // n_periods_before_saturation)) / - // depositScaledFactor - // return depositScaledFactor !== 0 ? calc : 0 - // } + if (isVested) { + const onMonthSecs = SECS_PER_DAY * DAYS_PER_MONTH + const n_periods_before_saturation = lockupSaturationSecs / onMonthSecs + const n_periods = lockupSecs / onMonthSecs + const n_unsaturated_periods = Math.min( + n_periods, + n_periods_before_saturation + ) + const n_saturated_periods = Math.max(0, n_periods - n_unsaturated_periods) + const calc = + (depositScaledFactor + + (maxExtraLockupVoteWeightScaledFactor / n_periods) * + (n_saturated_periods + + ((n_unsaturated_periods + 1) * n_unsaturated_periods) / + 2 / + n_periods_before_saturation)) / + depositScaledFactor + return depositScaledFactor !== 0 ? calc : 0 + } const calc = (depositScaledFactor + (maxExtraLockupVoteWeightScaledFactor * @@ -176,7 +325,8 @@ export const getPeriod = ( export const calcMintMultiplier = ( lockupSecs: number, registrar: Registrar | null, - realm: ProgramAccount | undefined + realm: ProgramAccount | undefined, + isVested?: boolean ) => { const mintCfgs = registrar?.votingMints const mintCfg = mintCfgs?.find( @@ -197,6 +347,7 @@ export const calcMintMultiplier = ( maxExtraLockupVoteWeightScaledFactor: maxExtraLockupVoteWeightScaledFactorNum, lockupSaturationSecs: lockupSaturationSecsNum, lockupSecs, + isVested, }) return parseFloat(calced.toFixed(2)) @@ -211,12 +362,10 @@ const getDepositsAdditionalInfoEvents = async ( registrar: PublicKey, voter: PublicKey ) => { - // The wallet can be any existing account for the simulation - // Note: when running a local validator ensure the account is copied from devnet: --clone ENmcpFCpxN1CqyUjuog9yyUVfdXBKF3LVCwLr7grJZpk -ud - const walletPk = new PublicKey('ENmcpFCpxN1CqyUjuog9yyUVfdXBKF3LVCwLr7grJZpk') //because we switch wallet in here we can't use rpc from npm module //anchor dont allow to switch wallets inside existing client //parse events response as anchor do + const latestBlockhash = await connection.getLatestBlockhash() const events: any[] = [] const parser = new EventParser(client.program.programId, client.program.coder) const maxRange = 8 @@ -224,20 +373,70 @@ const getDepositsAdditionalInfoEvents = async ( const numberOfSimulations = Math.ceil(maxIndex / maxRange) for (let i = 0; i < numberOfSimulations; i++) { const take = maxRange - const transaction = new Transaction({ feePayer: walletPk }) + const transaction = new Transaction({ feePayer: simulationWallet }) + transaction.lastValidBlockHeight = latestBlockhash.lastValidBlockHeight + transaction.recentBlockhash = latestBlockhash.blockhash const logVoterInfoIx = await client.program.methods .logVoterInfo(maxRange * i, take) .accounts({ registrar, voter }) .instruction() - transaction.add(logVoterInfoIx) - const batchOfDeposits = await simulateTransaction( - connection, - transaction, - 'recent' + transaction.add( + ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }) ) - parser.parseLogs(batchOfDeposits.value.logs!, (event) => { - events.push(event) - }) + transaction.add(logVoterInfoIx) + // TODO cache using fetchVotingPowerSimulation + + const batchOfDeposits = await connection.simulateTransaction(transaction) + const logEvents = parser.parseLogs(batchOfDeposits.value.logs!) + events.push(...[...logEvents]) } return events } + +export const getLockTokensVotingPowerPerWallet = async ( + walletsPks: PublicKey[], + realm: ProgramAccount, + client: VsrClient, + connection: Connection +) => { + const { registrar } = getRegistrarPDA( + realm.pubkey, + realm.account.communityMint, + client.program.programId + ) + const existingRegistrar = await tryGetRegistrar(registrar, client) + const latestBlockhash = await connection.getLatestBlockhash() + const votingPowers = await getVotingPowersForWallets({ + client: client, + registrarPk: registrar, + existingRegistrar: existingRegistrar!, + walletPks: walletsPks, + connection: connection, + latestBlockhash, + }) + + if (votingPowers) { + const votingPowerObj: Record = {} + for (const record of votingPowers) { + votingPowerObj[record.walletPk] = record.votingPower + } + + return votingPowerObj + } + return {} +} + +export const getDepositType = (deposit: Deposit): LockupType => { + if (typeof deposit.lockup.kind.monthly !== 'undefined') { + return 'monthly' + } else if (typeof deposit.lockup.kind.cliff !== 'undefined') { + return 'cliff' + } else if (typeof deposit.lockup.kind.constant !== 'undefined') { + return 'constant' + } else if (typeof deposit.lockup.kind.daily !== 'undefined') { + return 'daily' + } else if (typeof deposit.lockup.kind.none !== 'undefined') { + return 'none' + } + return 'none' +} diff --git a/VoteStakeRegistry/tools/types.ts b/VoteStakeRegistry/tools/types.ts index 464bf9529b..5bad4294d3 100644 --- a/VoteStakeRegistry/tools/types.ts +++ b/VoteStakeRegistry/tools/types.ts @@ -15,6 +15,7 @@ export interface VestingPeriod { info: string } export const MONTHLY = 'monthly' +export const DAILY = 'daily' export const CONSTANT = 'constant' export const lockupTypes: LockupKind[] = [ { @@ -37,13 +38,22 @@ export const lockupTypes: LockupKind[] = [ }, { value: MONTHLY, - displayName: 'Vested', + displayName: 'Vested monthly', info: [ 'Tokens are locked for a fixed duration and released over time at a rate of (locked amount / number of periods) per vesting period.', 'Vote weight declines linearly and with each vesting until release.', 'Example: You lock 12.000 tokens for one year with monthly vesting. Every month 1.000 tokens unlock. After the year, all tokens have unlocked.', ], }, + { + value: DAILY, + displayName: 'Vested daily', + info: [ + 'Tokens are locked for a fixed duration and released over time at a rate of (locked amount / number of periods) per vesting period.', + 'Vote weight declines linearly and with each vesting until release.', + 'Example: You lock 12.000 tokens for one year with daily vesting. Every day 3.28 tokens unlock. After the year, all tokens have unlocked.', + ], + }, ] export const vestingPeriods: VestingPeriod[] = [ diff --git a/VoterWeightPlugins/clients/PythVoterWeightPluginClient.ts b/VoterWeightPlugins/clients/PythVoterWeightPluginClient.ts new file mode 100644 index 0000000000..238783579d --- /dev/null +++ b/VoterWeightPlugins/clients/PythVoterWeightPluginClient.ts @@ -0,0 +1,121 @@ +import {Client} from "@solana/governance-program-library"; +import {PublicKey, TransactionInstruction} from "@solana/web3.js"; +import BN from "bn.js"; +import {Program, Provider, Wallet} from "@coral-xyz/anchor"; +import {VoterWeightAction} from "@solana/spl-governance"; +import {convertVoterWeightActionToType} from "../lib/utils"; +import queryClient from "@hooks/queries/queryClient"; +import { getMaxVoterWeightRecordAddress, getVoterWeightRecordAddress, PythStakingClient, StakeAccountPositions } from "@pythnetwork/staking-sdk"; + +// A wrapper for the PythClient from @pythnetwork/staking-sdk, that implements the generic plugin client interface +export class PythVoterWeightPluginClient extends Client { + readonly requiresInputVoterWeight = false; + // The pyth plugin does not have a registrar account + async getRegistrarAccount(): Promise { + return null; + } + + async getMaxVoterWeightRecordPDA() { + const [address, bump] = getMaxVoterWeightRecordAddress(); + + return { + maxVoterWeightPk: address, + maxVoterWeightRecordBump: bump, + } + } + + async getMaxVoterWeightRecord(realm: PublicKey, mint: PublicKey) { + const {maxVoterWeightPk} = await this.getMaxVoterWeightRecordPDA(); + return this.client.stakingProgram.account.maxVoterWeightRecord.fetch( + maxVoterWeightPk, + ); + } + + async getVoterWeightRecordPDA(realm: PublicKey, mint: PublicKey, voter: PublicKey) { + const stakeAccount = await this.getStakeAccount(voter) + const [address, bump] = getVoterWeightRecordAddress(stakeAccount); + + return { + voterWeightPk: address, + voterWeightRecordBump: bump, + } + } + + async getVoterWeightRecord(realm: PublicKey, mint: PublicKey, walletPk: PublicKey) { + const {voterWeightPk} = await this.getVoterWeightRecordPDA(realm, mint, walletPk); + return this.client.stakingProgram.account.voterWeightRecord.fetch( + voterWeightPk, + ); + } + + // NO-OP Pyth records are created through the Pyth dApp. + async createVoterWeightRecord(): Promise { + return null; + } + + // NO-OP + async createMaxVoterWeightRecord(): Promise { + return null; + } + + private async getStakeAccount(voter: PublicKey): Promise { + return queryClient.fetchQuery({ + queryKey: ['pyth getStakeAccount', voter.toBase58()], + queryFn: () => this.client.getMainStakeAccount(voter).then(x => x?.stakeAccountPosition), + }) + } + + async updateVoterWeightRecord( + voter: PublicKey, + realm: PublicKey, + mint: PublicKey, + action: VoterWeightAction, + inputRecordCallback?: () => Promise, + target?: PublicKey + ) { + const stakeAccount = await this.getStakeAccount(voter) + + const ix = await this.client.getUpdateVoterWeightInstruction( + stakeAccount, + { [convertVoterWeightActionToType(action)]: {} } as any, + target, + ) + + return { pre: [ix] }; + } + // NO-OP + async updateMaxVoterWeightRecord(): Promise { + return null; + } + async calculateVoterWeight(voter: PublicKey): Promise { + const voterWeight = await this.client.getVoterWeight(voter); + return new BN(voterWeight.toString()); + } + + constructor( + program: Program, + private client: PythStakingClient + ) { + super(program); + } + + static async connect(provider: Provider, programId: PublicKey, wallet: Wallet): Promise { + const pythClient = new PythStakingClient({ + connection: provider.connection, + wallet, + }) + + const dummyProgram = new Program( + { + version: "", + name: 'unrecognised', + accounts: [], + instructions: [] + }, + programId, + provider + ); + + return new PythVoterWeightPluginClient(dummyProgram, pythClient); + } +} \ No newline at end of file diff --git a/VoterWeightPlugins/clients/UnrecognisedVoterWeightPluginClient.ts b/VoterWeightPlugins/clients/UnrecognisedVoterWeightPluginClient.ts new file mode 100644 index 0000000000..afc7b402b2 --- /dev/null +++ b/VoterWeightPlugins/clients/UnrecognisedVoterWeightPluginClient.ts @@ -0,0 +1,45 @@ +import {Client} from "@solana/governance-program-library"; +import { PublicKey, TransactionInstruction} from "@solana/web3.js"; +import BN from "bn.js"; +import { Program, Provider} from "@coral-xyz/anchor"; + +// A passthrough plugin to be used when the UI does not recognise the voter weight plugin +export class UnrecognisedVoterWeightPluginClient extends Client { + readonly requiresInputVoterWeight = false; + async getRegistrarAccount(): Promise { + return null; + } + + async createVoterWeightRecord(): Promise { + return null; + } + + async createMaxVoterWeightRecord(): Promise { + return null; + } + + async updateVoterWeightRecord() { + return { pre: [], post: [] } + } + // NO-OP + async updateMaxVoterWeightRecord(): Promise { + return null; + } + async calculateVoterWeight(voter: PublicKey, realm: PublicKey, mint: PublicKey, inputVoterWeight: BN): Promise { + // In the absence of other information, just pass through the input voter weight here. + console.warn(`WARNING: Unrecognised voter weight plugin client used during calculateVoterWeight. Passing through the input voter weight of ${inputVoterWeight.toString()}`); + return inputVoterWeight; + } + + static async connect(provider: Provider, programId: PublicKey, devnet = false): Promise { + console.warn("WARNING: Unrecognised voter weight plugin client used."); + const dummyProgram = new Program( + { + version: "", + name: 'unrecognised', + accounts: [], + instructions: [] + }, programId, provider); + return new UnrecognisedVoterWeightPluginClient(dummyProgram, devnet); + } +} \ No newline at end of file diff --git a/VoterWeightPlugins/clients/index.ts b/VoterWeightPlugins/clients/index.ts new file mode 100644 index 0000000000..8c8a1a4325 --- /dev/null +++ b/VoterWeightPlugins/clients/index.ts @@ -0,0 +1,55 @@ +import { PluginName } from '@constants/plugins' +import { + Client, + GatewayClient, + QuadraticClient, +} from '@solana/governance-program-library' + +import { Provider, Wallet } from '@coral-xyz/anchor' +import { PythVoterWeightPluginClient } from './PythVoterWeightPluginClient' +import { ParclVoterWeightPluginClient } from 'ParclVotePlugin/ParclVoterWeightPluginClient' +import { PublicKey } from '@solana/web3.js' +import { VsrClient } from '../../VoteStakeRegistry/sdk/client' +import { NftVoterClient } from '@utils/uiTypes/NftVoterClient' +import { HeliumVsrClient } from '../../HeliumVotePlugin/sdk/client' +import { UnrecognisedVoterWeightPluginClient } from './UnrecognisedVoterWeightPluginClient' +import { DriftVoterClient } from 'DriftStakeVoterPlugin/DriftVoterClient' +import { TokenHaverClient } from 'TokenHaverPlugin/TokenHaverClient' + +/** + * Given a plugin name and program ID, load the appropriate client + * Note - the program ID is ignored by some clients, but if present, must match the IDL loaded by the client. + * @param plugin + * @param programId + * @param provider + * @param signer + */ +export const loadClient = ( + plugin: PluginName, + programId: PublicKey, + provider: Provider, + signer: Wallet +): Promise> => { + switch (plugin) { + case 'QV': + return QuadraticClient.connect(provider) + case 'gateway': + return GatewayClient.connect(provider) + case 'pyth': + return PythVoterWeightPluginClient.connect(provider, programId, signer) + case 'VSR': + return VsrClient.connect(provider, programId) + case 'HeliumVSR': + return HeliumVsrClient.connect(provider, programId) + case 'NFT': + return NftVoterClient.connect(provider, programId) + case 'drift': + return DriftVoterClient.connect(provider, programId) + case 'token_haver': + return TokenHaverClient.connect(provider, programId) + case 'parcl': + return ParclVoterWeightPluginClient.connect(provider, undefined, signer) + default: + return UnrecognisedVoterWeightPluginClient.connect(provider, programId) + } +} diff --git a/VoterWeightPlugins/hooks/useCalculatedMaxVoterWeight.ts b/VoterWeightPlugins/hooks/useCalculatedMaxVoterWeight.ts new file mode 100644 index 0000000000..4426bf5c12 --- /dev/null +++ b/VoterWeightPlugins/hooks/useCalculatedMaxVoterWeight.ts @@ -0,0 +1,38 @@ +import {CalculatedWeight, UseVoterWeightPluginsArgs, VoterWeightPluginInfo} from "../lib/types"; +import {calculateMaxVoterWeight} from "../lib/calculateVoterWeights"; +import {MintInfo} from "@solana/spl-token"; +import {useAsync, UseAsyncReturn} from "react-async-hook"; +import {useMintConfiguredMaxVoteWeight} from "./useMintConfiguredMaxVoteWeight"; + +type Args = Omit & { + plugins?: VoterWeightPluginInfo[], + mintInfo?: MintInfo, +} + +const argsAreSet = (args: Args): args is Required => + args.realmPublicKey !== undefined && args.governanceMintPublicKey !== undefined && + args.plugins !== undefined && args.mintInfo !== undefined && args.realmConfig !== undefined; + +export const useCalculatedMaxVoterWeight = (args: Args): UseAsyncReturn => { + const configuredMaxVoteWeight = useMintConfiguredMaxVoteWeight( + args.governanceMintPublicKey, + args.realmConfig, + args.mintInfo + ); + return useAsync( + async () => { + if (!argsAreSet(args)) return undefined; + return calculateMaxVoterWeight({ + ...args as Required, + configuredMaxVoteWeight + }); + }, + [ + args.realmPublicKey?.toString(), + args.governanceMintPublicKey?.toString(), + args.mintInfo, + args.realmConfig, + args.plugins?.length + ], + ); +} diff --git a/VoterWeightPlugins/hooks/useCalculatedVoterWeights.ts b/VoterWeightPlugins/hooks/useCalculatedVoterWeights.ts new file mode 100644 index 0000000000..3fa2b145d9 --- /dev/null +++ b/VoterWeightPlugins/hooks/useCalculatedVoterWeights.ts @@ -0,0 +1,45 @@ +import { ProgramAccount, TokenOwnerRecord } from '@solana/spl-governance' +import { + CalculatedWeight, + UseVoterWeightPluginsArgs, + VoterWeightPluginInfo, +} from '../lib/types' +import { calculateVoterWeight } from '../lib/calculateVoterWeights' +import { useAsync, UseAsyncReturn } from 'react-async-hook' +import {PublicKey} from "@solana/web3.js"; + +type Args = UseVoterWeightPluginsArgs & { + realmPublicKey?: PublicKey + governanceMintPublicKey?: PublicKey + walletPublicKeys?: PublicKey[] + plugins?: VoterWeightPluginInfo[] + tokenOwnerRecords?: ProgramAccount[] +} + +const argsAreSet = (args: Args): args is Required => + args.realmPublicKey !== undefined && args.governanceMintPublicKey !== undefined && args.walletPublicKeys !== undefined && + args.plugins !== undefined && args.tokenOwnerRecords !== undefined + +export const useCalculatedVoterWeights = (args: Args) : UseAsyncReturn => + useAsync( + async () => { + if (!argsAreSet(args)) return undefined; + + const voterWeights = args.walletPublicKeys?.map(wallet => { + const tokenOwnerRecord = args.tokenOwnerRecords?.find(tor => tor.account.governingTokenOwner.equals(wallet)); + return calculateVoterWeight({ + ...args as Required, + walletPublicKey: wallet, + tokenOwnerRecord, + }); + }); + return Promise.all(voterWeights); + }, + [ + args.realmPublicKey?.toString(), + args.governanceMintPublicKey?.toString(), + args.walletPublicKeys?.map(pubkey => pubkey.toString()).join(","), + args.tokenOwnerRecords?.map(tor => tor.account.governingTokenDepositAmount).join(","), + args.plugins?.length + ] + ) \ No newline at end of file diff --git a/VoterWeightPlugins/hooks/useMintConfiguredMaxVoteWeight.ts b/VoterWeightPlugins/hooks/useMintConfiguredMaxVoteWeight.ts new file mode 100644 index 0000000000..5940b87b82 --- /dev/null +++ b/VoterWeightPlugins/hooks/useMintConfiguredMaxVoteWeight.ts @@ -0,0 +1,20 @@ +import {PublicKey} from "@solana/web3.js"; +import {RealmConfig} from "@solana/spl-governance"; +import {getMintMaxVoteWeight} from "@models/voteWeights"; +import BN from "bn.js"; +import {MintInfo} from "@solana/spl-token"; + +export const useMintConfiguredMaxVoteWeight = ( + governanceMint?: PublicKey, + realmConfig?: RealmConfig, + mintInfo?: MintInfo +): BN => { + // this allows this hook to be set up before the realm config is loaded + if (!governanceMint || !realmConfig || !mintInfo) return new BN(0); + + if (realmConfig.councilMint && governanceMint.equals(realmConfig.councilMint)) { + return mintInfo?.supply || new BN(0); + } + + return getMintMaxVoteWeight(mintInfo, realmConfig.communityMintMaxVoteWeightSource); +} \ No newline at end of file diff --git a/VoterWeightPlugins/hooks/usePlugins.ts b/VoterWeightPlugins/hooks/usePlugins.ts new file mode 100644 index 0000000000..50206b9f8d --- /dev/null +++ b/VoterWeightPlugins/hooks/usePlugins.ts @@ -0,0 +1,83 @@ +import {VoterWeightPlugins} from "../lib/types"; +import {getPlugins} from "../lib/getPlugins"; +import {useConnection} from "@solana/wallet-adapter-react"; +import {useQuery, UseQueryResult} from "@tanstack/react-query"; +import useWalletOnePointOh from "@hooks/useWalletOnePointOh"; +import {AnchorProvider, Wallet} from "@coral-xyz/anchor"; +import {PublicKey} from "@solana/web3.js"; + +type Args = { + realmPublicKey?: PublicKey + governanceMintPublicKey?: PublicKey + walletPublicKeys?: PublicKey[] +} + +const argsAreSet = (args: Args): args is Required => + args.realmPublicKey !== undefined && args.governanceMintPublicKey !== undefined && args.walletPublicKeys !== undefined + +export const usePlugins = (args: Args): UseQueryResult => { + const { connection } = useConnection() + const wallet = useWalletOnePointOh() + const signer = wallet as unknown as Wallet; + const provider = wallet && new AnchorProvider( + connection, + signer, + AnchorProvider.defaultOptions() + ) + + const queryKeys = [ + 'getPlugins', + args.realmPublicKey?.toString(), + args.governanceMintPublicKey?.toString(), + args.walletPublicKeys?.map(pubkey => pubkey.toString()).join(",") + ] + + // Cache plugin loading with react-query + return useQuery( + queryKeys, + async () => { + if (!args.walletPublicKeys || !provider) return { + voterWeight: [], + maxVoterWeight: [] + }; + + try { + // Load the voter weight plugins associated with the realm and governance + const voterWeightPluginsPromise = getPlugins({ + ...(args as Required), + provider, + type: 'voterWeight', + wallets: args.walletPublicKeys, + signer + }); + // Load the max voter weight plugins associated with the realm and governance + const maxVoterWeightPluginsPromise = getPlugins({ + ...(args as Required), + provider, + type: 'maxVoterWeight', + wallets: args.walletPublicKeys, + signer + }); + + const [voterWeightPlugins, maxVoterWeightPlugins] = await Promise.all([ + voterWeightPluginsPromise, + maxVoterWeightPluginsPromise + ]); + + return { + voterWeight: voterWeightPlugins, + maxVoterWeight: maxVoterWeightPlugins + }; + } catch { + return { + voterWeight: [], + maxVoterWeight: [] + }; + } + + }, + { + enabled: argsAreSet(args), + } + ) +} \ No newline at end of file diff --git a/VoterWeightPlugins/hooks/useTokenOwnerRecord.ts b/VoterWeightPlugins/hooks/useTokenOwnerRecord.ts new file mode 100644 index 0000000000..29341da1f3 --- /dev/null +++ b/VoterWeightPlugins/hooks/useTokenOwnerRecord.ts @@ -0,0 +1,23 @@ +import {useUserCommunityTokenOwnerRecord, useUserCouncilTokenOwnerRecord} from "@hooks/queries/tokenOwnerRecord"; +import {TokenOwnerRecord, ProgramAccount} from "@solana/spl-governance"; +import {PublicKey} from "@solana/web3.js"; + +export const useTokenOwnerRecord = ( + governanceMintPublicKey?: PublicKey +): ProgramAccount | undefined => { + const communityTokenOwnerRecord = useUserCommunityTokenOwnerRecord().data?.result + const councilTokenOwnerRecord = useUserCouncilTokenOwnerRecord().data?.result + + // default to the community token owner record if there is no governance mint specified + if (!governanceMintPublicKey) return communityTokenOwnerRecord; + + if (councilTokenOwnerRecord?.account.governingTokenMint.equals(governanceMintPublicKey)) { + return councilTokenOwnerRecord; + } + + if (communityTokenOwnerRecord?.account.governingTokenMint.equals(governanceMintPublicKey)) { + return communityTokenOwnerRecord; + } + + return undefined; +} \ No newline at end of file diff --git a/VoterWeightPlugins/hooks/useVoterWeightPks.ts b/VoterWeightPlugins/hooks/useVoterWeightPks.ts new file mode 100644 index 0000000000..4ab00780ad --- /dev/null +++ b/VoterWeightPlugins/hooks/useVoterWeightPks.ts @@ -0,0 +1,51 @@ +import {UseVoterWeightPluginsArgs, VoterWeightPluginInfo} from "../lib/types"; +import {PublicKey} from "@solana/web3.js"; +import {getTokenOwnerRecordAddressSync} from "../lib/utils"; +import {useAsync, UseAsyncReturn} from "react-async-hook"; + +type Args = UseVoterWeightPluginsArgs & { + plugins?: VoterWeightPluginInfo[] +} + +const argsAreSet = (args: Args): args is Required => + args.realmPublicKey !== undefined && args.governanceMintPublicKey !== undefined && args.walletPublicKeys !== undefined && + args.plugins !== undefined + +export const useVoterWeightPks = (args: Args): UseAsyncReturn<{ + voterWeightPks: PublicKey[] | undefined, + maxVoterWeightPk: PublicKey | undefined +}> => + useAsync(async () => { + // still loading + if (!argsAreSet(args)) return { + voterWeightPks: undefined, + maxVoterWeightPk: undefined + }; + + const {realmPublicKey, governanceMintPublicKey, walletPublicKeys, plugins} = args; + + // no plugins - return the token owner record and null + if (plugins.length === 0) { + const tokenOwnerRecords = walletPublicKeys.map(walletPublicKey => getTokenOwnerRecordAddressSync(realmPublicKey, governanceMintPublicKey, walletPublicKey)); + return { + voterWeightPks: tokenOwnerRecords.map(([tokenOwnerRecord]) => tokenOwnerRecord), + maxVoterWeightPk: undefined + } + } + + const lastPlugin = plugins[plugins.length - 1]; + + const voterWeightPks = await Promise.all(walletPublicKeys.map(walletPublicKey => + lastPlugin.client.getVoterWeightRecordPDA(realmPublicKey, governanceMintPublicKey, walletPublicKey) + .then(pda => pda.voterWeightPk) + )); + const {maxVoterWeightPk} = await lastPlugin.client.getMaxVoterWeightRecordPDA(realmPublicKey, governanceMintPublicKey) || {}; + + return { + voterWeightPks, + maxVoterWeightPk + } + }, [ + args.plugins?.length, + args.walletPublicKeys?.map((pk) => pk.toBase58()).join(','), + ]) \ No newline at end of file diff --git a/VoterWeightPlugins/index.ts b/VoterWeightPlugins/index.ts new file mode 100644 index 0000000000..ba724ef251 --- /dev/null +++ b/VoterWeightPlugins/index.ts @@ -0,0 +1,7 @@ +export { useVoterWeightPlugins } from './useVoterWeightPlugins' +export { useGatewayVoterWeightPlugin } from './useGatewayVoterWeightPlugin' +export { useQuadraticVoterWeightPlugin } from './useQuadraticVoterWeightPlugin' +export { convertTypeToVoterWeightAction } from './lib/utils' +export { useHeliumClient } from './useHeliumClient' +export { useNftClient } from './useNftClient' +export { useVsrClient } from './useVsrClient' diff --git a/VoterWeightPlugins/lib/PluginDebug.tsx b/VoterWeightPlugins/lib/PluginDebug.tsx new file mode 100644 index 0000000000..2da8d244ce --- /dev/null +++ b/VoterWeightPlugins/lib/PluginDebug.tsx @@ -0,0 +1,81 @@ +import {useRealmVoterWeightPlugins} from "@hooks/useRealmVoterWeightPlugins"; +import {VoterWeightPluginInfo} from "./types"; +import {useState} from "react"; + +/** + * A useful debug dashboard for plugins, allowing you to see the voter weights and plugin config, without having to infer it + * through the UI. + * + * Access it using the query param ?debug on any DAO + * + * Should be removed before QV-2 is merged. + */ + +const Params = ({ plugin } : { plugin: VoterWeightPluginInfo }) => { + const trimmedParams = Object.entries(plugin.params as any).filter(([key]) => key !== 'reserved'); + return
+ {trimmedParams.map(([key, value]) =>
{key}: {JSON.stringify(value)}
)} +
+} + +const useKindToggle = () => { + const [kind, setKind] = useState<'community' | 'council'>('community') + const toggle = () => setKind(kind === 'community' ? 'council' : 'community') + return { kind, toggle } +} + +const KindToggle = ({ kind, toggle } : { kind: 'community' | 'council', toggle: () => void }) => { + return
+
Kind: {kind}
+ +
+} + +export const PluginDebug = () => { + const {kind, toggle} = useKindToggle(); + const {plugins, totalCalculatedVoterWeight, calculatedMaxVoterWeight, isReady} = useRealmVoterWeightPlugins(kind) + + return
+

Hello! This is a voter weight plugin debug dashboard

+ +
Voter Weight: {totalCalculatedVoterWeight?.value?.toString()}
+
Max Voter Weight: {calculatedMaxVoterWeight?.value?.toString()}
+
Is Ready: {isReady.toString()}
+
Voter Weight Plugins: +
    + {isReady && (plugins?.voterWeight || []).map((plugin, i) => +
  • +
    Plugin Name: {plugin.name}
    +
    Voter Weight (on-chain): {plugin.weights?.map(w => w?.toString()).join(",")}
    +
    Voter Weight + (calculated): {totalCalculatedVoterWeight?.details[i].pluginWeight?.toString()}
    +
    Voter Weight + (error): {totalCalculatedVoterWeight?.details[i].error?.stack}
    +
    Params:
    +
  • )} +
+
+
Max Voter Weight Plugins: +
    + {isReady && (plugins?.maxVoterWeight || []).map((plugin, i) => +
  • +
    Plugin Name: {plugin.name}
    +
    Max Voter Weight (on-chain): {plugin.weights?.map(w => w?.toString()).join(",")}
    +
    Max Voter Weight + (calculated): {calculatedMaxVoterWeight?.details[i].pluginWeight?.toString()}
    +
    Max Voter Weight + (error): {calculatedMaxVoterWeight?.details[i].error?.stack}
    +
    Params:
    +
  • )} +
+
+
+} \ No newline at end of file diff --git a/VoterWeightPlugins/lib/calculateVoterWeights.ts b/VoterWeightPlugins/lib/calculateVoterWeights.ts new file mode 100644 index 0000000000..9f8ae32f01 --- /dev/null +++ b/VoterWeightPlugins/lib/calculateVoterWeights.ts @@ -0,0 +1,156 @@ +import { CalculatedWeight, VoterWeightPluginInfo } from './types' +import { reduceAsync } from './utils' +import { PublicKey } from '@solana/web3.js' +import { ProgramAccount, TokenOwnerRecord } from '@solana/spl-governance' +import BN from 'bn.js' +import { MintInfo } from '@solana/spl-token' + +type CalculateVoterWeightParams = { + walletPublicKey: PublicKey + realmPublicKey: PublicKey + governanceMintPublicKey: PublicKey + plugins: VoterWeightPluginInfo[] + tokenOwnerRecord?: ProgramAccount + useOnChainWeight?: boolean +} + +type CalculateMaxVoterWeightParams = { + realmPublicKey: PublicKey + governanceMintPublicKey: PublicKey + plugins: VoterWeightPluginInfo[] + mintInfo: MintInfo + configuredMaxVoteWeight: BN + useOnChainWeight?: boolean +} + +const handlePluginSuccess = ( + inputVoterWeight: CalculatedWeight, + nextPlugin: VoterWeightPluginInfo, + nextWeight: BN | null +): CalculatedWeight => { + if (nextWeight === null) { + // Plugin failed to calculate voter weight, but did not throw an error, so we just assign a generic error + return { + value: null, + initialValue: inputVoterWeight.initialValue, + details: [ + ...inputVoterWeight.details, + { + pluginName: nextPlugin.name, + pluginWeight: null, + error: new Error('Plugin failed to calculate voter weight'), + }, + ], + } + } + + return { + value: nextWeight, + initialValue: inputVoterWeight.initialValue, + details: [ + ...inputVoterWeight.details, + { + pluginName: nextPlugin.name, + pluginWeight: nextWeight, + error: null, + }, + ], + } +} + +const handlePluginError = ( + inputVoterWeight: CalculatedWeight, + nextPlugin: VoterWeightPluginInfo, + error: Error +): CalculatedWeight => ({ + value: null, + initialValue: inputVoterWeight.initialValue, + details: [ + ...inputVoterWeight.details, + { + pluginName: nextPlugin.name, + pluginWeight: null, + error, + }, + ], +}) + +export const calculateVoterWeight = async ({ + walletPublicKey, + realmPublicKey, + governanceMintPublicKey, + plugins, + tokenOwnerRecord, +}: CalculateVoterWeightParams): Promise => { + const tokenOwnerRecordPower = + tokenOwnerRecord?.account.governingTokenDepositAmount ?? new BN(0) + + const startingWeight: CalculatedWeight = { + value: tokenOwnerRecordPower, + initialValue: tokenOwnerRecordPower, + details: [], + } + + const reducer = async ( + inputVoterWeight: CalculatedWeight, + nextPlugin: VoterWeightPluginInfo + ): Promise => { + if (inputVoterWeight.value === null) return inputVoterWeight + + try { + const nextWeight = await nextPlugin.client.calculateVoterWeight( + walletPublicKey, + realmPublicKey, + governanceMintPublicKey, + inputVoterWeight.value + ) + return handlePluginSuccess(inputVoterWeight, nextPlugin, nextWeight) + } catch (error) { + return handlePluginError(inputVoterWeight, nextPlugin, error) + } + } + + return reduceAsync( + plugins, + reducer, + startingWeight + ) +} + +export const calculateMaxVoterWeight = async ({ + realmPublicKey, + governanceMintPublicKey, + plugins, + configuredMaxVoteWeight, +}: CalculateMaxVoterWeightParams): Promise => { + const startingWeight: CalculatedWeight = { + value: configuredMaxVoteWeight, + initialValue: configuredMaxVoteWeight, + details: [], + } + + const reducer = async ( + inputVoterWeight: CalculatedWeight, + nextPlugin: VoterWeightPluginInfo + ): Promise => { + if (inputVoterWeight.value === null) return inputVoterWeight + + try { + const nextWeight = await nextPlugin.client.calculateMaxVoterWeight( + realmPublicKey, + governanceMintPublicKey, + inputVoterWeight.value + ) + + return handlePluginSuccess(inputVoterWeight, nextPlugin, nextWeight) + } catch (error) { + return handlePluginError(inputVoterWeight, nextPlugin, error) + } + } + + return reduceAsync( + plugins, + reducer, + startingWeight + ) +} diff --git a/VoterWeightPlugins/lib/createMaxVoterWeight.ts b/VoterWeightPlugins/lib/createMaxVoterWeight.ts new file mode 100644 index 0000000000..4a8033e632 --- /dev/null +++ b/VoterWeightPlugins/lib/createMaxVoterWeight.ts @@ -0,0 +1,49 @@ +import { + PublicKey, + TransactionInstruction, +} from '@solana/web3.js' +import {VoterWeightPluginInfo} from "./types"; + +interface CreateMaxVoterWeightRecordArgs { + realmPublicKey: PublicKey + governanceMintPublicKey: PublicKey + plugins?: VoterWeightPluginInfo[] +} + +export const createMaxVoterWeight = async ({ + realmPublicKey, + governanceMintPublicKey, + plugins = [], +}: CreateMaxVoterWeightRecordArgs): Promise => { + const ixes: TransactionInstruction[] = [] + + for (const plugin of plugins) { + const client = plugin.client + + const voterWeightRecord = await client.getMaxVoterWeightRecord( + realmPublicKey, + governanceMintPublicKey, + ) + + if (!voterWeightRecord) { + const ix = await client.createMaxVoterWeightRecord( + realmPublicKey, + governanceMintPublicKey + ) + if (ix) ixes.push(ix) + } + + const maxVoterWeightRecord = await client.getMaxVoterWeightRecord( + realmPublicKey, + governanceMintPublicKey + ) + if (!maxVoterWeightRecord) { + const ix = await client.createMaxVoterWeightRecord( + realmPublicKey, + governanceMintPublicKey + ) + if (ix) ixes.push(ix) + } + } + return ixes +} diff --git a/VoterWeightPlugins/lib/createVoterWeight.ts b/VoterWeightPlugins/lib/createVoterWeight.ts new file mode 100644 index 0000000000..b37554d285 --- /dev/null +++ b/VoterWeightPlugins/lib/createVoterWeight.ts @@ -0,0 +1,41 @@ +import { + PublicKey, + TransactionInstruction, +} from '@solana/web3.js' +import {VoterWeightPluginInfo} from "./types"; + +interface CreateVoterWeightRecordArgs { + walletPublicKey: PublicKey + realmPublicKey: PublicKey + governanceMintPublicKey: PublicKey + plugins?: VoterWeightPluginInfo[] +} + +export const createVoterWeight = async ({ + walletPublicKey, + realmPublicKey, + governanceMintPublicKey, + plugins = [], +}: CreateVoterWeightRecordArgs): Promise => { + const ixes: TransactionInstruction[] = [] + + for (const plugin of plugins) { + const client = plugin.client + + const voterWeightRecord = await client.getVoterWeightRecord( + realmPublicKey, + governanceMintPublicKey, + walletPublicKey + ) + + if (!voterWeightRecord) { + const ix = await client.createVoterWeightRecord( + walletPublicKey, + realmPublicKey, + governanceMintPublicKey + ) + if (ix) ixes.push(ix) + } + } + return ixes +} diff --git a/VoterWeightPlugins/lib/getPlugins.ts b/VoterWeightPlugins/lib/getPlugins.ts new file mode 100644 index 0000000000..2c3d4ab7ab --- /dev/null +++ b/VoterWeightPlugins/lib/getPlugins.ts @@ -0,0 +1,134 @@ +import { PublicKey, Connection } from '@solana/web3.js' +import { fetchRealmConfigQuery } from '@hooks/queries/realmConfig' +import { findPluginName, PluginName } from '@constants/plugins' +import { loadClient } from '../clients/' +import { Provider, Wallet } from '@coral-xyz/anchor' +import { getRegistrarPDA as getPluginRegistrarPDA } from '@utils/plugin/accounts' +import { PluginType, VoterWeightPluginInfo } from './types' +import BN from 'bn.js' +import { fetchRealmByPubkey } from '@hooks/queries/realm' + +const getInitialPluginProgramId = async ( + realmPublicKey: PublicKey, + governanceMintPublicKey: PublicKey, + connection: Connection, + type: PluginType +): Promise => { + const config = await fetchRealmConfigQuery(connection, realmPublicKey) + const realm = await fetchRealmByPubkey(connection, realmPublicKey) + const kind = realm.result?.account.communityMint.equals( + governanceMintPublicKey + ) + ? 'community' + : 'council' + + const governanceConfig = + config.result?.account?.[ + kind === 'community' ? 'communityTokenConfig' : 'councilTokenConfig' + ] + return type === 'voterWeight' + ? governanceConfig?.voterWeightAddin + : governanceConfig?.maxVoterWeightAddin +} + +const weightForWallet = async ( + client: any, + realmPublicKey: PublicKey, + governanceMintPublicKey: PublicKey, + wallet: PublicKey, + type: PluginType +): Promise => { + if (type === 'voterWeight') { + const voterWeightRecord = (await client.getVoterWeightRecord( + realmPublicKey, + governanceMintPublicKey, + wallet + )) as { voterWeight: BN } | null + return voterWeightRecord?.voterWeight + } else { + // this is slightly inefficient, since this section does not depend on the input wallet + // For wallets with a large amount of delegators, it might be noticeable if caching is not happening correctly. + // If so, it should be optimised. + const maxVoterWeightRecord = (await client.getMaxVoterWeightRecord( + realmPublicKey, + governanceMintPublicKey + )) as { maxVoterWeight: BN } | null + return maxVoterWeightRecord?.maxVoterWeight + } +} + +export const getPlugins = async ({ + realmPublicKey, + governanceMintPublicKey, + provider, + type, + wallets, + signer, +}: { + realmPublicKey: PublicKey + governanceMintPublicKey: PublicKey + provider: Provider + type: PluginType + wallets: PublicKey[] + signer: Wallet +}): Promise => { + const plugins: VoterWeightPluginInfo[] = [] + let programId = await getInitialPluginProgramId( + realmPublicKey, + governanceMintPublicKey, + provider.connection, + type + ) + + if (programId) { + // build plugin list till we get null, which means we are at the end of the plugin chain + do { + const pluginName = findPluginName(programId) + const client = await loadClient( + pluginName as PluginName, + programId, + provider, + signer + ) + + // obtain the currently stored on-chain voter weight or max voter weight depending on the passed-in type + const weights: (BN | undefined)[] = await Promise.all( + wallets.map((wallet) => + weightForWallet( + client, + realmPublicKey, + governanceMintPublicKey, + wallet, + type + ) + ) + ) + + const { registrar: registrarPublicKey } = getPluginRegistrarPDA( + realmPublicKey, + governanceMintPublicKey, + programId, + pluginName + ) + + const registrarData = await client.getRegistrarAccount( + realmPublicKey, + governanceMintPublicKey + ) + + plugins.push({ + client, + programId, + name: pluginName as PluginName, + type, + weights, + registrarPublicKey, + params: registrarData ?? {}, + }) + + programId = registrarData?.previousVoterWeightPluginProgramId + } while (programId) + } + + return plugins.reverse() +} diff --git a/VoterWeightPlugins/lib/types.ts b/VoterWeightPlugins/lib/types.ts new file mode 100644 index 0000000000..f3bc5bf52a --- /dev/null +++ b/VoterWeightPlugins/lib/types.ts @@ -0,0 +1,45 @@ +import {PublicKey} from "@solana/web3.js"; +import {BN, Idl} from "@coral-xyz/anchor"; +import {PluginName} from "@constants/plugins"; +import {Client} from "@solana/governance-program-library"; +import {RealmConfig} from "@solana/spl-governance"; + +export type PluginType = 'voterWeight' | 'maxVoterWeight' + +export type UseVoterWeightPluginsArgs = { + realmPublicKey?: PublicKey + governanceMintPublicKey?: PublicKey + walletPublicKeys?: PublicKey[], + realmConfig?: RealmConfig +} + +export type VoterWeightPluginInfo = { + programId: PublicKey + name: PluginName + params: TParams + type: PluginType + weights: (BN | undefined)[] | undefined // the weight after applying this plugin + registrarPublicKey: PublicKey + client: Client +} + +export type VoterWeightPlugins = Record + +export type CalculatedWeight = { + value: BN | null // null means "something went wrong", if we are not still loading + initialValue: BN | null // The initial voter weight, before any plugins were applied + details: ({ + pluginName: PluginName + } & ({ + pluginWeight: null + error: Error + }|{ + pluginWeight: BN + error: null + }))[] +} + +export interface useVoterWeightPluginReadinessReturnType { + isReady: boolean //defines if the plugin is loading + isEnabled: boolean //defines if the plugin is enabled in the realm +} \ No newline at end of file diff --git a/VoterWeightPlugins/lib/updateMaxVoterWeight.ts b/VoterWeightPlugins/lib/updateMaxVoterWeight.ts new file mode 100644 index 0000000000..b41032a794 --- /dev/null +++ b/VoterWeightPlugins/lib/updateMaxVoterWeight.ts @@ -0,0 +1,28 @@ +import { + PublicKey, + TransactionInstruction, +} from '@solana/web3.js' +import {VoterWeightPluginInfo} from "./types"; + +interface UpdateMaxVoterWeightRecordArgs { + realmPublicKey: PublicKey + governanceMintPublicKey: PublicKey + plugins?: VoterWeightPluginInfo[] +} + +export const updateMaxVoterWeight = async ({ + realmPublicKey, + governanceMintPublicKey, + plugins = [], +}: UpdateMaxVoterWeightRecordArgs): Promise => { + const ixes: TransactionInstruction[] = [] + + for (const plugin of plugins) { + const updateMaxVoterWeightRecordIx = await plugin.client.updateMaxVoterWeightRecord( + realmPublicKey, + governanceMintPublicKey + ) + if (updateMaxVoterWeightRecordIx) ixes.push(updateMaxVoterWeightRecordIx) + } + return ixes +} diff --git a/VoterWeightPlugins/lib/updateVoterWeight.ts b/VoterWeightPlugins/lib/updateVoterWeight.ts new file mode 100644 index 0000000000..cb778e0ad9 --- /dev/null +++ b/VoterWeightPlugins/lib/updateVoterWeight.ts @@ -0,0 +1,51 @@ +import { + PublicKey, + TransactionInstruction, +} from '@solana/web3.js' +import {VoterWeightAction} from "@solana/spl-governance"; +import {VoterWeightPluginInfo} from "./types"; + +interface UpdateVoterWeightRecordArgs { + walletPublicKey: PublicKey + realmPublicKey: PublicKey + governanceMintPublicKey: PublicKey + plugins?: VoterWeightPluginInfo[] + action?: VoterWeightAction + target?: PublicKey +} + +export const updateVoterWeight = async ({ + walletPublicKey, + realmPublicKey, + governanceMintPublicKey, + plugins = [], + action, + target +}: UpdateVoterWeightRecordArgs): Promise<{ pre: TransactionInstruction[], post: TransactionInstruction[]}> => { + const preIxes: TransactionInstruction[] = [] + const postIxes: TransactionInstruction[] = [] + + // This callback returns the previous plugin's voter weight record PDA + // We pass it into the current plugin's updateVoterWeightRecord method + // so that it knows what the previous voter weight record was. + // Most VWRs are derived the same way, but some (e.g. VSR) use a different derivation + // function, so this decouples the plugins in this regard. + let getVoterWeightRecordCallback: (() => Promise) | undefined = undefined; + + for (const plugin of plugins) { + const updateVoterWeightRecordIx = await plugin.client.updateVoterWeightRecord( + walletPublicKey, + realmPublicKey, + governanceMintPublicKey, + action, + getVoterWeightRecordCallback, + target + ) + preIxes.push(...updateVoterWeightRecordIx.pre) + postIxes.push(...updateVoterWeightRecordIx.post || []) + + getVoterWeightRecordCallback = async () => (await plugin.client.getVoterWeightRecordPDA(realmPublicKey, governanceMintPublicKey, walletPublicKey)).voterWeightPk + } + + return { pre: preIxes, post: postIxes } +} diff --git a/VoterWeightPlugins/lib/utils.ts b/VoterWeightPlugins/lib/utils.ts new file mode 100644 index 0000000000..4599581f52 --- /dev/null +++ b/VoterWeightPlugins/lib/utils.ts @@ -0,0 +1,59 @@ +import {PublicKey} from "@solana/web3.js"; +import {GOVERNANCE_PROGRAM_SEED, VoterWeightAction} from "@solana/spl-governance"; +import {DEFAULT_GOVERNANCE_PROGRAM_ID} from "@solana/governance-program-library"; +import {UpdateVoterWeightRecordTypes} from "@utils/uiTypes/VotePlugin"; + +export const reduceAsync = async ( + arr: TElem[], + reducer: ( + acc: Awaited, + item: TElem + ) => Promise, + initialValue: TOut +): Promise => + arr.reduce(async (acc, item) => reducer(await acc, item), Promise.resolve(initialValue)) + +type PublicKeyMap = { + [key: string]: PublicKey | undefined; +} + +/** + * Used to cache react-query responses. + * Convert to strings to avoid object equality issues. + * @param args + */ +export const queryKeys = (args: PublicKeyMap) => + Object.values(args) + .filter((value): value is PublicKey => value !== undefined) + .map((value) => value.toString()) + +// A synchronous version of the getTokenOwnerRecordAddress function in @solana/spl-governance +// More convenient to use in hooks +export const getTokenOwnerRecordAddressSync = (realm: PublicKey, mint: PublicKey, voter: PublicKey, programId = DEFAULT_GOVERNANCE_PROGRAM_ID) => + PublicKey.findProgramAddressSync([ + Buffer.from(GOVERNANCE_PROGRAM_SEED), + realm.toBuffer(), + mint.toBuffer(), + voter.toBuffer(), + ], programId) + + +export function convertVoterWeightActionToType(action: VoterWeightAction): UpdateVoterWeightRecordTypes { + switch (action) { + case VoterWeightAction.CastVote: return "castVote"; + case VoterWeightAction.CommentProposal: return "commentProposal"; + case VoterWeightAction.CreateGovernance: return "createGovernance"; + case VoterWeightAction.CreateProposal: return "createProposal"; + case VoterWeightAction.SignOffProposal: return "signOffProposal"; + } +} + +export const convertTypeToVoterWeightAction = (type: UpdateVoterWeightRecordTypes): VoterWeightAction => { + switch (type) { + case "castVote": return VoterWeightAction.CastVote; + case "commentProposal": return VoterWeightAction.CommentProposal; + case "createGovernance": return VoterWeightAction.CreateGovernance; + case "createProposal": return VoterWeightAction.CreateProposal; + case "signOffProposal": return VoterWeightAction.SignOffProposal; + } +} \ No newline at end of file diff --git a/VoterWeightPlugins/useGatewayVoterWeightPlugin.ts b/VoterWeightPlugins/useGatewayVoterWeightPlugin.ts new file mode 100644 index 0000000000..fc936b4592 --- /dev/null +++ b/VoterWeightPlugins/useGatewayVoterWeightPlugin.ts @@ -0,0 +1,36 @@ +import { GATEWAY_PLUGINS_PKS } from '@constants/plugins' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' + +import { useVoterWeightPluginReadinessReturnType } from './lib/types' +import { PublicKey } from '@solana/web3.js' +import {GatewayClient} from "@solana/governance-program-library"; + +export interface useGatewayVoterWeightPluginReturnType + extends useVoterWeightPluginReadinessReturnType { + gatekeeperNetwork: PublicKey | undefined + gatewayClient: GatewayClient +} + +type GatewayPluginParams = { + gatekeeperNetwork: PublicKey | undefined +} + +export const useGatewayVoterWeightPlugin = (): useGatewayVoterWeightPluginReturnType => { + const { isReady, plugins } = useRealmVoterWeightPlugins() + + const gatewayPlugin = plugins?.voterWeight.find((plugin) => + GATEWAY_PLUGINS_PKS.includes(plugin.programId.toString()) + ) + + const isEnabled = gatewayPlugin !== undefined + const gatekeeperNetwork = ( + (gatewayPlugin?.params as GatewayPluginParams) || undefined + )?.gatekeeperNetwork + + return { + isReady, + gatekeeperNetwork, + isEnabled, + gatewayClient: gatewayPlugin?.client as GatewayClient, + } +} diff --git a/VoterWeightPlugins/useHeliumClient.ts b/VoterWeightPlugins/useHeliumClient.ts new file mode 100644 index 0000000000..c9af5a864a --- /dev/null +++ b/VoterWeightPlugins/useHeliumClient.ts @@ -0,0 +1,26 @@ +import { HELIUM_VSR_PLUGINS_PKS} from '@constants/plugins' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' + +import { useVoterWeightPluginReadinessReturnType } from './lib/types' +import {HeliumVsrClient} from "../HeliumVotePlugin/sdk/client"; + +export interface useHeliumClientReturnType + extends useVoterWeightPluginReadinessReturnType { + heliumClient: HeliumVsrClient | undefined +} + +export const useHeliumClient = (): useHeliumClientReturnType => { + const { isReady, plugins } = useRealmVoterWeightPlugins() + + const heliumPlugin = plugins?.voterWeight.find((plugin) => + HELIUM_VSR_PLUGINS_PKS.includes(plugin.programId.toString()) + ) + + const isEnabled = heliumPlugin !== undefined + + return { + isReady, + heliumClient: heliumPlugin?.client as HeliumVsrClient, + isEnabled, + } +} diff --git a/VoterWeightPlugins/useNftClient.ts b/VoterWeightPlugins/useNftClient.ts new file mode 100644 index 0000000000..0ca7289cb0 --- /dev/null +++ b/VoterWeightPlugins/useNftClient.ts @@ -0,0 +1,28 @@ +import {NFT_PLUGINS_PKS} from '@constants/plugins' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' + +import {useVoterWeightPluginReadinessReturnType, VoterWeightPluginInfo} from './lib/types' +import {NftVoterClient} from "@utils/uiTypes/NftVoterClient"; + +export interface useNftClientReturnType + extends useVoterWeightPluginReadinessReturnType { + nftClient: NftVoterClient | undefined + plugin: VoterWeightPluginInfo | undefined +} + +export const useNftClient = (): useNftClientReturnType => { + const { isReady, plugins } = useRealmVoterWeightPlugins() + + const plugin = plugins?.voterWeight.find((plugin) => + NFT_PLUGINS_PKS.includes(plugin.programId.toString()) + ) + + const isEnabled = plugin !== undefined + + return { + isReady, + nftClient: plugin?.client as NftVoterClient, + plugin, + isEnabled, + } +} diff --git a/VoterWeightPlugins/useQuadraticVoterWeightPlugin.ts b/VoterWeightPlugins/useQuadraticVoterWeightPlugin.ts new file mode 100644 index 0000000000..58df5482b2 --- /dev/null +++ b/VoterWeightPlugins/useQuadraticVoterWeightPlugin.ts @@ -0,0 +1,34 @@ +import { QV_PLUGINS_PKS } from '@constants/plugins' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' + +import { useVoterWeightPluginReadinessReturnType } from './lib/types' + +export interface useQuadraticVoterWeightPluginReturnType + extends useVoterWeightPluginReadinessReturnType { + coefficients: Coefficients +} + +export type Coefficients = [a: number, b: number, c: number] + +export type QuadraticPluginParams = { + quadraticCoefficients: Coefficients +} + +export const useQuadraticVoterWeightPlugin = (): useQuadraticVoterWeightPluginReturnType => { + const { isReady, plugins } = useRealmVoterWeightPlugins() + + const quadraticPlugin = plugins?.voterWeight.find((plugin) => + QV_PLUGINS_PKS.includes(plugin.programId.toString()) + ) + + const isEnabled = quadraticPlugin !== undefined + const coefficients = ( + (quadraticPlugin?.params as QuadraticPluginParams) || undefined + )?.quadraticCoefficients + + return { + isReady, + coefficients, + isEnabled, + } +} diff --git a/VoterWeightPlugins/useVoterWeightPlugins.ts b/VoterWeightPlugins/useVoterWeightPlugins.ts new file mode 100644 index 0000000000..98c145e34c --- /dev/null +++ b/VoterWeightPlugins/useVoterWeightPlugins.ts @@ -0,0 +1,200 @@ +/** + * This is the *main* voter weight plugin hook. It exposes everything the rest of the code should need to know about voter weight plugins, including: + * - the calculated voter weights based on the realm's plugin configuration + * - the list of plugins, their names and details + * - a number of functions for creating plugin instructions (e.g. updateVoterWeightRecord etc) + * Notably not included in here are functions to cast vote or any other instructions on the spl-governance program. + * Although these occasionally differ per plugin (castNftVote), they are typically generic and receive a voter weight record as an input. + * + * This hook deliberately avoids using other hooks in the realms UI. In principle, this allows it to be exported to a separate npm library and used in other SPL-Governance UIs in the future. + * + * Realms itself should prefer useRealmVoterWeightPlugins which is a convenience wrapper for this hook. + */ +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import queryClient from '@hooks/queries/queryClient' +import { updateVoterWeight } from './lib/updateVoterWeight' +import { createVoterWeight } from './lib/createVoterWeight' +import { + CalculatedWeight, PluginType, + UseVoterWeightPluginsArgs, + VoterWeightPlugins, +} from './lib/types' +import { createMaxVoterWeight } from './lib/createMaxVoterWeight' +import { updateMaxVoterWeight } from './lib/updateMaxVoterWeight' +import {useMintInfoByPubkeyQuery} from '@hooks/queries/mintInfo' +import { useCalculatedVoterWeights } from './hooks/useCalculatedVoterWeights' +import { useCalculatedMaxVoterWeight } from './hooks/useCalculatedMaxVoterWeight' +import { usePlugins } from './hooks/usePlugins' +import { queryKeys } from './lib/utils' +import { useVoterWeightPks } from './hooks/useVoterWeightPks' +import { PluginName } from '@constants/plugins' +import {ProgramAccount, TokenOwnerRecord, VoterWeightAction} from "@solana/spl-governance"; +import {useTokenOwnerRecordsDelegatedToUser} from "@hooks/queries/tokenOwnerRecord"; +import {useTokenOwnerRecord} from "./hooks/useTokenOwnerRecord"; + +/** + * Represents the return type of the `useVoterWeightPlugins` hook. + */ +export interface UseVoterWeightPluginsReturnType { + isReady: boolean + plugins: VoterWeightPlugins | undefined // undefined means we are still loading + updateVoterWeightRecords: (walletPk: PublicKey, action?: VoterWeightAction, target?: PublicKey) => Promise<{ + pre: TransactionInstruction[] + post: TransactionInstruction[] + }> + createVoterWeightRecords: (walletPk: PublicKey) => Promise + updateMaxVoterWeightRecords: () => Promise + createMaxVoterWeightRecords: () => Promise + calculatedVoterWeights: CalculatedWeight[] | undefined // undefined means we are still loading + calculatedMaxVoterWeight: CalculatedWeight | undefined // undefined means we are still loading + voterWeightPks: PublicKey[] | undefined // the voter weight pubkeys to be used in the governance instruction itself + maxVoterWeightPk: PublicKey | undefined // the max voter weight pubkey to be used in the governance instruction itself + + //auxiliary functions to the ui + includesPlugin: (name: PluginName) => boolean +} + +/** + * Retrieves voter weight plugin information, calculated voter weights and provides functions to create/update voter weight records. + * + * @returns {UseVoterWeightPluginsReturnType} + * @param args + */ +export const useVoterWeightPlugins = ( + args: UseVoterWeightPluginsArgs +): UseVoterWeightPluginsReturnType => { + const { realmPublicKey, governanceMintPublicKey, walletPublicKeys } = args + const mintInfo = useMintInfoByPubkeyQuery(args.governanceMintPublicKey).data?.result; + const walletTokenOwnerRecord = useTokenOwnerRecord(args.governanceMintPublicKey); + const delegatedTokenOwnerRecords = useTokenOwnerRecordsDelegatedToUser().data; + const { data: plugins } = usePlugins(args) + const { result: calculatedVoterWeights} = useCalculatedVoterWeights({ + ...args, + plugins: plugins?.voterWeight, + tokenOwnerRecords: [walletTokenOwnerRecord, ...(delegatedTokenOwnerRecords || [])].filter(Boolean) as ProgramAccount[], + }) + const { result: calculatedMaxVoterWeight} = useCalculatedMaxVoterWeight({ + ...args, + plugins: plugins?.maxVoterWeight, + mintInfo, + realmConfig: args.realmConfig + }) + const pks = useVoterWeightPks({ + ...args, + plugins: plugins?.voterWeight, + }).result ?? { voterWeightPks: undefined, maxVoterWeightPk: undefined } + + const createVoterWeightRecords = (walletPublicKey: PublicKey): Promise => { + if (!realmPublicKey || !governanceMintPublicKey) { + return Promise.resolve([]) + } + + const queryArgs = { + realmPublicKey, + governanceMintPublicKey, + walletPublicKey, + } + + return queryClient.fetchQuery({ + queryKey: ['createVoterWeightRecords', ...queryKeys(queryArgs)], + queryFn: () => + createVoterWeight({ + walletPublicKey, + realmPublicKey, + governanceMintPublicKey, + plugins: plugins?.voterWeight, + }), + }) + } + + const updateVoterWeightRecords = (walletPublicKey: PublicKey, action?: VoterWeightAction, target?: PublicKey): Promise<{ + pre: TransactionInstruction[] + post: TransactionInstruction[] + }> => { + if (!realmPublicKey || !governanceMintPublicKey) { + return Promise.resolve({ pre: [], post: [] }) + } + + const queryArgs = { + realmPublicKey, + governanceMintPublicKey, + walletPublicKey, + } + + return queryClient.fetchQuery({ + queryKey: ['updateVoterWeightRecords', ...queryKeys(queryArgs), action], + queryFn: () => + updateVoterWeight({ + walletPublicKey, + realmPublicKey, + governanceMintPublicKey, + plugins: plugins?.voterWeight, + action, + target + }), + }) + } + + const createMaxVoterWeightRecords = (): Promise => { + if (!realmPublicKey || !governanceMintPublicKey || !walletPublicKeys) { + return Promise.resolve([]) + } + + const queryArgs = { + realmPublicKey, + governanceMintPublicKey, + } + + return queryClient.fetchQuery({ + queryKey: ['createMaxVoterWeightRecords', ...queryKeys(queryArgs)], + queryFn: () => + createMaxVoterWeight({ + realmPublicKey, + governanceMintPublicKey, + plugins: plugins?.maxVoterWeight, + }), + }) + } + + const updateMaxVoterWeightRecords = (): Promise => { + if (!realmPublicKey || !governanceMintPublicKey || !walletPublicKeys) { + return Promise.resolve([]) + } + + const queryArgs = { + realmPublicKey, + governanceMintPublicKey, + } + + return queryClient.fetchQuery({ + queryKey: ['updateMaxVoterWeightRecords', ...queryKeys(queryArgs)], + queryFn: () => + updateMaxVoterWeight({ + realmPublicKey, + governanceMintPublicKey, + plugins: plugins?.maxVoterWeight, + }), + }) + } + + const includesPlugin = (pluginName: PluginName, type: PluginType = 'voterWeight') => + plugins?.[type]?.some((plugin) => plugin.name === pluginName) || false + + // if we have the plugins, we are ready + // otherwise, if the realm exists, and the governance mint does not, we have nothing to load + // an example of this is a realm with no council token. + const isReady = plugins !== undefined || (!!realmPublicKey && !governanceMintPublicKey) + + return { + isReady, + updateVoterWeightRecords, + createVoterWeightRecords, + updateMaxVoterWeightRecords, + createMaxVoterWeightRecords, + plugins, + calculatedVoterWeights, + calculatedMaxVoterWeight, + ...pks, + includesPlugin, + } +} diff --git a/VoterWeightPlugins/useVsrClient.ts b/VoterWeightPlugins/useVsrClient.ts new file mode 100644 index 0000000000..a038d94e08 --- /dev/null +++ b/VoterWeightPlugins/useVsrClient.ts @@ -0,0 +1,28 @@ +import { VSR_PLUGIN_PKS} from '@constants/plugins' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' + +import {useVoterWeightPluginReadinessReturnType, VoterWeightPluginInfo} from './lib/types' +import {VsrClient} from "../VoteStakeRegistry/sdk/client"; + +export interface useVsrClientReturnType + extends useVoterWeightPluginReadinessReturnType { + vsrClient: VsrClient | undefined + plugin: VoterWeightPluginInfo | undefined +} + +export const useVsrClient = (): useVsrClientReturnType => { + const { isReady, plugins } = useRealmVoterWeightPlugins() + + const plugin = plugins?.voterWeight.find((plugin) => + VSR_PLUGIN_PKS.includes(plugin.programId.toString()) + ) + + const isEnabled = plugin !== undefined + + return { + isReady, + vsrClient: plugin?.client as VsrClient, + plugin, + isEnabled, + } +} diff --git a/actions/addPlugins/addGatewayPlugin.ts b/actions/addPlugins/addGatewayPlugin.ts new file mode 100644 index 0000000000..85cdaf4faf --- /dev/null +++ b/actions/addPlugins/addGatewayPlugin.ts @@ -0,0 +1,58 @@ +// During realm creation, add a plugin that provides sybil resistance protection (by default provided by civic.com) using proof of uniqueness passes +import { Connection, PublicKey } from '@solana/web3.js' +import { AnchorProvider, Wallet } from '@coral-xyz/anchor' +import { GatewayClient } from '@solana/governance-program-library' +import { getRegistrarPDA } from '@utils/plugin/accounts' +import { SYSTEM_PROGRAM_ID } from '@solana/spl-governance' +import { AddPluginResult } from './types' + +export const addGatewayPlugin = async ( + connection: Connection, + wallet: Wallet, + realmPk: PublicKey, + communityMintPk: PublicKey, + programIdPk: PublicKey, + predecessorPluginProgram: PublicKey | undefined, // if chained, set the previous plugin here + passType: PublicKey // The type of sybil resistance protection +): Promise => { + const options = AnchorProvider.defaultOptions() + const provider = new AnchorProvider(connection, wallet as Wallet, options) + const isDevnet = connection.rpcEndpoint.includes('devnet') + const gatewayClient = await GatewayClient.connect(provider, isDevnet) + + const { registrar } = await getRegistrarPDA( + realmPk, + communityMintPk, + gatewayClient.program.programId + ) + + const gatewayRegistrarInstruction = await gatewayClient.program.methods + .createRegistrar(!!predecessorPluginProgram) // chain with the previous if it exists + .accounts({ + registrar, + realm: realmPk, + governanceProgramId: programIdPk, + realmAuthority: wallet.publicKey, // the realm authority is not yet transferred to the Realm PDA + governingTokenMint: communityMintPk, + gatekeeperNetwork: passType, + payer: wallet.publicKey, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .remainingAccounts( + predecessorPluginProgram + ? [ + { + pubkey: predecessorPluginProgram, + isWritable: false, + isSigner: false, + }, + ] + : [] + ) + .instruction() + + return { + pluginProgramId: gatewayClient.program.programId, + instructions: [gatewayRegistrarInstruction], + } +} diff --git a/actions/addPlugins/addQVPlugin.ts b/actions/addPlugins/addQVPlugin.ts new file mode 100644 index 0000000000..e9805c5626 --- /dev/null +++ b/actions/addPlugins/addQVPlugin.ts @@ -0,0 +1,96 @@ +// During realm creation, add a plugin that adapts the vote via the quadratic formula ax^1/2 + bx + c +import { Connection, PublicKey } from '@solana/web3.js' +import { AnchorProvider, Wallet } from '@coral-xyz/anchor' +import { + DEFAULT_COEFFICIENTS, + toAnchorType, +} from '../../QuadraticPlugin/sdk/api' +import {Coefficients, QuadraticClient} from '@solana/governance-program-library' +import { getRegistrarPDA } from '@utils/plugin/accounts' +import { SYSTEM_PROGRAM_ID } from '@solana/spl-governance' +import { AddPluginResult } from './types' +import { fetchMintInfoByPubkey } from '@hooks/queries/mintInfo' +import { DEFAULT_MINT_DECIMALS } from '@tools/governance/prepareRealmCreation' + +// if the user has set coefficients, use them, otherwise use the default +// by default 'a' is set to the square root of 10^decimals where decimals is the number of decimals of the mint +// 'b' and 'c' are set to 0 by default, but can be overridden by the user +export async function getCoefficients( + coefficientsFromForm: Coefficients | undefined, + existingCommunityMintPk: PublicKey | undefined, + connection: Connection +): Promise { + let qvCoefficients = coefficientsFromForm + if (!qvCoefficients) { + const existingCommunityMint = existingCommunityMintPk + ? (await fetchMintInfoByPubkey(connection, existingCommunityMintPk)) + .result + : undefined + const communityMintDecimals = + existingCommunityMint?.decimals || DEFAULT_MINT_DECIMALS + const aCoefficient = Math.sqrt(10 ** communityMintDecimals) // sqrt(10^6)=1000 for a 6 decimal token + qvCoefficients = [ + aCoefficient, + DEFAULT_COEFFICIENTS[1], + DEFAULT_COEFFICIENTS[2], + ] + } + return qvCoefficients +} + +export const addQVPlugin = async ( + connection: Connection, + wallet: Wallet, + realmPk: PublicKey, + communityMintPk: PublicKey, + programIdPk: PublicKey, + predecessorPluginProgram: PublicKey | undefined, // if chained, set the previous plugin here + coefficientsFromForm: Coefficients | undefined, + existingCommunityMintPk: PublicKey | undefined +): Promise => { + const qvCoefficients = await getCoefficients( + coefficientsFromForm, + existingCommunityMintPk, + connection + ) + + const options = AnchorProvider.defaultOptions() + const provider = new AnchorProvider(connection, wallet as Wallet, options) + const isDevnet = connection.rpcEndpoint.includes('devnet') + const quadraticClient = await QuadraticClient.connect(provider, isDevnet) + + const { registrar } = await getRegistrarPDA( + realmPk, + communityMintPk, + quadraticClient.program.programId + ) + + const qvRegistrarInstruction = await quadraticClient.program.methods + .createRegistrar(toAnchorType(qvCoefficients), !!predecessorPluginProgram) // chain with the previous if it exists + .accounts({ + registrar, + realm: realmPk, + governanceProgramId: programIdPk, + realmAuthority: wallet.publicKey, // the realm authority is not yet transferred to the Realm PDA + governingTokenMint: communityMintPk, + payer: wallet.publicKey, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .remainingAccounts( + predecessorPluginProgram + ? [ + { + pubkey: predecessorPluginProgram, + isWritable: false, + isSigner: false, + }, + ] + : [] + ) + .instruction() + + return { + pluginProgramId: quadraticClient.program.programId, + instructions: [qvRegistrarInstruction], + } +} diff --git a/actions/addPlugins/types.ts b/actions/addPlugins/types.ts new file mode 100644 index 0000000000..4218e20605 --- /dev/null +++ b/actions/addPlugins/types.ts @@ -0,0 +1,6 @@ +import {PublicKey, TransactionInstruction} from "@solana/web3.js"; + +export type AddPluginResult = { + pluginProgramId: PublicKey, + instructions: TransactionInstruction[] +} \ No newline at end of file diff --git a/actions/cancelProposal.ts b/actions/cancelProposal.ts index c3a345107a..f017e9f345 100644 --- a/actions/cancelProposal.ts +++ b/actions/cancelProposal.ts @@ -1,20 +1,22 @@ -import { - Keypair, - PublicKey, - Transaction, - TransactionInstruction, -} from '@solana/web3.js' +import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js' -import { getGovernanceProgramVersion, RpcContext } from '@solana/spl-governance' +import { + RpcContext, + TokenOwnerRecord, + withRefundProposalDeposit, +} from '@solana/spl-governance' import { Proposal } from '@solana/spl-governance' import { ProgramAccount } from '@solana/spl-governance' -import { sendTransaction } from 'utils/send' import { withCancelProposal } from '@solana/spl-governance' +import { getProposalDepositPk } from '@utils/helpers' +import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' +import { SequenceType, sendTransactionsV3 } from '@utils/sendTransactions' export const cancelProposal = async ( { connection, wallet, programId, walletPubkey }: RpcContext, realmPk: PublicKey, - proposal: ProgramAccount | undefined + proposal: ProgramAccount | undefined, + proposalOwner: ProgramAccount ) => { const instructions: TransactionInstruction[] = [] const signers: Keypair[] = [] @@ -22,10 +24,7 @@ export const cancelProposal = async ( // Explicitly request the version before making RPC calls to work around race conditions in resolving // the version for RealmInfo - const programVersion = await getGovernanceProgramVersion( - connection, - programId - ) + const programVersion = await fetchProgramVersion(connection, programId) withCancelProposal( instructions, @@ -38,16 +37,63 @@ export const cancelProposal = async ( governanceAuthority ) - const transaction = new Transaction({ feePayer: walletPubkey }) + //its possible that delegate payed for deposit created with someone else token owner record. + //there is need of check both deposits. + const [possibleDelegateDeposit, possibleTorDeposit] = [ + proposalOwner.account.governanceDelegate + ? getProposalDepositPk( + proposal!.pubkey, + proposalOwner.account.governanceDelegate, + programId + ) + : null, + getProposalDepositPk( + proposal!.pubkey, + proposalOwner.account.governingTokenOwner, + programId + ), + ] - transaction.add(...instructions) + //Release sol if deposit exempt setting threshold hit + const [delegateDeposit, torDeposit] = await Promise.all([ + possibleDelegateDeposit + ? connection.getBalance(possibleDelegateDeposit) + : null, + connection.getBalance(possibleTorDeposit), + ]) - await sendTransaction({ - transaction, - wallet, + let refundAddress + if (delegateDeposit && delegateDeposit > 0 && possibleDelegateDeposit) { + refundAddress = proposalOwner.account.governanceDelegate + } else if (torDeposit && torDeposit > 0) { + refundAddress = proposalOwner.account.governingTokenOwner + } + + if (refundAddress) { + await withRefundProposalDeposit( + instructions, + programId!, + programVersion, + proposal!.pubkey, + refundAddress + ) + } + + const txes = [instructions].map((txBatch) => { + return { + instructionsSet: txBatch.map((x) => { + return { + transactionInstruction: x, + signers: signers, + } + }), + sequenceType: SequenceType.Sequential, + } + }) + + await sendTransactionsV3({ connection, - signers, - sendingMessage: 'Cancelling proposal', - successMessage: 'Proposal cancelled', + wallet, + transactionInstructions: txes, }) } diff --git a/actions/castVote.ts b/actions/castVote.ts index e3c477a38a..71aa202a1f 100644 --- a/actions/castVote.ts +++ b/actions/castVote.ts @@ -1,13 +1,22 @@ -import { Keypair, Transaction, TransactionInstruction } from '@solana/web3.js' +import { + Connection, + Keypair, + PublicKey, + TransactionInstruction, +} from '@solana/web3.js' import { ChatMessageBody, - getGovernanceProgramVersion, + GovernanceAccountType, GOVERNANCE_CHAT_PROGRAM_ID, Proposal, Realm, - TokenOwnerRecord, + VoteChoice, + VoteKind, + VoteType, withPostChatMessage, - YesNoVote, + withCreateTokenOwnerRecord, + getVoteRecordAddress, + getTokenOwnerRecord, } from '@solana/spl-governance' import { ProgramAccount } from '@solana/spl-governance' import { RpcContext } from '@solana/spl-governance' @@ -18,77 +27,297 @@ import { withCastVote } from '@solana/spl-governance' import { VotingClient } from '@utils/uiTypes/VotePlugin' import { chunks } from '@utils/helpers' import { - sendTransactionsV2, SequenceType, - transactionInstructionsToTypedInstructionsSets, + txBatchesToInstructionSetWithSigners, } from '@utils/sendTransactions' -import { sendTransaction } from '@utils/send' -import { NftVoterClient } from '@solana/governance-program-library' import { calcCostOfNftVote, checkHasEnoughSolToVote } from '@tools/nftVoteCalc' import useNftProposalStore from 'NftVotePlugin/NftProposalStore' +import { HeliumVsrClient } from 'HeliumVotePlugin/sdk/client' +import { NftVoterClient } from '@utils/uiTypes/NftVoterClient' +import { fetchRealmByPubkey } from '@hooks/queries/realm' +import { fetchProposalByPubkeyQuery } from '@hooks/queries/proposal' +import { DELEGATOR_BATCH_VOTE_SUPPORT_BY_PLUGIN } from '@constants/flags' +import { fetchTokenOwnerRecordByPubkey } from '@hooks/queries/tokenOwnerRecord' +import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' +import { fetchVoteRecordByPubkey } from '@hooks/queries/voteRecord' +import { findPluginName } from '@constants/plugins' +import { BN } from '@coral-xyz/anchor' +import { postComment } from './chat/postMessage' -export async function castVote( - { connection, wallet, programId, walletPubkey }: RpcContext, - realm: ProgramAccount, +const getVetoTokenMint = ( proposal: ProgramAccount, - tokeOwnerRecord: ProgramAccount, - yesNoVote: YesNoVote, - message?: ChatMessageBody | undefined, - votingPlugin?: VotingClient, - runAfterConfirmation?: (() => void) | null -) { - const signers: Keypair[] = [] - const instructions: TransactionInstruction[] = [] + realm: ProgramAccount +) => { + const communityMint = realm.account.communityMint + const councilMint = realm.account.config.councilMint + const governingMint = proposal.account.governingTokenMint + const vetoTokenMint = governingMint.equals(communityMint) + ? councilMint + : communityMint + if (vetoTokenMint === undefined) + throw new Error('There is no token that can veto this proposal') + return vetoTokenMint +} - const governanceAuthority = walletPubkey - const payer = walletPubkey - // Explicitly request the version before making RPC calls to work around race conditions in resolving - // the version for RealmInfo +const createDelegatorVote = async ({ + connection, + realmPk, + proposalPk, + tokenOwnerRecordPk, + delegatePk, + vote, + votingPlugin, +}: { + connection: Connection + realmPk: PublicKey + proposalPk: PublicKey + tokenOwnerRecordPk: PublicKey + delegatePk: PublicKey + vote: Vote + votingPlugin: VotingClient | undefined +}) => { + // + const realm = (await fetchRealmByPubkey(connection, realmPk)).result + if (!realm) throw new Error() + const proposal = (await fetchProposalByPubkeyQuery(connection, proposalPk)) + .result + if (!proposal) throw new Error() - const programVersion = await getGovernanceProgramVersion( - connection, - programId + if ( + !DELEGATOR_BATCH_VOTE_SUPPORT_BY_PLUGIN[ + findPluginName(votingPlugin?.client?.program.programId) + ] ) + throw new Error() + + const programVersion = await fetchProgramVersion(connection, realm.owner) - //will run only if any plugin is connected with realm - const plugin = await votingPlugin?.withCastPluginVote( - instructions, + const castVoteIxs: TransactionInstruction[] = [] + + const pluginAddresses = await votingPlugin?.withCastPluginVote( + castVoteIxs, proposal, - tokeOwnerRecord + tokenOwnerRecordPk + //createCastNftVoteTicketIxs ) - await withCastVote( - instructions, - programId, + castVoteIxs, + realm.owner, programVersion, realm.pubkey, proposal.account.governance, proposal.pubkey, proposal.account.tokenOwnerRecord, - tokeOwnerRecord.pubkey, - governanceAuthority, + tokenOwnerRecordPk, + delegatePk, proposal.account.governingTokenMint, - Vote.fromYesNoVote(yesNoVote), + vote, + delegatePk, + pluginAddresses?.voterWeightPk, + pluginAddresses?.maxVoterWeightRecord + ) + + return castVoteIxs +} + +const createTokenOwnerRecordIfNeeded = async ({ + connection, + realmPk, + tokenOwnerRecordPk, + payer, + governingTokenMint, +}: { + connection: Connection + realmPk: PublicKey + tokenOwnerRecordPk: PublicKey + payer: PublicKey + governingTokenMint: PublicKey +}) => { + const realm = await fetchRealmByPubkey(connection, realmPk) + if (!realm.result) throw new Error() + const version = await fetchProgramVersion(connection, realm.result.owner) + + const tokenOwnerRecord = await fetchTokenOwnerRecordByPubkey( + connection, + tokenOwnerRecordPk + ) + if (tokenOwnerRecord.result) return [] + // create token owner record + const ixs: TransactionInstruction[] = [] + await withCreateTokenOwnerRecord( + ixs, + realm.result.owner, + version, + realmPk, payer, - plugin?.voterWeightPk, - plugin?.maxVoterWeightRecord + governingTokenMint, + payer ) + return ixs +} + +export async function castVote( + { connection, wallet, programId, walletPubkey }: RpcContext, + realm: ProgramAccount, + proposal: ProgramAccount, + tokenOwnerRecord: PublicKey, + voteKind: VoteKind, + message?: ChatMessageBody | undefined, + votingPlugin?: VotingClient, + runAfterConfirmation?: (() => void) | null, + voteWeights?: number[], + additionalTokenOwnerRecords?: PublicKey[], + calculatedVoterWeight: BN | null = null +) { + const chatMessageSigners: Keypair[] = [] + const createCastNftVoteTicketIxs: TransactionInstruction[] = [] + const createPostMessageTicketIxs: TransactionInstruction[] = [] + + const governanceAuthority = walletPubkey + const payer = walletPubkey + // Explicitly request the version before making RPC calls to work around race conditions in resolving + // the version for RealmInfo + const programVersion = await fetchProgramVersion(connection, programId) + + const isMulti = + proposal.account.voteType !== VoteType.SINGLE_CHOICE && + proposal.account.accountType === GovernanceAccountType.ProposalV2 + + // It is not clear that defining these extraneous fields, `deny` and `veto`, is actually necessary. + // See: https://discord.com/channels/910194960941338677/910630743510777926/1044741454175674378 + const vote = isMulti + ? new Vote({ + voteType: VoteKind.Approve, + approveChoices: proposal.account.options.map((_o, index) => { + if (voteWeights?.includes(index)) { + return new VoteChoice({ rank: 0, weightPercentage: 100 }) + } else { + return new VoteChoice({ rank: 0, weightPercentage: 0 }) + } + }), + deny: undefined, + veto: undefined, + }) + : voteKind === VoteKind.Approve + ? new Vote({ + voteType: VoteKind.Approve, + approveChoices: [new VoteChoice({ rank: 0, weightPercentage: 100 })], + deny: undefined, + veto: undefined, + }) + : voteKind === VoteKind.Deny + ? new Vote({ + voteType: VoteKind.Deny, + approveChoices: undefined, + deny: true, + veto: undefined, + }) + : voteKind == VoteKind.Veto + ? new Vote({ + voteType: VoteKind.Veto, + veto: true, + deny: undefined, + approveChoices: undefined, + }) + : new Vote({ + voteType: VoteKind.Abstain, + veto: undefined, + deny: undefined, + approveChoices: undefined, + }) + + const tokenMint = + voteKind === VoteKind.Veto + ? getVetoTokenMint(proposal, realm) + : proposal.account.governingTokenMint + + const castVoteIxs: TransactionInstruction[] = [] + const pluginCastVoteIxs: TransactionInstruction[] = [] + + if (calculatedVoterWeight !== null && calculatedVoterWeight.gtn(0)) { + //will run only if any plugin is connected with realm + const plugin = await votingPlugin?.withCastPluginVote( + pluginCastVoteIxs, + proposal, + tokenOwnerRecord, + createCastNftVoteTicketIxs + ) + + await withCastVote( + castVoteIxs, + programId, + programVersion, + realm.pubkey, + proposal.account.governance, + proposal.pubkey, + proposal.account.tokenOwnerRecord, + tokenOwnerRecord, + governanceAuthority, + tokenMint, + vote, + payer, + plugin?.voterWeightPk, + plugin?.maxVoterWeightRecord + ) + } + + const delegatorCastVoteAtoms = + additionalTokenOwnerRecords && + DELEGATOR_BATCH_VOTE_SUPPORT_BY_PLUGIN[ + findPluginName(votingPlugin?.client?.program.programId) + ] + ? ( + await Promise.all( + additionalTokenOwnerRecords.map(async (tokenOwnerRecordPk) => { + // Skip vote if already voted + const voteRecordPk = await getVoteRecordAddress( + realm.owner, + proposal.pubkey, + tokenOwnerRecordPk + ) + const voteRecord = await fetchVoteRecordByPubkey( + connection, + voteRecordPk + ) + if (voteRecord.found) return undefined + + const torOwnerPk = ( + await getTokenOwnerRecord(connection, tokenOwnerRecordPk) + ).account.governingTokenOwner + + return createDelegatorVote({ + connection, + realmPk: realm.pubkey, + proposalPk: proposal.pubkey, + tokenOwnerRecordPk, + delegatePk: walletPubkey, + vote, + votingPlugin: votingPlugin?.for(torOwnerPk), + }) + }) + ) + ).filter((x): x is NonNullable => x !== undefined) + : [] + + const pluginPostMessageIxs: TransactionInstruction[] = [] + const postMessageIxs: TransactionInstruction[] = [] if (message) { const plugin = await votingPlugin?.withUpdateVoterWeightRecord( - instructions, - tokeOwnerRecord, - 'commentProposal' + pluginPostMessageIxs, + 'commentProposal', + createPostMessageTicketIxs ) + await withPostChatMessage( - instructions, - signers, + postMessageIxs, + chatMessageSigners, GOVERNANCE_CHAT_PROGRAM_ID, programId, realm.pubkey, proposal.account.governance, proposal.pubkey, - tokeOwnerRecord.pubkey, + tokenOwnerRecord, governanceAuthority, payer, undefined, @@ -96,85 +325,173 @@ export async function castVote( plugin?.voterWeightPk ) } - const shouldChunk = votingPlugin?.client instanceof NftVoterClient - const instructionsCountThatMustHaveTheirOwnChunk = message ? 4 : 2 - if (shouldChunk) { + + const isNftVoter = votingPlugin?.client instanceof NftVoterClient + const isHeliumVoter = votingPlugin?.client instanceof HeliumVsrClient + const tokenOwnerRecordIxs = await createTokenOwnerRecordIfNeeded({ + connection, + realmPk: realm.pubkey, + tokenOwnerRecordPk: tokenOwnerRecord, + payer, + governingTokenMint: tokenMint, + }) + + if (!isNftVoter && !isHeliumVoter) { + const batch1 = [ + ...tokenOwnerRecordIxs, + ...pluginCastVoteIxs, + ...castVoteIxs, + ...pluginPostMessageIxs, + ...postMessageIxs, + ] + // chunk size chosen conservatively. "Atoms" refers to atomic clusters of instructions (namely, updatevoterweight? + vote) + const delegatorBatches = chunks(delegatorCastVoteAtoms, 2).map((x) => + x.flat() + ) + const actions = [batch1, ...delegatorBatches].map((ixs) => ({ + instructionsSet: ixs.map((ix) => ({ + transactionInstruction: ix, + signers: chatMessageSigners.filter((kp) => + ix.keys.find((key) => key.isSigner && key.pubkey.equals(kp.publicKey)) + ), + })), + sequenceType: SequenceType.Parallel, + })) + + await postComment({ + connection, + wallet, + transactionInstructions: actions, + callbacks: { + afterAllTxConfirmed: () => { + if (runAfterConfirmation) { + runAfterConfirmation() + } + }, + }, + }) + } + + // we need to chunk instructions + if (isHeliumVoter) { + // @asktree: I'm aware of no rationale for chunking in this particular manner + const chunkerz = chunks( + [ + ...pluginCastVoteIxs, + ...castVoteIxs, + ...pluginPostMessageIxs, + ...postMessageIxs, + ], + 2 + ) + + const ixsChunks = chunkerz.map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + message ? [[], chatMessageSigners] : [], // seeing signer related bugs when posting chat? This is likely culprit + batchIdx + ), + sequenceType: SequenceType.Sequential, + } + }) + + await postComment({ + connection, + wallet, + transactionInstructions: ixsChunks, + callbacks: { + afterAllTxConfirmed: () => { + if (runAfterConfirmation) { + runAfterConfirmation() + } + }, + }, + }) + } + + // we need to chunk instructions + if (isNftVoter) { const { openNftVotingCountingModal, closeNftVotingCountingModal, } = useNftProposalStore.getState() - //update voter weight + cast vote from spl gov need to be in one transaction - const instructionsWithTheirOwnChunk = instructions.slice( - -instructionsCountThatMustHaveTheirOwnChunk - ) - const remainingInstructionsToChunk = instructions.slice( - 0, - instructions.length - instructionsCountThatMustHaveTheirOwnChunk - ) - const splInstructionsWithAccountsChunk = chunks( - instructionsWithTheirOwnChunk, - 2 + const createNftVoteTicketsChunks = chunks( + [...createCastNftVoteTicketIxs, ...createPostMessageTicketIxs], + 1 ) - const nftsAccountsChunks = chunks(remainingInstructionsToChunk, 2) - const signerChunks = Array( - splInstructionsWithAccountsChunk.length + nftsAccountsChunks.length - ).fill([]) + // last element of pluginCastVoteIxs + const last = pluginCastVoteIxs[pluginCastVoteIxs.length - 1] + // everything except last element of pluginCastVoteIxs + const nftCountingChunks = pluginCastVoteIxs.slice(0, -1) + const voteChunk = [last, ...castVoteIxs] // the final nft-voter.CastNftVote instruction has to in same tx as the vote + const chunkedIxs = [...chunks(nftCountingChunks, 2), voteChunk].filter( + (x) => x.length > 0 + ) - const singersMap = message - ? [...signerChunks.slice(0, signerChunks.length - 1), signers] - : signerChunks + // note that we are not chunking postMessageIxs, not yet supported (somehow) const instructionsChunks = [ - ...nftsAccountsChunks.map((x) => - transactionInstructionsToTypedInstructionsSets(x, SequenceType.Parallel) - ), - ...splInstructionsWithAccountsChunk.map((x) => - transactionInstructionsToTypedInstructionsSets( - x, - SequenceType.Sequential - ) - ), + ...createNftVoteTicketsChunks.map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [], + batchIdx + ), + sequenceType: SequenceType.Parallel, + } + }), + ...chunkedIxs.map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + message ? [[], chatMessageSigners] : [], // seeing signer related bugs when posting chat? This is likely culprit + batchIdx + ), + sequenceType: SequenceType.Sequential, + } + }), ] const totalVoteCost = await calcCostOfNftVote( + connection, message, instructionsChunks.length, proposal.pubkey, - votingPlugin + votingPlugin, + realm.pubkey, + walletPubkey ) const hasEnoughSol = await checkHasEnoughSolToVote( totalVoteCost, - wallet.publicKey!, + walletPubkey, connection ) if (!hasEnoughSol) { - return + throw new Error('Not enough SOL.') } - await sendTransactionsV2({ + await postComment({ connection, wallet, - TransactionInstructions: instructionsChunks, - signersSet: singersMap, - showUiComponent: true, - runAfterApproval: - instructionsChunks.length > 2 ? openNftVotingCountingModal : null, - runAfterTransactionConfirmation: () => { - if (runAfterConfirmation) { - runAfterConfirmation() - } - closeNftVotingCountingModal( - votingPlugin.client as NftVoterClient, - proposal, - wallet.publicKey! - ) + transactionInstructions: instructionsChunks, + callbacks: { + afterFirstBatchSign: () => { + instructionsChunks.length > 2 ? openNftVotingCountingModal() : null + }, + afterAllTxConfirmed: () => { + if (runAfterConfirmation) { + runAfterConfirmation() + } + closeNftVotingCountingModal( + votingPlugin.client as NftVoterClient, + proposal, + wallet.publicKey! + ) + }, }, }) - } else { - const transaction = new Transaction() - transaction.add(...instructions) - - await sendTransaction({ transaction, wallet, connection, signers }) } } diff --git a/actions/chat/postMessage.ts b/actions/chat/postMessage.ts index 3965d01935..cbea1c6d47 100644 --- a/actions/chat/postMessage.ts +++ b/actions/chat/postMessage.ts @@ -1,7 +1,7 @@ import { PublicKey, Keypair, - Transaction, + // Transaction, TransactionInstruction, } from '@solana/web3.js' import { @@ -14,8 +14,14 @@ import { ChatMessageBody } from '@solana/spl-governance' import { withPostChatMessage } from '@solana/spl-governance' import { ProgramAccount } from '@solana/spl-governance' import { RpcContext } from '@solana/spl-governance' -import { sendTransaction } from '../../utils/send' import { VotingClient } from '@utils/uiTypes/VotePlugin' +import { chunks } from '@utils/helpers' +import { + SequenceType, + sendTransactionsV3, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { sendSignAndConfirmTransactionsProps } from '@blockworks-foundation/mangolana/lib/transactions' export async function postChatMessage( { connection, wallet, programId, walletPubkey }: RpcContext, @@ -28,14 +34,15 @@ export async function postChatMessage( ) { const signers: Keypair[] = [] const instructions: TransactionInstruction[] = [] + const createNftTicketsIxs: TransactionInstruction[] = [] const governanceAuthority = walletPubkey const payer = walletPubkey //will run only if plugin is connected with realm const plugin = await client?.withUpdateVoterWeightRecord( instructions, - tokeOwnerRecord, - 'commentProposal' + 'commentProposal', + createNftTicketsIxs ) await withPostChatMessage( @@ -54,8 +61,58 @@ export async function postChatMessage( plugin?.voterWeightPk ) - const transaction = new Transaction() - transaction.add(...instructions) + // createTicketIxs is a list of instructions that create nftActionTicket only for nft-voter-v2 plugin + // so it will be empty for other plugins or just spl-governance + const nftTicketAccountsChuncks = chunks(createNftTicketsIxs, 1) + + const postMessageIxsChunk = [instructions] + + const instructionsChunks = [ + ...nftTicketAccountsChuncks.map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [], + batchIdx + ), + sequenceType: SequenceType.Parallel, + } + }), + ...postMessageIxsChunk.map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [signers], + batchIdx + ), + sequenceType: SequenceType.Sequential, + } + }), + ] + + await postComment({ + connection, + wallet, + transactionInstructions: instructionsChunks, + callbacks: undefined, + }) +} - await sendTransaction({ transaction, wallet, connection, signers }) +export async function postComment( + transactionProps: sendSignAndConfirmTransactionsProps & { + lookupTableAccounts?: any + autoFee?: boolean +}) { + try { + await sendTransactionsV3(transactionProps) + } catch (e) { + if (e.message.indexOf('Transaction too large:') !== -1) { + const numbers = e.message.match(/\d+/g) + const [size, maxSize] = numbers ? numbers.map(Number) : [0, 0] + if (size > maxSize) { + throw new Error(`You must reduce your comment by ${size - maxSize} character(s).`) + } + } + throw e + } } diff --git a/actions/createLUTproposal.ts b/actions/createLUTproposal.ts new file mode 100644 index 0000000000..dd797decc9 --- /dev/null +++ b/actions/createLUTproposal.ts @@ -0,0 +1,299 @@ +import { + AddressLookupTableProgram, + Keypair, + PublicKey, + TransactionInstruction, +} from '@solana/web3.js' +import { + ProgramAccount, + Realm, + TokenOwnerRecord, + VoteType, + getSignatoryRecordAddress, + withInsertTransaction, + withSignOffProposal, + withAddSignatory, + RpcContext, +} from '@solana/spl-governance' +import { + withCreateProposal +} from '@realms-today/spl-governance' +import { + sendTransactionsV3, + SequenceType, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { chunks } from '@utils/helpers' +import { VotingClient } from '@utils/uiTypes/VotePlugin' +import { trySentryLog } from '@utils/logs' +import { deduplicateObjsFilter } from '@utils/instructionTools' +import { sendSignAndConfirmTransactions } from '@utils/modifiedMangolana' +import { InstructionDataWithHoldUpTime } from './createProposal' +import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' + +/** This is a modified version of createProposal that makes a lookup table, which is useful for especially large instructions */ +// TODO make a more generic, less redundant solution +export const createLUTProposal = async ( + { connection, wallet, programId, walletPubkey }: RpcContext, + realm: ProgramAccount, + governance: PublicKey, + tokenOwnerRecord: ProgramAccount, + name: string, + descriptionLink: string, + governingTokenMint: PublicKey, + proposalIndex: number, + instructionsData: InstructionDataWithHoldUpTime[], + isDraft: boolean, + options: string[], + client?: VotingClient, + callbacks?: Parameters[0]['callbacks'] +): Promise => { + // Assumption: + // `payer` is a valid `Keypair` with enough SOL to pay for the execution + + const payer = walletPubkey + + const instructions: TransactionInstruction[] = [] + const governanceAuthority = walletPubkey + const signatory = walletPubkey + const prerequisiteInstructions: TransactionInstruction[] = [] + const prerequisiteInstructionsSigners: (Keypair | null)[] = [] + // sum up signers + const signers: Keypair[] = instructionsData.flatMap((x) => x.signers ?? []) + + // Explicitly request the version before making RPC calls to work around race conditions in resolving + // the version for RealmInfo + + // Changed this because it is misbehaving on my local validator setup. + const programVersion = await fetchProgramVersion(connection, programId) + + // V2 Approve/Deny configuration + const voteType = VoteType.SINGLE_CHOICE + const useDenyOption = true + + //will run only if plugin is connected with realm + const plugin = await client?.withUpdateVoterWeightRecord( + instructions, + 'createProposal' + ) + + const proposalAddress = await withCreateProposal( + instructions, + programId, + programVersion, + realm.pubkey!, + governance, + tokenOwnerRecord.pubkey, + name, + descriptionLink, + governingTokenMint, + governanceAuthority, + proposalIndex, + voteType, + options, + useDenyOption, + payer, + plugin?.voterWeightPk + ) + + await withAddSignatory( + instructions, + programId, + programVersion, + proposalAddress, + tokenOwnerRecord.pubkey, + governanceAuthority, + signatory, + payer + ) + + // TODO: Return signatoryRecordAddress from the SDK call + const signatoryRecordAddress = await getSignatoryRecordAddress( + programId, + proposalAddress, + signatory + ) + + const insertInstructions: TransactionInstruction[] = [] + + const chunkBys = instructionsData + .filter((x) => x.chunkBy) + .map((x) => x.chunkBy!) + + const lowestChunkBy = chunkBys.length ? Math.min(...chunkBys) : 2 + + for (const [index, instruction] of instructionsData + .filter((x) => x.data) + .entries()) { + if (instruction.data) { + if (instruction.prerequisiteInstructions) { + prerequisiteInstructions.push(...instruction.prerequisiteInstructions) + } + if (instruction.prerequisiteInstructionsSigners) { + prerequisiteInstructionsSigners.push( + ...instruction.prerequisiteInstructionsSigners + ) + } + await withInsertTransaction( + insertInstructions, + programId, + programVersion, + governance, + proposalAddress, + tokenOwnerRecord.pubkey, + governanceAuthority, + index, + 0, + instruction.holdUpTime || 0, + [instruction.data], + payer + ) + } + } + + if (!isDraft) { + withSignOffProposal( + insertInstructions, // SingOff proposal needs to be executed after inserting instructions hence we add it to insertInstructions + programId, + programVersion, + realm.pubkey, + governance, + proposalAddress, + signatory, + signatoryRecordAddress, + undefined + ) + } + + const insertChunks = chunks(insertInstructions, lowestChunkBy) + const signerChunks = Array(insertChunks.length) + + signerChunks.push(...chunks(signers, lowestChunkBy)) + signerChunks.fill([]) + + const deduplicatedPrerequisiteInstructions = prerequisiteInstructions.filter( + deduplicateObjsFilter + ) + + const deduplicatedPrerequisiteInstructionsSigners = prerequisiteInstructionsSigners.filter( + deduplicateObjsFilter + ) + + const signersSet = [ + ...chunks([...deduplicatedPrerequisiteInstructionsSigners], lowestChunkBy), + [], + ...signerChunks, + ] + + const txes = [ + ...chunks(deduplicatedPrerequisiteInstructions, lowestChunkBy), + instructions, + ...insertChunks, + ].map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + signersSet, + batchIdx + ), + sequenceType: SequenceType.Sequential, + } + }) + + const keys = txes + .map((x) => + x.instructionsSet.map((y) => + y.transactionInstruction.keys.map((z) => z.pubkey) + ) + ) + .flat() + .flat() + const slot = await connection.getSlot() + + const [ + lookupTableInst, + lookupTableAddress, + ] = AddressLookupTableProgram.createLookupTable({ + authority: payer, + payer: payer, + recentSlot: slot, + }) + + // add addresses to the `lookupTableAddress` table via an `extend` instruction + // need to split into multiple instructions because of the ~20 address limit + // https://docs.solana.com/developing/lookup-tables#:~:text=NOTE%3A%20Due%20to,transaction%27s%20memory%20limits. + // const extendInstruction = AddressLookupTableProgram.extendLookupTable({ + // payer: payer, + // authority: payer, + // lookupTable: lookupTableAddress, + // addresses: keys, + // }) + const extendInstructions = chunks(keys, 15).map((chunk) => + AddressLookupTableProgram.extendLookupTable({ + payer: payer, + authority: payer, + lookupTable: lookupTableAddress, + addresses: chunk, + }) + ) + + // Send this `extendInstruction` in a transaction to the cluster + // to insert the listing of `addresses` into your lookup table with address `lookupTableAddress` + + console.log('lookup table address:', lookupTableAddress.toBase58()) + + let resolve = undefined + const promise = new Promise((r) => { + //@ts-ignore + resolve = r + }) + + // TODO merge all into one call of sendSignAndConfirmTransactions, so the user only signs once + await sendSignAndConfirmTransactions({ + connection, + wallet, + transactionInstructions: [ + { + instructionsSet: [{ transactionInstruction: lookupTableInst }], + sequenceType: SequenceType.Sequential, + }, + ...extendInstructions.map((x) => { + return { + instructionsSet: [{ transactionInstruction: x }], + sequenceType: SequenceType.Sequential, + } + }), + ], + callbacks: { + afterAllTxConfirmed: resolve, + }, + }) + await promise + + const lookupTableAccount = await connection + .getAddressLookupTable(lookupTableAddress, { commitment: 'singleGossip' }) + .then((res) => res.value) + if (lookupTableAccount === null) throw new Error() + + await sendTransactionsV3({ + callbacks, + connection, + wallet, + transactionInstructions: txes, + lookupTableAccounts: [lookupTableAccount], + }) + + const logInfo = { + realmId: realm.pubkey.toBase58(), + realmSymbol: realm.account.name, + wallet: wallet.publicKey?.toBase58(), + proposalAddress: proposalAddress.toBase58(), + proposalIndex: proposalIndex, + cluster: connection.rpcEndpoint.includes('devnet') ? 'devnet' : 'mainnet', + } + trySentryLog({ + tag: 'proposalCreated', + objToStringify: logInfo, + }) + return proposalAddress +} diff --git a/actions/createMultisigWallet.ts b/actions/createMultisigWallet.ts index d28010c8e1..bd0d8e0961 100644 --- a/actions/createMultisigWallet.ts +++ b/actions/createMultisigWallet.ts @@ -1,35 +1,21 @@ -import { Connection, PublicKey } from '@solana/web3.js' - -import { - sendTransactionsV2, - SequenceType, - transactionInstructionsToTypedInstructionsSets, - WalletSigner, -} from 'utils/sendTransactions' +import { sendTransactionsV3, SequenceType } from 'utils/sendTransactions' import { chunks } from '@utils/helpers' -import { prepareRealmCreation } from '@tools/governance/prepareRealmCreation' +import { + prepareRealmCreation, + RealmCreation, + Web3Context, +} from '@tools/governance/prepareRealmCreation' +import { trySentryLog } from '@utils/logs' /// Creates multisig realm with community mint with 0 supply /// and council mint used as multisig token -interface MultisigWallet { - connection: Connection - wallet: WalletSigner - programIdAddress: string - - realmName: string - councilYesVotePercentage: number - councilWalletPks: PublicKey[] -} +type MultisigWallet = RealmCreation & Web3Context export default async function createMultisigWallet({ connection, wallet, - programIdAddress, - realmName, - - councilYesVotePercentage, - councilWalletPks, + ...params }: MultisigWallet) { const { communityMintPk, @@ -43,48 +29,50 @@ export default async function createMultisigWallet({ } = await prepareRealmCreation({ connection, wallet, - programIdAddress, + ...params, + }) - realmName, - tokensToGovernThreshold: undefined, + try { + const councilMembersChunks = chunks(councilMembersInstructions, 8) - existingCommunityMintPk: undefined, - communityMintSupplyFactor: undefined, - transferCommunityMintAuthority: true, - communityYesVotePercentage: councilYesVotePercentage, + const allSigners = [...mintsSetupSigners, ...realmSigners] - createCouncil: true, - existingCouncilMintPk: undefined, - transferCouncilMintAuthority: true, - councilWalletPks, - }) + const txes = [ + ...chunks(mintsSetupInstructions, 5), + ...councilMembersChunks, + ...chunks(realmInstructions, 15), + ].map((txBatch) => { + return { + instructionsSet: txBatch.map((txInst) => { + const signers = allSigners.filter((x) => + txInst.keys + .filter((key) => key.isSigner) + .find((key) => key.pubkey.equals(x.publicKey)) + ) + return { + transactionInstruction: txInst, + signers, + } + }), + sequenceType: SequenceType.Sequential, + } + }) - try { - const councilMembersChunks = chunks(councilMembersInstructions, 10) - // only walletPk needs to sign the minting instructions and it's a signer by default and we don't have to include any more signers - const councilMembersSignersChunks = Array(councilMembersChunks.length).fill( - [] - ) - console.log('CREATE MULTISIG WALLET: sending transactions') - const tx = await sendTransactionsV2({ + const tx = await sendTransactionsV3({ connection, - showUiComponent: true, wallet, - signersSet: [ - mintsSetupSigners, - ...councilMembersSignersChunks, - realmSigners, - ], - TransactionInstructions: [ - mintsSetupInstructions, - ...councilMembersChunks, - realmInstructions, - ].map((x) => - transactionInstructionsToTypedInstructionsSets( - x, - SequenceType.Sequential - ) - ), + transactionInstructions: txes, + }) + + const logInfo = { + realmId: realmPk, + realmSymbol: params.realmName, + wallet: wallet.publicKey?.toBase58(), + cluster: connection.rpcEndpoint.includes('devnet') ? 'devnet' : 'mainnet', + } + trySentryLog({ + tag: 'realmCreated', + objToStringify: logInfo, }) return { diff --git a/actions/createNFTRealm.ts b/actions/createNFTRealm.ts index e886251dc4..507df28b07 100644 --- a/actions/createNFTRealm.ts +++ b/actions/createNFTRealm.ts @@ -1,83 +1,52 @@ import { - GoverningTokenConfigAccountArgs, - GoverningTokenType, SetRealmAuthorityAction, SYSTEM_PROGRAM_ID, withCreateTokenOwnerRecord, withSetRealmAuthority, } from '@solana/spl-governance' - -import { - Connection, - Keypair, - PublicKey, - TransactionInstruction, -} from '@solana/web3.js' -import { AnchorProvider, Wallet } from '@project-serum/anchor' - +import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js' +import { AnchorProvider, Wallet } from '@coral-xyz/anchor' import { - sendTransactionsV2, SequenceType, - WalletSigner, - transactionInstructionsToTypedInstructionsSets, + sendTransactionsV3, + txBatchesToInstructionSetWithSigners, } from 'utils/sendTransactions' import { chunks } from '@utils/helpers' -import { nftPluginsPks } from '@hooks/useVotingPlugins' - import { getVoterWeightRecord, getMaxVoterWeightRecord, getRegistrarPDA, } from '@utils/plugin/accounts' -import { NftVoterClient } from '@solana/governance-program-library' - -import { prepareRealmCreation } from '@tools/governance/prepareRealmCreation' -interface NFTRealm { - connection: Connection - wallet: WalletSigner - programIdAddress: string - - realmName: string - collectionAddress: string - collectionCount: number - tokensToGovernThreshold: number | undefined - - communityYesVotePercentage: number - existingCommunityMintPk: PublicKey | undefined - // communityMintSupplyFactor: number | undefined - createCouncil: boolean - existingCouncilMintPk: PublicKey | undefined - transferCouncilMintAuthority: boolean | undefined - councilWalletPks: PublicKey[] -} +import { + prepareRealmCreation, + RealmCreation, + Web3Context, +} from '@tools/governance/prepareRealmCreation' +import { trySentryLog } from '@utils/logs' +import { NftVoterClient } from '@utils/uiTypes/NftVoterClient' + +type NFTRealm = Web3Context & + RealmCreation & { + collectionAddress: string + nftCollectionCount: number + } export default async function createNFTRealm({ connection, wallet, - programIdAddress, - realmName, - tokensToGovernThreshold = 1, collectionAddress, - collectionCount, - existingCommunityMintPk, - communityYesVotePercentage, - // communityMintSupplyFactor: rawCMSF, - - createCouncil = false, - existingCouncilMintPk, - transferCouncilMintAuthority = true, - // councilYesVotePercentage, - councilWalletPks, + ...params }: NFTRealm) { const options = AnchorProvider.defaultOptions() const provider = new AnchorProvider(connection, wallet as Wallet, options) const nftClient = await NftVoterClient.connect(provider) + const { nftCollectionCount } = params const { - communityMintGovPk, + mainGovernancePk, communityMintPk, councilMintPk, realmPk, @@ -91,36 +60,16 @@ export default async function createNFTRealm({ mintsSetupSigners, councilMembersInstructions, } = await prepareRealmCreation({ + ...params, connection, wallet, - programIdAddress, - - realmName, - tokensToGovernThreshold, - - existingCommunityMintPk, - nftCollectionCount: collectionCount, - communityMintSupplyFactor: undefined, - transferCommunityMintAuthority: false, // delay this until we have created NFT instructions - communityYesVotePercentage, - - createCouncil, - existingCouncilMintPk, - transferCouncilMintAuthority, - councilWalletPks, - - communityTokenConfig: new GoverningTokenConfigAccountArgs({ - voterWeightAddin: new PublicKey(nftPluginsPks[0]), - maxVoterWeightAddin: new PublicKey(nftPluginsPks[0]), - tokenType: GoverningTokenType.Liquid, - }), }) console.log('NFT REALM realm public-key', realmPk.toBase58()) - const { registrar } = await getRegistrarPDA( - realmPk, - communityMintPk, - nftClient!.program.programId + const { registrar } = getRegistrarPDA( + realmPk, + communityMintPk, + nftClient!.program.programId ) const instructionCR = await nftClient!.program.methods .createRegistrar(10) // Max collections @@ -128,7 +77,7 @@ export default async function createNFTRealm({ registrar, realm: realmPk, governanceProgramId: programIdPk, - // realmAuthority: communityMintGovPk, + // realmAuthority: mainGovernancePk, realmAuthority: walletPk, governingTokenMint: communityMintPk, payer: walletPk, @@ -165,11 +114,14 @@ export default async function createNFTRealm({ ) const instructionCC = await nftClient!.program.methods - .configureCollection(minCommunityTokensToCreateAsMintValue, collectionCount) + .configureCollection( + minCommunityTokensToCreateAsMintValue, + nftCollectionCount + ) .accounts({ registrar, realm: realmPk, - // realmAuthority: communityMintGovPk, + // realmAuthority: mainGovernancePk, realmAuthority: walletPk, collection: new PublicKey(collectionAddress), maxVoterWeightRecord: maxVoterWeightRecord, @@ -195,7 +147,7 @@ export default async function createNFTRealm({ programVersion, realmPk, walletPk, - communityMintGovPk, + mainGovernancePk, SetRealmAuthorityAction.SetChecked ) @@ -240,27 +192,43 @@ export default async function createNFTRealm({ ) const nftSigners: Keypair[] = [] console.log('CREATE NFT REALM: sending transactions') - const tx = await sendTransactionsV2({ + const signers = [ + mintsSetupSigners, + ...councilMembersSignersChunks, + realmSigners, + nftSigners, + ] + const txes = [ + mintsSetupInstructions, + ...councilMembersChunks, + realmInstructions, + nftConfigurationInstructions, + ].map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + signers, + batchIdx + ), + sequenceType: SequenceType.Sequential, + } + }) + + const tx = await sendTransactionsV3({ connection, - showUiComponent: true, wallet, - signersSet: [ - mintsSetupSigners, - ...councilMembersSignersChunks, - realmSigners, - nftSigners, - ], - TransactionInstructions: [ - mintsSetupInstructions, - ...councilMembersChunks, - realmInstructions, - nftConfigurationInstructions, - ].map((x) => - transactionInstructionsToTypedInstructionsSets( - x, - SequenceType.Sequential - ) - ), + transactionInstructions: txes, + }) + + const logInfo = { + realmId: realmPk, + realmSymbol: params.realmName, + wallet: wallet.publicKey?.toBase58(), + cluster: connection.rpcEndpoint.includes('devnet') ? 'devnet' : 'mainnet', + } + trySentryLog({ + tag: 'realmCreated', + objToStringify: logInfo, }) return { diff --git a/actions/createProposal.ts b/actions/createProposal.ts index 2ae6235978..43c7d02625 100644 --- a/actions/createProposal.ts +++ b/actions/createProposal.ts @@ -1,40 +1,41 @@ import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js' - import { - getGovernanceProgramVersion, getInstructionDataFromBase64, Governance, ProgramAccount, Realm, TokenOwnerRecord, VoteType, - withCreateProposal, getSignatoryRecordAddress, + RpcContext, + withInsertTransaction, + InstructionData, + withSignOffProposal, + withAddSignatory, + MultiChoiceType, } from '@solana/spl-governance' -import { RpcContext } from '@solana/spl-governance' -import { withInsertTransaction } from '@solana/spl-governance' -import { InstructionData } from '@solana/spl-governance' -import { withSignOffProposal } from '@solana/spl-governance' import { - sendTransactionsV2, + withCreateProposal, +} from '@realms-today/spl-governance' +import { + sendTransactionsV3, SequenceType, - transactionInstructionsToTypedInstructionsSets, + txBatchesToInstructionSetWithSigners, } from '@utils/sendTransactions' import { chunks } from '@utils/helpers' import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes' import { VotingClient } from '@utils/uiTypes/VotePlugin' -import { NftVoterClient } from '@solana/governance-program-library' -import { withAddSignatory } from '@solana/spl-governance' - +import { trySentryLog } from '@utils/logs' +import { deduplicateObjsFilter } from '@utils/instructionTools' +import { NftVoterClient } from '@utils/uiTypes/NftVoterClient' +import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' export interface InstructionDataWithHoldUpTime { data: InstructionData | null holdUpTime: number | undefined prerequisiteInstructions: TransactionInstruction[] - chunkSplitByDefault?: boolean chunkBy?: number signers?: Keypair[] - shouldSplitIntoSeparateTxs?: boolean | undefined - prerequisiteInstructionsSigners?: Keypair[] + prerequisiteInstructionsSigners?: (Keypair | null)[] } export class InstructionDataWithHoldUpTime { @@ -53,7 +54,6 @@ export class InstructionDataWithHoldUpTime { ? instruction.customHoldUpTime : governance?.account?.config.minInstructionHoldUpTime this.prerequisiteInstructions = instruction.prerequisiteInstructions || [] - this.chunkSplitByDefault = instruction.chunkSplitByDefault || false this.chunkBy = instruction.chunkBy || 2 this.prerequisiteInstructionsSigners = instruction.prerequisiteInstructionsSigners || [] @@ -71,40 +71,45 @@ export const createProposal = async ( proposalIndex: number, instructionsData: InstructionDataWithHoldUpTime[], isDraft: boolean, - client?: VotingClient + options: string[], + client?: VotingClient, + callbacks?: Parameters[0]['callbacks'] ): Promise => { const instructions: TransactionInstruction[] = [] - + const createNftTicketsIxs: TransactionInstruction[] = [] const governanceAuthority = walletPubkey const signatory = walletPubkey const payer = walletPubkey const prerequisiteInstructions: TransactionInstruction[] = [] - const prerequisiteInstructionsSigners: Keypair[] = [] + const prerequisiteInstructionsSigners: (Keypair | null)[] = [] // sum up signers const signers: Keypair[] = instructionsData.flatMap((x) => x.signers ?? []) - const shouldSplitIntoSeparateTxs: boolean = instructionsData - .flatMap((x) => x.shouldSplitIntoSeparateTxs) - .some((x) => x) // Explicitly request the version before making RPC calls to work around race conditions in resolving // the version for RealmInfo // Changed this because it is misbehaving on my local validator setup. - const programVersion = await getGovernanceProgramVersion( - connection, - programId - ) + const programVersion = await fetchProgramVersion(connection, programId) // V2 Approve/Deny configuration - const voteType = VoteType.SINGLE_CHOICE - const options = ['Approve'] - const useDenyOption = true + const isMulti = options.length > 1 + + const useDenyOption = !isMulti + + const voteType = isMulti + ? VoteType.MULTI_CHOICE( + MultiChoiceType.FullWeight, + 1, + options.length, + options.length + ) + : VoteType.SINGLE_CHOICE //will run only if plugin is connected with realm const plugin = await client?.withUpdateVoterWeightRecord( instructions, - tokenOwnerRecord, 'createProposal', + createNftTicketsIxs, governance ) @@ -146,13 +151,13 @@ export const createProposal = async ( ) const insertInstructions: TransactionInstruction[] = [] - const splitToChunkByDefault = instructionsData.filter( - (x) => x.chunkSplitByDefault - ).length + const chunkBys = instructionsData .filter((x) => x.chunkBy) .map((x) => x.chunkBy!) - const chunkBy = chunkBys.length ? Math.min(...chunkBys) : 2 + + const lowestChunkBy = chunkBys.length ? Math.min(...chunkBys) : 2 + for (const [index, instruction] of instructionsData .filter((x) => x.data) .entries()) { @@ -182,8 +187,6 @@ export const createProposal = async ( } } - const insertInstructionCount = insertInstructions.length - if (!isDraft) { withSignOffProposal( insertInstructions, // SingOff proposal needs to be executed after inserting instructions hence we add it to insertInstructions @@ -197,58 +200,115 @@ export const createProposal = async ( undefined ) } - if ( - insertInstructionCount <= 2 && - !shouldSplitIntoSeparateTxs && - !splitToChunkByDefault && - !(client?.client instanceof NftVoterClient) - ) { - // This is an arbitrary threshold and we assume that up to 2 instructions can be inserted as a single Tx - // This is conservative setting and we might need to revise it if we have more empirical examples or - // reliable way to determine Tx size - // We merge instructions with prerequisiteInstructions - // Prerequisite instructions can came from instructions as something we need to do before instruction can be executed - // For example we create ATAs if they don't exist as part of the proposal creation flow - await sendTransactionsV2({ - wallet, - connection, - signersSet: [[], [], signers], - showUiComponent: true, - TransactionInstructions: [ - prerequisiteInstructions, - instructions, - insertInstructions, - ].map((x) => - transactionInstructionsToTypedInstructionsSets( - x, - SequenceType.Sequential - ) - ), + + const insertChunks = chunks(insertInstructions, lowestChunkBy) + const signerChunks = Array(insertChunks.length) + + signerChunks.push(...chunks(signers, lowestChunkBy)) + signerChunks.fill([]) + + const deduplicatedPrerequisiteInstructions = prerequisiteInstructions.filter( + deduplicateObjsFilter + ) + + const deduplicatedPrerequisiteInstructionsSigners = prerequisiteInstructionsSigners.filter( + deduplicateObjsFilter + ) + + const prerequisiteInstructionsChunks = chunks( + deduplicatedPrerequisiteInstructions, + lowestChunkBy + ) + + const prerequisiteInstructionsSignersChunks = chunks( + deduplicatedPrerequisiteInstructionsSigners, + lowestChunkBy + ).filter((keypairArray) => keypairArray.filter((keypair) => keypair)) + + const signersSet = [ + ...prerequisiteInstructionsSignersChunks, + [], + ...signerChunks, + ] + + const isNftVoter = client?.client instanceof NftVoterClient + if (!isNftVoter) { + const txes = [ + ...prerequisiteInstructionsChunks, + instructions, + ...insertChunks, + ].map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + signersSet, + batchIdx + ), + sequenceType: SequenceType.Sequential, + } }) - } else { - const insertChunks = chunks(insertInstructions, chunkBy) - const signerChunks = Array(insertChunks.length) - signerChunks.push(...chunks(signers, chunkBy)) - signerChunks.fill([]) - - console.log(`Creating proposal using ${insertChunks.length} chunks`) - await sendTransactionsV2({ + + await sendTransactionsV3({ + callbacks, + connection, wallet, + transactionInstructions: txes, + }) + } + + if (isNftVoter) { + // update voter weight records + const nftTicketAccountsChunk = chunks(createNftTicketsIxs, 1) + const splIxsWithAccountsChunk = [ + ...prerequisiteInstructionsChunks, + instructions, + ...insertChunks, + ] + + const instructionsChunks = [ + ...nftTicketAccountsChunk.map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [], + batchIdx + ), + sequenceType: SequenceType.Parallel, + } + }), + ...splIxsWithAccountsChunk.map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + signersSet, + batchIdx + ), + sequenceType: SequenceType.Sequential, + } + }), + ] + + // should add checking user has enough sol, refer castVote + + await sendTransactionsV3({ connection, - signersSet: [[...prerequisiteInstructionsSigners], [], ...signerChunks], - showUiComponent: true, - TransactionInstructions: [ - prerequisiteInstructions, - instructions, - ...insertChunks, - ].map((x) => - transactionInstructionsToTypedInstructionsSets( - x, - SequenceType.Sequential - ) - ), + wallet, + transactionInstructions: instructionsChunks, + callbacks, }) } + const logInfo = { + realmId: realm.pubkey.toBase58(), + realmSymbol: realm.account.name, + wallet: wallet.publicKey?.toBase58(), + proposalAddress: proposalAddress.toBase58(), + proposalIndex: proposalIndex, + cluster: connection.rpcEndpoint.includes('devnet') ? 'devnet' : 'mainnet', + } + trySentryLog({ + tag: 'proposalCreated', + objToStringify: logInfo, + }) return proposalAddress } diff --git a/actions/createTokenizedRealm.ts b/actions/createTokenizedRealm.ts index 6c7b531f86..301ae41ecf 100644 --- a/actions/createTokenizedRealm.ts +++ b/actions/createTokenizedRealm.ts @@ -1,52 +1,59 @@ -import { Connection, PublicKey } from '@solana/web3.js' - import { - sendTransactionsV2, - transactionInstructionsToTypedInstructionsSets, + sendTransactionsV3, SequenceType, - WalletSigner, + txBatchesToInstructionSetWithSigners, } from 'utils/sendTransactions' import { chunks } from '@utils/helpers' -import { prepareRealmCreation } from '@tools/governance/prepareRealmCreation' - -interface TokenizedRealm { - connection: Connection - wallet: WalletSigner - programIdAddress: string - - realmName: string - tokensToGovernThreshold: number | undefined +import { + prepareRealmCreation, + RealmCreation, + Web3Context, +} from '@tools/governance/prepareRealmCreation' +import { trySentryLog } from '@utils/logs' +import { Wallet } from '@coral-xyz/anchor' +import { + SetRealmAuthorityAction, + withSetRealmAuthority, +} from '@solana/spl-governance' +import { PluginName, pluginNameToCanonicalProgramId } from '@constants/plugins' +import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js' +import { addQVPlugin } from './addPlugins/addQVPlugin' +import { defaultSybilResistancePass } from '../GatewayPlugin/config' +import { addGatewayPlugin } from './addPlugins/addGatewayPlugin' +import {Coefficients} from "@solana/governance-program-library"; - communityYesVotePercentage: number - existingCommunityMintPk: PublicKey | undefined - transferCommunityMintAuthority: boolean | undefined - communityMintSupplyFactor: number | undefined +type CreateWithPlugin = { + pluginList: PluginName[] + coefficientA: number + coefficientB: number + coefficientC: number + civicPass: string +} +type TokenizedRealm = Web3Context & RealmCreation & CreateWithPlugin - createCouncil: boolean - existingCouncilMintPk: PublicKey | undefined - transferCouncilMintAuthority: boolean | undefined - councilWalletPks: PublicKey[] +function determineVoterWeightAddin( + pluginList: PluginName[] +): PublicKey | undefined { + if (pluginList.length === 0) return undefined + // the last plugin in the chain is the one that is attached to the realm. + return pluginNameToCanonicalProgramId(pluginList[pluginList.length - 1]) } export default async function createTokenizedRealm({ connection, wallet, - programIdAddress, - realmName, - tokensToGovernThreshold, - - existingCommunityMintPk, - transferCommunityMintAuthority = true, - communityYesVotePercentage, - communityMintSupplyFactor: rawCMSF, - - createCouncil = false, - existingCouncilMintPk, - transferCouncilMintAuthority = true, - // councilYesVotePercentage, - councilWalletPks, + pluginList, + ...params }: TokenizedRealm) { + // Check if the DAO requires any plugins at startup, and if so, add them. + const voterWeightAddin = determineVoterWeightAddin(pluginList) + // Note - this does not support council token addins or max voter weight yet as there are no examples of plugins that use that for a tokenised realm. + const communityTokenConfig = { + ...params.communityTokenConfig, + voterWeightAddin, + } + const { communityMintPk, councilMintPk, @@ -56,23 +63,15 @@ export default async function createTokenizedRealm({ mintsSetupInstructions, mintsSetupSigners, councilMembersInstructions, + walletPk, + programIdPk, + mainGovernancePk, + programVersion, } = await prepareRealmCreation({ connection, wallet, - programIdAddress, - - realmName, - tokensToGovernThreshold, - - existingCommunityMintPk, - communityMintSupplyFactor: rawCMSF, - transferCommunityMintAuthority, - communityYesVotePercentage, - - createCouncil, - existingCouncilMintPk, - transferCouncilMintAuthority, - councilWalletPks, + ...params, + communityTokenConfig, }) try { @@ -82,25 +81,102 @@ export default async function createTokenizedRealm({ [] ) console.log('CREATE GOV TOKEN REALM: sending transactions') - const tx = await sendTransactionsV2({ + + const pluginSigners: Keypair[] = [] + const pluginIxes: TransactionInstruction[] = [] + + let predecessorProgramId: PublicKey | undefined = undefined + + if (pluginList.includes('gateway')) { + // By default, use Civic's uniqueness pass. TODO allow this to be overridden in advanced mode. + const passType = new PublicKey( + params.civicPass || defaultSybilResistancePass.value + ) + + const { pluginProgramId, instructions } = await addGatewayPlugin( + connection, + wallet as Wallet, + realmPk, + communityMintPk, + programIdPk, + predecessorProgramId, + passType + ) + + pluginIxes.push(...instructions) + predecessorProgramId = pluginProgramId + } + if (pluginList.includes('QV')) { + const qvCoefficientsFromForm = [ + params.coefficientA, + params.coefficientB, + params.coefficientC, + ] as Coefficients + const { pluginProgramId, instructions } = await addQVPlugin( + connection, + wallet as Wallet, + realmPk, + communityMintPk, + programIdPk, + predecessorProgramId, + qvCoefficientsFromForm, + params.existingCommunityMintPk + ) + + pluginIxes.push(...instructions) + predecessorProgramId = pluginProgramId + } + + if (pluginIxes.length > 0) { + // finally, transfer the realm authority to the Realm PDA + // Set the community governance as the realm authority + withSetRealmAuthority( + pluginIxes, + programIdPk, + programVersion, + realmPk, + walletPk, + mainGovernancePk, + SetRealmAuthorityAction.SetChecked + ) + } + + const signers = [ + mintsSetupSigners, + ...councilMembersSignersChunks, + realmSigners, + pluginSigners, + ] + + const ixes = [ + mintsSetupInstructions, + ...councilMembersChunks, + realmInstructions, + pluginIxes, + ].map((ixBatch, batchIdx) => ({ + instructionsSet: txBatchesToInstructionSetWithSigners( + ixBatch, + signers, + batchIdx + ), + sequenceType: SequenceType.Sequential, + })) + + const tx = await sendTransactionsV3({ connection, - showUiComponent: true, wallet, - signersSet: [ - mintsSetupSigners, - ...councilMembersSignersChunks, - realmSigners, - ], - TransactionInstructions: [ - mintsSetupInstructions, - ...councilMembersChunks, - realmInstructions, - ].map((x) => - transactionInstructionsToTypedInstructionsSets( - x, - SequenceType.Sequential - ) - ), + transactionInstructions: ixes, + }) + + const logInfo = { + realmId: realmPk, + realmSymbol: params.realmName, + wallet: wallet.publicKey?.toBase58(), + cluster: connection.rpcEndpoint.includes('devnet') ? 'devnet' : 'mainnet', + } + trySentryLog({ + tag: 'realmCreated', + objToStringify: logInfo, }) return { diff --git a/actions/createTreasuryAccount.ts b/actions/createTreasuryAccount.ts deleted file mode 100644 index 2865c65578..0000000000 --- a/actions/createTreasuryAccount.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { - Keypair, - PublicKey, - Transaction, - TransactionInstruction, -} from '@solana/web3.js' - -import { - getGovernanceProgramVersion, - GovernanceConfig, - ProgramAccount, - Realm, - TokenOwnerRecord, - withCreateGovernance, - withCreateNativeTreasury, -} from '@solana/spl-governance' - -import { withCreateTokenGovernance } from '@solana/spl-governance' -import { RpcContext } from '@solana/spl-governance' -import { sendTransaction } from '@utils/send' -import { withCreateSplTokenAccount } from '@models/withCreateSplTokenAccount' -import { VotingClient } from '@utils/uiTypes/VotePlugin' - -export const createTreasuryAccount = async ( - { connection, wallet, programId, walletPubkey }: RpcContext, - realm: ProgramAccount, - mint: PublicKey | null, - config: GovernanceConfig, - tokenOwnerRecord: ProgramAccount, - client?: VotingClient -): Promise => { - const instructions: TransactionInstruction[] = [] - const signers: Keypair[] = [] - - // Explicitly request the version before making RPC calls to work around race conditions in resolving - // the version for RealmInfo - const programVersion = await getGovernanceProgramVersion( - connection, - programId - ) - - //will run only if plugin is connected with realm - const plugin = await client?.withUpdateVoterWeightRecord( - instructions, - tokenOwnerRecord, - 'createGovernance' - ) - - const tokenAccount = mint - ? await withCreateSplTokenAccount( - connection, - wallet!, - instructions, - signers, - mint - ) - : null - - const governanceAuthority = walletPubkey - - const governanceAddress = tokenAccount - ? await withCreateTokenGovernance( - instructions, - programId, - programVersion, - realm.pubkey, - tokenAccount.tokenAccountAddress, - config, - true, - walletPubkey, - tokenOwnerRecord.pubkey, - walletPubkey, - governanceAuthority, - plugin?.voterWeightPk - ) - : await withCreateGovernance( - instructions, - programId, - programVersion, - realm.pubkey, - undefined, - config, - tokenOwnerRecord.pubkey, - walletPubkey, - governanceAuthority, - plugin?.voterWeightPk - ) - - if (!tokenAccount) { - await withCreateNativeTreasury( - instructions, - programId, - programVersion, - governanceAddress, - walletPubkey - ) - } - - const transaction = new Transaction() - transaction.add(...instructions) - - await sendTransaction({ - transaction, - wallet, - connection, - signers, - sendingMessage: 'Creating treasury account', - successMessage: 'Treasury account has been created', - }) - - return governanceAddress -} diff --git a/actions/dryRunInstruction.ts b/actions/dryRunInstruction.ts index 2c7d141049..d19e84b8ff 100644 --- a/actions/dryRunInstruction.ts +++ b/actions/dryRunInstruction.ts @@ -1,11 +1,11 @@ import { InstructionData } from '@solana/spl-governance' import { + ComputeBudgetProgram, Connection, Transaction, TransactionInstruction, } from '@solana/web3.js' -import { simulateTransaction } from '../utils/send' import { WalletAdapter } from '@solana/wallet-adapter-base' export async function dryRunInstruction( @@ -15,7 +15,15 @@ export async function dryRunInstruction( prerequisiteInstructionsToRun?: TransactionInstruction[] | undefined, additionalInstructions?: InstructionData[] ) { + const recentBlockHash = await connection.getLatestBlockhash() const transaction = new Transaction({ feePayer: wallet.publicKey }) + transaction.lastValidBlockHeight = recentBlockHash.lastValidBlockHeight + transaction.recentBlockhash = recentBlockHash.blockhash + + transaction.add( + ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }) + ) + if (prerequisiteInstructionsToRun) { prerequisiteInstructionsToRun.map((x) => transaction.add(x)) } @@ -37,7 +45,11 @@ export async function dryRunInstruction( }) } - const result = await simulateTransaction(connection, transaction, 'single') + const result = await connection.simulateTransaction( + transaction, + undefined, + true + ) return { response: result.value, transaction } } diff --git a/actions/executeInstructions.ts b/actions/executeInstructions.ts index e0ad5b0528..1846ef759c 100644 --- a/actions/executeInstructions.ts +++ b/actions/executeInstructions.ts @@ -5,12 +5,11 @@ import { RpcContext, withExecuteTransaction, } from '@solana/spl-governance' -import { Transaction, TransactionInstruction } from '@solana/web3.js' -import { sendSignedTransaction, signTransaction } from '@utils/send' +import { ComputeBudgetProgram, TransactionInstruction } from '@solana/web3.js' import { - sendTransactionsV2, + sendTransactionsV3, SequenceType, - transactionInstructionsToTypedInstructionsSets, + txBatchesToInstructionSetWithSigners, } from '@utils/sendTransactions' export const executeInstructions = async ( @@ -31,41 +30,46 @@ export const executeInstructions = async ( proposal.account.governance, proposal.pubkey, instruction.pubkey, - [instruction.account.getSingleInstruction()] + [...instruction.account.getAllInstructions()] ) ) ) - if (multiTransactionMode) { - await sendTransactionsV2({ + const txes = [...instructions.map((x) => [x])].map((txBatch, batchIdx) => { + const batchWithComputeBudget = [ + ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }), + ...txBatch, + ] + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + batchWithComputeBudget, + [], + batchIdx + ), + sequenceType: SequenceType.Sequential, + } + }) + await sendTransactionsV3({ connection, - showUiComponent: true, - wallet: wallet!, - signersSet: Array(instructions.length).fill([]), - TransactionInstructions: instructions.map((x) => - transactionInstructionsToTypedInstructionsSets( - [x], - SequenceType.Parallel - ) - ), + wallet, + transactionInstructions: txes, }) } else { - const transaction = new Transaction() - - transaction.add(...instructions) - - const signedTransaction = await signTransaction({ - transaction, - wallet, - connection, - signers: [], + const txes = [instructions].map((txBatch) => { + return { + instructionsSet: txBatch.map((x) => { + return { + transactionInstruction: x, + } + }), + sequenceType: SequenceType.Sequential, + } }) - await sendSignedTransaction({ - signedTransaction, + await sendTransactionsV3({ connection, - sendingMessage: 'Executing instruction', - successMessage: 'Execution finalized', + wallet, + transactionInstructions: txes, }) } } diff --git a/actions/executeTransaction.ts b/actions/executeTransaction.ts index 884ca23e0b..8cf2f3f7a2 100644 --- a/actions/executeTransaction.ts +++ b/actions/executeTransaction.ts @@ -1,4 +1,9 @@ -import { Keypair, Transaction, TransactionInstruction } from '@solana/web3.js' +import { + ComputeBudgetProgram, + Keypair, + Transaction, + TransactionInstruction, +} from '@solana/web3.js' import { sendSignedAndAdjacentTransactions, @@ -10,10 +15,10 @@ import { RpcContext, Proposal, ProposalTransaction, - getGovernanceProgramVersion, withExecuteTransaction, ProgramAccount, } from '@solana/spl-governance' +import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' /** * Executes a proposal transaction @@ -35,10 +40,7 @@ export const executeTransaction = async ( // Explicitly request the version before making RPC calls to work around race conditions in resolving // the version for RealmInfo - const programVersion = await getGovernanceProgramVersion( - connection, - programId - ) + const programVersion = await fetchProgramVersion(connection, programId) await withExecuteTransaction( instructions, @@ -47,11 +49,14 @@ export const executeTransaction = async ( proposal.account.governance, proposal.pubkey, instruction.pubkey, - [instruction.account.getSingleInstruction()] + [...instruction.account.getAllInstructions()] ) // Create proposal transaction - const proposalTransaction = new Transaction().add(...instructions) + const proposalTransaction = new Transaction().add( + ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }), + ...instructions + ) // Sign and send all pre-execution transactions if (preExecutionTransactions && !preExecutionTransactions?.length) { @@ -66,7 +71,6 @@ export const executeTransaction = async ( }) ) ) - console.log('sent preExecutionTransactions', preExecutionTransactions) } // Some proposals require additional adjacent transactions due to tx size limits diff --git a/actions/finalizeVotes.ts b/actions/finalizeVotes.ts index 9779b22237..598b902c21 100644 --- a/actions/finalizeVotes.ts +++ b/actions/finalizeVotes.ts @@ -1,33 +1,30 @@ import { - getGovernanceProgramVersion, ProgramAccount, + TokenOwnerRecord, + withRefundProposalDeposit, } from '@solana/spl-governance' import { RpcContext } from '@solana/spl-governance' -import { - Keypair, - PublicKey, - Transaction, - TransactionInstruction, -} from '@solana/web3.js' -import { sendTransaction } from '@utils/send' +import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js' import { Proposal } from '@solana/spl-governance' import { withFinalizeVote } from '@solana/spl-governance' +import { getProposalDepositPk } from '@utils/helpers' +import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' +import { SequenceType } from '@blockworks-foundation/mangolana/lib/globalTypes' +import { sendTransactionsV3 } from '@utils/sendTransactions' export const finalizeVote = async ( { connection, wallet, programId }: RpcContext, realm: PublicKey, proposal: ProgramAccount, - maxVoterWeightPk: PublicKey | undefined + maxVoterWeightPk: PublicKey | undefined, + proposalOwner: ProgramAccount ) => { const signers: Keypair[] = [] const instructions: TransactionInstruction[] = [] // Explicitly request the version before making RPC calls to work around race conditions in resolving // the version for RealmInfo - const programVersion = await getGovernanceProgramVersion( - connection, - programId - ) + const programVersion = await fetchProgramVersion(connection, programId) await withFinalizeVote( instructions, @@ -41,16 +38,63 @@ export const finalizeVote = async ( maxVoterWeightPk ) - const transaction = new Transaction() + //its possible that delegate payed for deposit created with someone else token owner record. + //there is need of check both deposits. + const [possibleDelegateDeposit, possibleTorDeposit] = [ + proposalOwner.account.governanceDelegate + ? getProposalDepositPk( + proposal.pubkey, + proposalOwner.account.governanceDelegate, + programId + ) + : null, + getProposalDepositPk( + proposal.pubkey, + proposalOwner.account.governingTokenOwner, + programId + ), + ] - transaction.add(...instructions) + //Release sol if deposit exempt setting threshold hit + const [delegateDeposit, torDeposit] = await Promise.all([ + possibleDelegateDeposit + ? connection.getBalance(possibleDelegateDeposit) + : null, + connection.getBalance(possibleTorDeposit), + ]) - await sendTransaction({ - transaction, - wallet, + let refundAddress + if (delegateDeposit && delegateDeposit > 0 && possibleDelegateDeposit) { + refundAddress = proposalOwner.account.governanceDelegate + } else if (torDeposit && torDeposit > 0) { + refundAddress = proposalOwner.account.governingTokenOwner + } + + if (refundAddress) { + await withRefundProposalDeposit( + instructions, + programId!, + programVersion, + proposal.pubkey, + refundAddress + ) + } + + const txes = [instructions].map((txBatch) => { + return { + instructionsSet: txBatch.map((x) => { + return { + transactionInstruction: x, + signers: signers, + } + }), + sequenceType: SequenceType.Sequential, + } + }) + + await sendTransactionsV3({ connection, - signers, - sendingMessage: 'Finalizing votes', - successMessage: 'Votes finalized', + wallet, + transactionInstructions: txes, }) } diff --git a/actions/flagInstructionError.ts b/actions/flagInstructionError.ts index 665810f4e4..cc10702f62 100644 --- a/actions/flagInstructionError.ts +++ b/actions/flagInstructionError.ts @@ -1,16 +1,13 @@ -import { - Keypair, - PublicKey, - Transaction, - TransactionInstruction, -} from '@solana/web3.js' +import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js' -import { getGovernanceProgramVersion, Proposal } from '@solana/spl-governance' +import { Proposal } from '@solana/spl-governance' import { withFlagTransactionError } from '@solana/spl-governance' import { RpcContext } from '@solana/spl-governance' import { ProgramAccount } from '@solana/spl-governance' -import { sendTransaction } from '@utils/send' +import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' +import { SequenceType } from '@blockworks-foundation/mangolana/lib/globalTypes' +import { sendTransactionsV3 } from '@utils/sendTransactions' export const flagInstructionError = async ( { connection, wallet, programId, walletPubkey }: RpcContext, @@ -24,10 +21,7 @@ export const flagInstructionError = async ( // Explicitly request the version before making RPC calls to work around race conditions in resolving // the version for RealmInfo - const programVersion = await getGovernanceProgramVersion( - connection, - programId - ) + const programVersion = await fetchProgramVersion(connection, programId) withFlagTransactionError( instructions, @@ -39,16 +33,21 @@ export const flagInstructionError = async ( proposalInstruction ) - const transaction = new Transaction({ feePayer: walletPubkey }) - - transaction.add(...instructions) + const txes = [instructions].map((txBatch) => { + return { + instructionsSet: txBatch.map((x) => { + return { + transactionInstruction: x, + signers: signers, + } + }), + sequenceType: SequenceType.Sequential, + } + }) - await sendTransaction({ - transaction, + await sendTransactionsV3({ connection, wallet, - signers, - sendingMessage: 'Flagging instruction as broken', - successMessage: 'Instruction flagged as broken', + transactionInstructions: txes, }) } diff --git a/actions/registerProgramGovernance.ts b/actions/registerProgramGovernance.ts deleted file mode 100644 index 6a4b4a7e10..0000000000 --- a/actions/registerProgramGovernance.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { - Keypair, - PublicKey, - Transaction, - TransactionInstruction, -} from '@solana/web3.js' -import { - getGovernanceProgramVersion, - GovernanceType, - ProgramAccount, - Realm, - TokenOwnerRecord, -} from '@solana/spl-governance' -import { GovernanceConfig } from '@solana/spl-governance' -import { withCreateProgramGovernance } from '@solana/spl-governance' -import { RpcContext } from '@solana/spl-governance' -import { sendTransaction } from '@utils/send' -import { VotingClient } from '@utils/uiTypes/VotePlugin' - -export const registerProgramGovernance = async ( - { connection, wallet, programId, walletPubkey }: RpcContext, - governanceType: GovernanceType, - realm: ProgramAccount, - governedAccount: PublicKey, - config: GovernanceConfig, - transferAuthority: boolean, - tokenOwnerRecord: ProgramAccount, - client?: VotingClient -): Promise => { - const instructions: TransactionInstruction[] = [] - const signers: Keypair[] = [] - let governanceAddress - const governanceAuthority = walletPubkey - - // Explicitly request the version before making RPC calls to work around race conditions in resolving - // the version for RealmInfo - const programVersion = await getGovernanceProgramVersion( - connection, - programId - ) - - //will run only if plugin is connected with realm - const plugin = await client?.withUpdateVoterWeightRecord( - instructions, - tokenOwnerRecord, - 'createGovernance' - ) - - switch (governanceType) { - case GovernanceType.Program: { - governanceAddress = await withCreateProgramGovernance( - instructions, - programId, - programVersion, - realm.pubkey, - governedAccount, - config, - transferAuthority!, - walletPubkey, - tokenOwnerRecord.pubkey, - walletPubkey, - governanceAuthority, - plugin?.voterWeightPk - ) - break - } - default: { - throw new Error(`Governance type ${governanceType} is not supported yet.`) - } - } - - const transaction = new Transaction() - transaction.add(...instructions) - await sendTransaction({ - transaction, - wallet, - connection, - signers, - sendingMessage: 'Creating governance program account', - successMessage: 'Governance program account has been created', - }) - - return governanceAddress -} diff --git a/actions/relinquishVote.ts b/actions/relinquishVote.ts index 9c9c00f090..ffcd17e43b 100644 --- a/actions/relinquishVote.ts +++ b/actions/relinquishVote.ts @@ -1,23 +1,22 @@ import { Keypair, PublicKey, - Transaction, TransactionInstruction, } from '@solana/web3.js' import { Proposal } from '@solana/spl-governance' import { RpcContext } from '@solana/spl-governance' import { ProgramAccount } from '@solana/spl-governance' -import { sendTransaction } from '../utils/send' import { withRelinquishVote } from '@solana/spl-governance' import { VotingClient } from '@utils/uiTypes/VotePlugin' import { chunks } from '@utils/helpers' import { - sendTransactionsV2, + sendTransactionsV3, SequenceType, - transactionInstructionsToTypedInstructionsSets, + txBatchesToInstructionSetWithSigners, } from '@utils/sendTransactions' -import { NftVoterClient } from '@solana/governance-program-library' +import { NftVoterClient } from '@utils/uiTypes/NftVoterClient' +import { HeliumVsrClient } from 'HeliumVotePlugin/sdk/client' export const relinquishVote = async ( { connection, wallet, programId, programVersion, walletPubkey }: RpcContext, @@ -45,40 +44,65 @@ export const relinquishVote = async ( governanceAuthority, beneficiary ) - await plugin.withRelinquishVote(instructions, proposal, voteRecord) - const shouldChunk = plugin?.client instanceof NftVoterClient + + await plugin.withRelinquishVote( + instructions, + proposal, + voteRecord, + tokenOwnerRecord + ) + + const shouldChunk = + plugin?.client instanceof NftVoterClient || + plugin?.client instanceof HeliumVsrClient + if (shouldChunk) { const insertChunks = chunks(instructions, 2) - const signerChunks = Array(instructions.length).fill([]) const instArray = [ - ...insertChunks - .slice(0, 1) - .map((x) => - transactionInstructionsToTypedInstructionsSets( - x, - SequenceType.Sequential - ) - ), - ...insertChunks - .slice(1, insertChunks.length) - .map((x) => - transactionInstructionsToTypedInstructionsSets( - x, - SequenceType.Parallel - ) - ), + ...insertChunks.slice(0, 1).map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [], + batchIdx + ), + sequenceType: SequenceType.Sequential, + } + }), + ...insertChunks.slice(1, insertChunks.length).map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [], + batchIdx + ), + sequenceType: SequenceType.Parallel, + } + }), ] - await sendTransactionsV2({ + + await sendTransactionsV3({ connection, wallet, - TransactionInstructions: instArray, - signersSet: [...signerChunks], - showUiComponent: true, + transactionInstructions: instArray, }) } else { - const transaction = new Transaction() - transaction.add(...instructions) + const txes = [instructions].map((txBatch) => { + return { + instructionsSet: txBatch.map((x) => { + return { + transactionInstruction: x, + signers: signers, + } + }), + sequenceType: SequenceType.Sequential, + } + }) - await sendTransaction({ transaction, wallet, connection, signers }) + await sendTransactionsV3({ + connection, + wallet, + transactionInstructions: txes, + }) } } diff --git a/actions/signOffProposal.ts b/actions/signOffProposal.ts index 551bd23270..f7b79592f1 100644 --- a/actions/signOffProposal.ts +++ b/actions/signOffProposal.ts @@ -5,15 +5,12 @@ import { TransactionInstruction, } from '@solana/web3.js' -import { - getGovernanceProgramVersion, - Proposal, - RpcContext, -} from '@solana/spl-governance' +import { Proposal, RpcContext } from '@solana/spl-governance' import { SignatoryRecord } from '@solana/spl-governance' import { ProgramAccount } from '@solana/spl-governance' import { sendTransaction } from 'utils/send' import { withSignOffProposal } from '@solana/spl-governance' +import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' export const signOffProposal = async ( { connection, wallet, programId }: RpcContext, @@ -26,10 +23,7 @@ export const signOffProposal = async ( // Explicitly request the version before making RPC calls to work around race conditions in resolving // the version for RealmInfo - const programVersion = await getGovernanceProgramVersion( - connection, - programId - ) + const programVersion = await fetchProgramVersion(connection, programId) withSignOffProposal( instructions, diff --git a/actions/switchboardRefreshVoterWeight.ts b/actions/switchboardRefreshVoterWeight.ts deleted file mode 100644 index dadd3e88d7..0000000000 --- a/actions/switchboardRefreshVoterWeight.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Transaction } from '@solana/web3.js' -import { sendTransaction } from '@utils/send' - -export const sbRefreshWeight = async ( - voterWeightInstructions, - connection, - wallet -) => { - /*const voterWeightInstructions = useSwitchboardPluginStore((s) => s.state.instructions); - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current)*/ - - const transaction = new Transaction().add(voterWeightInstructions) - - await sendTransaction({ - transaction: transaction, - wallet: wallet, - signers: [], - connection: connection.current, - }) -} diff --git a/cli/createProposalScript.ts b/cli/createProposalScript.ts new file mode 100644 index 0000000000..1b8cae3d59 --- /dev/null +++ b/cli/createProposalScript.ts @@ -0,0 +1,185 @@ +import { EndpointTypes } from '@models/types' +import { Connection, Keypair, PublicKey } from '@solana/web3.js' +import { VsrClient } from 'VoteStakeRegistry/sdk/client' +import chalk from 'chalk' +import figlet from 'figlet' +import promptly from 'promptly' +import { readFileSync } from 'fs' +import { homedir } from 'os' +import { join } from 'path' +import NodeWallet from '@coral-xyz/anchor/dist/cjs/nodewallet' +import { AnchorProvider, Wallet } from '@coral-xyz/anchor' +import { createBase64Proposal } from './helpers/createBase64Proposal' +import { + getAllProposals, + getInstructionDataFromBase64, + getTokenOwnerRecord, + getTokenOwnerRecordAddress, +} from '@solana/spl-governance' +import { tryParseKey } from '@tools/validators/pubkey' + +const loadWalletFromFile = (walletPath: string): Keypair => { + const walletJSON = readFileSync(walletPath, 'utf-8') + const walletData = JSON.parse(walletJSON) + return Keypair.fromSecretKey(new Uint8Array(walletData)) +} + +const VSR_PROGRAM_ID = '4Q6WW2ouZ6V3iaNm56MTd5n2tnTm4C5fiH8miFHnAFHo' + +const ENDPOINT_URL = 'https://api.mainnet-beta.solana.com/' + +const CLUSTER = 'mainnet' + +const REALM = new PublicKey('DPiH3H3c7t47BMxqTxLsuPQpEC6Kne8GA9VXbxpnZxFE') + +const GOVERNANCE_PROGRAM = new PublicKey( + 'GqTPL6qRf5aUuqscLh8Rg2HTxPUXfhhAXDptTLhp1t2J' +) + +const PROPOSAL_MINT = new PublicKey( + 'MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac' +) + +class GovernanceCli { + #connectionContext = { + cluster: CLUSTER as EndpointTypes, + current: new Connection(ENDPOINT_URL, 'recent'), + endpoint: ENDPOINT_URL, + } + wallet: NodeWallet + walletKeyPair: Keypair + vsrClient: VsrClient + constructor(walletKeyPair: Keypair) { + this.walletKeyPair = walletKeyPair + } + async setupKeyPairWallet() { + console.log('Setting up wallet...') + const tempPayerWallet = Keypair.fromSecretKey(this.walletKeyPair.secretKey) + const tempWallet = new NodeWallet(tempPayerWallet) + this.wallet = tempWallet + console.log('Wallet ready') + } + async setupVoterClient() { + console.log('Setting up vsr...') + const options = AnchorProvider.defaultOptions() + const provider = new AnchorProvider( + this.#connectionContext.current, + (this.wallet as unknown) as Wallet, + options + ) + const vsrClient = await VsrClient.connect( + provider, + new PublicKey(VSR_PROGRAM_ID), + this.#connectionContext.cluster === 'devnet' + ) + this.vsrClient = vsrClient + console.log('Vsr ready') + } + async createProposal() { + const instructionsCount = await promptly.prompt( + 'How many instructions you want to use?' + ) + if (isNaN(instructionsCount)) { + console.log('Error instruction count is not a number') + return + } + const governancePk = await promptly.prompt( + 'Provide governance address for proposal: ' + ) + if (!tryParseKey(governancePk)) { + console.log('Error invalid publickey') + return + } + const delegatedWallet = await promptly.prompt( + 'Enter the address that delegated the token to you: ' + ) + if (!tryParseKey(delegatedWallet)) { + console.log('Error invalid publickey') + return + } + const title = await promptly.prompt('Title: ') + const description = await promptly.prompt('Description: ') + const instructions: string[] = [] + for (let i = 0; i < instructionsCount; i++) { + const instructionNumber = i + 1 + const inst = await promptly.prompt( + `Instruction ${instructionNumber} Base64: ` + ) + try { + getInstructionDataFromBase64(inst) + } catch (e) { + console.log('Error while parsing instruction: ', e) + } + instructions.push(inst) + } + + let tokenOwnerRecordPk: PublicKey | null = null + if (delegatedWallet) { + tokenOwnerRecordPk = await getTokenOwnerRecordAddress( + GOVERNANCE_PROGRAM, + REALM, + PROPOSAL_MINT, + new PublicKey(delegatedWallet) + ) + } else { + tokenOwnerRecordPk = await getTokenOwnerRecordAddress( + GOVERNANCE_PROGRAM, + REALM, + PROPOSAL_MINT, + this.wallet.publicKey + ) + } + const [tokenOwnerRecord, proposals] = await Promise.all([ + getTokenOwnerRecord(this.#connectionContext.current, tokenOwnerRecordPk), + getAllProposals( + this.#connectionContext.current, + GOVERNANCE_PROGRAM, + REALM + ), + ]) + const proposalIndex = proposals.flatMap((x) => x).length + + try { + const address = await createBase64Proposal( + this.#connectionContext.current, + this.wallet, + tokenOwnerRecord, + new PublicKey(governancePk), + REALM, + GOVERNANCE_PROGRAM, + PROPOSAL_MINT, + title, + description, + proposalIndex, + [...instructions], + this.vsrClient + ) + console.log( + `Success proposal created url: https://realms.today/dao/${REALM.toBase58()}/proposal/${address.toBase58()}` + ) + } catch (e) { + console.log('ERROR: ', e) + } + } + async init() { + await Promise.all([this.setupKeyPairWallet(), this.setupVoterClient()]) + } +} + +async function run() { + console.log( + chalk.red( + figlet.textSync('spl-governance-cli', { horizontalLayout: 'full' }) + ) + ) + ;(async () => { + //Load wallet from file system assuming its in default direction /Users/-USERNAME-/.config/solana/id.json + const walletPath = join(homedir(), '.config', 'solana', 'id.json') + const wallet = loadWalletFromFile(walletPath) + const cli = new GovernanceCli(wallet) + await cli.init() + await cli.createProposal() + })() +} + +run() diff --git a/cli/helpers/createBase64Proposal.ts b/cli/helpers/createBase64Proposal.ts new file mode 100644 index 0000000000..658ec9e613 --- /dev/null +++ b/cli/helpers/createBase64Proposal.ts @@ -0,0 +1,167 @@ +import { + getGovernanceProgramVersion, + getInstructionDataFromBase64, + getSignatoryRecordAddress, + ProgramAccount, + SYSTEM_PROGRAM_ID, + TokenOwnerRecord, + VoteType, + WalletSigner, + withAddSignatory, + withInsertTransaction, + withSignOffProposal, +} from '@solana/spl-governance' +import { + withCreateProposal +} from '@realms-today/spl-governance' +import { Connection, PublicKey, TransactionInstruction } from '@solana/web3.js' +import { chunk } from 'lodash' +import { sendSignAndConfirmTransactions } from '@blockworks-foundation/mangolana/lib/transactions' +import { SequenceType } from '@blockworks-foundation/mangolana/lib/globalTypes' +import { VsrClient } from 'VoteStakeRegistry/sdk/client' +import { + getRegistrarPDA, + getVoterPDA, + getVoterWeightPDA, +} from 'VoteStakeRegistry/sdk/accounts' + +export const createBase64Proposal = async ( + connection: Connection, + wallet: WalletSigner, + tokenOwnerRecord: ProgramAccount, + governance: PublicKey, + realm: PublicKey, + governanceProgram: PublicKey, + proposalMint: PublicKey, + name: string, + descriptionLink: string, + proposalIndex: number, + base64Instructions: string[], + client?: VsrClient +) => { + const instructions: TransactionInstruction[] = [] + const walletPk = wallet.publicKey! + const governanceAuthority = walletPk + const signatory = walletPk + const payer = walletPk + + // Changed this because it is misbehaving on my local validator setup. + const programVersion = await getGovernanceProgramVersion( + connection, + governanceProgram + ) + + // V2 Approve/Deny configuration + const voteType = VoteType.SINGLE_CHOICE + const options = ['Approve'] + const useDenyOption = true + let voterWeightPluginPk: PublicKey | undefined = undefined + if (client) { + const { registrar } = getRegistrarPDA( + realm, + proposalMint, + client.program.programId + ) + const { voter } = getVoterPDA( + registrar, + walletPk, + client.program.programId + ) + const { voterWeightPk } = getVoterWeightPDA( + registrar, + walletPk, + client.program.programId + ) + voterWeightPluginPk = voterWeightPk + const updateVoterWeightRecordIx = await client.program.methods + .updateVoterWeightRecord() + .accounts({ + registrar, + voter, + voterWeightRecord: voterWeightPk, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .instruction() + instructions.push(updateVoterWeightRecordIx) + } + + const proposalAddress = await withCreateProposal( + instructions, + governanceProgram, + programVersion, + realm, + governance, + tokenOwnerRecord.pubkey, + name, + descriptionLink, + proposalMint, + governanceAuthority, + proposalIndex, + voteType, + options, + useDenyOption, + payer, + voterWeightPluginPk + ) + + await withAddSignatory( + instructions, + governanceProgram, + programVersion, + proposalAddress, + tokenOwnerRecord.pubkey, + governanceAuthority, + signatory, + payer + ) + + const signatoryRecordAddress = await getSignatoryRecordAddress( + governanceProgram, + proposalAddress, + signatory + ) + const insertInstructions: TransactionInstruction[] = [] + for (const i in base64Instructions) { + const instruction = getInstructionDataFromBase64(base64Instructions[i]) + await withInsertTransaction( + insertInstructions, + governanceProgram, + programVersion, + governance, + proposalAddress, + tokenOwnerRecord.pubkey, + governanceAuthority, + Number(i), + 0, + 0, + [instruction], + payer + ) + } + withSignOffProposal( + insertInstructions, // SingOff proposal needs to be executed after inserting instructions hence we add it to insertInstructions + governanceProgram, + programVersion, + realm, + governance, + proposalAddress, + signatory, + signatoryRecordAddress, + undefined + ) + + const txChunks = chunk([...instructions, ...insertInstructions], 2) + + await sendSignAndConfirmTransactions({ + connection, + wallet, + transactionInstructions: txChunks.map((txChunk) => ({ + instructionsSet: txChunk.map((tx) => ({ + signers: [], + transactionInstruction: tx, + })), + sequenceType: SequenceType.Sequential, + })), + }) + return proposalAddress +} diff --git a/components/AboutRealm.tsx b/components/AboutRealm.tsx index 56973f0d4a..8a3e71cf2f 100644 --- a/components/AboutRealm.tsx +++ b/components/AboutRealm.tsx @@ -1,14 +1,15 @@ -import React from 'react' import useRealm from 'hooks/useRealm' +import useProgramVersion from '@hooks/useProgramVersion' const AboutRealm = () => { - const { realmInfo, realmDisplayName, symbol } = useRealm() + const { realmInfo, symbol } = useRealm() + const programVersion = useProgramVersion() return (

Name

-

{realmDisplayName || symbol}

+

{realmInfo?.displayName || symbol}

{realmInfo?.isCertified ? (
@@ -44,7 +45,7 @@ const AboutRealm = () => { ) : null}

Program Version

-

{realmInfo?.programVersion}

+

{programVersion}

) diff --git a/components/AdditionalProposalOptions.tsx b/components/AdditionalProposalOptions.tsx index 250ead7dec..86b3e720d5 100644 --- a/components/AdditionalProposalOptions.tsx +++ b/components/AdditionalProposalOptions.tsx @@ -1,21 +1,12 @@ import { ChevronDownIcon } from '@heroicons/react/outline' -import useRealm from '@hooks/useRealm' import VoteBySwitch from 'pages/dao/[symbol]/proposal/components/VoteBySwitch' -import { useState } from 'react' +import React, { useState } from 'react' import { LinkButton } from './Button' import Input from './inputs/Input' import Textarea from './inputs/Textarea' +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; -const AdditionalProposalOptions = ({ - title, - description, - setTitle, - setDescription, - defaultTitle, - defaultDescription, - voteByCouncil, - setVoteByCouncil, -}: { +const AdditionalProposalOptions: React.FC<{ title: string description: string setTitle: (evt) => void @@ -24,9 +15,18 @@ const AdditionalProposalOptions = ({ defaultDescription?: string voteByCouncil: boolean setVoteByCouncil: (val) => void +}> = ({ + title, + description, + setTitle, + setDescription, + defaultTitle, + defaultDescription, + voteByCouncil, + setVoteByCouncil, }) => { const [showOptions, setShowOptions] = useState(false) - const { canChooseWhoVote } = useRealm() + const { shouldShowVoteByCouncilToggle } = useVoteByCouncilToggle(); return ( <> - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - /> + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > )}
)} diff --git a/components/App.tsx b/components/App.tsx new file mode 100644 index 0000000000..a199520b87 --- /dev/null +++ b/components/App.tsx @@ -0,0 +1,337 @@ +import { ThemeProvider } from 'next-themes' +import dynamic from 'next/dynamic' +import React, { useEffect, useMemo } from 'react' +import Head from 'next/head' +import Script from 'next/script' +import { useRouter } from 'next/router' +import { GatewayProvider } from '@components/Gateway/GatewayProvider' +import { VSR_PLUGIN_PKS } from '@constants/plugins' +import ErrorBoundary from '@components/ErrorBoundary' +import useHandleGovernanceAssetsStore from '@hooks/handleGovernanceAssetsStore' +import handleRouterHistory from '@hooks/handleRouterHistory' +import NavBar from '@components/NavBar' +import PageBodyContainer from '@components/PageBodyContainer' +import tokenPriceService from '@utils/services/tokenPrice' +import TransactionLoader from '@components/TransactionLoader' +import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' +import useRealm from '@hooks/useRealm' +import NftVotingCountingModal from '@components/NftVotingCountingModal' +import { getResourcePathPart } from '@tools/core/resources' +import useSerumGovStore from 'stores/useSerumGovStore' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { + ConnectionProvider, + WalletProvider, +} from '@solana/wallet-adapter-react' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { DEVNET_RPC, MAINNET_RPC } from 'constants/endpoints' +import { + SquadsEmbeddedWalletAdapter, + detectEmbeddedInSquadsIframe, +} from '@sqds/iframe-adapter' +import { WALLET_PROVIDERS } from '@utils/wallet-adapters' +import { tryParsePublicKey } from '@tools/core/pubkey' +import { useAsync } from 'react-async-hook' +import { useVsrClient } from '../VoterWeightPlugins/useVsrClient' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import TermsPopupModal from './TermsPopup' + +const Notifications = dynamic(() => import('../components/Notification'), { + ssr: false, +}) + +const GoogleTag = React.memo( + function GoogleTag() { + return ( + + + + ) + }, + () => true +) + +interface Props { + children: React.ReactNode +} + +/** AppContents depends on providers itself, sadly, so this is where providers go. */ +export function App(props: Props) { + const router = useRouter() + const { cluster } = router.query + + const endpoint = useMemo( + () => (cluster === 'devnet' ? DEVNET_RPC : MAINNET_RPC), + [cluster] + ) + + const supportedWallets = useMemo( + () => + detectEmbeddedInSquadsIframe() + ? [new SquadsEmbeddedWalletAdapter()] + : WALLET_PROVIDERS.map((provider) => provider.adapter), + [] + ) + + return ( + + + {' '} + + + ) +} + +const allowedFaviconPaths = ['/realms/'] +const allowedDomains = [ + 'https://app.realms.today', + 'http://localhost', + 'http://localhost:3000', +] + +export function AppContents(props: Props) { + handleRouterHistory() + useHandleGovernanceAssetsStore() + useEffect(() => { + tokenPriceService.fetchSolanaTokenList() + }, []) + + const { getOwnedDeposits, resetDepositState } = useDepositStore() + + const { plugins } = useRealmVoterWeightPlugins('community') + const usesVsr = plugins?.voterWeight.find((plugin) => + VSR_PLUGIN_PKS.includes(plugin.programId.toString()) + ) + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + + const realm = useRealmQuery().data?.result + const config = useRealmConfigQuery().data?.result + + const { realmInfo } = useRealm() + const wallet = useWalletOnePointOh() + const connection = useLegacyConnectionContext() + + const router = useRouter() + const { cluster } = router.query + const updateSerumGovAccounts = useSerumGovStore( + (s) => s.actions.updateSerumGovAccounts + ) + const { vsrClient } = useVsrClient() + + const realmName = realmInfo?.displayName ?? realm?.account?.name + const title = realmName ? `${realmName}` : 'Realms' + + // Note: ?v==${Date.now()} is added to the url to force favicon refresh. + // Without it browsers would cache the last used and won't change it for different realms + // https://stackoverflow.com/questions/2208933/how-do-i-force-a-favicon-refresh + + const faviconUrl = useMemo(() => { + const symbol = router.query.symbol + + if (!symbol || tryParsePublicKey(symbol as string) !== undefined) { + return null + } + if (!isValidSymbol(symbol)) { + console.error('Invalid symbol') + return null + } + + const resourcePath = getResourcePathPart(symbol as string) + const fullUrl = `${ + window.location.origin + }/realms/${resourcePath}/favicon.ico?v=${Date.now()}` + + // Check if the domain is in the allow list + try { + const urlObject = new URL(fullUrl) + if (!allowedDomains.includes(urlObject.origin)) { + console.error('Domain not in allowed list') + return null + } + // Check if the path is in the allow list + if ( + !allowedFaviconPaths.some((path) => urlObject.pathname.startsWith(path)) + ) { + console.error('Path not in allowed list') + return null + } + + return urlObject.href + } catch (error) { + console.error('Invalid URL:', error) + return null + } + }, [router.query.symbol]) + + // Validate it's an ico file + function isValidSymbol(symbol) { + return ( + typeof symbol === 'string' && + symbol.trim() !== '' && + /^[a-zA-Z0-9-_]+$/.test(symbol) + ) + } + const { result: faviconExists } = useAsync(async () => { + if (!faviconUrl) { + return false + } + + try { + const response = await fetch(faviconUrl) + return response.status === 200 + } catch (error) { + console.error('Error fetching favicon:', error) + return false + } + }, [faviconUrl]) + + useEffect(() => { + if ( + realm && + usesVsr && + realm.pubkey && + wallet?.connected && + ownTokenRecord && + vsrClient + ) { + getOwnedDeposits({ + realmPk: realm.pubkey, + communityMintPk: realm.account.communityMint, + walletPk: ownTokenRecord!.account!.governingTokenOwner, + client: vsrClient, + connection: connection.current, + }) + } else if (!wallet?.connected || !ownTokenRecord) { + resetDepositState() + } + }, [ + config?.account.communityTokenConfig.voterWeightAddin, + connection, + getOwnedDeposits, + ownTokenRecord, + realm, + resetDepositState, + vsrClient, + wallet?.connected, + ]) + + useEffect(() => { + updateSerumGovAccounts(cluster as string | undefined) + }, [cluster, updateSerumGovAccounts]) + + return ( +
+ + + {title} + + {faviconUrl && faviconExists ? ( + <> + + + ) : ( + <> + + + + + + + + + + + + + + + )} + + + + + + + + + + {props.children} + + + + +
+ ) +} diff --git a/components/ApprovalQuorum.tsx b/components/ApprovalQuorum.tsx deleted file mode 100644 index 4335bd5b30..0000000000 --- a/components/ApprovalQuorum.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import Tooltip from './Tooltip' -import { - CheckCircleIcon, - InformationCircleIcon, -} from '@heroicons/react/outline' - -type ApprovalProgressProps = { - progress: number - showBg?: boolean - yesVotesRequired: number -} - -const ApprovalProgress = ({ - progress, - showBg, - yesVotesRequired, -}: ApprovalProgressProps) => { - return ( -
-
-
-
-

Approval Quorum

- - - -
- - {progress < 100 ? ( -

{`${yesVotesRequired?.toLocaleString( - undefined, - { - maximumFractionDigits: 0, - } - )} ${progress > 0 ? 'more' : ''} Yes vote${ - yesVotesRequired > 1 ? 's' : '' - } required`}

- ) : ( -
- -

- Required approval achieved -

-
- )} -
-
- {/* {progress < 100 ? ( */} -
-
= 100 ? 'bg-green' : 'bg-fgd-3' - } flex rounded`} - >
-
- {/* ) : null} */} -
- ) -} - -export default ApprovalProgress diff --git a/components/AssetsList/AssetItem.tsx b/components/AssetsList/AssetItem.tsx index c3f1368436..11ccbc6b63 100644 --- a/components/AssetsList/AssetItem.tsx +++ b/components/AssetsList/AssetItem.tsx @@ -1,13 +1,10 @@ import { useEffect, useState } from 'react' import { ExternalLinkIcon, TerminalIcon } from '@heroicons/react/outline' -import { ProgramAccount } from '@solana/spl-governance' -import { Governance } from '@solana/spl-governance' import { getProgramName } from '@components/instructions/programs/names' import { abbreviateAddress } from '@utils/formatting' import { PublicKey } from '@solana/web3.js' import Button, { SecondaryButton } from '@components/Button' import Tooltip from '@components/Tooltip' -import useWalletStore from 'stores/useWalletStore' import { getProgramData } from '@tools/sdk/bpfUpgradeableLoader/accounts' import useGovernanceAssets from '@hooks/useGovernanceAssets' import Modal from '@components/Modal' @@ -15,16 +12,17 @@ import UpgradeProgram from './UpgradeProgram' import CloseBuffers from './CloseBuffers' import { getExplorerUrl } from '@components/explorer/tools' import TransferUpgradeAuthority from './TransferUpgradeAuthority' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { AssetAccount } from '@utils/uiTypes/assets' const AssetItem = ({ item, panelView, }: { - item: ProgramAccount + item: AssetAccount panelView?: boolean }) => { const { canUseProgramUpgradeInstruction } = useGovernanceAssets() - const [isAuthority, setIsAuthority] = useState(true) const [slot, setSlot] = useState(0) const [openUpgradeModal, setOpenUpgradeModal] = useState(false) const [openCloseBuffersModal, setOpenCloseBuffersModal] = useState(false) @@ -32,29 +30,30 @@ const AssetItem = ({ false ) const [loadData, setLoadData] = useState(false) - const connection = useWalletStore((s) => s.connection) - const name = item ? getProgramName(item.account.governedAccount) : '' + const connection = useLegacyConnectionContext() + const name = item ? getProgramName(item.pubkey) : '' const governedAccount = item - ? abbreviateAddress(item?.account.governedAccount as PublicKey) + ? abbreviateAddress(item.pubkey as PublicKey) : '' - const programId = item!.account.governedAccount.toBase58() + const programId = item!.pubkey.toBase58() useEffect(() => { const handleSetProgramVersion = async () => { try { setLoadData(true) const programData = await getProgramData(connection.current, programId) - const isAuthority = - item.pubkey.toString() === programData?.authority?.toString() - setIsAuthority(isAuthority) setSlot(programData.slot) } catch (e) { console.log(e) } setLoadData(false) } - handleSetProgramVersion() - }, [JSON.stringify(item)]) + if (!panelView) { + handleSetProgramVersion() + } + + // 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 + }, [JSON.stringify(item), panelView]) return (
@@ -68,10 +67,7 @@ const AssetItem = ({ e.stopPropagation()} @@ -95,61 +91,54 @@ const AssetItem = ({
- {' '} - {isAuthority ? ( - <> - - setOpenCloseBuffersModal(true)} - disabled={!canUseProgramUpgradeInstruction} +
Upgrade
+ + + setOpenCloseBuffersModal(true)} + disabled={!canUseProgramUpgradeInstruction} + > + - -
Close Buffers
-
-
- setOpenTransferAuthorityModal(true)} - disabled={!canUseProgramUpgradeInstruction} +
Close Buffers
+ +
+ setOpenTransferAuthorityModal(true)} + disabled={!canUseProgramUpgradeInstruction} + > + - -
Transfer Authority
-
-
- - ) : ( -
- This governance is no longer the upgrade authority -
- )} +
Transfer Authority
+ +
+
)} - {isAuthority && openUpgradeModal && ( + {openUpgradeModal && ( { setOpenUpgradeModal(false) @@ -159,7 +148,7 @@ const AssetItem = ({ )} - {isAuthority && openCloseBuffersModal && ( + {openCloseBuffersModal && ( { setOpenCloseBuffersModal(false) @@ -169,7 +158,7 @@ const AssetItem = ({ )} - {isAuthority && openTransferAuthorityModal && ( + {openTransferAuthorityModal && ( { setOpenTransferAuthorityModal(false) diff --git a/components/AssetsList/AssetsCompactWrapper.tsx b/components/AssetsList/AssetsCompactWrapper.tsx index 66eb81cf14..59b0239057 100644 --- a/components/AssetsList/AssetsCompactWrapper.tsx +++ b/components/AssetsList/AssetsCompactWrapper.tsx @@ -1,80 +1,40 @@ -import React from 'react' import AssetsList from './AssetsList' import { ChevronRightIcon } from '@heroicons/react/solid' import useRealm from '@hooks/useRealm' import useQueryContext from '@hooks/useQueryContext' -import useWalletStore from 'stores/useWalletStore' import Link from 'next/link' -import { useRouter } from 'next/router' -import { TerminalIcon } from '@heroicons/react/outline' import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { GovernanceAccountType } from '@solana/spl-governance' -import EmptyState from '@components/EmptyState' -import { - NEW_PROGRAM_VIEW, - renderAddNewAssetTooltip, -} from 'pages/dao/[symbol]/assets' +import { AccountType } from '@utils/uiTypes/assets' const AssetsCompactWrapper = () => { - const router = useRouter() const { fmtUrlWithCluster } = useQueryContext() - const { - symbol, - realm, - ownVoterWeight, - toManyCommunityOutstandingProposalsForUser, - toManyCouncilOutstandingProposalsForUse, - } = useRealm() - const connected = useWalletStore((s) => s.connected) - const canCreateGovernance = realm - ? ownVoterWeight.canCreateGovernance(realm) - : null - const newAssetToolTip = renderAddNewAssetTooltip( - connected, - canCreateGovernance, - toManyCommunityOutstandingProposalsForUser, - toManyCouncilOutstandingProposalsForUse - ) + const { symbol } = useRealm() - const goToNewAssetForm = () => { - router.push(fmtUrlWithCluster(`/dao/${symbol}${NEW_PROGRAM_VIEW}`)) - } - const { getGovernancesByAccountTypes } = useGovernanceAssets() - const programGovernances = getGovernancesByAccountTypes([ - GovernanceAccountType.ProgramGovernanceV1, - GovernanceAccountType.ProgramGovernanceV2, - ]) + const { assetAccounts } = useGovernanceAssets() + const programGovernances = assetAccounts + .filter((x) => x.type === AccountType.PROGRAM) + .map((x) => x.governance) - return ( + return programGovernances.length < 1 ? ( + <> + ) : (
+
+
- {programGovernances.length > 0 ? ( -
- -
- ) : ( - } - onClickButton={goToNewAssetForm} - toolTipContent={newAssetToolTip} - /> - )}
) } diff --git a/components/AssetsList/AssetsList.tsx b/components/AssetsList/AssetsList.tsx index 5bc3ca6297..cae0284f84 100644 --- a/components/AssetsList/AssetsList.tsx +++ b/components/AssetsList/AssetsList.tsx @@ -1,17 +1,18 @@ import AssetItem from './AssetItem' import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { GovernanceAccountType } from '@solana/spl-governance' +import { AccountType } from '@utils/uiTypes/assets' interface AssetsListProps { panelView?: boolean } const AssetsList = ({ panelView }: AssetsListProps) => { - const { getGovernancesByAccountTypes } = useGovernanceAssets() - const programGovernances = getGovernancesByAccountTypes([ - GovernanceAccountType.ProgramGovernanceV1, - GovernanceAccountType.ProgramGovernanceV2, - ]) + const { assetAccounts } = useGovernanceAssets() + + const programGovernances = assetAccounts.filter( + (x) => x.type === AccountType.PROGRAM + ) + return !panelView ? (
{programGovernances.map((x) => ( diff --git a/components/AssetsList/BaseGovernanceForm.tsx b/components/AssetsList/BaseGovernanceForm.tsx deleted file mode 100644 index e9252421f4..0000000000 --- a/components/AssetsList/BaseGovernanceForm.tsx +++ /dev/null @@ -1,231 +0,0 @@ -import Input from '@components/inputs/Input' -import Select from '@components/inputs/Select' -import AmountSlider from '@components/Slider' -import Switch from '@components/Switch' -import useRealm from '@hooks/useRealm' -import { VoteTipping } from '@solana/spl-governance' -import { DISABLED_VOTER_WEIGHT } from '@tools/constants' -import { - fmtPercentage, - getMintMinAmountAsDecimal, - getMintNaturalAmountFromDecimal, - getMintSupplyFractionAsDecimalPercentage, - getMintSupplyPercentageAsDecimal, - parseMintNaturalAmountFromDecimal, -} from '@tools/sdk/units' -import BigNumber from 'bignumber.js' -import React, { useEffect, useState } from 'react' - -export interface BaseGovernanceFormFields { - minCommunityTokensToCreateProposal: number | string - minInstructionHoldUpTime: number - maxVotingTime: number - voteThreshold: number - voteTipping: VoteTipping -} - -const BaseGovernanceForm = ({ formErrors, form, setForm, setFormErrors }) => { - const { realmInfo, mint: realmMint } = useRealm() - const [minTokensPercentage, setMinTokensPercentage] = useState< - number | undefined - >() - const isMaxMinCommunityNumber = - form.minCommunityTokensToCreateProposal === DISABLED_VOTER_WEIGHT.toString() - const [showMinCommunity, setMinCommunity] = useState(!isMaxMinCommunityNumber) - - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - const validateMinMax = (e) => { - const fieldName = e.target.name - const min = e.target.min || 0 - const max = e.target.max || Number.MAX_SAFE_INTEGER - const value = form[fieldName] - const currentPrecision = new BigNumber(min).decimalPlaces() - - handleSetForm({ - value: - e.target.value === DISABLED_VOTER_WEIGHT.toString() - ? DISABLED_VOTER_WEIGHT.toString() - : parseFloat( - Math.max( - Number(min), - Math.min(Number(max), Number(value)) - ).toFixed(currentPrecision) - ), - propertyName: fieldName, - }) - } - function parseMinTokensToCreateProposal( - value: string | number, - mintDecimals: number - ) { - return typeof value === 'string' - ? parseMintNaturalAmountFromDecimal(value, mintDecimals) - : getMintNaturalAmountFromDecimal(value, mintDecimals) - } - const onMinTokensChange = (minTokensToCreateProposal: number | string) => { - const minTokens = realmMint - ? parseMinTokensToCreateProposal( - minTokensToCreateProposal, - realmMint.decimals - ) - : 0 - setMinTokensPercentage(getMinTokensPercentage(minTokens)) - } - const getMinTokensPercentage = (amount: number) => - realmMint ? getMintSupplyFractionAsDecimalPercentage(realmMint, amount) : 0 - - // Use 1% of mint supply as the default value for minTokensToCreateProposal and the default increment step in the input editor - const mintSupply1Percent = realmMint - ? getMintSupplyPercentageAsDecimal(realmMint, 1) - : 100 - const minTokenAmount = realmMint - ? getMintMinAmountAsDecimal(realmMint) - : 0.0001 - // If the supply is small and 1% is below the minimum mint amount then coerce to the minimum value - const minTokenStep = Math.max(mintSupply1Percent, minTokenAmount) - - const getSupplyPercent = () => { - const hasMinTokensPercentage = - !!minTokensPercentage && !isNaN(minTokensPercentage) - const percent = - hasMinTokensPercentage && minTokensPercentage - ? fmtPercentage(minTokensPercentage) - : '' - return hasMinTokensPercentage &&
{`${percent} of token supply`}
- } - - useEffect(() => { - onMinTokensChange(form.minCommunityTokensToCreateProposal) - }, [form.minCommunityTokensToCreateProposal, realmInfo?.symbol]) - - return ( - <> -
-
Min community tokens to create proposal
-
- { - setMinCommunity(!showMinCommunity) - if (!showMinCommunity === true) { - handleSetForm({ - value: 1, - propertyName: 'minCommunityTokensToCreateProposal', - }) - } else { - handleSetForm({ - value: DISABLED_VOTER_WEIGHT.toString(), - propertyName: 'minCommunityTokensToCreateProposal', - }) - } - }} - />{' '} -
- {showMinCommunity ? 'Enabled' : 'Disabled'} -
-
-
- - {showMinCommunity && ( - - handleSetForm({ - value: evt.target.value, - propertyName: 'minCommunityTokensToCreateProposal', - }) - } - error={formErrors['minCommunityTokensToCreateProposal']} - /> - )} - {showMinCommunity && getSupplyPercent()} - - handleSetForm({ - value: evt.target.value, - propertyName: 'minInstructionHoldUpTime', - }) - } - error={formErrors['minInstructionHoldUpTime']} - /> - - handleSetForm({ - value: evt.target.value, - propertyName: 'maxVotingTime', - }) - } - error={formErrors['maxVotingTime']} - /> - - handleSetForm({ - value: evt.target.value, - propertyName: 'voteThreshold', - }) - } - error={formErrors['voteThreshold']} - /> -
- { - handleSetForm({ - value: $e, - propertyName: 'voteThreshold', - }) - }} - /> -
- - - ) -} - -export default BaseGovernanceForm diff --git a/components/AssetsList/CloseBuffers.tsx b/components/AssetsList/CloseBuffers.tsx index 74f46a6e11..c28374e3aa 100644 --- a/components/AssetsList/CloseBuffers.tsx +++ b/components/AssetsList/CloseBuffers.tsx @@ -6,9 +6,8 @@ import Input from 'components/inputs/Input' import Button, { LinkButton } from '@components/Button' import Textarea from 'components/inputs/Textarea' import VoteBySwitch from 'pages/dao/[symbol]/proposal/components/VoteBySwitch' -import useWalletStore from 'stores/useWalletStore' import { getValidatedPublickKey } from 'utils/validations' -import { useEffect, useState } from 'react' +import React, { useEffect, useState } from 'react' import { UiInstruction } from 'utils/uiTypes/proposalCreationTypes' import { serializeInstructionToBase64 } from '@solana/spl-governance' import { useRouter } from 'next/router' @@ -24,8 +23,11 @@ import { InstructionDataWithHoldUpTime } from 'actions/createProposal' import { createCloseBuffer } from '@tools/sdk/bpfUpgradeableLoader/createCloseBuffer' import { abbreviateAddress } from '@utils/formatting' import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { Governance, ProgramAccount } from '@solana/spl-governance' import { AssetAccount } from '@utils/uiTypes/assets' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; interface CloseBuffersForm { governedAccount: AssetAccount | undefined @@ -35,21 +37,16 @@ interface CloseBuffersForm { title: string } -const CloseBuffers = ({ program }: { program: ProgramAccount }) => { +const CloseBuffers = ({ program }: { program: AssetAccount }) => { const { handleCreateProposal } = useCreateProposal() - const { - governedTokenAccountsWithoutNfts, - assetAccounts, - } = useGovernanceAssets() + const { governedTokenAccountsWithoutNfts } = useGovernanceAssets() const router = useRouter() - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const governedAccount = assetAccounts.find( - (x) => x.governance.pubkey.toBase58() === program.pubkey.toBase58() - ) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() const { fmtUrlWithCluster } = useQueryContext() const { symbol } = router.query - const { realmInfo, canChooseWhoVote, realm } = useRealm() + const realm = useRealmQuery().data?.result + const { realmInfo} = useRealm() const [isBuffersLoading, setIsBuffersLoading] = useState(false) const programId: PublicKey | undefined = realmInfo?.programId const [buffers, setBuffers] = useState< @@ -65,7 +62,7 @@ const CloseBuffers = ({ program }: { program: ProgramAccount }) => { ) const solAccounts = governedTokenAccountsWithoutNfts.filter((x) => x.isSol) const [form, setForm] = useState({ - governedAccount: governedAccount, + governedAccount: program, programId: programId?.toString(), solReceiverAddress: solAccounts.length ? solAccounts @@ -81,15 +78,13 @@ const CloseBuffers = ({ program }: { program: ProgramAccount }) => { description: '', title: '', }) - const [voteByCouncil, setVoteByCouncil] = useState(false) + const { voteByCouncil, shouldShowVoteByCouncilToggle, setVoteByCouncil } = useVoteByCouncilToggle(); const [showOptions, setShowOptions] = useState(false) const [isLoading, setIsLoading] = useState(false) const [formErrors, setFormErrors] = useState({}) const proposalTitle = `Close buffers for program ${ - form.governedAccount?.governance?.account.governedAccount - ? abbreviateAddress( - form.governedAccount?.governance?.account.governedAccount - ) + form.governedAccount?.pubkey + ? abbreviateAddress(form.governedAccount?.pubkey) : '' }` @@ -135,7 +130,7 @@ const CloseBuffers = ({ program }: { program: ProgramAccount }) => { const closeIx = await createCloseBuffer( buffers[i].pubkey, new PublicKey(form.solReceiverAddress), - form.governedAccount.governance.pubkey + form.governedAccount.extensions.program!.authority ) serializedInstruction = serializeInstructionToBase64(closeIx) } @@ -189,6 +184,7 @@ const CloseBuffers = ({ program }: { program: ProgramAccount }) => { propertyName: 'programId', value: programId?.toString(), }) + // 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 }, [realmInfo?.programId]) useEffect(() => { @@ -203,7 +199,7 @@ const CloseBuffers = ({ program }: { program: ProgramAccount }) => { { memcmp: { offset: 5, - bytes: form.governedAccount!.governance!.pubkey.toBase58(), + bytes: form.governedAccount!.extensions.program!.authority.toBase58(), }, }, ], @@ -215,10 +211,11 @@ const CloseBuffers = ({ program }: { program: ProgramAccount }) => { } setIsBuffersLoading(false) } - if (form.governedAccount?.governance?.pubkey.toBase58()) { + if (form.governedAccount?.extensions.program!.authority.toBase58()) { getBuffers() } - }, [form.governedAccount?.governance?.pubkey.toBase58()]) + // 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.governedAccount?.extensions.program!.authority.toBase58()]) return ( <>

@@ -303,13 +300,13 @@ const CloseBuffers = ({ program }: { program: ProgramAccount }) => { }) } /> - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - /> + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > )} )} diff --git a/components/AssetsList/NewProgramForm.tsx b/components/AssetsList/NewProgramForm.tsx index ef0470535a..cd018639b1 100644 --- a/components/AssetsList/NewProgramForm.tsx +++ b/components/AssetsList/NewProgramForm.tsx @@ -4,77 +4,57 @@ import Input from 'components/inputs/Input' import PreviousRouteBtn from 'components/PreviousRouteBtn' import Tooltip from 'components/Tooltip' import useQueryContext from 'hooks/useQueryContext' -import useRealm from 'hooks/useRealm' -import { RpcContext, VoteTipping } from '@solana/spl-governance' -import { PublicKey } from '@solana/web3.js' +import { Keypair, PublicKey, Transaction } from '@solana/web3.js' import { tryParseKey } from 'tools/validators/pubkey' import { isFormValid } from 'utils/formValidation' -import { getGovernanceConfig } from 'utils/GovernanceTools' import { notify } from 'utils/notifications' import { useRouter } from 'next/router' -import React, { useEffect, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' +import { useCallback, useEffect, useMemo, useState } from 'react' import * as yup from 'yup' -import BaseGovernanceForm, { - BaseGovernanceFormFields, -} from './BaseGovernanceForm' -import { registerProgramGovernance } from 'actions/registerProgramGovernance' -import { GovernanceType } from '@solana/spl-governance' -import Switch from 'components/Switch' import { debounce } from '@utils/debounce' -import { MIN_COMMUNITY_TOKENS_TO_CREATE_W_0_SUPPLY } from '@tools/constants' -import { getProgramVersionForRealm } from '@models/registry/api' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import { getMintDecimalAmount } from '@tools/sdk/units' -interface NewProgramForm extends BaseGovernanceFormFields { +import { createSetUpgradeAuthority } from '@tools/sdk/bpfUpgradeableLoader/createSetUpgradeAuthority' +import { AssetAccount } from '@utils/uiTypes/assets' +import { sendTransaction } from '@utils/send' +import useGovernanceAssetsStore from 'stores/useGovernanceAssetsStore' +import GovernedAccountSelect from 'pages/dao/[symbol]/proposal/components/GovernedAccountSelect' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { usePrevious } from '@hooks/usePrevious' +interface NewProgramForm { programId: string - transferAuthority: boolean + authority: null | AssetAccount } const defaultFormValues = { programId: '', - // TODO: This is temp. fix to avoid wrong default for Multisig DAOs - // This should be dynamic and set to 1% of the community mint supply or - // MIN_COMMUNITY_TOKENS_TO_CREATE_W_0_SUPPLY when supply is 0 - minCommunityTokensToCreateProposal: MIN_COMMUNITY_TOKENS_TO_CREATE_W_0_SUPPLY, - minInstructionHoldUpTime: 0, - maxVotingTime: 3, - voteThreshold: 60, - transferAuthority: true, - voteTipping: VoteTipping.Strict, -} + authority: null, +} as const + const NewProgramForm = () => { const router = useRouter() const { fmtUrlWithCluster } = useQueryContext() - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const { - realmInfo, - realm, - mint: realmMint, - symbol, - ownVoterWeight, - } = useRealm() - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - const connected = useWalletStore((s) => s.connected) - const { fetchRealm } = useWalletStore((s) => s.actions) + + const realm = useRealmQuery().data?.result + const realmMint = useRealmCommunityMintInfoQuery().data?.result + const { symbol } = router.query + const { assetAccounts } = useGovernanceAssetsStore() + + const wallet = useWalletOnePointOh() + const connection = useLegacyConnectionContext() + const connected = !!wallet?.connected const [form, setForm] = useState({ ...defaultFormValues, }) + const prevFormProgramId = usePrevious(form.programId) const [isLoading, setIsLoading] = useState(false) const [formErrors, setFormErrors] = useState({}) - const tokenOwnerRecord = ownVoterWeight.canCreateGovernanceUsingCouncilTokens() - ? ownVoterWeight.councilTokenRecord - : realm && ownVoterWeight.canCreateGovernanceUsingCommunityTokens(realm) - ? ownVoterWeight.communityTokenRecord - : undefined - const handleSetForm = ({ propertyName, value }) => { + const handleSetForm = useCallback(({ propertyName, value }) => { setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } + setForm((prevForm) => ({ ...prevForm, [propertyName]: value })) + }, []) const handleCreate = async () => { try { if (!realm) { @@ -83,46 +63,29 @@ const NewProgramForm = () => { if (!connected) { throw 'Please connect your wallet' } - if (!tokenOwnerRecord) { - throw "You don't have enough governance power to create a new program governance" - } + const { isValid, validationErrors } = await isFormValid(schema, form) setFormErrors(validationErrors) if (isValid && realmMint) { setIsLoading(true) - const rpcContext = new RpcContext( - new PublicKey(realm.owner.toString()), - getProgramVersionForRealm(realmInfo!), - wallet!, - connection.current, - connection.endpoint - ) - - const governanceConfigValues = { - minTokensToCreateProposal: form.minCommunityTokensToCreateProposal, - minInstructionHoldUpTime: form.minInstructionHoldUpTime, - maxVotingTime: form.maxVotingTime, - voteThresholdPercentage: form.voteThreshold, - mintDecimals: realmMint.decimals, - voteTipping: form.voteTipping, - } - const governanceConfig = getGovernanceConfig( - realmInfo?.programVersion!, - governanceConfigValues - ) - await registerProgramGovernance( - rpcContext, - GovernanceType.Program, - realm, + const transferUpgradeAuthIx = await createSetUpgradeAuthority( new PublicKey(form.programId), - governanceConfig, - form.transferAuthority, - tokenOwnerRecord!, - client + wallet!.publicKey!, + form.authority!.governance.nativeTreasuryAddress! ) + const transaction = new Transaction() + transaction.add(transferUpgradeAuthIx) + const signers: Keypair[] = [] + await sendTransaction({ + transaction, + wallet: wallet!, + connection: connection.current, + signers, + sendingMessage: 'Transferring authority', + successMessage: 'Authority has been transferred', + }) setIsLoading(false) - fetchRealm(realmInfo!.programId, realmInfo!.realmId) router.push(fmtUrlWithCluster(`/dao/${symbol}/`)) } } catch (e) { @@ -135,70 +98,74 @@ const NewProgramForm = () => { setIsLoading(false) } } - //if you altering this look at useEffect for form.programId - const schema = yup.object().shape({ - programId: yup - .string() - .test( - 'programIdTest', - 'program id validation error', - async function (val: string) { - if (val) { - try { - const pubKey = tryParseKey(val) - if (!pubKey) { - return this.createError({ - message: `Invalid account address`, - }) - } - const accountData = await connection.current.getParsedAccountInfo( - pubKey - ) - if (!accountData || !accountData.value) { + const schema = useMemo(() => { + return yup.object().shape({ + programId: yup + .string() + .test( + 'programIdTest', + 'program id validation error', + async function (val: string) { + if (val) { + try { + const pubKey = tryParseKey(val) + if (!pubKey) { + return this.createError({ + message: `Invalid account address`, + }) + } + + const accountData = await connection.current.getParsedAccountInfo( + pubKey + ) + if (!accountData || !accountData.value) { + return this.createError({ + message: `Account not found`, + }) + } + return true + } catch (e) { return this.createError({ - message: `Account not found`, + message: `Invalid account address`, }) } - return true - } catch (e) { + } else { return this.createError({ - message: `Invalid account address`, + message: `Program id is required`, }) } - } else { - return this.createError({ - message: `Program id is required`, - }) } - } - ), - }) + ), + }) + }, [connection]) + useEffect(() => { - if (form.programId) { + if (form.programId && form.programId !== prevFormProgramId) { //now validation contains only programId if more fields come it would be good to reconsider this method. debounce.debounceFcn(async () => { const { validationErrors } = await isFormValid(schema, form) setFormErrors(validationErrors) }) } - }, [form.programId]) + }, [form, form.programId, schema, prevFormProgramId]) + useEffect(() => { - setForm({ - ...form, - minCommunityTokensToCreateProposal: realmMint?.supply.isZero() - ? MIN_COMMUNITY_TOKENS_TO_CREATE_W_0_SUPPLY - : realmMint - ? getMintDecimalAmount(realmMint!, realmMint!.supply).toNumber() * 0.01 - : 0, - }) - }, [JSON.stringify(realmMint)]) + const wallet = assetAccounts.find( + (x) => + x.governance.nativeTreasuryAddress?.toBase58() === router.query?.wallet + ) + if (wallet && router.query?.wallet) { + handleSetForm({ value: wallet, propertyName: 'authority' }) + } + }, [router.query, assetAccounts, handleSetForm]) + return (
-

Create new program governance

+

Add program to wallet

{ } error={formErrors['programId']} /> -
-
Transfer upgrade authority to governance
-
- - handleSetForm({ - value: checked, - propertyName: 'transferAuthority', - }) - } - /> -
-
- + x.governance.pubkey)} + onChange={(value) => { + handleSetForm({ value, propertyName: 'authority' }) + }} + value={form.authority} + error={formErrors['authority']} + type="wallet" + >
diff --git a/components/AssetsList/TransferUpgradeAuthority.tsx b/components/AssetsList/TransferUpgradeAuthority.tsx index 4334e1c4b0..169973d87c 100644 --- a/components/AssetsList/TransferUpgradeAuthority.tsx +++ b/components/AssetsList/TransferUpgradeAuthority.tsx @@ -5,9 +5,8 @@ import Input from 'components/inputs/Input' import Button, { LinkButton } from '@components/Button' import Textarea from 'components/inputs/Textarea' import VoteBySwitch from 'pages/dao/[symbol]/proposal/components/VoteBySwitch' -import useWalletStore from 'stores/useWalletStore' import { getValidatedPublickKey } from 'utils/validations' -import { useEffect, useState } from 'react' +import React, { useEffect, useState } from 'react' import { UiInstruction } from 'utils/uiTypes/proposalCreationTypes' import { serializeInstructionToBase64 } from '@solana/spl-governance' import { useRouter } from 'next/router' @@ -19,9 +18,10 @@ import useCreateProposal from '@hooks/useCreateProposal' import { InstructionDataWithHoldUpTime } from 'actions/createProposal' import { createSetUpgradeAuthority } from '@tools/sdk/bpfUpgradeableLoader/createSetUpgradeAuthority' import { abbreviateAddress } from '@utils/formatting' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { Governance, ProgramAccount } from '@solana/spl-governance' import { AssetAccount } from '@utils/uiTypes/assets' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; interface CloseBuffersForm { governedAccount: AssetAccount | undefined @@ -31,25 +31,18 @@ interface CloseBuffersForm { title: string } -const TransferUpgradeAuthority = ({ - program, -}: { - program: ProgramAccount -}) => { +const TransferUpgradeAuthority = ({ program }: { program: AssetAccount }) => { const { handleCreateProposal } = useCreateProposal() - const { assetAccounts } = useGovernanceAssets() const router = useRouter() - const wallet = useWalletStore((s) => s.current) - const governedAccount = assetAccounts.find( - (x) => x.governance.pubkey.toBase58() === program.pubkey.toBase58() - ) + const wallet = useWalletOnePointOh() const { fmtUrlWithCluster } = useQueryContext() const { symbol } = router.query - const { realmInfo, canChooseWhoVote, realm } = useRealm() + const realm = useRealmQuery().data?.result + const { realmInfo} = useRealm() const programId: PublicKey | undefined = realmInfo?.programId const [form, setForm] = useState({ - governedAccount: governedAccount, + governedAccount: program, programId: programId?.toString(), newUpgradeAuthority: wallet?.publicKey?.toBase58() ? wallet?.publicKey?.toBase58() @@ -57,15 +50,13 @@ const TransferUpgradeAuthority = ({ description: '', title: '', }) - const [voteByCouncil, setVoteByCouncil] = useState(false) + const { voteByCouncil, shouldShowVoteByCouncilToggle, setVoteByCouncil } = useVoteByCouncilToggle(); const [showOptions, setShowOptions] = useState(false) const [isLoading, setIsLoading] = useState(false) const [formErrors, setFormErrors] = useState({}) const proposalTitle = `Transfer upgrade authority for program ${ - form.governedAccount?.governance?.account.governedAccount - ? abbreviateAddress( - form.governedAccount?.governance?.account.governedAccount - ) + form.governedAccount?.pubkey + ? abbreviateAddress(form.governedAccount?.pubkey) : '' }` @@ -108,8 +99,8 @@ const TransferUpgradeAuthority = ({ wallet?.publicKey ) { const transferUpgradeAuthIx = await createSetUpgradeAuthority( - form.governedAccount.governance.account.governedAccount, - form.governedAccount.governance.pubkey, + form.governedAccount.pubkey, + form.governedAccount.extensions.program!.authority, new PublicKey(form.newUpgradeAuthority) ) serializedInstruction = serializeInstructionToBase64( @@ -165,6 +156,7 @@ const TransferUpgradeAuthority = ({ propertyName: 'programId', value: programId?.toString(), }) + // 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 }, [realmInfo?.programId]) return ( @@ -228,13 +220,13 @@ const TransferUpgradeAuthority = ({ }) } /> - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - /> + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > )} )} diff --git a/components/AssetsList/UpgradeProgram.tsx b/components/AssetsList/UpgradeProgram.tsx index 3792d0d84d..ccdf9c99e7 100644 --- a/components/AssetsList/UpgradeProgram.tsx +++ b/components/AssetsList/UpgradeProgram.tsx @@ -5,9 +5,8 @@ import Input from 'components/inputs/Input' import Button, { LinkButton } from '@components/Button' import Textarea from 'components/inputs/Textarea' import VoteBySwitch from 'pages/dao/[symbol]/proposal/components/VoteBySwitch' -import useWalletStore from 'stores/useWalletStore' import { validateBuffer } from 'utils/validations' -import { useEffect, useState } from 'react' +import React, { useEffect, useState } from 'react' import { ProgramUpgradeForm, UiInstruction, @@ -16,7 +15,6 @@ import { getInstructionDataFromBase64, serializeInstructionToBase64, } from '@solana/spl-governance' -import { Governance, ProgramAccount } from '@solana/spl-governance' import { useRouter } from 'next/router' import { notify } from 'utils/notifications' import useQueryContext from 'hooks/useQueryContext' @@ -24,48 +22,45 @@ import { validateInstruction } from 'utils/instructionTools' import * as yup from 'yup' import { createUpgradeInstruction } from '@tools/sdk/bpfUpgradeableLoader/createUpgradeInstruction' import { debounce } from '@utils/debounce' -import { isFormValid } from '@utils/formValidation' +import { isFormValid, validatePubkey } from '@utils/formValidation' import ProgramUpgradeInfo from 'pages/dao/[symbol]/proposal/components/instructions/bpfUpgradeableLoader/ProgramUpgradeInfo' import { getProgramName } from '@components/instructions/programs/names' import useCreateProposal from '@hooks/useCreateProposal' -import useGovernanceAssets from '@hooks/useGovernanceAssets' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { AssetAccount } from '@utils/uiTypes/assets' +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; interface UpgradeProgramCompactForm extends ProgramUpgradeForm { description: string title: string } -const UpgradeProgram = ({ - program, -}: { - program: ProgramAccount -}) => { +const UpgradeProgram = ({ program }: { program: AssetAccount }) => { const router = useRouter() - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const { assetAccounts } = useGovernanceAssets() - const governedAccount = assetAccounts.find( - (x) => x.governance.pubkey.toBase58() === program.pubkey.toBase58() - ) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() const { handleCreateProposal } = useCreateProposal() const { fmtUrlWithCluster } = useQueryContext() - const { fetchRealmGovernance } = useWalletStore((s) => s.actions) const { symbol } = router.query - const { realmInfo, canChooseWhoVote, realm } = useRealm() + const realm = useRealmQuery().data?.result + const { realmInfo} = useRealm() const programId: PublicKey | undefined = realmInfo?.programId const [form, setForm] = useState({ - governedAccount: governedAccount, + governedAccount: program, programId: programId?.toString(), + bufferSpillAddress: wallet?.publicKey ? wallet.publicKey.toBase58() : '', bufferAddress: '', description: '', title: '', }) - const [voteByCouncil, setVoteByCouncil] = useState(false) + const { voteByCouncil, shouldShowVoteByCouncilToggle, setVoteByCouncil } = useVoteByCouncilToggle(); const [showOptions, setShowOptions] = useState(false) const [isLoading, setIsLoading] = useState(false) const [formErrors, setFormErrors] = useState({}) - const proposalTitle = `Upgrade ${form.governedAccount?.governance?.account.governedAccount.toBase58()}` - const name = program ? getProgramName(program.account.governedAccount) : '' + const proposalTitle = `Upgrade ${form.governedAccount?.pubkey.toBase58()}` + const name = program ? getProgramName(program.pubkey) : '' const handleSetForm = ({ propertyName, value }) => { setFormErrors({}) @@ -80,7 +75,7 @@ const UpgradeProgram = ({ await validateBuffer( connection, val, - form.governedAccount?.governance?.pubkey + form.governedAccount?.extensions.program?.authority ) return true } catch (e) { @@ -94,6 +89,12 @@ const UpgradeProgram = ({ }) } }), + bufferSpillAddress: yup + .string() + .required("Spill account is required") + .test('is-spill-account-valid', 'Invalid Spill Account', function (val: string) { + return val ? validatePubkey(val) : true + }), governedAccount: yup .object() .nullable() @@ -109,10 +110,10 @@ const UpgradeProgram = ({ wallet?.publicKey ) { const upgradeIx = await createUpgradeInstruction( - form.governedAccount.governance.account.governedAccount, + form.governedAccount.pubkey, new PublicKey(form.bufferAddress), - form.governedAccount.governance.pubkey, - wallet!.publicKey + form.governedAccount.extensions.program!.authority, + new PublicKey(form.bufferSpillAddress!) ) serializedInstruction = serializeInstructionToBase64(upgradeIx) } @@ -142,15 +143,10 @@ const UpgradeProgram = ({ prerequisiteInstructions: instruction.prerequisiteInstructions || [], } try { - // Fetch governance to get up to date proposalCount - const selectedGovernance = (await fetchRealmGovernance( - governance?.pubkey - )) as ProgramAccount - proposalAddress = await handleCreateProposal({ title: form.title ? form.title : proposalTitle, description: form.description ? form.description : '', - governance: selectedGovernance, + governance: governance!, instructionsData: [instructionData], voteByCouncil, isDraft: false, @@ -171,6 +167,7 @@ const UpgradeProgram = ({ propertyName: 'programId', value: programId?.toString(), }) + // 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 }, [realmInfo?.programId]) useEffect(() => { @@ -180,6 +177,7 @@ const UpgradeProgram = ({ setFormErrors(validationErrors) }) } + // 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.bufferAddress]) return ( <> @@ -198,8 +196,21 @@ const UpgradeProgram = ({ noMaxWidth={true} error={formErrors['bufferAddress']} /> + + handleSetForm({ + value: evt.target.value, + propertyName: 'bufferSpillAddress', + }) + } + noMaxWidth={true} + error={formErrors['bufferSpillAddress']} + /> - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - /> + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > )} )} diff --git a/components/Button.tsx b/components/Button.tsx index 41496ada1f..93e7f1ad41 100644 --- a/components/Button.tsx +++ b/components/Button.tsx @@ -3,7 +3,8 @@ import Loading, { LoadingDots } from './Loading' import Tooltip from './Tooltip' import Header from './Header' import GradientCheckmarkCircle from './NewRealmWizard/components/GradientCheckmarkCircle' -interface ButtonProps { +import SimpleCheckmarkCircle from './NewRealmWizard/components/SimpleCheckmarkCircle' +export interface ButtonProps { className?: string isLoading?: boolean onClick?: () => void @@ -11,6 +12,7 @@ interface ButtonProps { small?: boolean tooltipMessage?: string style?: any + type?: 'button' | 'submit' } const Button: FunctionComponent = ({ @@ -21,6 +23,7 @@ const Button: FunctionComponent = ({ small, tooltipMessage = '', style, + type = 'button', ...props }) => { return ( @@ -34,6 +37,7 @@ const Button: FunctionComponent = ({ }`} {...props} style={style} + type={type} disabled={disabled} > @@ -53,12 +57,14 @@ export const SecondaryButton: FunctionComponent = ({ isLoading, small = false, tooltipMessage = '', + type = 'button', ...props }) => { return ( ) } + +export const ProposalTypeRadioButton: FunctionComponent = ({ + className = '', + selected = false, + disabled = false, + children, + ...props +}) => { + let classNames = + 'group default-transition px-2 py-1 min-h-[72px] min-w-[186px] rounded-lg border disabled:cursor-not-allowed' + + if (selected) { + classNames += ' bg-fgd-1 border-fgd-1 focus:border-blue' + } else { + classNames += ' focus:bg-fgd-3 focus:border-none' + } + + if (!disabled) { + classNames += + 'hover:bg-bkg-4 hover:border-fgd-1 hover:bg-white/30 hover:text-black border-fgd-3' + } else { + classNames += ' bg-none text-fgd-4 border-bkg-4' + } + + classNames += ` ${className}` + return ( + + ) +} diff --git a/components/ButtonGroup.tsx b/components/ButtonGroup.tsx index 40a9cf301a..d9a2d4e746 100644 --- a/components/ButtonGroup.tsx +++ b/components/ButtonGroup.tsx @@ -33,6 +33,7 @@ const ButtonGroup: FunctionComponent = ({ ) : null} {values.map((v, i) => (
- ) : ( -
- -
- ) - }, [provider]) + const walletAddressFormatted = publicKey ? abbreviateAddress(publicKey) : '' return (
{ {...props} >
- {displayAddressImage} + { + // TODO bring back debug wallet + } + {debugAdapter ? ( +
+ DEBUG +
+ ) : null} + {connected && publicKey ? ( +
+ +
+ ) : ( +
+ +
+ )}
- {connected && current?.publicKey ? ( + {connected && publicKey ? ( <> - {displayAddressComponent} + {connected && publicKey ? ( + + ) : null} {walletAddressFormatted} ) : ( <> - Connect + {isLoading ? : 'Connect'} - {provider?.name} + {wallet?.adapter.name} )} @@ -185,25 +158,26 @@ const ConnectWalletButton = (props) => { <> - {WALLET_PROVIDERS.map(({ name, url, adapter: { icon } }) => ( - - - - ))} + {wallet?.adapter.name === name ? ( + + ) : null} + + + ))}
Devnet @@ -215,7 +189,7 @@ const ConnectWalletButton = (props) => { />
- {current && current.publicKey && ( + {wallet && publicKey && ( <>
{
- - - +
+ + )} + + ) +} diff --git a/components/Dialect/index.tsx b/components/Dialect/index.tsx new file mode 100644 index 0000000000..b1f0bc4e8f --- /dev/null +++ b/components/Dialect/index.tsx @@ -0,0 +1,17 @@ +'use client' + +import { web3 } from '@coral-xyz/anchor' +import { DialectSolanaSdk } from '@dialectlabs/react-sdk-blockchain-solana' +import { NotificationsButton } from '@dialectlabs/react-ui' + +const REALMS_PUBLIC_KEY = new web3.PublicKey( + 'BUxZD6aECR5B5MopyvvYqJxwSKDBhx2jSSo1U32en6mj' +) + +export default function DialectNotifications() { + return ( + + + + ) +} diff --git a/components/DialectNotificationsModal/index.tsx b/components/DialectNotificationsModal/index.tsx deleted file mode 100644 index 81b5092cf3..0000000000 --- a/components/DialectNotificationsModal/index.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import { - Backend, - Config, - defaultVariables, - DialectContextProvider, - DialectThemeProvider, - DialectWalletAdapter, - IncomingThemeVariables, - Notifications, -} from '@dialectlabs/react-ui' -import * as anchor from '@project-serum/anchor' -import { SignerWalletAdapter } from '@solana/wallet-adapter-base' -import { useTheme } from 'next-themes' -import { useEffect, useMemo, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' - -const REALMS_PUBLIC_KEY = new anchor.web3.PublicKey( - 'BUxZD6aECR5B5MopyvvYqJxwSKDBhx2jSSo1U32en6mj' -) - -const themeVariables: IncomingThemeVariables = { - dark: { - bellButton: - '!bg-bkg-2 !shadow-none text-fgd-1 h-10 rounded-full w-10 hover:bg-bkg-3', - button: `${defaultVariables.dark.button} border-none bg-primary-light border-primary-light font-bold rounded-full hover:bg-fgd-1 hover:opacity-100`, - buttonLoading: `${defaultVariables.dark.buttonLoading} rounded-full min-h-[40px]`, - colors: { - bg: 'bg-bkg-1', - toggleBackgroundActive: 'bg-primary-light', - }, - outlinedInput: `${defaultVariables.light.outlinedInput} focus-within:bg-bkg-3 focus-within:border-primary-light`, - addormentButton: `${defaultVariables.dark.addormentButton} text-bkg-2 bg-primary-light hover:bg-fgd-1`, - disabledButton: `${defaultVariables.dark.disabledButton} border-primary-light font-bold rounded-full border-fgd-3 text-fgd-3 cursor-not-allowed`, - modal: `${defaultVariables.dark.modal} bg-bkg-1 sm:border sm:border-fgd-4 shadow-md sm:rounded-md`, - modalWrapper: `${defaultVariables.dark.modalWrapper} sm:top-14 rounded-md`, - secondaryDangerButton: `${defaultVariables.dark.secondaryDangerButton} rounded-full`, - }, - light: { - bellButton: - '!bg-bkg-2 !shadow-none text-fgd-1 h-10 rounded-full w-10 hover:bg-bkg-3', - button: `${defaultVariables.light.button} border-none bg-primary-light border-primary-light font-bold rounded-full hover:bg-fgd-1 hover:opacity-100`, - buttonLoading: `${defaultVariables.light.buttonLoading} rounded-full min-h-[40px]`, - colors: { - bg: 'bg-bkg-1', - toggleBackgroundActive: 'bg-primary-light', - }, - textStyles: { - input: `${defaultVariables.light.textStyles.input} text-fgd-1 placeholder:text-fgd-3`, - }, - outlinedInput: `${defaultVariables.light.outlinedInput} focus-within:bg-bkg-3 focus-within:border-primary-light`, - addormentButton: `${defaultVariables.dark.addormentButton} text-bkg-2 bg-primary-light`, - modal: `${defaultVariables.light.modal} sm:border sm:rounded-md sm:border-fgd-4 sm:shadow-md`, - modalWrapper: `${defaultVariables.dark.modalWrapper} sm:top-14`, - secondaryDangerButton: `${defaultVariables.light.secondaryDangerButton} rounded-full`, - }, -} - -const walletToDialectWallet = ( - wallet?: SignerWalletAdapter -): DialectWalletAdapter => ({ - publicKey: wallet?.publicKey || undefined, - connected: - (wallet?.connected && !wallet?.connecting && Boolean(wallet?.publicKey)) || - false, - // @ts-ignore - signMessage: wallet?.signMessage - ? // @ts-ignore - (msg) => wallet.signMessage(msg) - : undefined, - signTransaction: wallet?.signTransaction - ? (tx) => wallet.signTransaction(tx) - : undefined, - signAllTransactions: wallet?.signAllTransactions - ? (txs) => wallet.signAllTransactions(txs) - : undefined, -}) - -interface DialectNotificationsModalProps { - onBackClick?: () => void - onModalClose: () => void -} - -export default function DialectNotificationsModal( - props: DialectNotificationsModalProps -) { - const { theme } = useTheme() - const wallet = useWalletStore((s) => s.current) - - const [ - dialectWalletAdapter, - setDialectWalletAdapter, - ] = useState(() => walletToDialectWallet(wallet)) - - useEffect(() => { - setDialectWalletAdapter(walletToDialectWallet(wallet)) - }, [wallet]) - - const dialectConfig = useMemo( - (): Config => ({ - backends: [Backend.DialectCloud], - environment: 'production', - dialectCloud: { - tokenStore: 'local-storage', - }, - }), - [] - ) - - return ( - - - - - - ) -} diff --git a/components/DropdownBtn.tsx b/components/DropdownBtn.tsx deleted file mode 100644 index c6ee09c5d5..0000000000 --- a/components/DropdownBtn.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { Menu } from '@headlessui/react' -import { ChevronDownIcon } from '@heroicons/react/solid' -import Loading from '@components/Loading' - -export interface DropdownBtnOptions { - isDefault: boolean | undefined - label: string - callback: () => Promise -} - -const DropdownBtn = ({ - options, - isLoading, -}: { - options: DropdownBtnOptions[] - isLoading?: boolean -}) => { - const defaultFunction = options.find((x) => x.isDefault) - if (!defaultFunction) { - throw 'DropdownBtn must have at least one default option' - } - const filtredOptions = options.filter((x) => !x.isDefault) - return ( -
- {isLoading ? ( - - ) : ( - <> - - -
- - {({ open }) => ( - <> - - - - - {filtredOptions.map((x) => ( - - - - ))} - - - )} - -
- - )} -
- ) -} - -export default DropdownBtn diff --git a/components/DropdownMenu/DropdownMenu.tsx b/components/DropdownMenu/DropdownMenu.tsx new file mode 100644 index 0000000000..0a63f81979 --- /dev/null +++ b/components/DropdownMenu/DropdownMenu.tsx @@ -0,0 +1,40 @@ +import React from 'react' +import * as Dropdown from '@radix-ui/react-dropdown-menu' +import { DotsVerticalIcon } from '@heroicons/react/solid' + +interface Props { + triggerButton: React.ReactNode + children: React.ReactNode[] | React.ReactNode +} + +const DropdownMenu: React.FC = (props) => { + return ( + + + + + + + {(Array.isArray(props.children) ? props.children : [props.children]) + .filter((menuItem) => menuItem) + .map((menuItem: React.ReactNode) => ( + + {menuItem} + + ))} + + + ) +} + +export default DropdownMenu diff --git a/components/DropdownMenu/index.css b/components/DropdownMenu/index.css new file mode 100644 index 0000000000..b8e1d30a67 --- /dev/null +++ b/components/DropdownMenu/index.css @@ -0,0 +1,83 @@ +.DropdownMenuContent { + min-width: 220px; + background-color: rgba(0, 0, 0); + padding: 0.5rem 5px; + z-index: 20; + border-radius: 4px; + box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), + 0px 10px 20px -15px rgba(22, 23, 24, 0.2); + animation-duration: 400ms; + animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); + will-change: transform, opacity; +} +.DropdownMenuContent[data-side='top'] { + animation-name: slideDownAndFade; +} +.DropdownMenuContent[data-side='right'] { + animation-name: slideLeftAndFade; +} +.DropdownMenuContent[data-side='bottom'] { + animation-name: slideUpAndFade; +} +.DropdownMenuContent[data-side='left'] { + animation-name: slideRightAndFade; +} + +.DropdownMenuItem { + font-size: 13px; + line-height: 1; + color: var(--violet11); + border-radius: 3px; + display: flex; + align-items: center; + height: 25px; + padding: 1rem 0.25rem; + position: relative; + padding-left: 25px; + user-select: none; + outline: none; +} + +@keyframes slideUpAndFade { + from { + opacity: 0; + transform: translateY(2px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideRightAndFade { + from { + opacity: 0; + transform: translateX(-2px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes slideDownAndFade { + from { + opacity: 0; + transform: translateY(-2px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideLeftAndFade { + from { + opacity: 0; + transform: translateX(2px); + } + to { + opacity: 1; + transform: translateX(0); + } +} diff --git a/components/EmptyState.tsx b/components/EmptyState.tsx deleted file mode 100644 index a9d0fa96df..0000000000 --- a/components/EmptyState.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { FunctionComponent, ReactNode } from 'react' -import { LinkButton } from './Button' -import Tooltip from './Tooltip' - -interface EmptyStateProps { - buttonText?: string - disableButton?: boolean - icon?: ReactNode - onClickButton?: () => void - desc?: string - title?: string - toolTipContent?: string -} - -const EmptyState: FunctionComponent = ({ - buttonText, - disableButton, - icon, - onClickButton, - desc, - title, - toolTipContent, -}) => { - return ( -
- {icon ?
{icon}
: null} - {title ?

{title}

: null} - {desc ? ( -

- {desc} -

- ) : null} - {buttonText && onClickButton ? ( - - - {buttonText} - - - ) : null} -
- ) -} - -export default EmptyState diff --git a/components/Footer.tsx b/components/Footer.tsx index 2fa52d8b16..26ea1dba66 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -3,11 +3,19 @@ import cx from 'classnames' import { ExternalLinkIcon } from '@heroicons/react/outline' import SocialIcons from '@components/SocialIcons' +import { useEffect, useState } from 'react' const Footer = () => { const { REALM } = process.env + const [usingRealmFromProcessEnv, setUsingRealmFromProcessEnv] = useState( + false + ) + + useEffect(() => { + setUsingRealmFromProcessEnv(!!REALM) + }, [REALM]) - if (REALM) { + if (usingRealmFromProcessEnv) { return null } @@ -23,19 +31,20 @@ const Footer = () => { 'justify-around', 'w-full', 'h-20', - 'pb-24', + 'pb-0', + 'lg:pb-24', 'gap-y-8', - 'md:gap-y-0' + 'md:gap-y-0', + 'z-[1]' )} > -
-
{ className={cx('flex', 'flex-col', 'items-center', 'justify-center')} > -
-
- © 2022 Solana Technology Services LLC +
+
+ © 2024 Realms Today Ltd
- | + | Terms - | + | Privacy Policy
-
- Powered by Solana -
-
-
Read the Docs
+ +
+ Powered by Solana +
) diff --git a/components/ForwarderProgram/ForwarderProgram.tsx b/components/ForwarderProgram/ForwarderProgram.tsx new file mode 100644 index 0000000000..c6f168ccbd --- /dev/null +++ b/components/ForwarderProgram/ForwarderProgram.tsx @@ -0,0 +1,116 @@ +import Checkbox from '@components/inputs/Checkbox' +import Input from '@components/inputs/Input' +import { MANGO_INSTRUCTION_FORWARDER } from '@components/instructions/tools' +import { BN } from '@coral-xyz/anchor' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { tryParsePublicKey } from '@tools/core/pubkey' +import { useCallback, useState } from 'react' + +export function wrapWithForwarder( + ix: TransactionInstruction, + executableBy: PublicKey, + executableUntilUnixTs: number +): TransactionInstruction { + return new TransactionInstruction({ + keys: [ + { + pubkey: executableBy, + isSigner: true, + isWritable: false, + }, + { + pubkey: ix.programId, + isSigner: false, + isWritable: false, + }, + ...ix.keys, + ], + programId: new PublicKey(MANGO_INSTRUCTION_FORWARDER), + data: Buffer.concat([ + new BN(executableUntilUnixTs).toArrayLike(Buffer, 'le', 8), + ix.data, + ]), + }) +} + +export const useForwarderProgramHelpers = () => { + const [form, setForm] = useState({ + useExecutableBy: false, + wallet: '', + timestamp: '', + }) + + const withForwarderWrapper = useCallback( + (ix: TransactionInstruction) => { + if (form.useExecutableBy) { + return wrapWithForwarder( + ix, + new PublicKey(form.wallet), + Number(form.timestamp) + ) + } else { + return ix + } + }, + [form] + ) + return { form, setForm, withForwarderWrapper } +} + +type ForwarderProgramForm = { + useExecutableBy: boolean + wallet: string + timestamp: string +} + +const ForwarderProgram = ({ + form, + setForm, +}: ReturnType) => { + const isInvalidPubkey = form.wallet && !tryParsePublicKey(form.wallet) + return ( +
+
+ { + setForm({ + ...form, + useExecutableBy: e.target.checked, + }) + }} + label={'Use executable by'} + /> +
+ {form.useExecutableBy && ( + <> + + setForm({ + ...form, + wallet: evt.target.value, + }) + } + error={isInvalidPubkey ? 'Invalid publickey' : ''} + /> + + setForm({ + ...form, + timestamp: evt.target.value, + }) + } + /> + + )} +
+ ) +} + +export default ForwarderProgram diff --git a/components/Gateway/GatewayButton.tsx b/components/Gateway/GatewayButton.tsx index ba9ffc8f1c..6031376932 100644 --- a/components/Gateway/GatewayButton.tsx +++ b/components/Gateway/GatewayButton.tsx @@ -1,28 +1,8 @@ -import { IdentityButton, useGateway } from '@civic/solana-gateway-react' -import { FC, useEffect } from 'react' -import useGatewayPluginStore from '../../GatewayPlugin/store/gatewayPluginStore' -import useVotePluginsClientStore from '../../stores/useVotePluginsClientStore' +import { IdentityButton } from '@civic/solana-gateway-react' +import { FC } from 'react' export const GatewayButton: FC = () => { - const { setGatewayToken, state } = useGatewayPluginStore() - const currentClient = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - - const { gatewayToken } = useGateway() - - // As soon as the Civic GatewayProvider finds a gateway token - // add it to the state, so that the voting plugin can use it - useEffect(() => { - if ( - gatewayToken && - state.gatewayToken?.toBase58() !== gatewayToken.publicKey.toBase58() - ) { - setGatewayToken(gatewayToken.publicKey, currentClient) - } - }, [gatewayToken]) - return ( - + ) } diff --git a/components/Gateway/GatewayCard.tsx b/components/Gateway/GatewayCard.tsx index 113aeb861c..e5d37d1997 100644 --- a/components/Gateway/GatewayCard.tsx +++ b/components/Gateway/GatewayCard.tsx @@ -1,152 +1,134 @@ -/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import Button from '@components/Button' -import Loading from '@components/Loading' -import useRealm from '@hooks/useRealm' -import { GatewayClient } from '@solana/governance-program-library' -import { - getTokenOwnerRecordAddress, - SYSTEM_PROGRAM_ID, - withCreateTokenOwnerRecord, -} from '@solana/spl-governance' -import { Transaction, TransactionInstruction } from '@solana/web3.js' -import { sendTransaction } from '@utils/send' -import { useState, useEffect, useMemo } from 'react' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import useWalletStore from 'stores/useWalletStore' -import useGatewayPluginStore from '../../GatewayPlugin/store/gatewayPluginStore' import { GatewayButton } from '@components/Gateway/GatewayButton' -import { getRegistrarPDA, getVoterWeightRecord } from '@utils/plugin/accounts' -import { useRecords } from '@components/Gateway/useRecords' - -// TODO lots of overlap with NftBalanceCard here - we need to separate the logic for creating the Token Owner Record -// from the rest of this logic -const GatewayCard = () => { - const connected = useWalletStore((s) => s.connected) - const wallet = useWalletStore((s) => s.current) - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const gatekeeperNetwork = useGatewayPluginStore( - (s) => s.state.gatekeeperNetwork - ) - const isLoading = useGatewayPluginStore((s) => s.state.isLoadingGatewayToken) - const connection = useWalletStore((s) => s.connection) - const [, setTokenOwneRecordPk] = useState('') - const { realm, mint, councilMint, realmInfo } = useRealm() - const { fetchRealm } = useWalletStore((s) => s.actions) - const records = useRecords() +import Modal from '@components/Modal' +import { InformationCircleIcon } from '@heroicons/react/solid' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useState } from 'react' +import { useGatewayVoterWeightPlugin } from '../../VoterWeightPlugins' +import { + useRealmVoterWeightPlugins, + useRealmVoterWeights, +} from '@hooks/useRealmVoterWeightPlugins' +import { BN } from '@coral-xyz/anchor' +import { GatewayStatus, useGateway } from '@civic/solana-gateway-react' +import useUserGovTokenAccountQuery from '@hooks/useUserGovTokenAccount' +import BigNumber from 'bignumber.js' +import PluginVotingPower from '@components/ProposalVotingPower/PluginVotingPower' - // show the join button if any of the records required by the chain of plugins are not yet created - const showJoinButton = useMemo(() => { - return ( - (!records.tokenOwnerRecord.accountExists && - records.tokenOwnerRecord.accountRequired) || - (!records.voteWeightRecord.accountExists && - records.voteWeightRecord.accountRequired) - ) - }, [records, client]) +interface Props { + role: 'community' | 'council' +} - const handleRegister = async () => { - const instructions: TransactionInstruction[] = [] - const { voterWeightPk } = await getVoterWeightRecord( - realm!.pubkey, - realm!.account.communityMint, - wallet!.publicKey!, - client.client!.program.programId - ) - const { registrar } = await getRegistrarPDA( - realm!.pubkey, - realm!.account.communityMint, - client.client!.program.programId - ) - // If a vote weight record is needed (i.e. the realm has a voter weight plugin) - // but doesn't exist yet, add the instruction to create it to the list - if ( - !records.voteWeightRecord.accountExists && - records.voteWeightRecord.accountRequired - ) { - const createVoterWeightRecordIx = await (client.client as GatewayClient).program.methods - .createVoterWeightRecord(wallet!.publicKey!) - .accounts({ - voterWeightRecord: voterWeightPk, - registrar, - payer: wallet!.publicKey!, - systemProgram: SYSTEM_PROGRAM_ID, - }) - .instruction() +const GatewayCard = ({ role }: Props) => { + const [showGatewayModal, setShowGatewayModal] = useState(false) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const { gatewayStatus } = useGateway() - instructions.push(createVoterWeightRecordIx) - } + const { + gatekeeperNetwork, + isReady, + isEnabled, + } = useGatewayVoterWeightPlugin() + const { communityWeight, councilWeight } = useRealmVoterWeights() - // If a token owner record doesn't exist yet, - // add the instruction to create it to the list - if ( - !records.tokenOwnerRecord.accountExists && - records.tokenOwnerRecord.accountRequired - ) { - await withCreateTokenOwnerRecord( - instructions, - realm!.owner!, - realmInfo?.programVersion!, - realm!.pubkey, - wallet!.publicKey!, - realm!.account.communityMint, - wallet!.publicKey! - ) - } - const transaction = new Transaction() - transaction.add(...instructions) + const { plugins } = useRealmVoterWeightPlugins(role) - await sendTransaction({ - transaction: transaction, - wallet: wallet!, - connection: connection.current, - signers: [], - sendingMessage: `Registering`, - successMessage: `Registered`, - }) - await fetchRealm(realm?.owner, realm?.pubkey) - } + const userAta = useUserGovTokenAccountQuery('community').data?.result + const depositAmount = userAta?.amount + ? new BigNumber(userAta.amount.toString()) + : new BigNumber(0) - useEffect(() => { - const getTokenOwnerRecord = async () => { - const defaultMint = !mint?.supply.isZero() - ? 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() - } - }, [realm?.pubkey.toBase58(), wallet?.connected]) + const hasTokens = + depositAmount.isGreaterThan(0) || + councilWeight?.value?.gt(new BN(0)) || + communityWeight?.value?.gt(new BN(0)) - return ( -
-
- {!connected && ( + if (!connected) { + return ( +
+
Please connect your wallet
+
+
+ ) + } + if (hasTokens) { + return ( +
+
+
+

Verify to vote

+ + setShowGatewayModal(true)} + /> + +
+ {isEnabled && + isReady && + wallet && + wallet.publicKey && + gatekeeperNetwork && + hasTokens && } +
+

+ {gatewayStatus === GatewayStatus.ACTIVE + ? 'You are approved to vote' + : 'Verify your personhood with Civic Pass to vote.'} +

+ { + // check if the last plugin is gateway to show the voting power + plugins?.voterWeight[plugins.voterWeight.length - 1].name === + 'gateway' && + } + {showGatewayModal && ( + setShowGatewayModal(false)} + isOpen={showGatewayModal} + > +
+

Verify to vote

+
+
+ 1 +
+
+

Connect Governance Wallet

+
+ Connect the wallet with your governance token(s). + Consolidate multiple tokens into one wallet before voting. +
+
+
+
+
+ 2 +
+
+

Verify Identity

+
+ Verify your identity using Civic Pass to prevent voting + abuse, such as Sybil attacks. +
+
+
+
+
+ 3 +
+
+

Vote

+
Vote with confidence in a fair system.
+
+
+
+
)} - {isLoading && } - {!isLoading && - connected && - wallet && - wallet.publicKey && - gatekeeperNetwork && }
- {connected && showJoinButton && ( - - )} -
- ) + ) + } + return null } export default GatewayCard diff --git a/components/Gateway/GatewayProvider.tsx b/components/Gateway/GatewayProvider.tsx index 337dd97cba..39b0e3a957 100644 --- a/components/Gateway/GatewayProvider.tsx +++ b/components/Gateway/GatewayProvider.tsx @@ -1,8 +1,9 @@ import { FC } from 'react' import { GatewayProvider as InternalGatewayProvider } from '@civic/solana-gateway-react' -import useWalletStore from '../../stores/useWalletStore' -import useVotePluginsClientStore from '../../stores/useVotePluginsClientStore' -import useGatewayPluginStore from '../../GatewayPlugin/store/gatewayPluginStore' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useGatewayVoterWeightPlugin } from 'VoterWeightPlugins' +import { useConnection } from '@solana/wallet-adapter-react' +import {getNetworkFromEndpoint} from "@utils/connection"; /** * Wrapper for the Civic Gateway Provider react component. This component is responsible for @@ -12,22 +13,21 @@ import useGatewayPluginStore from '../../GatewayPlugin/store/gatewayPluginStore' * @constructor */ export const GatewayProvider: FC = ({ children }) => { - const wallet = useWalletStore((s) => s.current) - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const gatekeeperNetwork = useGatewayPluginStore( - (s) => s.state.gatekeeperNetwork - ) - const connection = useWalletStore((s) => s.connection) + const wallet = useWalletOnePointOh() + const { gatekeeperNetwork, isReady } = useGatewayVoterWeightPlugin() + const { connection } = useConnection() + const network = getNetworkFromEndpoint(connection.rpcEndpoint); + const cluster = network === 'mainnet' + ? 'mainnet-beta' + : network - if (!wallet || !wallet.publicKey || !client || !gatekeeperNetwork) + if (!wallet || !wallet.publicKey || !isReady || !gatekeeperNetwork) return <>{children} return ( { - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - const { tokenRecords, realm } = useRealm() - const ownTokenRecord = wallet?.publicKey - ? tokenRecords[wallet.publicKey!.toBase58()] - : null - - // TODO replace these with useDispatch - const [tokenOwnerRecord, setTokenOwnerRecord] = useState({ - publicKey: null, - accountExists: false, - accountRequired: true, - }) - const [voteWeightRecord, setVoteWeightRecord] = useState({ - publicKey: null, - accountExists: false, - accountRequired: true, - }) - - const getVoteWeightRecordPK = useCallback( - async (client: Client) => { - if (realm && wallet && wallet.publicKey) { - const { voterWeightPk } = await getPluginVoterWeightRecord( - realm.pubkey, - realm.account.communityMint, - wallet.publicKey, - client.program.programId - ) - return voterWeightPk - } else { - return undefined - } - }, - [realm, wallet, client] - ) - - const accountExists = useCallback( - async (publicKey: PublicKey) => { - const account = await connection.current.getAccountInfo(publicKey) - return !!account - }, - [connection] - ) - - useEffect(() => { - ;(async () => { - // tokenOwnerRecord - if (ownTokenRecord) { - setTokenOwnerRecord({ - publicKey: ownTokenRecord.pubkey, - accountExists: true, - accountRequired: true, - }) - } else { - console.log('useRecords: token owner record not found') - } - - // voteWeightRecord - if (client && client.client) { - const voteWeightRecordPK = await getVoteWeightRecordPK(client.client) - if (voteWeightRecordPK) { - setVoteWeightRecord({ - publicKey: voteWeightRecordPK, - accountExists: await accountExists(voteWeightRecordPK), - accountRequired: true, - }) - } else { - console.log('useRecords: voter weight record not found') - } - } else { - console.log('useRecords: voter weight record not needed') - setVoteWeightRecord({ - publicKey: null, - accountExists: false, - accountRequired: true, - }) - } - })() - }, [client, wallet]) - - return { - tokenOwnerRecord, - voteWeightRecord, - } -} diff --git a/components/GovernancePower/GovernancePowerCard.tsx b/components/GovernancePower/GovernancePowerCard.tsx new file mode 100644 index 0000000000..ae2686428f --- /dev/null +++ b/components/GovernancePower/GovernancePowerCard.tsx @@ -0,0 +1,90 @@ +import { ChevronRightIcon } from '@heroicons/react/solid' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import useQueryContext from '@hooks/useQueryContext' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { GoverningTokenType } from '@solana/spl-governance' +import Link from 'next/link' +import { useRouter } from 'next/router' +import GovernancePowerForRole from './GovernancePowerForRole' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' + +const GovernancePowerTitle = () => { + const { symbol } = useRouter().query + const { fmtUrlWithCluster } = useQueryContext() + const connected = useWalletOnePointOh()?.connected ?? undefined + + return ( +
+

My governance power

+ + + View + + + +
+ ) +} +/* +// TODO: refactor deposit components to their own generic DepositForRole component +const VanillaDeposit = ({ role }: { role: 'community' | 'council' }) => { + const { connection } = useConnection() + + const realmPk = useSelectedRealmPubkey() + + const { result: kind } = useAsync(async () => { + if (realmPk === undefined) return undefined + return determineVotingPowerType(connection, realmPk, role) + }, [connection, realmPk, role]) + + return kind === 'vanilla' ? : <> +} */ + +const GovernancePowerCard = () => { + const connected = useWalletOnePointOh()?.connected ?? false + + const { isReady: communityIsReady } = useRealmVoterWeightPlugins('community') + const { isReady: councilIsReady } = useRealmVoterWeightPlugins('council') + const isReady = communityIsReady && councilIsReady + + const realmConfig = useRealmConfigQuery().data?.result + + return ( +
+ + {!connected ? ( +
+ Connect your wallet to see governance power +
+ ) : !isReady ? ( + <> +
+
+ + ) : ( +
+ {realmConfig?.account.communityTokenConfig.tokenType === + GoverningTokenType.Dormant ? null : ( + + )} + {realmConfig?.account.councilTokenConfig.tokenType === + GoverningTokenType.Dormant ? null : ( + + )} +
+ )} +
+ ) +} + +export default GovernancePowerCard diff --git a/components/GovernancePower/GovernancePowerForRole.tsx b/components/GovernancePower/GovernancePowerForRole.tsx new file mode 100644 index 0000000000..ebfdbafa8c --- /dev/null +++ b/components/GovernancePower/GovernancePowerForRole.tsx @@ -0,0 +1,55 @@ +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useAsync } from 'react-async-hook' +import { determineVotingPowerType } from '@hooks/queries/governancePower' +import { useConnection } from '@solana/wallet-adapter-react' +import useSelectedRealmPubkey from '@hooks/selectedRealm/useSelectedRealmPubkey' +import VanillaVotingPower from './Power/Vanilla/VanillaVotingPower' +import { Deposit } from './Power/Vanilla/Deposit' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import { PluginName } from '@constants/plugins' +import { VotingPowerCards } from '@components/GovernancePower/Power/VotingPowerCards' + +type VotingPowerDisplayType = PluginName | 'composite' + +export default function GovernancePowerForRole({ + role, + ...props +}: { + role: 'community' | 'council' + hideIfZero?: boolean + className?: string +}) { + const { connection } = useConnection() + const realmPk = useSelectedRealmPubkey() + const { plugins } = useRealmVoterWeightPlugins(role) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + + const { result: kind } = useAsync< + VotingPowerDisplayType | undefined + >(async () => { + if (realmPk === undefined) return undefined + // if there are multiple plugins, show the generic plugin voting power + if ((plugins?.voterWeight.length ?? 0) > 1) return 'composite' + return determineVotingPowerType(connection, realmPk, role) + }, [connection, plugins?.voterWeight.length, realmPk, role]) + + if (connected && kind === undefined && !props.hideIfZero) { + return ( +
+ ) + } + return ( + <> + {role === 'community' ? ( + + ) : // council + kind === 'vanilla' ? ( +
+ + +
+ ) : null} + + ) +} diff --git a/components/GovernancePower/Power/VSRCard.tsx b/components/GovernancePower/Power/VSRCard.tsx new file mode 100644 index 0000000000..c9cbbd09b9 --- /dev/null +++ b/components/GovernancePower/Power/VSRCard.tsx @@ -0,0 +1,40 @@ +import {FC} from "react"; +import {useUserCommunityTokenOwnerRecord} from "@hooks/queries/tokenOwnerRecord"; +import LockedCommunityVotingPower from "@components/ProposalVotingPower/LockedCommunityVotingPower"; +import VanillaVotingPower from "@components/GovernancePower/Power/Vanilla/VanillaVotingPower"; +import {ExclamationIcon} from "@heroicons/react/solid"; +import VanillaWithdrawTokensButton from "@components/TokenBalance/VanillaWithdrawTokensButton"; +import {VotingCardProps} from "@components/GovernancePower/Power/VotingPowerCards"; + +export const VSRCard: FC = ({role, ...props}) => { + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + + //VSR if dao transited to use plugin and some users have still deposited tokens they should withdraw before + //depositing to plugin + const didWithdrawFromVanillaSetup = + !ownTokenRecord || + ownTokenRecord.account.governingTokenDepositAmount.isZero() + + return ( + didWithdrawFromVanillaSetup ? ( + + ) : ( + //TODO make a better generic little prompt for when a plugin is used but there are still tokens in vanilla + <> + +
+
+ + + Please withdraw your tokens and deposit again to get + governance power + +
+
+ +
+
+ + ) + ) +} \ No newline at end of file diff --git a/components/GovernancePower/Power/Vanilla/Deposit.tsx b/components/GovernancePower/Power/Vanilla/Deposit.tsx new file mode 100644 index 0000000000..36c1dcec3f --- /dev/null +++ b/components/GovernancePower/Power/Vanilla/Deposit.tsx @@ -0,0 +1,38 @@ +import { BigNumber } from 'bignumber.js' +import { useRealmQuery } from '@hooks/queries/realm' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import { getMintMetadata } from '@components/instructions/programs/splToken' +import useUserGovTokenAccountQuery from '@hooks/useUserGovTokenAccount' +import { DepositTokensButton } from '@components/DepositTokensButton' + +/** Contextual deposit, shows only if relevant */ +export const Deposit = ({ role }: { role: 'community' | 'council' }) => { + const realm = useRealmQuery().data?.result + const mint = + role === 'community' + ? realm?.account.communityMint + : realm?.account.config.councilMint + + const mintInfo = useMintInfoByPubkeyQuery(mint).data?.result + const userAta = useUserGovTokenAccountQuery(role).data?.result + + const depositAmount = userAta?.amount + ? new BigNumber(userAta.amount.toString()) + : new BigNumber(0) + + const tokenName = getMintMetadata(mint)?.name ?? realm?.account.name ?? '' + + return !depositAmount.isGreaterThan(0) ? null : ( + <> +
+ You have{' '} + {mintInfo + ? depositAmount.shiftedBy(-mintInfo.decimals).toFormat() + : depositAmount.toFormat()}{' '} + more {tokenName} tokens in your wallet. Do you want to deposit them to + increase your voting power in this Dao? +
+ + + ) +} diff --git a/components/GovernancePower/Power/Vanilla/VanillaCard.tsx b/components/GovernancePower/Power/Vanilla/VanillaCard.tsx new file mode 100644 index 0000000000..79f896ac80 --- /dev/null +++ b/components/GovernancePower/Power/Vanilla/VanillaCard.tsx @@ -0,0 +1,11 @@ +import VanillaVotingPower from "@components/GovernancePower/Power/Vanilla/VanillaVotingPower"; +import {Deposit} from "@components/GovernancePower/Power/Vanilla/Deposit"; +import { VotingCardProps } from "../VotingPowerCards"; +import {FC} from "react"; + +export const VanillaCard:FC = (props) => ( +
+ + +
+) \ No newline at end of file diff --git a/components/GovernancePower/Power/Vanilla/VanillaVotingPower.tsx b/components/GovernancePower/Power/Vanilla/VanillaVotingPower.tsx new file mode 100644 index 0000000000..6a0b8a8a34 --- /dev/null +++ b/components/GovernancePower/Power/Vanilla/VanillaVotingPower.tsx @@ -0,0 +1,164 @@ +import { BigNumber } from 'bignumber.js' +import { useMemo } from 'react' + +import { useTokenOwnerRecordsDelegatedToUser } from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import { useConnection } from '@solana/wallet-adapter-react' +import { getVanillaGovpower, useVanillaGovpower } from '@hooks/queries/governancePower' +import { + useAddressQuery_CommunityTokenOwner, + useAddressQuery_CouncilTokenOwner, +} from '@hooks/queries/addresses/tokenOwnerRecord' +import { useAsync } from 'react-async-hook' +import BN from 'bn.js' +import { getMintMetadata } from '@components/instructions/programs/splToken' +import VotingPowerPct from '@components/ProposalVotingPower/VotingPowerPct' +import { useSelectedDelegatorStore } from 'stores/useSelectedDelegatorStore' +import { abbreviateAddress } from '@utils/formatting' +import clsx from 'clsx' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { GoverningTokenType } from '@solana/spl-governance' +import {ExclamationIcon, QuestionMarkCircleIcon} from "@heroicons/react/outline"; +import Tooltip from "@components/Tooltip"; + +interface Props { + className?: string + role: 'community' | 'council' + hideIfZero?: boolean + unrecognizedPlugin?: boolean + children?: React.ReactNode +} + +export default function VanillaVotingPower({ + role, + hideIfZero, + children, + unrecognizedPlugin = false, + ...props +}: Props) { + const realm = useRealmQuery().data?.result + const realmConfig = useRealmConfigQuery().data?.result + + const { data: communityTOR } = useAddressQuery_CommunityTokenOwner() + const { data: councilTOR } = useAddressQuery_CouncilTokenOwner() + + const { connection } = useConnection() + + const relevantTOR = role === 'community' ? communityTOR : councilTOR + const relevantMint = + role === 'community' + ? realm?.account.communityMint + : realm?.account.config.councilMint + + const mintInfo = useMintInfoByPubkeyQuery(relevantMint).data?.result + + const personalAmount = useVanillaGovpower(relevantTOR) + + // If the user is using a delegator, we want to show that and not count the other delegators + const selectedDelegator = useSelectedDelegatorStore((s) => + role === 'community' ? s.communityDelegator : s.councilDelegator + ) + + const { data: torsDelegatedToUser } = useTokenOwnerRecordsDelegatedToUser() + + const { result: delegatorsAmount } = useAsync( + async () => + selectedDelegator !== undefined + ? new BN(0) + : torsDelegatedToUser === undefined || relevantMint === undefined + ? undefined + : ( + await Promise.all( + torsDelegatedToUser + .filter((x) => + x.account.governingTokenMint.equals(relevantMint) + ) + .map((x) => getVanillaGovpower(connection, x.pubkey)) + ) + ).reduce((partialSum, a) => partialSum.add(a), new BN(0)), + [connection, relevantMint, selectedDelegator, torsDelegatedToUser] + ) + + const totalAmount = (delegatorsAmount ?? new BN(0)).add( + personalAmount ?? new BN(0) + ) + + const formattedTotal = useMemo( + () => + mintInfo && totalAmount !== undefined + ? new BigNumber(totalAmount.toString()) + .shiftedBy(-mintInfo.decimals) + .toString() + : undefined, + [totalAmount, mintInfo] + ) + + const formattedDelegatorsAmount = useMemo( + () => + mintInfo && delegatorsAmount !== undefined + ? new BigNumber(delegatorsAmount.toString()) + .shiftedBy(-mintInfo.decimals) + .toString() + : undefined, + [delegatorsAmount, mintInfo] + ) + + const tokenName = + getMintMetadata(relevantMint)?.name ?? realm?.account.name ?? '' + + const disabled = + role === 'community' + ? realmConfig?.account.communityTokenConfig.tokenType === + GoverningTokenType.Dormant + : realmConfig?.account.councilTokenConfig.tokenType === + GoverningTokenType.Dormant + + return ( +
+ {unrecognizedPlugin &&
+ + Unrecognized plugin + + + +
} +
+
+ {tokenName} + {role === 'council' ? ' Council' : ''} votes +
+
+
+
+ {formattedTotal ?? 0} +
+
+ {selectedDelegator !== undefined ? ( + // if we're acting as a specific delegator, show that instead of the delegator aggregation + <>(as {abbreviateAddress(selectedDelegator)}) + ) : formattedDelegatorsAmount !== undefined && + formattedDelegatorsAmount !== '0' ? ( + <>({formattedDelegatorsAmount} from delegators) + ) : null} +
+
+ + {mintInfo && ( + + )} +
+
+ {children} +
+ ) +} diff --git a/components/GovernancePower/Power/Vanilla/useDepositCallback.tsx b/components/GovernancePower/Power/Vanilla/useDepositCallback.tsx new file mode 100644 index 0000000000..94a69be61f --- /dev/null +++ b/components/GovernancePower/Power/Vanilla/useDepositCallback.tsx @@ -0,0 +1,110 @@ +import { useCallback } from 'react' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { fetchRealmByPubkey } from '@hooks/queries/realm' +import { useConnection } from '@solana/wallet-adapter-react' +import { Keypair, TransactionInstruction } from '@solana/web3.js' +import { approveTokenTransfer } from '@utils/tokens' +import useSelectedRealmPubkey from '@hooks/selectedRealm/useSelectedRealmPubkey' +import { withDepositGoverningTokens } from '@solana/spl-governance' +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + Token, + TOKEN_PROGRAM_ID, +} from '@solana/spl-token' +import BN from 'bn.js' +import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' +import queryClient from "@hooks/queries/queryClient"; +import {useJoinRealm} from "@hooks/useJoinRealm"; +import { SequenceType, sendTransactionsV3 } from '@utils/sendTransactions' + +export const useDepositCallback = ( + role: 'community' | 'council' | 'undefined' +) => { + const { handleRegister } = useJoinRealm(); + const wallet = useWalletOnePointOh() + const walletPk = wallet?.publicKey ?? undefined + const realmPk = useSelectedRealmPubkey() + const { connection } = useConnection() + return useCallback( + async (amount: BN) => { + if (realmPk === undefined || walletPk === undefined) throw new Error() + const { result: realm } = await fetchRealmByPubkey(connection, realmPk) + if (realm === undefined) throw new Error() + + const mint = + role === 'community' + ? realm.account.communityMint + : realm.account.config.councilMint + if (mint === undefined) throw new Error() + + const userAtaPk = await Token.getAssociatedTokenAddress( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + mint, + walletPk, // owner + true + ) + + const instructions: TransactionInstruction[] = [] + const signers: Keypair[] = [] + + // Checks if the connected wallet is the Squads Multisig extension (or any PDA wallet for future reference). If it is the case, it will not use an ephemeral signer. + const transferAuthority = wallet?.name == "SquadsX" + ? undefined + : approveTokenTransfer(instructions, [], userAtaPk, wallet!.publicKey!, amount); + + if (transferAuthority) { + signers.push(transferAuthority); + } + + const programVersion = await fetchProgramVersion(connection, realm.owner) + + const publicKeyToUse = transferAuthority != undefined && wallet?.publicKey != null ? transferAuthority.publicKey : wallet?.publicKey; + + if (!publicKeyToUse) { + throw new Error() + } + + await withDepositGoverningTokens( + instructions, + realm.owner, + programVersion, + realm.pubkey, + userAtaPk, + mint, + walletPk, + publicKeyToUse, + walletPk, + amount + ) + + // instructions required to create voter weight records for any plugins connected to the realm + // no need to create the TOR, as it is already created by the deposit. + const pluginRegisterInstructions = await handleRegister(false) + + const txes = [[...instructions, ...pluginRegisterInstructions]].map((txBatch) => { + return { + instructionsSet: txBatch.map((x) => { + return { + transactionInstruction: x, + signers: signers, + } + }), + sequenceType: SequenceType.Sequential, + } + }) + + await sendTransactionsV3({ + connection, + wallet: wallet!, + transactionInstructions: txes, + }) + + // Force the UI to recalculate voter weight + queryClient.invalidateQueries({ + queryKey: ['calculateVoterWeight'], + }) + }, + [connection, realmPk, role, wallet, walletPk] + ) +} diff --git a/components/GovernancePower/Power/VotingPowerCards.tsx b/components/GovernancePower/Power/VotingPowerCards.tsx new file mode 100644 index 0000000000..01d34b4c58 --- /dev/null +++ b/components/GovernancePower/Power/VotingPowerCards.tsx @@ -0,0 +1,114 @@ +import { FC, ReactNode } from 'react' +import { PluginName } from '@constants/plugins' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import PythVotingPower from '../../../PythVotePlugin/components/PythVotingPower' +import GatewayCard from '@components/Gateway/GatewayCard' +import NftVotingPower from '@components/ProposalVotingPower/NftVotingPower' +import LockedCommunityNFTRecordVotingPower from '@components/ProposalVotingPower/LockedCommunityNFTRecordVotingPower' +import QuadraticVotingPower from '@components/ProposalVotingPower/QuadraticVotingPower' +import { VSRCard } from '@components/GovernancePower/Power/VSRCard' +import { VanillaCard } from '@components/GovernancePower/Power/Vanilla/VanillaCard' +import DriftVotingPower from 'DriftStakeVoterPlugin/components/DriftVotingPower' +import TokenHaverVotingPower from '@components/ProposalVotingPower/TokenHaverVotingPower' +import ParclVotingPower from 'ParclVotePlugin/components/ParclVotingPower' + +/**** + * Note to plugin implementors. + * + * To add a plugin with a dedicated Vote Power UI, add the plugin name to the `pluginsWithDedicatedVotingPowerUI` list below. + * Then register the dedicated UI in CardForPlugin + * + ***/ + +// A list of all the plugins that have a dedicated voting power UI in realms. +// Plugins will use the vanilla voting power UI if they are not in this list. +// The vanilla voting power UI will: +// - assume the user can "deposit" tokens into the DAO +// - show the votes simply using the plucin's calculatedVoteWeight without explanation +// This is a reasonable placeholder for some plugins, but to make life easier for users, +// plugin developers may want to add their own. +const pluginsWithDedicatedVotingPowerUI = [ + 'NFT', + 'pyth', + 'HeliumVSR', + 'VSR', + 'gateway', + 'QV', + 'drift', + 'token_haver', + "parcl" +] as const + +export type VotingCardProps = { + role: 'community' | 'council' + hideIfZero?: boolean + className?: string +} + +// True if the plugin has a dedicated voting power UI +// The type assertion here does the following: +// - pass any plugin name +// - narrow the type to a plugin that requires a dedicated UI +// - adding to the pluginsWithDedicatedVotingPowerUI list forces the CardForPlugin component to be updated +const hasDedicatedVotingPowerUI = ( + plugin: PluginName +): plugin is typeof pluginsWithDedicatedVotingPowerUI[number] => + pluginsWithDedicatedVotingPowerUI.includes( + plugin as typeof pluginsWithDedicatedVotingPowerUI[number] + ) + +const CardForPlugin: FC< + { plugin: typeof pluginsWithDedicatedVotingPowerUI[number] } & VotingCardProps +> = ({ plugin, role, ...props }) => { + switch (plugin) { + case 'NFT': + return + case 'pyth': + return + case 'HeliumVSR': + return + case 'VSR': + return + case 'gateway': + return + case 'QV': + return + case 'drift': + return + case 'token_haver': + return + case 'parcl': + return + } +} + +/** + * A component that renders the voting power cards for a given set of plugins. + * + * NOTE: This applies only to the community role at present, as practically plugins are only applied to community + * governances. However, there is little reason why this could not be extended to the council role, so to ensure + * future-compatibility we are passing the role here. + */ +export const VotingPowerCards: FC = (props) => { + const { plugins } = useRealmVoterWeightPlugins(props.role) + const cards = (plugins?.voterWeight ?? []) + .map((plugin, pluginIdx): ReactNode | undefined => { + return hasDedicatedVotingPowerUI(plugin.name) ? ( + + ) : undefined + }) + .filter(Boolean) // filter out undefined + + const includesUnrecognizedPlugin = plugins?.voterWeight.some( + (plugin) => plugin.name === 'unknown' + ) + + if (!cards.length) { + // No dedicated plugin cards - add the vanilla card + cards.push( + + ) + } + + return <>{cards} +} diff --git a/components/ImageTextSelection.tsx b/components/ImageTextSelection.tsx new file mode 100644 index 0000000000..3f0c8d8196 --- /dev/null +++ b/components/ImageTextSelection.tsx @@ -0,0 +1,72 @@ +type ImageTextElement = { + id: T + name: string + image?: string +} + +export default function ImageTextSelection({ + selected, + className, + onClick, + imageTextElements, +}: { + selected: T | null + className?: string + onClick: (selected: T | null) => void + imageTextElements: ImageTextElement[] +}) { + return ( +
+
+ {selected === null + ? 'All' + : imageTextElements.find(({ id }) => id === selected)!.name} +
+ +
+ {imageTextElements.map(({ id, name, image }, index) => { + return ( +
+ {image ? ( + // Image + onClick(id)} + /> + ) : ( + // Text + onClick(id)} + > + {name} + + )} + + {selected === id ? ( + // Selected visual +
+ ) : null} +
+ ) + })} +
+
+ ) +} diff --git a/components/InstructionDataUI.tsx b/components/InstructionDataUI.tsx new file mode 100644 index 0000000000..d6776aab74 --- /dev/null +++ b/components/InstructionDataUI.tsx @@ -0,0 +1,71 @@ +import cx from 'classnames' +import { ReactNode } from 'react' +import { PublicKey } from '@solana/web3.js' + +export const InstructionDataUI = ({ children }: { children: ReactNode }) => { + return
{children}
+} + +export const DataUIRow = ({ children }: { children: ReactNode }) => { + return
{children}
+} + +export const DataUILabel = ({ + label, + className, +}: { + label: string + className?: string +}) => {label}: + +export const DataUIText = ({ + text, + className, +}: { + text: string + className?: string +}) => {text} + +export const DataUIAmount = ({ + amount, + symbol = '', + className, +}: { + amount: number + symbol: string + className?: string +}) => ( + <> + + {amount.toLocaleString()} {symbol} + + +) + +export const DataUIAddress = ({ + address, + className, +}: { + address: PublicKey + className?: string +}) => {address.toBase58()} + +export const DataUIDateUTC = ({ + date, + className, +}: { + date: Date + className?: string +}) => {date.toISOString()} UTC + +export const DataUIWarning = ({ + message, + className, +}: { + message: string + className?: string +}) => ( + + {message.toUpperCase()} + +) diff --git a/components/InstructionOptions.tsx b/components/InstructionOptions.tsx deleted file mode 100644 index 1ddbc5f40f..0000000000 --- a/components/InstructionOptions.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { Fragment } from 'react' -import { Listbox, Transition } from '@headlessui/react' -import { SelectorIcon } from '@heroicons/react/solid' - -// Add more options as needed -export enum InstructionOptions { - none = 'none', - castleRefresh = 'Castle: Refresh', - castleReconcileRefresh = 'Castle: Reconcile and Refresh', -} - -export type InstructionOption = `${InstructionOptions}` - -// Mapping between listbox option label and underlying option -const executionOptions: { label: string; value: InstructionOption }[] = [ - { label: 'Select Option', value: InstructionOptions.none }, - { label: 'Castle: Deposit', value: InstructionOptions.castleRefresh }, - { - label: 'Castle: Withdraw', - value: InstructionOptions.castleReconcileRefresh, - }, -] - -export default function InstructionOptionInput(props: { - value: InstructionOption - setValue: (updatedValue: InstructionOption) => void -}) { - const { value, setValue } = props - - const selectedOption = executionOptions.find((o) => o.value === value) - - return ( - -
- - {selectedOption?.label} - - - - - - - {executionOptions.map((option, optionIdx) => ( - - `cursor-default select-none relative py-2 px-4 ${ - active - ? 'text-amber-900 bg-amber-100' - : 'text-primary-light' - }` - } - value={option.value} - > - {({ selected }) => ( - <> - - {option.label} - - - )} - - ))} - - -
-
- ) -} diff --git a/components/Link.tsx b/components/Link.tsx deleted file mode 100644 index ab7216acc4..0000000000 --- a/components/Link.tsx +++ /dev/null @@ -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 }) => ( - - - -) - -interface LinkProps { - className?: string -} - -const Link: FunctionComponent = ({ - children, - className, - ...props -}) => { - return ( - - {children} - - - ) -} - -export default Link diff --git a/components/LinkLeft.tsx b/components/LinkLeft.tsx deleted file mode 100644 index efa1c85165..0000000000 --- a/components/LinkLeft.tsx +++ /dev/null @@ -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 }) => ( - - - -) - -interface LinkLeftProps { - className?: string - href?: string -} - -const LinkLeft: FunctionComponent = ({ - children, - className, - ...props -}) => { - return ( - - {children} - - - ) -} - -export default LinkLeft diff --git a/components/LinksCompactWrapper.tsx b/components/LinksCompactWrapper.tsx deleted file mode 100644 index be6cf630ec..0000000000 --- a/components/LinksCompactWrapper.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { - CloudDownloadIcon, - DocumentIcon, - LinkIcon, -} from '@heroicons/react/outline' - -const LinksCompactWrapper = () => { - return ( - <> -
- - -

Docs that may help you

-
- - -
- - -

Docs & tutorials

-
-
- - -
- - -

About SPL

-
-
- - ) -} - -export default LinksCompactWrapper diff --git a/components/Logo.tsx b/components/Logo.tsx deleted file mode 100644 index 4e25a23ed7..0000000000 --- a/components/Logo.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import Link from 'next/link' - -export default function RealmsLogo() { - return ( - - - - - - - - - - - - - - - - - - - - - ) -} diff --git a/components/Mango/ProgramSelector.tsx b/components/Mango/ProgramSelector.tsx new file mode 100644 index 0000000000..ba8bf37f85 --- /dev/null +++ b/components/Mango/ProgramSelector.tsx @@ -0,0 +1,73 @@ +import { useEffect, useState } from 'react' +import { + BOOST_MAINNET_GROUP, + MANGO_BOOST_PROGRAM_ID, + MANGO_V4_MAINNET_GROUP, +} from '@hooks/useMangoV4' +import { MANGO_V4_ID } from '@blockworks-foundation/mango-v4' +import { PublicKey } from '@metaplex-foundation/js' +import useProgramSelector from './useProgramSelector' +import { InstructionInputType } from 'pages/dao/[symbol]/proposal/components/instructions/inputInstructionType' +import InstructionForm, { + InstructionInput, +} from 'pages/dao/[symbol]/proposal/components/instructions/FormCreator' + +type Program = { name: string; val: PublicKey; group: PublicKey } + +interface ProgramSelectorForm { + program: Program +} + +const ProgramSelector = ({ + programSelectorHook, +}: { + programSelectorHook: ReturnType +}) => { + const programs: Program[] = [ + { + name: 'Mango v4 program', + val: MANGO_V4_ID['mainnet-beta'], + group: MANGO_V4_MAINNET_GROUP, + }, + { + name: 'JLP boost program', + val: MANGO_BOOST_PROGRAM_ID, + group: BOOST_MAINNET_GROUP, + }, + ] + const [form, setForm] = useState({ + program: programs[0], + }) + + useEffect(() => { + if (programSelectorHook.setProgram) { + programSelectorHook.setProgram(form.program) + } + }, [form.program, programSelectorHook]) + + const inputs: InstructionInput[] = [ + { + label: 'Program', + name: 'program', + type: InstructionInputType.SELECT, + initialValue: form.program, + options: programs, + }, + ] + + return ( + <> + {form && ( + null} + formErrors={{}} + > + )} + + ) +} + +export default ProgramSelector diff --git a/components/Mango/useProgramSelector.tsx b/components/Mango/useProgramSelector.tsx new file mode 100644 index 0000000000..03a61bff6b --- /dev/null +++ b/components/Mango/useProgramSelector.tsx @@ -0,0 +1,14 @@ +import { PublicKey } from '@solana/web3.js' +import { useState } from 'react' + +type Program = { name: string; val: PublicKey; group: PublicKey } + +const useProgramSelector = () => { + const [program, setProgram] = useState() + return { + program, + setProgram, + } +} + +export default useProgramSelector diff --git a/components/Members/AddMemberForm.tsx b/components/Members/AddMemberForm.tsx index eaa6d9caa0..672de73e32 100644 --- a/components/Members/AddMemberForm.tsx +++ b/components/Members/AddMemberForm.tsx @@ -3,75 +3,97 @@ import useRealm from 'hooks/useRealm' import Input from 'components/inputs/Input' import Button, { SecondaryButton } from '@components/Button' import VoteBySwitch from 'pages/dao/[symbol]/proposal/components/VoteBySwitch' -import { getMintMinAmountAsDecimal } from '@tools/sdk/units' import { abbreviateAddress, precision } from 'utils/formatting' -import useWalletStore from 'stores/useWalletStore' import { getMintSchema } from 'utils/validations' -import { useEffect, useState } from 'react' +import React, { FC, useMemo, useState } from 'react' import { MintForm, UiInstruction } from 'utils/uiTypes/proposalCreationTypes' import useGovernanceAssets from 'hooks/useGovernanceAssets' import { getInstructionDataFromBase64, - Governance, - ProgramAccount, + serializeInstructionToBase64, + withDepositGoverningTokens, } from '@solana/spl-governance' import { useRouter } from 'next/router' import { notify } from 'utils/notifications' import useQueryContext from 'hooks/useQueryContext' -import { getMintInstruction } from 'utils/instructionTools' +import { getMintInstruction, validateInstruction } from 'utils/instructionTools' import AddMemberIcon from '@components/AddMemberIcon' import { ArrowCircleDownIcon, ArrowCircleUpIcon, } from '@heroicons/react/outline' import useCreateProposal from '@hooks/useCreateProposal' - -interface AddMemberForm extends MintForm { +import { AssetAccount } from '@utils/uiTypes/assets' +import useProgramVersion from '@hooks/useProgramVersion' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import BigNumber from 'bignumber.js' +import { getMintNaturalAmountFromDecimalAsBN } from '@tools/sdk/units' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { DEFAULT_GOVERNANCE_PROGRAM_VERSION } from '@components/instructions/tools' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; + +interface AddMemberForm extends Omit { description: string title: string } -const AddMemberForm = ({ close }) => { - const [voteByCouncil, setVoteByCouncil] = useState(false) +const AddMemberForm: FC<{ close: () => void; mintAccount: AssetAccount }> = ({ + close, + mintAccount, +}) => { + const programVersion = useProgramVersion() const [showOptions, setShowOptions] = useState(false) const [isLoading, setIsLoading] = useState(false) const [formErrors, setFormErrors] = useState({}) const { handleCreateProposal } = useCreateProposal() const router = useRouter() - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const { voteByCouncil, shouldShowVoteByCouncilToggle, setVoteByCouncil } = useVoteByCouncilToggle(); const { fmtUrlWithCluster } = useQueryContext() - const { fetchRealmGovernance } = useWalletStore((s) => s.actions) const { symbol } = router.query - const { assetAccounts } = useGovernanceAssets() - const { realmInfo, canChooseWhoVote, councilMint, realm } = useRealm() + const realm = useRealmQuery().data?.result + const { realmInfo } = useRealm() + const { data: mintInfo } = useMintInfoByPubkeyQuery(mintAccount.pubkey) const programId: PublicKey | undefined = realmInfo?.programId const [form, setForm] = useState({ destinationAccount: '', amount: 1, - mintAccount: undefined, programId: programId?.toString(), description: '', title: '', }) - const schema = getMintSchema({ form, connection }) + const schema = getMintSchema({ form: { ...form, mintAccount }, connection }) - const mintMinAmount = form.mintAccount - ? getMintMinAmountAsDecimal(councilMint!) + const mintMinAmount = mintInfo?.found + ? new BigNumber(1).shiftedBy(mintInfo.result.decimals).toNumber() : 1 const currentPrecision = precision(mintMinAmount) - const proposalTitle = `Add council member ${ - form.destinationAccount - ? abbreviateAddress(new PublicKey(form.destinationAccount)) - : '' - }` + const govpop = + realm !== undefined && + (mintAccount.pubkey.equals(realm.account.communityMint) + ? 'community ' + : realm.account.config.councilMint && + mintAccount.pubkey.equals(realm.account.config.councilMint) + ? 'council ' + : '') + let abbrevAddress: string + try { + abbrevAddress = abbreviateAddress(new PublicKey(form.destinationAccount)) + } catch { + abbrevAddress = '' + } + // note the lack of space is not a typo + const proposalTitle = `Add ${govpop}member ${abbrevAddress}` const setAmount = (event) => { const value = event.target.value @@ -101,26 +123,94 @@ const AddMemberForm = ({ close }) => { }) } - const getInstruction = async (): Promise => { - return getMintInstruction({ - schema, - form, - programId, - connection, - wallet, - governedMintInfoAccount: form.mintAccount, - setFormErrors, - }) + const getInstruction = async (): Promise => { + if ((programVersion ?? DEFAULT_GOVERNANCE_PROGRAM_VERSION) >= 3) { + const isValid = await validateInstruction({ + schema, + form: { ...form, mintAccount }, + setFormErrors, + }) + if (!isValid) { + return false + } + + if ( + programId === undefined || + realm === undefined || + form.destinationAccount === undefined || + !wallet?.publicKey || + mintInfo?.result === undefined + ) { + return false + } + + const goofySillyArrayForBuilderPattern = [] + const tokenMint = mintAccount.pubkey + await withDepositGoverningTokens( + goofySillyArrayForBuilderPattern, + programId, + programVersion ?? DEFAULT_GOVERNANCE_PROGRAM_VERSION, + realm.pubkey, + tokenMint, + tokenMint, + new PublicKey(form.destinationAccount), + mintAccount.extensions.mint!.account.mintAuthority!, + new PublicKey(form.destinationAccount), + getMintNaturalAmountFromDecimalAsBN( + form.amount ?? 1, + mintInfo?.result.decimals + ), + true // make recipient a signer + ) + const ix = goofySillyArrayForBuilderPattern[0] + + // This is not needed if we make the recipient a signer, which we do now + /* + const prerequisiteInstructions: TransactionInstruction[] = [] + // now we have to see if recipient has token owner record already or not. + // this is due to a bug -- unnecessary signer check in program if there's not a token owner record. + const mustCreateTOR = + (await connection.current.getAccountInfo(tokenOwnerRecordPk)) === null + if (mustCreateTOR) { + await withCreateTokenOwnerRecord( + prerequisiteInstructions, + programId, + programVersion, + realm.pubkey, + new PublicKey(form.destinationAccount), + tokenMint, + wallet.publicKey + ) + } */ + + return { + serializedInstruction: serializeInstructionToBase64(ix), + isValid: true, + governance: mintAccount.governance, + //prerequisiteInstructions, + } + } else { + const mintInstruction = await getMintInstruction({ + schema, + form: { ...form, mintAccount }, + programId, + connection, + wallet, + governedMintInfoAccount: mintAccount, + setFormErrors, + }) + return mintInstruction.isValid ? mintInstruction : false + } } //TODO common handle propose const handlePropose = async () => { setIsLoading(true) - const instruction: UiInstruction = await getInstruction() + const instruction = await getInstruction() - if (instruction.isValid && wallet && realmInfo) { - const governance = form.mintAccount?.governance + if (!!instruction && wallet && realmInfo) { + const governance = mintAccount.governance let proposalAddress: PublicKey | null = null @@ -138,14 +228,10 @@ const AddMemberForm = ({ close }) => { } try { - const selectedGovernance = (await fetchRealmGovernance( - governance?.pubkey - )) as ProgramAccount - proposalAddress = await handleCreateProposal({ title: form.title ? form.title : proposalTitle, description: form.description ? form.description : '', - governance: selectedGovernance, + governance, instructionsData: [instructionData], voteByCouncil, isDraft: false, @@ -157,6 +243,7 @@ const AddMemberForm = ({ close }) => { router.push(url) } catch (error) { + console.log('Error creating proposal', error); notify({ type: 'error', message: `${error}`, @@ -169,21 +256,6 @@ const AddMemberForm = ({ close }) => { setIsLoading(false) } - useEffect(() => { - const initForm = async () => { - handleSetForm({ - value: assetAccounts.find( - (x) => - x.governance?.account.governedAccount.toBase58() === - realm?.account.config.councilMint?.toBase58() - ), - propertyName: 'mintAccount', - }) - } - - initForm() - }, []) - return ( <>
@@ -273,13 +345,13 @@ const AddMemberForm = ({ close }) => { onBlur={validateAmountOnBlur} /> - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - /> + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > )} )} @@ -305,4 +377,26 @@ const AddMemberForm = ({ close }) => { ) } +const useCouncilMintAccount = () => { + const realm = useRealmQuery().data?.result + const { assetAccounts } = useGovernanceAssets() + const councilMintAccount = useMemo( + () => + assetAccounts.find( + (x) => + x.pubkey.toBase58() === realm?.account.config.councilMint?.toBase58() + ), + [assetAccounts, realm?.account.config.councilMint] + ) + return councilMintAccount +} +export const AddCouncilMemberForm: FC<{ close: () => void }> = (props) => { + const councilMintAccount = useCouncilMintAccount() + return councilMintAccount ? ( + + ) : ( +
Council not found
+ ) +} + export default AddMemberForm diff --git a/components/Members/MemberOverview.tsx b/components/Members/MemberOverview.tsx index ad4f9a8a4e..2446768d97 100644 --- a/components/Members/MemberOverview.tsx +++ b/components/Members/MemberOverview.tsx @@ -1,4 +1,3 @@ -import { DisplayAddress } from '@cardinal/namespaces-components' import { getExplorerUrl } from '@components/explorer/tools' import { ChatAltIcon, @@ -11,7 +10,11 @@ import useQueryContext from '@hooks/useQueryContext' import useRealm from '@hooks/useRealm' import { getVoteRecordsByVoterMapByProposal } from '@models/api' import { isYesVote } from '@models/voteRecords' -import { GOVERNANCE_CHAT_PROGRAM_ID, VoteRecord } from '@solana/spl-governance' +import { + GOVERNANCE_CHAT_PROGRAM_ID, + GoverningTokenType, + VoteRecord, +} from '@solana/spl-governance' import { ChatMessage, ProgramAccount } from '@solana/spl-governance' import { getGovernanceChatMessagesByVoter } from '@solana/spl-governance' @@ -20,21 +23,235 @@ import { tryParsePublicKey } from '@tools/core/pubkey' import { accountsToPubkeyMap } from '@tools/sdk/accounts' import { fmtMintAmount } from '@tools/sdk/units' import { notify } from '@utils/notifications' -import tokenService from '@utils/services/token' +import tokenPriceService from '@utils/services/tokenPrice' import { Member } from '@utils/uiTypes/members' -import React, { useEffect, useMemo, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' +import { FC, useCallback, useEffect, useMemo, useState } from 'react' import { WalletTokenRecordWithProposal } from './types' import PaginationComponent from '@components/Pagination' -import useMembersStore from 'stores/useMembersStore' +import { LinkButton } from '@components/Button' +import useProgramVersion from '@hooks/useProgramVersion' +import { useRouter } from 'next/router' +import { Instructions } from '@utils/uiTypes/proposalCreationTypes' +import { abbreviateAddress } from '@utils/formatting' +import useGovernanceForGovernedAddress from '@hooks/useGovernanceForGovernedAddress' +import useProposalCreationButtonTooltip from '@hooks/useProposalCreationButtonTooltip' +import Tooltip from '@components/Tooltip' +import RevokeMyMembership from './RevokeMyMembership' +import { useRealmQuery } from '@hooks/queries/realm' +import { DEFAULT_GOVERNANCE_PROGRAM_VERSION } from '@components/instructions/tools' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { useRealmProposalsQuery } from '@hooks/queries/proposal' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { + DasNftObject, + useDigitalAssetsByOwner, +} from '@hooks/queries/digitalAssets' +import { useNftRegistrarCollection } from '@hooks/useNftRegistrarCollection' +import { NFT_PLUGINS_PKS } from '@constants/plugins' +import { ProfileName } from '@components/Profile/ProfileName' + +const RevokeMembership: FC<{ member: PublicKey; mint: PublicKey }> = ({ + member, + mint, +}) => { + const wallet = useWalletOnePointOh() + const realm = useRealmQuery().data?.result + const { symbol } = useRealm() + + const router = useRouter() + const { fmtUrlWithCluster } = useQueryContext() + const governance = useGovernanceForGovernedAddress(mint) + + const govpop = + realm !== undefined && + (mint.equals(realm.account.communityMint) + ? 'community ' + : realm.account.config.councilMint && + mint.equals(realm.account.config.councilMint) + ? 'council ' + : '') + let abbrevAddress: string + try { + abbrevAddress = abbreviateAddress(member) + } catch { + abbrevAddress = '' + } + // note the lack of space is not a typo + const proposalTitle = `Remove ${govpop}member ${abbrevAddress}` + + const tooltipContent = useProposalCreationButtonTooltip( + governance ? [governance] : [] + ) + + return !wallet?.publicKey?.equals(member) ? ( + <> + + + router.push( + fmtUrlWithCluster( + `/dao/${symbol}/proposal/new?i=${ + Instructions.RevokeGoverningTokens + }&t=${proposalTitle}&memberKey=${member.toString()}` + ) + ) + } + > + + Revoke Membership + + + + ) : ( + + ) +} + +const getNftMetadataTooltip = (nft) => { + // console.log(nft) + const collection = nft.grouping.find((x) => x.group_key === 'collection') + ?.group_value + return ( +
+
+ {nft.compression.compressed ? 'Compressed NFT' : 'NFT'} +
+
+

+ Name: {nft.content.metadata.name} +

+

+ Symbol:{' '} + {nft.content.metadata.symbol} +

+

+ Description:{' '} + {nft.content.metadata.description} +

+

+ {nft.compression.compressed ? 'Asset ID: ' : 'Address: '}{' '} + {nft.id} +

+

+ Ownership: {nft.ownership.owner} +

+

+ Collection: {collection} +

+
+
+ ) +} + +const NftDisplayList = ({ + member, + communityAmount, + councilAmount, +}: { + member: Member + communityAmount: string + councilAmount: string +}) => { + const { data: nfts, isLoading } = useDigitalAssetsByOwner( + new PublicKey(member.walletAddress) + ) + + const usedCollectionsPks: string[] = useNftRegistrarCollection() + const verifiedNfts: DasNftObject[] | undefined = useMemo( + () => + nfts?.filter((nft) => { + const collection = nft.grouping.find( + (x) => x.group_key === 'collection' + ) + return ( + collection && + usedCollectionsPks.includes(collection.group_value) && + nft.creators?.filter((x) => x.verified).length > 0 + ) + }), + [nfts, usedCollectionsPks] + ) + + if (isLoading) { + return ( +
+
+ Loading NFTs... +
+
+ ) + } + + if (!verifiedNfts || verifiedNfts.length === 0) { + return ( +
+
+ Something went wrong, fail to fetch.. +
+
+ ) + } + + return ( +
+
+ {(communityAmount || !councilAmount) && ( + + {verifiedNfts?.map((nft) => { + return ( + + + + ) + })} + + )} +
+
+ ) +} + +const MemberOverview = ({ + member, + activeMembers, + vsrDisplay +}: { + member: Member + activeMembers: any[] | undefined, + vsrDisplay?: boolean +}) => { + const programVersion = useProgramVersion() + const realm = useRealmQuery().data?.result + const config = useRealmConfigQuery().data?.result + const connection = useLegacyConnectionContext() + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const { symbol } = useRouter().query + const { data: proposalsArray } = useRealmProposalsQuery() + const proposalsByProposal = useMemo( + () => + proposalsArray === undefined + ? {} + : Object.fromEntries( + proposalsArray.map((x) => [x.pubkey.toString(), x]) + ), + [proposalsArray] + ) + + const currentPluginPk = config?.account.communityTokenConfig.voterWeightAddin + const isNftMode = + (currentPluginPk && + NFT_PLUGINS_PKS.includes(currentPluginPk?.toBase58())) || + false -const MemberOverview = ({ member }: { member: Member }) => { - const { realm } = useRealm() - const connection = useWalletStore((s) => s.connection) - const selectedRealm = useWalletStore((s) => s.selectedRealm) - const { mint, councilMint, proposals, symbol } = useRealm() const { fmtUrlWithCluster } = useQueryContext() - const activeMembers = useMembersStore((s) => s.compact.activeMembers) const [ownVoteRecords, setOwnVoteRecords] = useState< WalletTokenRecordWithProposal[] >([]) @@ -45,39 +262,39 @@ const MemberOverview = ({ member }: { member: Member }) => { walletAddress, councilVotes, communityVotes, - votesCasted, hasCouncilTokenOutsideRealm, hasCommunityTokenOutsideRealm, } = member const walletPublicKey = tryParsePublicKey(walletAddress) const tokenName = realm - ? tokenService.getTokenInfo(realm?.account.communityMint.toBase58())?.symbol + ? tokenPriceService.getTokenInfo(realm?.account.communityMint.toBase58()) + ?.symbol : '' const communityAmount = useMemo( () => communityVotes && communityVotes && !communityVotes.isZero() ? fmtMintAmount(mint, communityVotes) : '', - [walletAddress] + [communityVotes, mint] ) - const councilAmount = useMemo( () => councilVotes && councilVotes && !councilVotes.isZero() ? fmtMintAmount(councilMint, councilVotes) : '', - [walletAddress] + [councilMint, councilVotes] ) - const getVoteRecordsAndChatMsgs = async () => { + const getVoteRecordsAndChatMsgs = useCallback(async () => { + if (!realm) throw new Error() let voteRecords: { [pubKey: string]: ProgramAccount } = {} let chatMessages: { [pubKey: string]: ProgramAccount } = {} try { const results = await Promise.all([ getVoteRecordsByVoterMapByProposal( connection.current, - selectedRealm!.programId!, + realm.owner, new PublicKey(walletAddress) ), getGovernanceChatMessagesByVoter( @@ -95,49 +312,52 @@ const MemberOverview = ({ member }: { member: Member }) => { }) } return { voteRecords, chat: chatMessages } - } + }, [connection, realm, walletAddress]) useEffect(() => { - //we get voteRecords sorted by proposal date and match it with proposal name and chat msgs leaved by token holder. - const handleSetVoteRecords = async () => { - const { voteRecords, chat } = await getVoteRecordsAndChatMsgs() - const voteRecordsArray: WalletTokenRecordWithProposal[] = Object.keys( - voteRecords - ) - .sort((a, b) => { - const prevProposal = proposals[a] - const nextProposal = proposals[b] - return ( - prevProposal?.account.getStateTimestamp() - - nextProposal?.account.getStateTimestamp() - ) - }) - .reverse() - .filter((x) => proposals[x]) - .flatMap((x) => { - const currentProposal = proposals[x] - const currentChatsMsgPk = Object.keys(chat).filter( - (c) => - chat[c]?.account.proposal.toBase58() === - currentProposal?.pubkey.toBase58() - ) - const currentChatMsgs = currentChatsMsgPk.map( - (c) => chat[c].account.body.value - ) - return { - proposalPublicKey: x, - proposalName: currentProposal?.account.name, - chatMessages: currentChatMsgs, - ...voteRecords[x], - } - }) + if (realm) { + //we get voteRecords sorted by proposal date and match it with proposal name and chat msgs leaved by token holder. + const handleSetVoteRecords = async () => { + const { voteRecords, chat } = await getVoteRecordsAndChatMsgs() + const voteRecordsArray: WalletTokenRecordWithProposal[] = Object.keys( + voteRecords + ) + .sort((a, b) => { + const prevProposal = proposalsByProposal[a] + const nextProposal = proposalsByProposal[b] + return ( + prevProposal?.account.getStateTimestamp() - + nextProposal?.account.getStateTimestamp() + ) + }) + .reverse() + .filter((x) => proposalsByProposal[x]) + .flatMap((x) => { + const currentProposal = proposalsByProposal[x] + const currentChatsMsgPk = Object.keys(chat).filter( + (c) => + chat[c]?.account.proposal.toBase58() === + currentProposal?.pubkey.toBase58() + ) + const currentChatMsgs = currentChatsMsgPk.map( + (c) => chat[c].account.body.value + ) + return { + proposalPublicKey: x, + proposalName: currentProposal?.account.name, + chatMessages: currentChatMsgs, + ...voteRecords[x], + } + }) - setOwnVoteRecords(voteRecordsArray) + setOwnVoteRecords(voteRecordsArray) + } + handleSetVoteRecords() } - handleSetVoteRecords() - }, [walletAddress]) + }, [getVoteRecordsAndChatMsgs, proposalsByProposal, realm, walletAddress]) const memberVotePowerRank = useMemo(() => { + if (activeMembers === undefined) return undefined const sortedMembers = activeMembers.sort((a, b) => a.communityVotes.cmp(b.communityVotes) === 1 ? -1 : 1 ) @@ -146,55 +366,81 @@ const MemberOverview = ({ member }: { member: Member }) => { (m) => m.walletAddress === member?.walletAddress ) + 1 ) - }, [JSON.stringify(activeMembers.length), member.walletAddress]) + }, [activeMembers, member?.walletAddress]) + const paginateVotes = useCallback( + (page) => { + return ownVoteRecords.slice(page * perPage, (page + 1) * perPage) + }, + [ownVoteRecords] + ) useEffect(() => { setRecentVotes(paginateVotes(0)) - }, [JSON.stringify(ownVoteRecords)]) + }, [paginateVotes]) const perPage = 8 const totalPages = Math.ceil(ownVoteRecords.length / perPage) const onPageChange = (page) => { setRecentVotes(paginateVotes(page)) } - const paginateVotes = (page) => { - return ownVoteRecords.slice(page * perPage, (page + 1) * perPage) - } - const Address = useMemo(() => { - return ( - - ) - }, [walletPublicKey?.toBase58()]) + const councilMintKey = realm?.account.config.councilMint + const communityMintKey = realm?.account.communityMint + + const isRevokableCouncilMember = + !councilVotes.isZero() && + councilMintKey && + config?.account.councilTokenConfig.tokenType === + GoverningTokenType.Membership + + const isRevokableCommunityMember = + !communityVotes.isZero() && + communityMintKey && + config?.account.communityTokenConfig.tokenType === + GoverningTokenType.Membership + return ( <>
-

{Address}

- e.stopPropagation()} - > - Explorer - - +

+ +

+
+ e.stopPropagation()} + > + Explorer + + + {(programVersion ?? DEFAULT_GOVERNANCE_PROGRAM_VERSION) >= 3 && + realm !== undefined && + (isRevokableCouncilMember || isRevokableCommunityMember) && ( + + )} +
- {(communityAmount || !councilAmount) && ( + {(communityAmount || !councilAmount && !vsrDisplay) && (
-

{tokenName} Votes

+

{tokenName} votes

{communityAmount || 0}{' '} {hasCommunityTokenOutsideRealm && ( @@ -205,9 +451,9 @@ const MemberOverview = ({ member }: { member: Member }) => {

Vote Power Rank: {memberVotePowerRank}

)} - {councilAmount && ( + {councilAmount && !vsrDisplay && (
-

Council Votes

+

Council votes

{councilAmount}{' '} {hasCouncilTokenOutsideRealm && ( @@ -218,7 +464,9 @@ const MemberOverview = ({ member }: { member: Member }) => { )}

Votes Cast

-
{votesCasted}
+
+ {ownVoteRecords.length} +

Yes Votes:{' '} @@ -232,6 +480,14 @@ const MemberOverview = ({ member }: { member: Member }) => {

+ {isNftMode && ( + + )} +

{ownVoteRecords?.length} Recent Votes diff --git a/components/Members/MembersTabs.tsx b/components/Members/MembersTabs.tsx index 328735fb22..f33188870c 100644 --- a/components/Members/MembersTabs.tsx +++ b/components/Members/MembersTabs.tsx @@ -1,29 +1,50 @@ import { FunctionComponent, useMemo } from 'react' -import useWalletStore from 'stores/useWalletStore' -import { LogoutIcon, UserCircleIcon } from '@heroicons/react/outline' -import useRealm from '@hooks/useRealm' -import tokenService from '@utils/services/token' +import { LogoutIcon } from '@heroicons/react/outline' +import tokenPriceService from '@utils/services/tokenPrice' import { fmtMintAmount } from '@tools/sdk/units' import { PublicKey } from '@solana/web3.js' -import { AddressImage, DisplayAddress } from '@cardinal/namespaces-components' import { Member } from '@utils/uiTypes/members' import { MintInfo } from '@solana/spl-token' +import { useRealmQuery } from '@hooks/queries/realm' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { NFT_PLUGINS_PKS } from '@constants/plugins' +import { ProfileName } from '@components/Profile/ProfileName' +import { ProfileImage } from '@components/Profile' interface MembersTabsProps { activeTab: Member onChange: (x) => void tabs: Array + vsrMode?: boolean } const MembersTabs: FunctionComponent = ({ activeTab, onChange, tabs, + vsrMode }) => { - const { mint, councilMint, realm } = useRealm() + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + + const config = useRealmConfigQuery().data?.result + const currentPluginPk = config?.account.communityTokenConfig.voterWeightAddin + const isNftMode = + (currentPluginPk && + NFT_PLUGINS_PKS.includes(currentPluginPk?.toBase58())) || + false + const tokenName = realm - ? tokenService.getTokenInfo(realm?.account.communityMint.toBase58())?.symbol + ? tokenPriceService.getTokenInfo(realm?.account.communityMint.toBase58()) + ?.symbol : '' + + const nftName = isNftMode ? 'NFT' : undefined return (
= ({ mint={mint} councilMint={councilMint} activeTab={activeTab} - tokenName={tokenName || ''} + tokenName={tokenName || nftName || ''} onChange={onChange} + vsrMode={vsrMode} > ) ) @@ -67,19 +89,20 @@ const MemberItems = ({ activeTab, tokenName, onChange, + vsrMode }: { member: Member mint?: MintInfo councilMint?: MintInfo activeTab: Member tokenName: string - onChange: (member: Member) => void + onChange: (member: Member) => void, + vsrMode?: boolean }) => { const { walletAddress, councilVotes, communityVotes, - votesCasted, hasCommunityTokenOutsideRealm, hasCouncilTokenOutsideRealm, } = member @@ -91,30 +114,27 @@ const MemberItems = ({ councilVotes && !councilVotes.isZero() ? fmtMintAmount(councilMint, councilVotes) : null - const { connection } = useWalletStore((s) => s) const renderAddressName = useMemo(() => { return ( - ) + // 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 }, [walletAddress]) const renderAddressImage = useMemo( () => ( - } + ), + // 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 [walletAddress] ) return ( @@ -134,25 +154,27 @@ const MemberItems = ({

{renderAddressName}

-

Votes Cast: {votesCasted}

- - {(communityAmount || !councilAmount) && ( - - {tokenName} Votes {communityAmount || 0} - {hasCommunityTokenOutsideRealm && ( - - )} - - )} - {councilAmount && ( - - Council Votes {councilAmount}{' '} - {hasCouncilTokenOutsideRealm && ( - - )} - - )} - + {vsrMode ? + '' : + + {(communityAmount || !councilAmount) && ( + + {tokenName} votes {communityAmount || 0} + {hasCommunityTokenOutsideRealm && ( + + )} + + )} + {councilAmount && ( + + Council votes {councilAmount}{' '} + {hasCouncilTokenOutsideRealm && ( + + )} + + )} + + }

diff --git a/components/Members/RevokeMyMembership.tsx b/components/Members/RevokeMyMembership.tsx new file mode 100644 index 0000000000..a5618f43b2 --- /dev/null +++ b/components/Members/RevokeMyMembership.tsx @@ -0,0 +1,226 @@ +import Button, { LinkButton, SecondaryButton } from '@components/Button' +import Select from '@components/inputs/Select' +import TokenAmountInput from '@components/inputs/TokenAmountInput' +import Modal from '@components/Modal' +import { ExclamationCircleIcon, XCircleIcon } from '@heroicons/react/outline' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import { useRealmQuery } from '@hooks/queries/realm' +import useProgramVersion from '@hooks/useProgramVersion' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { createRevokeGoverningTokens } from '@solana/spl-governance' +import { useConnection } from '@solana/wallet-adapter-react' +import { PublicKey } from '@solana/web3.js' +import { getMintNaturalAmountFromDecimalAsBN } from '@tools/sdk/units' +import { sendTransactionsV3 } from '@utils/sendTransactions' +import useMembershipTypes from 'pages/dao/[symbol]/proposal/components/instructions/SplGov/useMembershipTypes' +import { FC, useCallback, useEffect, useMemo, useState } from 'react' + +type Form = { + membershipPopulation?: 'council' | 'community' + amount?: string +} +type Errors = { + [K in keyof Form]?: string +} + +function capitalizeFirstLetter(string) { + return string.charAt(0).toUpperCase() + string.slice(1) +} + +const Form: FC<{ closeModal: () => void }> = ({ closeModal }) => { + const wallet = useWalletOnePointOh() + const { connection } = useConnection() + const realm = useRealmQuery().data?.result + + const programVersion = useProgramVersion() + + const [isLoading, setIsLoading] = useState(false) + + const membershipTypes = useMembershipTypes() + + const [form, setForm] = useState
({ + amount: '1', + }) + + const [formErrors, setFormErrors] = useState({}) + + // If there's only one membership type, we can just select that for the user. + // @asktree style note: I create a new variable rather than using `setForm` here because I don't like side effects + const selectedMembershipType = useMemo( + () => + form.membershipPopulation ?? Object.keys(membershipTypes).length === 1 + ? Object.keys(membershipTypes)[0] + : undefined, + [form.membershipPopulation, membershipTypes] + ) + + const selectedMint = useMemo( + () => + selectedMembershipType === undefined + ? undefined + : (membershipTypes[selectedMembershipType] as PublicKey | undefined), + [membershipTypes, selectedMembershipType] + ) + + const { data: mintInfo } = useMintInfoByPubkeyQuery(selectedMint) + + // erase errors on dirtying + useEffect(() => { + setFormErrors({}) + }, [form]) + + const submit = useCallback(async () => { + if (!programVersion) throw new Error() + const errors: Errors = {} + // START jank validation + if (selectedMint === undefined) { + errors['membershipPopulation'] = 'Membership type must be defined' + } + if (form.amount === undefined || form.amount === '') { + errors['amount'] = 'An amount must be supplied' + } + if (Object.keys(errors).length > 0) { + setFormErrors(errors) + return false + } + + if (selectedMint === undefined || form.amount === undefined) + throw new Error() + // END jank validation + // though its worth noting this jank validation is actually a lot easier to debug + // than current schema based approach because the stack traces are clearer + + if ( + realm === undefined || + mintInfo?.result === undefined || + !wallet?.publicKey + ) { + throw new Error('proposal created before necessary data is fetched') + } + + const ix = await createRevokeGoverningTokens( + realm.owner, + programVersion, + realm.pubkey, + wallet.publicKey, + selectedMint, + wallet.publicKey, + getMintNaturalAmountFromDecimalAsBN( + parseFloat(form.amount), + mintInfo.result.decimals + ) + ) + + setIsLoading(true) + + try { + await sendTransactionsV3({ + connection: connection, + wallet: wallet, + transactionInstructions: [ + { instructionsSet: [{ transactionInstruction: ix }] }, + ], + }) + closeModal() + location.reload() //TODO invalidate queries (atm there are none used) + } catch { + setIsLoading(false) + } + + setIsLoading(false) + }, [ + closeModal, + connection, + form.amount, + mintInfo?.result, + programVersion, + realm, + selectedMint, + wallet, + ]) + + return ( +
+
+
+
+
+
+
+

+ WARNING! It is not possible to withdraw Membership + tokens. Using this form will permanently burn your + membership tokens. This cannot be undone without approval from + the DAO! +

+
+
+
+
+
+ + setForm((p) => ({ ...p, amount: x }))} + error={formErrors.amount} + setError={(x) => setFormErrors((p) => ({ ...p, amount: x }))} + /> +
+ closeModal()} + > + Cancel + + + +
+
+ ) +} + +const RevokeMyMembership: FC = () => { + const [open, setOpen] = useState(false) + + return ( + <> + setOpen(true)} + > + + Leave DAO + + {open && ( + setOpen(false)}> + setOpen(false)} /> + + )} + + ) +} + +export default RevokeMyMembership diff --git a/components/Members/types.ts b/components/Members/types.ts index 79bea9dd17..a1abb462bc 100644 --- a/components/Members/types.ts +++ b/components/Members/types.ts @@ -1,18 +1,6 @@ -import { TokenOwnerRecord, VoteRecord } from '@solana/spl-governance' +import { VoteRecord } from '@solana/spl-governance' import { ProgramAccount } from '@solana/spl-governance' -export enum ViewState { - MainView, - MemberOverview, - AddMember, -} - -export interface TokenRecordsWithWalletAddress { - walletAddress: string - council?: ProgramAccount | undefined - community?: ProgramAccount | undefined -} - export interface WalletTokenRecordWithProposal extends ProgramAccount { proposalPublicKey: string diff --git a/components/Members/useMembers.tsx b/components/Members/useMembers.tsx index 318cdd7d83..40bec70b02 100644 --- a/components/Members/useMembers.tsx +++ b/components/Members/useMembers.tsx @@ -1,301 +1,274 @@ -import { TokenRecordsWithWalletAddress } from './types' -import useRealm from '@hooks/useRealm' -import { useEffect, useMemo } from 'react' -import useWalletStore from 'stores/useWalletStore' -import { - getMultipleAccountInfoChunked, - getTokenAccountsByMint, - parseTokenAccountData, - TokenProgramAccount, -} from '@utils/tokens' import { AccountInfo, ASSOCIATED_TOKEN_PROGRAM_ID, Token, TOKEN_PROGRAM_ID, } from '@solana/spl-token' -import { Member, Delegates } from 'utils/uiTypes/members' -import { BN } from '@project-serum/anchor' import { PublicKey } from '@solana/web3.js' -import { usePrevious } from '@hooks/usePrevious' +import { BN_ZERO } from '@solana/spl-governance' +import { + getMultipleAccountInfoChunked, + getTokenAccountsByMint, + TokenProgramAccount, +} from '@utils/tokens' +import { parseTokenAccountData } from '@utils/parseTokenAccountData' import { capitalize } from '@utils/helpers' -import useMembersStore from 'stores/useMembersStore' -export default function useMembers() { - const { tokenRecords, councilTokenOwnerRecords, realm, config } = useRealm() - const connection = useWalletStore((s) => s.connection) - const previousRealmPubKey = usePrevious(realm?.pubkey.toBase58()) as string - const setMembers = useMembersStore((s) => s.setMembers) - const setDelegates = useMembersStore((s) => s.setDelegates) +import { Member } from 'utils/uiTypes/members' +import { useRealmQuery } from '@hooks/queries/realm' +import { useCouncilTokenOwnerRecordsForRealmQuery } from '@hooks/queries/tokenOwnerRecord' +import { useQuery } from '@tanstack/react-query' +import { useConnection } from '@solana/wallet-adapter-react' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { NFT_PLUGINS_PKS } from '@constants/plugins' +import { useNftRegistrarCollection } from '@hooks/useNftRegistrarCollection' +import { fetchDigitalAssetsByOwner } from '@hooks/queries/digitalAssets' +import { getNetworkFromEndpoint } from '@utils/connection' +import { BN } from '@coral-xyz/anchor' - const fetchCouncilMembersWithTokensOutsideRealm = async () => { - if (realm?.account.config.councilMint) { - const tokenAccounts = await getTokenAccountsByMint( - connection.current, - realm.account.config.councilMint.toBase58() - ) - const tokenAccountsInfo: TokenProgramAccount[] = [] - for (const acc of tokenAccounts) { - tokenAccountsInfo.push(acc) - } - //we filter out people who dont have any tokens and we filter out accounts owned by realm e.g. - //accounts that holds deposited tokens inside realm. - return tokenAccountsInfo.filter( - (x) => - !x.account.amount.isZero() && - x.account.owner.toBase58() !== realm?.pubkey.toBase58() - ) - } - return [] - } +/** + * @deprecated + * legacy structure for fetching data, you should probably not be using it. + */ +export const useMembersQuery = () => { + const realm = useRealmQuery().data?.result + const { data: tors } = useCouncilTokenOwnerRecordsForRealmQuery() - //This will need to be rewritten for better performance if some realm hits more then +-5k+ members - const fetchCommunityMembersATAS = async () => { - if (realm?.account.communityMint) { - const ATAS: PublicKey[] = [] - //we filter out people who never voted and has tokens inside realm - const communityTokenRecordsWallets = tokenRecordArray - .filter((x) => - x.community?.account.governingTokenDepositAmount.isZero() - ) - .map((x) => x.walletAddress) - for (const walletAddress of communityTokenRecordsWallets) { - const ata = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID - TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID - realm!.account.communityMint, // mint - new PublicKey(walletAddress), // owner - true - ) - ATAS.push(ata) - } - const ownersAtas = await getMultipleAccountInfoChunked( - connection.current, - ATAS - ) - const ownersAtasParsed: TokenProgramAccount[] = ownersAtas - .filter((x) => x) - .map((r) => { - const publicKey = r!.owner - const data = Buffer.from(r!.data) - const account = parseTokenAccountData(r!.owner, data) - return { publicKey, account } - }) - return ownersAtasParsed - } - return [] - } + const connection = useConnection() + const config = useRealmConfigQuery().data?.result + const currentPluginPk = config?.account.communityTokenConfig.voterWeightAddin + const isNftMode = + currentPluginPk && NFT_PLUGINS_PKS.includes(currentPluginPk?.toBase58()) + const usedCollectionsPks = useNftRegistrarCollection() - const matchMembers = ( - membersArray, - membersToMatch, - type, - pushNonExisting = false - ) => { - const votesPropoName = `${type.toLowerCase()}Votes` - const hasVotesOutsidePropName = `has${capitalize(type)}TokenOutsideRealm` - const members = [...membersArray] - for (const memberToMatch of membersToMatch) { - //We match members that had deposited tokens at least once - const member = members.find( - (x) => x.walletAddress === memberToMatch.account.owner.toBase58() - ) - if (member) { - member[votesPropoName] = member[votesPropoName].add( - memberToMatch.account.amount - ) - if (!memberToMatch.account.amount.isZero()) { - member[hasVotesOutsidePropName] = true - } - } else if (pushNonExisting) { - //we add members who never deposited tokens inside realm - members.push({ - walletAddress: memberToMatch.account.owner.toBase58(), - votesCasted: 0, - [votesPropoName]: memberToMatch.account.amount, - communityVotes: new BN(0), - [hasVotesOutsidePropName]: true, - }) - } - } - return members - } + const network = getNetworkFromEndpoint(connection.connection.rpcEndpoint) + if (network === 'localnet') throw new Error() + const enabled = + tors !== undefined && + realm !== undefined && + (!isNftMode || usedCollectionsPks !== undefined) - const tokenRecordArray: TokenRecordsWithWalletAddress[] = useMemo( - () => - tokenRecords - ? Object.keys(tokenRecords).flatMap((x) => { - return { - walletAddress: x, - community: { ...tokenRecords[x] }, - } - }) - : [], - [JSON.stringify(tokenRecords)] - ) + const query = useQuery({ + enabled, + queryKey: [], + queryFn: async () => { + if (!enabled) throw new Error() - const councilRecordArray: TokenRecordsWithWalletAddress[] = useMemo( - () => - councilTokenOwnerRecords - ? Object.keys(councilTokenOwnerRecords).flatMap((x) => { - return { - walletAddress: x, - council: { ...councilTokenOwnerRecords[x] }, - } - }) - : [], - [JSON.stringify(councilTokenOwnerRecords)] - ) + const councilMint = realm.account.config.councilMint - //for community we exclude people who never vote - const communityAndCouncilTokenRecords = [ - ...tokenRecordArray, - ...councilRecordArray, - ] - //merge community and council vote records to one big array of members - //sort them by totalVotes sum of community and council votes - const membersWithTokensDeposited = useMemo( - () => - //remove duplicated walletAddresses - Array.from( - new Set(communityAndCouncilTokenRecords.map((s) => s.walletAddress)) - ) - //deduplication - .map((walletAddress) => { - return { - ...communityAndCouncilTokenRecords - .filter((x) => x.walletAddress === walletAddress) - .reduce( - (acc, curr) => { - const obj = { - ...acc, - walletAddress: curr.walletAddress, - communityVotes: curr.community - ? curr.community.account.governingTokenDepositAmount - : acc.communityVotes, - councilVotes: curr.council - ? curr.council.account.governingTokenDepositAmount - : acc.councilVotes, - } + const communityMint = realm.account.communityMint - if (curr.community) { - obj['votesCasted'] += curr.community.account.totalVotesCount - obj['delegateWalletCommunity'] = - curr.community.account.governanceDelegate - } - if (curr.council) { - obj['votesCasted'] += curr.council.account.totalVotesCount - obj['delegateWalletCouncil'] = - curr.council.account.governanceDelegate - } - return obj - }, - { - walletAddress: '', - votesCasted: 0, - councilVotes: new BN(0), - communityVotes: new BN(0), - } - ), - } - }) - .sort((a, b) => { - return a.votesCasted - b.votesCasted - }) - .reverse(), + const tokenRecordArray = isNftMode + ? await Promise.all( + tors.map(async (x) => { + const ownedNfts = await fetchDigitalAssetsByOwner( + network, + x.account.governingTokenOwner + ) - [ - JSON.stringify(tokenRecordArray), - JSON.stringify(councilRecordArray), - realm?.pubkey.toBase58(), - ] - ) + const verifiedNfts = ownedNfts.filter((nft) => { + const collection = nft.grouping.find( + (x) => x.group_key === 'collection' + ) + return ( + collection && + usedCollectionsPks.includes(collection.group_value) + ) + }) - // Loop through Members list to get our delegates and their tokens - // Return a object of key: walletId and value: object of arrays for council/community tokenOwnerRecords. - const getDelegateWalletMap = (members: Array): Delegates => { - const delegateMap = {} as Delegates - members.forEach((member: Member) => { - if (member?.delegateWalletCouncil) { - const walletId = member?.delegateWalletCouncil.toBase58() - if (delegateMap[walletId]) { - const oldCouncilRecords = delegateMap[walletId].councilMembers || [] + x.account.governingTokenDepositAmount = new BN( // maybe should use add? + verifiedNfts.length * 10 ** 6 + ) + return { + walletAddress: x.account.governingTokenOwner.toString(), + community: x, + _kind: 'community' as const, + } + }) + ) + : tors + .filter((x) => x.account.governingTokenMint.equals(communityMint)) + .map((x) => ({ + walletAddress: x.account.governingTokenOwner.toString(), + community: x, + _kind: 'community' as const, + })) - delegateMap[walletId] = { - ...delegateMap[walletId], - councilMembers: [...oldCouncilRecords, member], - councilTokenCount: - (delegateMap[walletId]?.councilTokenCount || 0) + - member.councilVotes.toNumber(), - } - } else { - delegateMap[walletId] = { - councilMembers: [member], - councilTokenCount: member.councilVotes - ? member.councilVotes.toNumber() - : 0, + const councilRecordArray = + councilMint !== undefined + ? tors + .filter((x) => x.account.governingTokenMint.equals(councilMint)) + .map((x) => ({ + walletAddress: x.account.governingTokenOwner.toString(), + council: x, + _kind: 'council' as const, + })) + : [] + + const fetchCouncilMembersWithTokensOutsideRealm = async () => { + if (realm?.account.config.councilMint) { + const tokenAccounts = await getTokenAccountsByMint( + connection.connection, + realm.account.config.councilMint.toBase58() + ) + const tokenAccountsInfo: TokenProgramAccount[] = [] + for (const acc of tokenAccounts) { + tokenAccountsInfo.push(acc) } + // we filter out people who dont have any tokens and we filter out accounts owned by realm e.g. + // accounts that holds deposited tokens inside realm. + return tokenAccountsInfo.filter( + (x) => + !x.account.amount.isZero() && + x.account.owner.toBase58() !== realm?.pubkey.toBase58() + ) } + return [] } - if (member?.delegateWalletCommunity) { - const walletId = member?.delegateWalletCommunity.toBase58() - if (delegateMap[walletId]) { - const oldCommunityRecords = - delegateMap[walletId].communityMembers || [] - - delegateMap[walletId] = { - ...delegateMap[walletId], - communityMembers: [...oldCommunityRecords, member], - communityTokenCount: - (delegateMap[walletId]?.communityTokenCount || 0) + - member.communityVotes.toNumber(), + // This will need to be rewritten for better performance if some realm hits more then +-5k+ members + const fetchCommunityMembersATAS = async () => { + if (realm?.account.communityMint) { + const ATAS: PublicKey[] = [] + // we filter out people who never voted and has tokens inside realm + const communityTokenRecordsWallets = tokenRecordArray + .filter((x) => + x.community?.account.governingTokenDepositAmount.isZero() + ) + .map((x) => x.walletAddress) + for (const walletAddress of communityTokenRecordsWallets) { + const ata = await Token.getAssociatedTokenAddress( + ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID + TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID + realm.account.communityMint, // mint + new PublicKey(walletAddress), // owner + true + ) + ATAS.push(ata) } - } else { - delegateMap[walletId] = { - communityMembers: [member], - communityTokenCount: member.communityVotes - ? member.communityVotes.toNumber() - : 0, + const ownersAtas = await getMultipleAccountInfoChunked( + connection.connection, + ATAS + ) + const ownersAtasParsed: TokenProgramAccount[] = ownersAtas + .filter((x) => x) + .map((r) => { + const publicKey = r!.owner + const data = Buffer.from(r!.data) + const account = parseTokenAccountData(r!.owner, data) + return { publicKey, account } + }) + return ownersAtasParsed + } + return [] + } + + const matchMembers = ( + membersArray, + membersToMatch, + type, + pushNonExisting = false + ) => { + const votesPropoName = `${type.toLowerCase()}Votes` + const hasVotesOutsidePropName = `has${capitalize( + type + )}TokenOutsideRealm` + const members = [...membersArray] + for (const memberToMatch of membersToMatch) { + // We match members that had deposited tokens at least once + const member = members.find( + (x) => x.walletAddress === memberToMatch.account.owner.toBase58() + ) + if (member) { + member[votesPropoName] = member[votesPropoName].add( + memberToMatch.account.amount + ) + if (!memberToMatch.account.amount.isZero()) { + member[hasVotesOutsidePropName] = true + } + } else if (pushNonExisting) { + // we add members who never deposited tokens inside realm + members.push({ + walletAddress: memberToMatch.account.owner.toBase58(), + votesCasted: 0, + [votesPropoName]: memberToMatch.account.amount, + communityVotes: BN_ZERO, + [hasVotesOutsidePropName]: true, + }) } } + return members } - }) - return delegateMap - } + // for community we exclude people who never vote + const communityAndCouncilTokenRecords = [ + ...tokenRecordArray, + ...councilRecordArray, + ] + // merge community and council vote records to one big array of members + // sort them by totalVotes sum of community and council votes + const membersWithTokensDeposited = + // remove duplicated walletAddresses + Array.from( + new Set(communityAndCouncilTokenRecords.map((s) => s.walletAddress)) + ) + // deduplication + .map((walletAddress) => { + return { + ...communityAndCouncilTokenRecords + .filter((x) => x.walletAddress === walletAddress) + .reduce( + (acc, curr) => { + const obj = { + ...acc, + walletAddress: curr.walletAddress, + communityVotes: + curr._kind === 'community' + ? curr.community.account.governingTokenDepositAmount + : acc.communityVotes, + councilVotes: + curr._kind === 'council' + ? curr.council.account.governingTokenDepositAmount + : acc.councilVotes, + } + if (curr._kind === 'community') { + obj.delegateWalletCommunity = + curr.community.account.governanceDelegate + } + if (curr._kind === 'council') { + obj.delegateWalletCouncil = + curr.council.account.governanceDelegate + } + return obj + }, + { + walletAddress: '', + councilVotes: BN_ZERO, + communityVotes: BN_ZERO, + } + ), + } + }) + // .sort((a, b) => a.votesCasted - b.votesCasted) + .reverse() + + // Move to store if will be used more across application + + console.log('useMembers is fetching') - //Move to store if will be used more across application - useEffect(() => { - const handleSetMembers = async () => { let members = [...membersWithTokensDeposited] + const [councilMembers, communityMembers] = await Promise.all([ + fetchCouncilMembersWithTokensOutsideRealm(), + fetchCommunityMembersATAS(), + ]) - const councilMembers = await fetchCouncilMembersWithTokensOutsideRealm() - const communityMembers = await fetchCommunityMembersATAS() members = matchMembers(members, councilMembers, 'council', true) members = matchMembers(members, communityMembers, 'community') - setMembers(members) - } - const getDelegates = async () => { - const members = [...membersWithTokensDeposited] - const delegateMap = getDelegateWalletMap(members) - setDelegates(delegateMap) - } - - if ( - realm?.pubkey && - previousRealmPubKey !== realm?.pubkey.toBase58() && - !config?.account.communityTokenConfig.voterWeightAddin - ) { - handleSetMembers() - getDelegates() - } - if ( - !realm?.pubkey || - (realm.pubkey && config?.account.communityTokenConfig.voterWeightAddin) - ) { - getDelegates() - setMembers([]) - } - }, [realm?.pubkey.toBase58()]) + const activeMembers = members.filter( + (x) => !x.councilVotes.isZero() || !x.communityVotes.isZero() + ) + return activeMembers + }, + }) + return query } diff --git a/components/Modal.tsx b/components/Modal.tsx index bd922fcb99..f91d897393 100644 --- a/components/Modal.tsx +++ b/components/Modal.tsx @@ -28,7 +28,7 @@ const Modal = ({
{ + const { result: ownVoterWeight } = useLegacyVoterWeight() + const { assetAccounts } = useGovernanceAssets() + const nota = '$$_NOTA_$$' + const lastOptIndex = multiChoiceForm.options.length - 1 + const governance = multiChoiceForm.governance + const hideNotaButton = multiChoiceForm.options[lastOptIndex] === nota + + const handleMultiForm = ({ propertyName, value }) => { + updateMultiFormErrors({}) + updateMultiChoiceForm({ ...multiChoiceForm, [propertyName]: value }) + } + + const handleNotaButton = () => { + const options = [...multiChoiceForm.options] + options.push(nota) + handleMultiForm({ propertyName: 'options', value: options }) + } + + const updateOption = (odx: number, value: string) => { + const updatedOptions = [...multiChoiceForm.options] + updatedOptions[odx] = value + handleMultiForm({ value: updatedOptions, propertyName: 'options' }) + } + + const removeOption = (odx: number) => { + const updatedOptions = [...multiChoiceForm.options] + handleMultiForm({ + value: updatedOptions.filter((_o, i) => i !== odx), + propertyName: 'options', + }) + } + + const addOption = () => { + const updatedOptions = [...multiChoiceForm.options] + const len = updatedOptions.length - 1 + + if (updatedOptions.length > 9) { + return + } + if (updatedOptions[len] === nota) { + // insert new empty option at the second last position if NOTA exists + updatedOptions.splice(len, 0, '') + } else { + // insert new empty option at the last position if not NOTA doesn't exist + updatedOptions.push('') + } + handleMultiForm({ value: updatedOptions, propertyName: 'options' }) + } + + return ( +
+ + ownVoterWeight?.canCreateProposal(x.governance.account.config) + )} + onChange={(value: AssetAccount) => { + handleMultiForm({ + value: value.governance.pubkey, + propertyName: 'governance', + }) + }} + value={ + governance + ? assetAccounts.find( + (x) => + x.governance.pubkey.equals(governance) && + x.type === AccountType.SOL + ) + : null + } + error={multiFormErrors['governance']} + shouldBeGoverned={null} + governance={null} + /> +

Add Choices

+ {multiChoiceForm.options.map((option, index) => { + // copy index to keep its value for onChange function + const odx = index + + return ( +
+
+

Choice {odx + 1}

+ {odx > 1 ? ( + removeOption(odx)} + > + + Remove + + ) : null} +
+ Add a Label +
+ This is the text voters will see when they vote. +
+ updateOption(odx, event.target.value)} + disabled={option === nota && index > 1 && index === lastOptIndex} + /> +
+ ) + })} +
+
+ addOption()} + disabled={multiChoiceForm.options.length > 9} + className="flex flex-row items-center gap-2 font-bold pt-2" + > + +
Add another voting choice
+
+
+
+ handleNotaButton()} + disabled={hideNotaButton || multiChoiceForm.options.length > 9} + className="flex flex-row items-center gap-2 font-bold pt-2" + > + +
Add 'None of the Above' choice
+
+
+
+
+ ) +} + +export default MultiChoiceForm diff --git a/components/MultiChoiceVotes.tsx b/components/MultiChoiceVotes.tsx new file mode 100644 index 0000000000..8f31672d96 --- /dev/null +++ b/components/MultiChoiceVotes.tsx @@ -0,0 +1,111 @@ +import { Proposal, ProposalState } from '@solana/spl-governance' +import { useRealmQuery } from '@hooks/queries/realm' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' +import { BN } from '@coral-xyz/anchor' +import { StyledLabel, StyledSubLabel } from './inputs/styles' +import { ChevronRight } from '@carbon/icons-react' +import { CheckCircleIcon } from '@heroicons/react/solid' +import { fmtBnMintDecimals } from '@tools/sdk/units' +import BigNumber from 'bignumber.js' + +const MultiChoiceVotes = ({ + proposal, + limit, +}: { + proposal: Proposal + limit: number +}) => { + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + + const proposalMint = + proposal.governingTokenMint.toBase58() === + realm?.account.communityMint.toBase58() + ? mint + : councilMint + + const totalVoteWeight = proposal.options.reduce( + (a, b) => a.add(b.voteWeight), + new BN(0) + ) + + const isComplete = proposal.state === ProposalState.Completed + let highestWeight = new BN(0) + + for (const option of proposal.options) { + highestWeight = option.voteWeight.gt(highestWeight) + ? option.voteWeight + : highestWeight + } + + const nota = '$$_NOTA_$$' + const last = proposal.options.length - 1 + + return ( +
+ {proposal.options.slice(0, limit).map((option, index) => { + const optionVotes = option.voteWeight + const optionWeightPct = totalVoteWeight.isZero() // dont divide by zero + ? new BN(0) + : optionVotes.muln(1000).div(totalVoteWeight) + + return ( +
+
+
+ + {option.label === nota && index === last + ? 'None of the Above' + : option.label} + + {proposalMint === undefined ? null : ( + + {new BigNumber(optionVotes.toString()) + .shiftedBy(-proposalMint.decimals) + .toFormat(0)}{' '} + votes + + )} +
+
+ {isComplete && + !highestWeight.eq(new BN(0)) && + option.voteWeight.eq(highestWeight) && ( + + )} + {fmtBnMintDecimals(optionWeightPct, 1)}% +
+
+
+
+
+
+ ) + })} + {limit < proposal.options.length && ( +
+ +
+ {proposal.options.length - limit} more choice + {proposal.options.length - limit !== 1 && 's'}{' '} +
+ +
+
+ )} +
+ ) +} + +export default MultiChoiceVotes diff --git a/components/NFTGallery.tsx b/components/NFTGallery.tsx new file mode 100644 index 0000000000..0974b2adcf --- /dev/null +++ b/components/NFTGallery.tsx @@ -0,0 +1,66 @@ +import { getExplorerUrl } from '@components/explorer/tools' +import { PhotographIcon } from '@heroicons/react/outline' +import ImgWithLoader from '@components/ImgWithLoader' +import { MdScheduleSend } from 'react-icons/md' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' + +const NFTGallery = ({ + nfts, + onClickSendNft, +}: { + nfts: any[] | undefined + onClickSendNft: (nft: any) => void | Promise +}) => { + const connection = useLegacyConnectionContext() + + return ( +
+ {nfts === undefined ? ( + <> +
+
+
+
+ + ) : nfts?.length ? ( + nfts.map((x) => ( +
+ e.stopPropagation()} + > + + + +
+ )) + ) : ( +
+ +
+ )} +
+ ) +} + +export default NFTGallery diff --git a/components/NFTS/NFTSCompactWrapper.tsx b/components/NFTS/NFTSCompactWrapper.tsx index 91f1893762..e18de5ab38 100644 --- a/components/NFTS/NFTSCompactWrapper.tsx +++ b/components/NFTS/NFTSCompactWrapper.tsx @@ -1,29 +1,19 @@ -import { getExplorerUrl } from '@components/explorer/tools' -import ImgWithLoader from '@components/ImgWithLoader' import { ChevronRightIcon } from '@heroicons/react/solid' -import useGovernanceAssets from '@hooks/useGovernanceAssets' +import { useRealmDigitalAssetsQuery } from '@hooks/queries/digitalAssets' import useQueryContext from '@hooks/useQueryContext' -import useRealm from '@hooks/useRealm' -import React from 'react' -import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' -import useWalletStore from 'stores/useWalletStore' import Link from 'next/link' -import Loading from '@components/Loading' -import useGovernanceAssetsStore from 'stores/useGovernanceAssetsStore' +import { useRouter } from 'next/router' +import { useMemo } from 'react' const NFTSCompactWrapper = () => { - const { nftsGovernedTokenAccounts } = useGovernanceAssets() - const connection = useWalletStore((s) => s.connection) - const realmNfts = useTreasuryAccountStore((s) => s.allNfts) - const isLoading = useTreasuryAccountStore((s) => s.isLoadingNfts) - const isLoadingAssets = useGovernanceAssetsStore( - (s) => s.loadGovernedAccounts - ) - const { symbol } = useRealm() + const { data: nfts } = useRealmDigitalAssetsQuery() + const nftsCount = useMemo(() => nfts?.flat().length ?? 0, [nfts]) + + const { symbol } = useRouter().query const { fmtUrlWithCluster } = useQueryContext() - return nftsGovernedTokenAccounts.length ? ( + return nftsCount > 0 ? (
-
+

NFTs

{
-
{ )) ) : null}
-
+
*/}
) : null } diff --git a/components/NFTS/NFTSelector.tsx b/components/NFTS/NFTSelector.tsx index 9c8f762330..0393c7f471 100644 --- a/components/NFTS/NFTSelector.tsx +++ b/components/NFTS/NFTSelector.tsx @@ -1,143 +1,82 @@ -import React, { - forwardRef, - useEffect, - useImperativeHandle, - useState, -} from 'react' -import { PhotographIcon } from '@heroicons/react/solid' -import { NFTWithMint } from '@utils/uiTypes/nfts' -import { CheckCircleIcon } from '@heroicons/react/solid' -import { PublicKey } from '@solana/web3.js' -import Loading from '@components/Loading' -import { getNfts } from '@utils/tokens' import ImgWithLoader from '@components/ImgWithLoader' -import useWalletStore from 'stores/useWalletStore' - -export interface NftSelectorFunctions { - handleGetNfts: () => void -} +import Loading from '@components/Loading' +import { CheckCircleIcon, PhotographIcon } from '@heroicons/react/solid' +import { useDigitalAssetsByOwner } from '@hooks/queries/digitalAssets' +import { PublicKey } from '@solana/web3.js' +import clsx from 'clsx' +import { SetStateAction } from 'react' -function NFTSelector( - { - ownersPk, - onNftSelect, - nftWidth = '150px', - nftHeight = '150px', - selectable = true, - predefinedNfts, - selectedNft, - }: { - ownersPk: PublicKey[] - onNftSelect: (nfts: NFTWithMint[]) => void - nftWidth?: string - nftHeight?: string - selectable?: boolean - predefinedNfts?: NFTWithMint[] - selectedNft?: NFTWithMint | null - }, - ref: React.Ref -) { - const isPredefinedMode = typeof predefinedNfts !== 'undefined' - const [nfts, setNfts] = useState([]) - const [selected, setSelected] = useState([]) - const connection = useWalletStore((s) => s.connection) - const [isLoading, setIsLoading] = useState(false) - const handleSelectNft = (nft: NFTWithMint) => { - const nftMint: string[] = [] - selected.map((x) => { - nftMint.push(x.mintAddress) - }) - // Deselects NFT if clicked on again. - if (nftMint.includes(nft.mintAddress)) { - setSelected((current) => - current.filter((item) => { - return item.mintAddress !== nft.mintAddress - }) - ) - } else { - setSelected((current) => [...current, nft]) - } - } - const handleGetNfts = async () => { - setIsLoading(true) - const response = await Promise.all( - ownersPk.map((x) => getNfts(x, connection)) - ) - const nfts = response.flatMap((x) => x) - if (nfts.length === 1) { - setSelected([nfts[0]]) - } - setNfts(nfts) - setIsLoading(false) - } - useImperativeHandle(ref, () => ({ - handleGetNfts, - })) +/** Select NFTs owned by a given governance */ +function NFTSelector({ + nftWidth = '150px', + nftHeight = '150px', + selectedNfts, + setSelectedNfts, + owner, +}: { + owner: PublicKey + selectedNfts: PublicKey[] + setSelectedNfts: React.Dispatch> + nftWidth?: string + nftHeight?: string +}) { + const { data: nfts, isLoading } = useDigitalAssetsByOwner(owner) - useEffect(() => { - if (selectedNft) { - setSelected([selectedNft]) - } - }, []) - useEffect(() => { - if (ownersPk.length && !isPredefinedMode) { - handleGetNfts() - } - }, [JSON.stringify(ownersPk.map((x) => x.toBase58()))]) - useEffect(() => { - if (!isPredefinedMode && selected) { - onNftSelect(selected) - } - }, [selected]) - useEffect(() => { - if (predefinedNfts && isPredefinedMode) { - setNfts(predefinedNfts) - } - }, [predefinedNfts]) return ( <> -
+
{!isLoading ? ( - nfts.length ? ( + nfts?.length ? (
- {nfts.map((x) => ( + {nfts.map((nft) => (
(selectable ? handleSelectNft(x) : null)} - key={x.mintAddress} - className={`bg-bkg-2 flex items-center justify-center cursor-pointer default-transition rounded-lg border border-transparent ${ - selectable ? 'hover:border-primary-dark' : '' - } relative overflow-hidden`} + onClick={() => + setSelectedNfts((prev) => { + const alreadyIncluded = prev.find( + (x) => x.toString() === nft.id + ) + return alreadyIncluded + ? prev.filter((x) => x.toString() !== nft.id) + : [...prev, new PublicKey(nft.id)] + }) + } + key={nft.id} + className={clsx( + `bg-bkg-2 flex-shrink-0 flex items-center justify-center cursor-pointer default-transition rounded-lg relative overflow-hidden`, + selectedNfts.find((k) => k.toString() === nft.id) + ? 'border-4 border-green' + : 'border border-transparent hover:border-primary-dark ' + )} style={{ width: nftWidth, height: nftHeight, }} > - {selected?.map((i) => ( - <> - {selected && x.mintAddress === i.mintAddress && ( - - )} - - ))} - + {selectedNfts.find((k) => k.toString() === nft.id) && ( + + )} + +
))}
) : (
{"Account doesn't have any NFTs"} - +
) ) : ( - + )}
) } -export default forwardRef(NFTSelector) +export default NFTSelector diff --git a/components/NFTVotePluginSettingsDisplay.tsx b/components/NFTVotePluginSettingsDisplay.tsx new file mode 100644 index 0000000000..2dec9cf6c5 --- /dev/null +++ b/components/NFTVotePluginSettingsDisplay.tsx @@ -0,0 +1,105 @@ +import { PublicKey } from '@solana/web3.js' +import type BN from 'bn.js' +import cx from 'classnames' + +import NFTIcon from '@components/treasuryV2/icons/NFTCollectionPreviewIcon' +import { useConnection } from '@solana/wallet-adapter-react' +import { useAsync } from 'react-async-hook' +import { fetchDigitalAssetById } from '@hooks/queries/digitalAssets' +import { getNetworkFromEndpoint } from '@utils/connection' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import BigNumber from 'bignumber.js' +import {useNftRegistrar} from "@hooks/useNftRegistrar"; + +interface CollectionConfig { + collection: PublicKey + size: number + weight: BN +} + +interface Props { + className?: string +} + +export function NFTVotePluginSettingsDisplay(props: Props) { + const { connection } = useConnection() + const registrar = useNftRegistrar(); + + const { result: configsWithNames } = useAsync(async () => { + const collectionConfigs = (registrar?.collectionConfigs || + []) as CollectionConfig[] + const network = getNetworkFromEndpoint(connection.rpcEndpoint) + if (network === 'localnet') throw new Error() + + return Promise.all( + collectionConfigs.map(async (collectionConfig) => { + const collectionNft = await fetchDigitalAssetById( + network, + collectionConfig.collection + ) + const name = collectionNft?.result?.content.metadata.name + return { name: name ?? 'Unknown Collection', ...collectionConfig } + }) + ) + }, [connection.rpcEndpoint, registrar?.collectionConfigs]) + + const governingMint = useMintInfoByPubkeyQuery(registrar?.governingTokenMint) + .data?.result + + return configsWithNames === undefined ? ( +
+
+ {' '} + NFT Voting Configuration +
+
+
+ ) : ( +
+
+ {' '} + NFT Voting Configuration +
+ {configsWithNames.map((collection, i) => ( +
+
+
{i + 1}.
+
+
+ {collection.name} +
+
+ {collection.collection.toBase58()} +
+
+
# NFTs in Collection:
+
{collection.size}
+ {governingMint && ( + <> +
Vote Weight per NFT:
+
+ {new BigNumber(collection.weight.toString()) + .shiftedBy(-governingMint.decimals) + .toFormat()} +
+ + )} +
+ {/* */} +
+
+
+ ))} +
+ ) +} diff --git a/components/NavBar.tsx b/components/NavBar.tsx index 173126aa62..ab3a147c9d 100644 --- a/components/NavBar.tsx +++ b/components/NavBar.tsx @@ -1,15 +1,20 @@ import useQueryContext from '@hooks/useQueryContext' import Link from 'next/link' - -import ConnectWalletButton from './ConnectWalletButton' -import NotificationsSwitch from './NotificationsSwitch' +import dynamic from 'next/dynamic' import ThemeSwitch from './ThemeSwitch' +import { ExternalLinkIcon } from '@heroicons/react/outline' +import DialectNotifications from './Dialect' + +const ConnectWalletButtonDynamic = dynamic( + async () => await import('./ConnectWalletButton'), + { ssr: false } +) const NavBar = () => { const { fmtUrlWithCluster } = useQueryContext() return ( -
+
@@ -18,14 +23,23 @@ const NavBar = () => { srcSet="/img/logotype-realms-blue-white.svg" media="(min-width: 640px)" /> - +
diff --git a/components/NewRealmWizard/PageTemplate.tsx b/components/NewRealmWizard/PageTemplate.tsx index 7a5ae790c5..d186c31688 100644 --- a/components/NewRealmWizard/PageTemplate.tsx +++ b/components/NewRealmWizard/PageTemplate.tsx @@ -2,16 +2,19 @@ import { useEffect, useState } from 'react' import { useRouter } from 'next/router' import Head from 'next/head' -import { isWizardValid } from '@utils/formValidation' +import { isWizardValid, validateSolAddress } from '@utils/formValidation' import CreateDAOWizard from '@components/NewRealmWizard/CreateDAOWizard' -import useWalletStore from 'stores/useWalletStore' // import { FORM_NAME as NFT_FORM } from 'pages/realms/new/nft' import { FORM_NAME as MULTISIG_WALLET_FORM } from 'pages/realms/new/multisig' import { FORM_NAME as COMMUNITY_TOKEN_FORM } from 'pages/realms/new/community-token' +import { useProgramVersionByIdQuery } from '@hooks/queries/useProgramVersionQuery' +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 (
{children} @@ -26,13 +29,16 @@ export default function FormPage({ handleSubmit, submissionPending, }) { - const { connected, current: wallet } = useWalletStore((s) => s) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected const userAddress = wallet?.publicKey?.toBase58() + + const { query, push } = useRouter() const [formData, setFormData] = useState({ + _programVersion: undefined, memberAddresses: autoInviteWallet && userAddress ? [userAddress] : undefined, }) - const { query, push } = useRouter() const currentStep = formData?.currentStep || 0 const title = `Create ${ type === MULTISIG_WALLET_FORM @@ -42,6 +48,24 @@ export default function FormPage({ : 'NFT community DAO' } | Realms` + // Update formData's _programVersion + const programIdInput = + formData.programId ?? DEFAULT_GOVERNANCE_PROGRAM_ID.toString() + const validProgramId = + programIdInput && validateSolAddress(programIdInput) + ? new PublicKey(programIdInput) + : undefined + const programVersionQuery = useProgramVersionByIdQuery(validProgramId) + + useEffect(() => { + if (programVersionQuery.data) { + setFormData((prev) => ({ + ...prev, + _programVersion: programVersionQuery.data, + })) + } + }, [programVersionQuery.data]) + useEffect(() => { async function tryToConnect() { try { @@ -52,17 +76,21 @@ export default function FormPage({ throw new Error('No valid wallet connected') } } catch (err) { + // @asktree: why would this be the correct behavior if the user isn't connected? if (currentStep > 0) handlePreviousButton(1) } } tryToConnect() + // 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 }, [connected]) useEffect(() => { if (currentStep > 0 && !isWizardValid({ currentStep, steps, formData })) { + // @asktree: Why would this be the correct behavior for validation failure? It just seems silently confusing for the user (or the dev as the case may be). handlePreviousButton(currentStep) } + // 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 }, [currentStep]) function handleNextButtonClick({ step: fromStep, data }) { @@ -71,17 +99,11 @@ export default function FormPage({ ...data, } const nextStep = steps - .map( - ({ required }) => - required === 'true' || - !!eval(required.replace('form', 'updatedFormState')) - ) + .map(({ required }) => required(updatedFormState)) .indexOf(true, fromStep + 1) updatedFormState.currentStep = nextStep > -1 ? nextStep : steps.length + 1 - console.log('next button clicked', fromStep, nextStep) - for (const key in updatedFormState) { if (updatedFormState[key] == null) { delete updatedFormState[key] @@ -91,13 +113,6 @@ export default function FormPage({ } function handlePreviousButton(fromStep) { - console.log( - 'previous button clicked from step:', - fromStep, - currentStep, - query - ) - if (fromStep === 0) { push( { @@ -109,10 +124,7 @@ export default function FormPage({ ) } else { const previousStep = steps - .map( - ({ required }) => - required === 'true' || !!eval(required.replace('form', 'formData')) - ) + .map(({ required }) => required(formData)) .lastIndexOf(true, fromStep - 1) const updatedFormState = { diff --git a/components/NewRealmWizard/components/AdvancedOptionsDropdown.tsx b/components/NewRealmWizard/components/AdvancedOptionsDropdown.tsx index 79d3cf0dd3..144eed3fd2 100644 --- a/components/NewRealmWizard/components/AdvancedOptionsDropdown.tsx +++ b/components/NewRealmWizard/components/AdvancedOptionsDropdown.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { ReactNode, useState } from 'react' import { Transition } from '@headlessui/react' import Text from '@components/Text' @@ -6,6 +6,12 @@ export default function AdvancedOptionsDropdown({ className = 'mt-10 md:mt-16 w-fit', children, title = 'Advanced Options', + icon, +}: { + children: ReactNode + icon?: ReactNode + className?: string + title?: string }) { const [open, setOpen] = useState(false) return ( @@ -20,6 +26,7 @@ export default function AdvancedOptionsDropdown({ {title} + {icon}
diff --git a/components/NewRealmWizard/components/CivicPassSelector.tsx b/components/NewRealmWizard/components/CivicPassSelector.tsx new file mode 100644 index 0000000000..99e2172c4f --- /dev/null +++ b/components/NewRealmWizard/components/CivicPassSelector.tsx @@ -0,0 +1,100 @@ +import * as DropdownMenu from '@radix-ui/react-dropdown-menu' +import { useEffect, useState } from 'react' +interface Props { + className?: string + selectedPass: string + onPassSelected: (string) => void +} +import cx from '@hub/lib/cx' +import { availablePasses } from 'GatewayPlugin/config' +import { ChevronDownIcon } from '@heroicons/react/solid' + +const itemStyles = cx( + 'border', + 'cursor-pointer', + 'gap-x-4', + 'grid-cols-[150px,1fr,20px]', + 'grid', + 'h-14', + 'items-center', + 'px-4', + 'w-full', + 'rounded-md', + 'text-left', + 'transition-colors', + 'dark:bg-neutral-800', + 'dark:border-neutral-700', + 'dark:hover:bg-neutral-700' +) + +const labelStyles = cx('font-700', 'dark:text-neutral-50', 'w-full') +const iconStyles = cx('fill-neutral-500', 'h-5', 'transition-transform', 'w-4') +const descriptionStyles = cx('dark:text-neutral-400 text-sm') + +export default function CivicPassSelector({ + className, + onPassSelected, +}: Props) { + const [open, setOpen] = useState(false) + const [selectedPassState, setSelectedPass] = useState(availablePasses[0]) + + useEffect(() => { + onPassSelected(selectedPassState.value) + }, [onPassSelected, selectedPassState.value]) + + return ( +
+ +
+ +
+ {selectedPassState?.name || 'Select a Civic Pass'} +
+
+ {selectedPassState?.description || ''} +
+ +
+ + + {availablePasses.slice(0, -1).map((config, i) => ( + { + setSelectedPass(config) + }} + > +
{config.name}
+
{config.description}
+
+ ))} +
+
+
+
+ {!selectedPassState.isSybilResistance && ( +
+ Warning: This pass type does + not provide sybil resistance. +
+ )} +
+ ) +} diff --git a/components/NewRealmWizard/components/FormField.tsx b/components/NewRealmWizard/components/FormField.tsx index db40264e57..ef45925017 100644 --- a/components/NewRealmWizard/components/FormField.tsx +++ b/components/NewRealmWizard/components/FormField.tsx @@ -3,7 +3,7 @@ interface Props { advancedOption?: boolean children: React.ReactNode className?: string - description: string | React.ReactNode + description?: string | React.ReactNode disabled?: boolean optional?: boolean title: string @@ -59,14 +59,16 @@ export default function FormField({ {titleExtra}
- - {description} - + {description && ( + + {description} + + )}
{children}
) diff --git a/components/NewRealmWizard/components/FormSummary.tsx b/components/NewRealmWizard/components/FormSummary.tsx index e99d980d78..c73ffe76b7 100644 --- a/components/NewRealmWizard/components/FormSummary.tsx +++ b/components/NewRealmWizard/components/FormSummary.tsx @@ -76,6 +76,7 @@ function CommunityInfo({ mintAddress, transferMintAuthority, mintSupplyFactor, + communityAbsoluteMaxVoteWeight, yesVotePercentage, minimumNumberOfTokensToGovern, nftInfo, @@ -90,7 +91,7 @@ function CommunityInfo({ <>
- Community info + Community Info
{nftIsCommunityToken ? ( @@ -150,6 +151,13 @@ function CommunityInfo({ )} + {communityAbsoluteMaxVoteWeight && ( + + + {communityAbsoluteMaxVoteWeight} + + + )}
) @@ -159,7 +167,7 @@ function CouncilInfo({ tokenInfo, mintAddress, transferMintAuthority, - // yesVotePercentage, + yesVotePercentage, numberOfMembers, }) { const updatedTokenInfo = { @@ -176,16 +184,18 @@ function CouncilInfo({
+ {yesVotePercentage !== undefined && ( + + + {yesVotePercentage}% + + + )} {numberOfMembers} - {/* - - {yesVotePercentage}% - - */} {updatedTokenInfo.name !== TO_BE_GENERATED && ( @@ -230,6 +240,16 @@ export default function WizardSummary({ >
{formData?.name}
+ {formData?.isQuadratic && ( + + + Civic Plugin + + + Quadratic Voting Plugin + + + )} {type === MULTISIG_FORM ? (
@@ -250,6 +270,9 @@ export default function WizardSummary({ tokenInfo={formData.communityTokenInfo} transferMintAuthority={formData.transferCommunityMintAuthority} mintSupplyFactor={formData.communityMintSupplyFactor} + communityAbsoluteMaxVoteWeight={ + formData.communityAbsoluteMaxVoteWeight + } yesVotePercentage={formData.communityYesVotePercentage} minimumNumberOfTokensToGovern={ formData.minimumNumberOfCommunityTokensToGovern @@ -264,10 +287,7 @@ export default function WizardSummary({ formData.transferCouncilMintAuthority || !formData.useExistingCouncilToken } - // yesVotePercentage={ - // formData?.councilYesVotePercentage || - // formData.communityYesVotePercentage - // } + yesVotePercentage={formData.councilYesVotePercentage} numberOfMembers={formData?.memberAddresses?.length} /> )} @@ -288,8 +308,10 @@ export default function WizardSummary({ type === MULTISIG_FORM ? 'Create wallet' : `Create ${ - type === COMMUNITY_TOKEN_FORM + type === COMMUNITY_TOKEN_FORM && !formData?.isQuadratic ? 'Community Token' + : type === COMMUNITY_TOKEN_FORM && formData?.isQuadratic + ? 'Quadratic Voting' : 'NFT Community' } DAO` } diff --git a/components/NewRealmWizard/components/Input.tsx b/components/NewRealmWizard/components/Input.tsx index f5d34de250..adff8668ba 100644 --- a/components/NewRealmWizard/components/Input.tsx +++ b/components/NewRealmWizard/components/Input.tsx @@ -106,7 +106,7 @@ const Input = React.forwardRef( export default Input -export function FieldMessage({ +function FieldMessage({ error = '', warning = '', success = '', diff --git a/components/NewRealmWizard/components/NFTCollectionModal.tsx b/components/NewRealmWizard/components/NFTCollectionModal.tsx index 4b064b7f04..e1c5d8ab97 100644 --- a/components/NewRealmWizard/components/NFTCollectionModal.tsx +++ b/components/NewRealmWizard/components/NFTCollectionModal.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' import { abbreviateAddress } from '@utils/formatting' import Header from '@components/Header' @@ -7,25 +7,122 @@ import NFTCollectionSelector from '@components/NewRealmWizard/components/NFTColl import { WalletIcon } from './steps/AddNFTCollectionForm' import Modal from '@components/Modal' +import { + DasNftObject, + dasByIdQueryFn, + digitalAssetsQueryKeys, + useDigitalAssetsByOwner, +} from '@hooks/queries/digitalAssets' +import { useConnection } from '@solana/wallet-adapter-react' +import { useAsync } from 'react-async-hook' +import queryClient from '@hooks/queries/queryClient' +import { getNetworkFromEndpoint } from '@utils/connection' +import { PublicKey } from '@solana/web3.js' +import { ON_NFT_VOTER_V2 } from '@constants/flags' + +function filterAndMapVerifiedCollections(nfts: DasNftObject[]) { + return nfts + ?.filter((nft) => { + if ( + nft.grouping && + nft.grouping.find((x) => x.group_key === 'collection') + ) { + return true + } else { + return false + } + }) + .filter((nft) => ON_NFT_VOTER_V2 || !nft.compression.compressed) + .reduce((prev, curr) => { + const collectionKey = curr.grouping.find( + (x) => x.group_key === 'collection' + )?.group_value + if (typeof collectionKey === 'undefined') return prev + + if (prev[collectionKey]) { + prev[collectionKey].push(curr) + } else { + prev[collectionKey] = [curr] + } + return prev + }, {}) +} + +export const useOwnerVerifiedCollections = (owner: PublicKey) => { + const { connection } = useConnection() + const network = getNetworkFromEndpoint(connection.rpcEndpoint) + if (network === 'localnet') throw new Error() + const { data: ownedNfts } = useDigitalAssetsByOwner(owner) + + const enabled = owner !== undefined && ownedNfts !== undefined + return useAsync(async () => { + if (!enabled) throw new Error() + + const verifiedNfts = filterAndMapVerifiedCollections(ownedNfts) + const verifiedCollections = await Promise.all( + Object.keys(verifiedNfts).map(async (collectionKey) => { + const { result: collection } = await queryClient.fetchQuery({ + queryKey: digitalAssetsQueryKeys.byId( + network, + new PublicKey(collectionKey) + ), + queryFn: () => dasByIdQueryFn(network, new PublicKey(collectionKey)), + staleTime: Infinity, + }) + if (collection !== undefined) { + return { + ...collection, + collectionMintAddress: collectionKey, + nfts: verifiedNfts[collectionKey], + } + } else { + return null + } + }) + ) + + return verifiedCollections.filter((x) => x !== null) + }, [connection, ownedNfts, enabled]) +} + export default function NFTCollectionModal({ - show, + isShow, walletPk, - collections, + setError, onClose, onSelect, }) { + const { result: collections, loading } = useOwnerVerifiedCollections(walletPk) + const [show, setShow] = useState(false) const [selected, setSelected] = useState('') - function close() { onClose() setSelected('') } function handleChoose() { - onSelect({ key: selected, collection: collections[selected] }) + onSelect({ key: selected, collection: collections![selected] }) close() } + useEffect(() => { + if (collections && Object.keys(collections).length === 0) { + setError( + 'collectionInput', + { + type: 'error', + message: 'Current wallet has no verified collection', + }, + { shouldFocus: true } + ) + } else { + setShow(isShow) + } + }, [isShow, collections, setError]) + + if (!show) { + return <> + } return ( show && ( @@ -42,6 +139,7 @@ export default function NFTCollectionModal({
) { const [loading, setLoading] = useState(true) const loadingClassName = `${loading ? '' : 'hidden'} ${className}` const imageClassName = `${loading ? 'hidden' : ''} ${className}` @@ -16,6 +19,7 @@ function ImageWithLoader({ className, ...props }) {
setLoading(false)} /> @@ -23,10 +27,22 @@ function ImageWithLoader({ className, ...props }) { ) } -const NFTCollectionSelector = ({ collections = {}, onChange, value }) => { +const NFTCollectionSelector = ({ + isLoading, + collections = {}, + onChange, + value, +}) => { const optionClass = 'z-0 group flex flex-wrap md:items-center md:space-x-8 flex-wrap py-4 px-2 md:px-8 relative w-full default-transition rounded-md hover:cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 hover:opacity-100 hover:bg-bkg-3' + if (isLoading) { + return ( +
+ Loading verified NFT collections from your wallet... +
+ ) + } if (Object.keys(collections).length === 0) { return (
@@ -40,9 +56,10 @@ const NFTCollectionSelector = ({ collections = {}, onChange, value }) => {
{Object.keys(collections).map((key) => { const collection = collections[key] - const totalNfts = collection.nfts.length - const images = collection.nfts.slice(0, 2).map((nft) => nft.image) - + const totalNfts = collection?.nfts.length + const images = collection?.nfts + .slice(0, 2) + .map((nft) => nft.content.links?.image) for (let i = images.length; i < 3; i++) { images.unshift('') } @@ -57,13 +74,13 @@ const NFTCollectionSelector = ({ collections = {}, onChange, value }) => { >
- {collection?.name} + {collection?.content.metadata.name} {totalNfts} {`NFT${totalNfts === 1 ? '' : 's'}`} @@ -74,7 +91,7 @@ const NFTCollectionSelector = ({ collections = {}, onChange, value }) => {
{src && ( diff --git a/components/NewRealmWizard/components/SimpleCheckmarkCircle.tsx b/components/NewRealmWizard/components/SimpleCheckmarkCircle.tsx new file mode 100644 index 0000000000..27cc0e72f5 --- /dev/null +++ b/components/NewRealmWizard/components/SimpleCheckmarkCircle.tsx @@ -0,0 +1,16 @@ +export default function ({ selected = false }) { + return ( +
+ {selected && +
+ } +
+ ) + } + \ No newline at end of file diff --git a/components/NewRealmWizard/components/TokenInfoTable.tsx b/components/NewRealmWizard/components/TokenInfoTable.tsx index 329f2f288e..3447900a7b 100644 --- a/components/NewRealmWizard/components/TokenInfoTable.tsx +++ b/components/NewRealmWizard/components/TokenInfoTable.tsx @@ -31,7 +31,7 @@ export function GenericTokenIcon() { ) } -export function TokenInfoCell({ title = '', children }) { +function TokenInfoCell({ title = '', children }) { return (
diff --git a/components/NewRealmWizard/components/TokenInput.tsx b/components/NewRealmWizard/components/TokenInput.tsx index 6ffc5ed4e2..13a06a8df1 100644 --- a/components/NewRealmWizard/components/TokenInput.tsx +++ b/components/NewRealmWizard/components/TokenInput.tsx @@ -1,10 +1,8 @@ import { useEffect, useState } from 'react' -import { TokenListProvider, TokenInfo } from '@solana/spl-token-registry' import { MintInfo, u64 } from '@solana/spl-token' import { PublicKey } from '@solana/web3.js' import { getMintSupplyAsDecimal } from '@tools/sdk/units' -import useWalletStore from 'stores/useWalletStore' import { tryGetMint } from '@utils/tokens' import { validatePubkey } from '@utils/formValidation' import { preventNegativeNumberInput } from '@utils/helpers' @@ -16,6 +14,10 @@ import Input, { RadioGroup } from '@components/NewRealmWizard/components/Input' import TokenInfoTable, { GenericTokenIcon, } from '@components/NewRealmWizard/components/TokenInfoTable' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { TokenInfo } from '@utils/services/types' +import tokenPriceService from '@utils/services/tokenPrice' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' interface MintInfoWithDecimalSupply extends MintInfo { supplyAsDecimal: number @@ -58,8 +60,10 @@ export default function TokenInput({ onValidation, disableMinTokenInput = false, }) { - const { connected, connection, current: wallet } = useWalletStore((s) => s) - const [tokenList, setTokenList] = useState() + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const tokenList = tokenPriceService._tokenList const [tokenMintAddress, setTokenMintAddress] = useState('') const [tokenInfo, setTokenInfo] = useState() const validMintAddress = tokenInfo && tokenInfo !== PENDING_COIN @@ -74,22 +78,9 @@ export default function TokenInput({ if (!connected) { wallet?.connect() } + // 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 }, [wallet]) - useEffect(() => { - async function getTokenList() { - const tokenList = await new TokenListProvider().resolve() - const filteredTokenList = tokenList - .filterByClusterSlug( - connection.cluster === 'mainnet' ? 'mainnet-beta' : connection.cluster - ) - .getList() - setTokenList(filteredTokenList) - } - - getTokenList() - }, [connection.cluster]) - useEffect(() => { async function getTokenInfo(tokenMintAddress) { setTokenInfo(PENDING_COIN) @@ -119,6 +110,7 @@ export default function TokenInput({ } else { setTokenInfo(undefined) } + // 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 }, [tokenList, tokenMintAddress]) useEffect(() => { @@ -134,6 +126,7 @@ export default function TokenInput({ suggestedMinTokenAmount, walletIsMintAuthority, }) + // 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 }, [validMintAddress, walletIsMintAuthority, tokenInfo]) return ( @@ -228,7 +221,7 @@ export default function TokenInput({ render={({ field, fieldState: { error } }) => ( +export type AddCouncil = AddCouncilV2 | AddCouncilV3 export default function AddCouncilForm({ type, @@ -90,10 +96,12 @@ export default function AddCouncilForm({ useEffect(() => { updateUserInput(formData, AddCouncilSchema, setValue) + // 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 }, []) useEffect(() => { setValue('addCouncil', forceCouncil || undefined) + // 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 }, [forceCouncil]) useEffect(() => { @@ -102,12 +110,14 @@ export default function AddCouncilForm({ setValue('transferCouncilMintAuthority', undefined) setCouncilTokenInfo(undefined) } + // 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 }, [useExistingCouncilToken]) useEffect(() => { if (!addCouncil) { setValue('useExistingCouncilToken', undefined, { shouldValidate: true }) } + // 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 }, [addCouncil]) function handleTokenInput({ tokenInfo }) { diff --git a/components/NewRealmWizard/components/steps/AddNFTCollectionForm.tsx b/components/NewRealmWizard/components/steps/AddNFTCollectionForm.tsx index b973fca6b0..9c70cd0ebb 100644 --- a/components/NewRealmWizard/components/steps/AddNFTCollectionForm.tsx +++ b/components/NewRealmWizard/components/steps/AddNFTCollectionForm.tsx @@ -1,16 +1,11 @@ -import React, { useEffect, useState } from 'react' +import { useEffect, useState } from 'react' import { useForm, Controller } from 'react-hook-form' import { yupResolver } from '@hookform/resolvers/yup' import * as yup from 'yup' -import { deprecated } from '@metaplex-foundation/mpl-token-metadata' -import axios from 'axios' - import { updateUserInput, validatePubkey } from '@utils/formValidation' import { notify } from '@utils/notifications' import { abbreviateAddress } from '@utils/formatting' -import useWalletStore from 'stores/useWalletStore' - import { NewButton as Button } from '@components/Button' import Text from '@components/Text' import FormHeader from '@components/NewRealmWizard/components/FormHeader' @@ -21,101 +16,10 @@ import Input, { } from '@components/NewRealmWizard/components/Input' import AdviceBox from '@components/NewRealmWizard/components/AdviceBox' import NFTCollectionModal from '@components/NewRealmWizard/components/NFTCollectionModal' - -function filterAndMapVerifiedCollections(nfts) { - return nfts - .filter((nft) => { - if (nft.data?.collection) { - return nft.data?.collection?.verified - } else { - return nft.collection?.verified - } - }) - .map((nft) => { - if (nft.data.collection) { - return nft.data - } else { - return nft - } - }) - .reduce((prev, curr) => { - const collectionKey = curr.collection?.key - if (typeof collectionKey === 'undefined') return prev - - if (prev[collectionKey]) { - prev[collectionKey].push(curr) - } else { - prev[collectionKey] = [curr] - } - return prev - }, {}) -} - -async function enrichItemInfo(item, uri) { - const { data: response } = await axios.get(uri) - return { - ...item, - ...response, - } -} - -async function enrichCollectionInfo(connection, collectionKey) { - const data = await deprecated.Metadata.findByMint(connection, collectionKey) - - const collectionData = data!.data!.data - - return enrichItemInfo( - { - ...collectionData, - collectionMintAddress: collectionKey, - }, - collectionData.uri - ) -} - -async function getNFTCollectionInfo(connection, collectionKey) { - const { data: result } = await deprecated.Metadata.findByMint( - connection, - collectionKey - ) - console.log('NFT findByMint result', result) - if (result?.collection?.verified && result.collection?.key) { - // here we were given a child of the collection (hence the "collection" property is present) - const collectionInfo = await enrichCollectionInfo( - connection, - result.collection.key - ) - const nft = await enrichItemInfo(result.data, result.data.uri) - collectionInfo.nfts = [nft] - return collectionInfo - } else { - // assume we've been given the collection address already, so we need to go find it's children - const children = await deprecated.Metadata.findMany(connection, { - updateAuthority: result!.updateAuthority, - }) - - const verifiedCollections = filterAndMapVerifiedCollections(children) - if (verifiedCollections[collectionKey]) { - const collectionInfo = await enrichCollectionInfo( - connection, - collectionKey - ) - const nfts = await Promise.all( - verifiedCollections[collectionKey].map((item) => { - return enrichItemInfo(item.data, item.data.uri) - }) - ) - collectionInfo.nfts = nfts - return collectionInfo - } else { - throw new Error( - 'Address did not return collection with children whose "collection.key" matched' - ) - } - } - - // 3iBYdnzA418tD2o7vm85jBeXgxbdUyXzX9Qfm2XJuKME -} +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { dasByIdQueryFn } from '@hooks/queries/digitalAssets' +import { getNetworkFromEndpoint } from '@utils/connection' export const AddNFTCollectionSchema = { collectionKey: yup.string().required(), @@ -139,7 +43,7 @@ export interface AddNFTCollection { numberOfNFTs: number } -export interface NFT_Creator { +interface NFT_Creator { address: string verified: number share: number @@ -150,7 +54,7 @@ interface NFT_Attributes { trait_type: string value: number } -export interface NFT { +interface NFT { name: string symbol: string uri: string @@ -225,17 +129,16 @@ export default function AddNFTCollectionForm({ onSubmit, onPrevClick, }) { - const { connected, connection, current: wallet } = useWalletStore((s) => s) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected const [walletConnecting, setWalletConnecting] = useState(false) const [requestPending, setRequestPending] = useState(false) const [isModalOpen, setIsModalOpen] = useState(false) - const [collectionsInWallet, setCollectionsInWallet] = useState({}) + // const [collectionsInWallet, setCollectionsInWallet] = useState({}) - const [ - selectedNFTCollection, - setSelectedNFTCollection, - ] = useState() + const [selectedNFTCollection, setSelectedNFTCollection] = useState() const schema = yup.object(AddNFTCollectionSchema).required() const { @@ -252,7 +155,12 @@ export default function AddNFTCollectionForm({ mode: 'all', resolver: yupResolver(schema), }) - const [unverifiedCollection, setUnverifiedCollection] = useState(false) + const [ + collectionVerificationState, + setCollectionVerificationState, + ] = useState< + 'none' | 'invalid' | 'verified' | 'is nft but no collection details' + >('none') const collectionKey = watch('collectionKey') const numberOfNFTs = watch('numberOfNFTs') || 10000 const approvalPercent = watch('communityYesVotePercentage', 60) || 60 @@ -263,15 +171,17 @@ export default function AddNFTCollectionForm({ useEffect(() => { updateUserInput(formData, AddNFTCollectionSchema, setValue) setSelectedNFTCollection(formData?.collectionMetadata) + // 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 }, []) useEffect(() => { - if (unverifiedCollection || selectedNFTCollection) { + if (collectionVerificationState === 'invalid' || selectedNFTCollection) { setFocus('numberOfNFTs') } else { // setFocus('collectionInput') } - }, [unverifiedCollection, selectedNFTCollection]) + // 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 + }, [collectionVerificationState, selectedNFTCollection]) function serializeValues(values) { const data = { @@ -290,18 +200,26 @@ export default function AddNFTCollectionForm({ handleClearSelectedNFT(false) setRequestPending(true) try { - const collectionInfo = await getNFTCollectionInfo( - connection.current, + const network = getNetworkFromEndpoint(connection.endpoint) + if (network === 'localnet') throw new Error() + const { result: collectionInfo } = await dasByIdQueryFn( + network, collectionInput ) + console.log('NFT collection info from user input:', collectionInfo) - setValue('collectionKey', collectionInfo.collectionMintAddress) + setValue('collectionKey', collectionInput) + setCollectionVerificationState( + collectionInfo?.grouping.length === 0 + ? 'verified' + : 'is nft but no collection details' + ) setSelectedNFTCollection(collectionInfo) setRequestPending(false) } catch (err) { setRequestPending(false) setValue('collectionKey', collectionInput) - setUnverifiedCollection(true) + setCollectionVerificationState('invalid') } } else { setError('collectionInput', { @@ -317,7 +235,7 @@ export default function AddNFTCollectionForm({ } clearErrors('collectionInput') setValue('collectionKey', '') - setUnverifiedCollection(false) + setCollectionVerificationState('none') setSelectedNFTCollection(undefined) } @@ -332,7 +250,6 @@ export default function AddNFTCollectionForm({ async function handleSelectFromWallet() { try { setWalletConnecting(true) - if (!connected) { if (wallet) await wallet.connect() } @@ -340,49 +257,7 @@ export default function AddNFTCollectionForm({ throw new Error('No valid wallet connected') } - const ownedNfts = await deprecated.Metadata.findDataByOwner( - connection.current, - wallet.publicKey - ) - console.log('NFT wallet contents', ownedNfts) - const verfiedNfts = filterAndMapVerifiedCollections(ownedNfts) - console.log('NFT verified nft by collection', verfiedNfts) - - const verifiedCollections = {} - for (const collectionKey in verfiedNfts) { - const collectionInfo = await enrichCollectionInfo( - connection.current, - collectionKey - ) - const nftsWithInfo = await Promise.all( - verfiedNfts[collectionKey].slice(0, 2).map((nft) => { - return enrichItemInfo(nft.data, nft.data.uri) - }) - ) - - verifiedCollections[collectionKey] = { - ...collectionInfo, - nfts: nftsWithInfo, - } - } - - console.log( - 'NFT verified collection metadata with nfts', - verifiedCollections - ) - if (Object.keys(verifiedCollections).length === 0) { - setError( - 'collectionInput', - { - type: 'error', - message: 'Current wallet has no verified collection', - }, - { shouldFocus: true } - ) - } else { - setCollectionsInWallet(verifiedCollections) - setIsModalOpen(true) - } + setIsModalOpen(true) setWalletConnecting(false) } catch (error) { setWalletConnecting(false) @@ -400,19 +275,24 @@ export default function AddNFTCollectionForm({ onSubmit={handleSubmit(serializeValues)} data-testid="add-nft-collection-form" > - setIsModalOpen(false)} - walletPk={wallet?.publicKey} - collections={collectionsInWallet} - onSelect={({ key, collection }) => { - if (key && collection) { - handleClearSelectedNFT(true) - setValue('collectionKey', key) - setSelectedNFTCollection(collection) - } - }} - /> + {isModalOpen && ( + setIsModalOpen(false)} + onSelect={({ key, collection }) => { + if (key && collection) { + handleClearSelectedNFT(true) + setValue('collectionKey', collection.id) + // const enhancedCollection = transitToNFT(collection) + // const nfts = collection.nfts.map((nft) => transitToNFT(nft)) + // setSelectedNFTCollection({ ...enhancedCollection, nfts }) + setSelectedNFTCollection(collection) + } + }} + /> + )} - {!unverifiedCollection && ( + {collectionVerificationState === 'none' && (
Getting collection data ) : ( - {!selectedNFTCollection?.name ? ( + {!selectedNFTCollection?.content.metadata.name ? ( 'Select a collection to preview...' ) : ( <> @@ -512,7 +397,7 @@ export default function AddNFTCollectionForm({ )}
- {!selectedNFTCollection?.name ? ( + {!selectedNFTCollection?.content.metadata.name ? ( ) : (
@@ -522,8 +407,8 @@ export default function AddNFTCollectionForm({ .map((nft, index) => { return ( collection item
- {selectedNFTCollection?.name || + {selectedNFTCollection?.content.metadata.name || '(Collection has no name)'} diff --git a/components/NewRealmWizard/components/steps/BasicDetailsForm.tsx b/components/NewRealmWizard/components/steps/BasicDetailsForm.tsx index 43ff4c4a34..2ed7a5fbd3 100644 --- a/components/NewRealmWizard/components/steps/BasicDetailsForm.tsx +++ b/components/NewRealmWizard/components/steps/BasicDetailsForm.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react' -import { useForm, Controller } from 'react-hook-form' +import { useForm, Controller, useWatch } from 'react-hook-form' import { yupResolver } from '@hookform/resolvers/yup' import * as yup from 'yup' @@ -14,6 +14,8 @@ import { DEFAULT_GOVERNANCE_PROGRAM_ID } from '@components/instructions/tools' import { updateUserInput, validateSolAddress } from '@utils/formValidation' import { FORM_NAME as MUTISIG_FORM } from 'pages/realms/new/multisig' +import { useProgramVersionByIdQuery } from '@hooks/queries/useProgramVersionQuery' +import { PublicKey } from '@solana/web3.js' export const BasicDetailsSchema = { avatar: yup.string(), @@ -42,6 +44,16 @@ export default function BasicDetailsForm({ totalSteps, onSubmit, onPrevClick, +}: { + // TODO type me + type: any + formData: BasicDetails + currentStep: any + totalSteps: any + // eslint-disable-next-line @typescript-eslint/ban-types + onSubmit: Function + // eslint-disable-next-line @typescript-eslint/ban-types + onPrevClick: Function }) { const schema = yup.object(BasicDetailsSchema).required() const { @@ -54,8 +66,16 @@ export default function BasicDetailsForm({ resolver: yupResolver(schema), }) + const programIdInput = useWatch({ name: 'programId', control }) + const validProgramId = + programIdInput && validateSolAddress(programIdInput) + ? new PublicKey(programIdInput) + : undefined + const programVersionQuery = useProgramVersionByIdQuery(validProgramId) + useEffect(() => { updateUserInput(formData, BasicDetailsSchema, setValue) + // 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 }, []) function serializeValues(values) { @@ -116,6 +136,20 @@ export default function BasicDetailsForm({ data-testid="programId-input" error={errors.programId?.message || ''} autoComplete="on" + success={ + !programVersionQuery.isLoading && + programVersionQuery.data !== 1 + ? `Program version ${programVersionQuery.data}` + : undefined + } + warning={ + !programVersionQuery.isLoading && + programVersionQuery.data === 1 + ? 'Program version could not be verified' + : programVersionQuery.isFetching + ? 'Fetching program version...' + : undefined + } {...field} /> diff --git a/components/NewRealmWizard/components/steps/CommunityTokenDetailsForm.tsx b/components/NewRealmWizard/components/steps/CommunityTokenDetailsForm.tsx index 4d29400db9..7e917e561c 100644 --- a/components/NewRealmWizard/components/steps/CommunityTokenDetailsForm.tsx +++ b/components/NewRealmWizard/components/steps/CommunityTokenDetailsForm.tsx @@ -11,8 +11,14 @@ import FormField from '@components/NewRealmWizard/components/FormField' import FormFooter from '@components/NewRealmWizard/components/FormFooter' import AdvancedOptionsDropdown from '@components/NewRealmWizard/components/AdvancedOptionsDropdown' import Input, { RadioGroup } from '@components/NewRealmWizard/components/Input' +import { CogIcon, ExternalLinkIcon } from '@heroicons/react/outline' + import { GenericTokenIcon } from '@components/NewRealmWizard/components/TokenInfoTable' import TokenInput, { TokenWithMintInfo, COMMUNITY_TOKEN } from '../TokenInput' +import { getCoefficients } from '../../../../actions/addPlugins/addQVPlugin' +import { useConnection } from '@solana/wallet-adapter-react' +import { PublicKey } from '@solana/web3.js' +import CivicPassSelector from '../CivicPassSelector' export const CommunityTokenSchema = { useExistingCommunityToken: yup @@ -44,11 +50,8 @@ export const CommunityTokenSchema = { .number() .positive('Must be greater than 0') .transform((value) => (isNaN(value) ? undefined : value)) - .when(['suggestedMinTokenAmount', 'useExistingCommunityToken'], { - is: (suggestedMinTokenAmount, useExistingCommunityToken) => { - if (useExistingCommunityToken === false) return false - return suggestedMinTokenAmount > 0 - }, + .when('useExistingCommunityToken', { + is: false, then: (schema) => schema.required('Required'), otherwise: (schema) => schema.optional(), }), @@ -57,6 +60,17 @@ export const CommunityTokenSchema = { .positive('Must be greater than 0') .max(1, 'Must not be greater than 1') .transform((value) => (isNaN(value) ? undefined : value)), + useSupplyFactor: yup + .boolean() + .oneOf( + [true, false], + 'You must specify what type of max voter weight you want to use.' + ) + .required('Required'), + communityAbsoluteMaxVoteWeight: yup + .number() + .positive('Must be greater than 0') + .transform((value) => (isNaN(value) ? undefined : value)), } export interface CommunityToken { @@ -65,6 +79,13 @@ export interface CommunityToken { transferCommunityMintAuthority?: boolean minimumNumberOfCommunityTokensToGovern?: number communityMintSupplyFactor?: number + isQuadratic?: boolean + coefficientA: number + coefficientB: number + coefficientC: number + civicPass: string + useSupplyFactor: boolean + communityAbsoluteMaxVoteWeight?: number } export default function CommunityTokenForm({ @@ -76,35 +97,76 @@ export default function CommunityTokenForm({ onPrevClick, }) { const schema = yup.object(CommunityTokenSchema).required() + const { connection } = useConnection() + const { watch, control, setValue, handleSubmit, formState: { isValid }, - } = useForm({ + } = useForm({ + // @asktree: I set default values here in order to eliminate a bug where a value was only being set as a side effect of opening advanced options + defaultValues: { + useSupplyFactor: true, + isQuadratic: false, + coefficientA: 1000, + coefficientB: 0, + coefficientC: 0, + }, mode: 'all', resolver: yupResolver(schema), }) const useExistingCommunityToken = watch('useExistingCommunityToken') + const communityTokenMintAddress = watch('communityTokenMintAddress') + const useSupplyFactor = watch('useSupplyFactor') + const isQuadratic = watch('isQuadratic') + const coefficientA = watch('coefficientA') + const coefficientB = watch('coefficientB') + const coefficientC = watch('coefficientC') const [communityTokenInfo, setCommunityTokenInfo] = useState< TokenWithMintInfo | undefined >() + useEffect(() => { + const fetchCoefficients = async () => { + const coefficients = await getCoefficients( + undefined, + new PublicKey(communityTokenMintAddress), + connection + ) + setValue('coefficientA', coefficients[0].toFixed(2)) + setValue('coefficientB', coefficients[1]) + setValue('coefficientC', coefficients[2]) + } + + // If the user wants to use a pre-existing token, we need to adjust the coefficients ot match the decimals of that token + if (communityTokenMintAddress) { + fetchCoefficients() + } + }, [connection, communityTokenMintAddress, setValue]) + useEffect(() => { updateUserInput(formData, CommunityTokenSchema, setValue) - }, []) + }, [formData, setValue]) useEffect(() => { if (!useExistingCommunityToken) { setValue('communityTokenMintAddress', undefined) + // @asktree: it seems wrong that this would be a form value at all given that it has no corresponding user input. setValue('suggestedMinTokenAmount', undefined) setValue('minimumNumberOfCommunityTokensToGovern', undefined) setValue('transferCommunityMintAuthority', undefined, { shouldValidate: true, }) } - }, [useExistingCommunityToken]) + }, [setValue, useExistingCommunityToken]) + + useEffect(() => { + if (useSupplyFactor) { + setValue('communityAbsoluteMaxVoteWeight', undefined) + } else setValue('communityMintSupplyFactor', undefined) + }, [setValue, useSupplyFactor]) function handleTokenInput({ suggestedMinTokenAmount, tokenInfo }) { setCommunityTokenInfo(tokenInfo) @@ -126,7 +188,7 @@ export default function CommunityTokenForm({ const data = { transferCommunityMintAuthority: null, minimumNumberOfCommunityTokensToGovern: null, - communityMintSupplyFactor: null, + // communityMintSupplyFactor: null, ...values, } if (values.useExistingCommunityToken) { @@ -137,6 +199,17 @@ export default function CommunityTokenForm({ data.communityTokenInfo = null } + if (useSupplyFactor) { + data.communityMintSupplyFactor = + values.communityMintSupplyFactor === undefined + ? null + : values.communityMintSupplyFactor + } else + data.communityAbsoluteMaxVoteWeight = + values.communityAbsoluteMaxVoteWeight === undefined + ? null + : values.communityAbsoluteMaxVoteWeight + onSubmit({ step: currentStep, data }) } @@ -156,8 +229,7 @@ export default function CommunityTokenForm({ name="useExistingCommunityToken" control={control} defaultValue={undefined} - // eslint-disable-next-line @typescript-eslint/no-unused-vars - render={({ field: { ref, ...field } }) => ( + render={({ field: { ref: _, ...field } }) => (
)} -
- {useExistingCommunityToken === false && ( - + {useExistingCommunityToken === false && ( ( )} /> - - )} - {useExistingCommunityToken && ( - + )} +
+ + + ( +
+ + + +
+ )} + /> + {useSupplyFactor === false && ( + ( + + } + data-testid="programId-input" + error={error?.message || ''} + {...field} + onChange={(ev) => { + preventNegativeNumberInput(ev) + field.onChange(ev) + }} + /> + + )} + /> + )} + {useSupplyFactor && ( ( + {isQuadratic &&
+
+ Note:  + Quadratic Voting DAOs typically have a lower circulating supply factor + than non-quadratic DAOs. This is because the quadratic formula + reduces the weight of votes overall. +
+
+ Consider optionally setting a value < 1 here to increase the accuracy of approval thresholds. +
+
} )} /> -
- )} + )} + + ( +
+ + + +
+ )} + /> + + {isQuadratic && ( + + } + > +
+

+ Changes advised for advanced users only +

+
+ ( + +
+ +
+
+ )} + /> + + +
+

See Docs

+ + + +
+
+
+ ( + + { + preventNegativeNumberInput(ev) + field.onChange(ev) + }} + /> + + )} + /> + ( + + { + preventNegativeNumberInput(ev) + field.onChange(ev) + }} + /> + + )} + /> + ( + + { + preventNegativeNumberInput(ev) + field.onChange(ev) + }} + /> + + )} + /> +
+
+ )} + s) + const current = useWalletOnePointOh() const userAddress = current?.publicKey?.toBase58() const inputElement = useRef(null) const [inviteList, setInviteList] = useState([]) @@ -182,6 +182,7 @@ export default function InviteMembersForm({ // go to next step: serializeValues({ memberAddresses: 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 }, [formData]) useEffect(() => { @@ -189,6 +190,7 @@ export default function InviteMembersForm({ shouldValidate: true, shouldDirty: true, }) + // 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 }, [inviteList]) // The user can get to this screen without connecting their wallet. If they @@ -202,6 +204,7 @@ export default function InviteMembersForm({ ) { setInviteList((currentList) => currentList.concat(userAddress)) } + // 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 }, [userAddress]) function serializeValues(values) { diff --git a/components/NewRealmWizard/components/steps/YesVotePercentageThresholdForm.tsx b/components/NewRealmWizard/components/steps/YesVotePercentageThresholdForm.tsx index 8cc37e0293..b2d5b013d5 100644 --- a/components/NewRealmWizard/components/steps/YesVotePercentageThresholdForm.tsx +++ b/components/NewRealmWizard/components/steps/YesVotePercentageThresholdForm.tsx @@ -31,15 +31,16 @@ export const CouncilYesVotePercentageSchema = { .number() .transform((value) => (isNaN(value) ? 0 : value)) .max(100, 'Approval cannot require more than 100% of votes') - .when('$memberAddresses', (memberAddresses, schema) => { - if (memberAddresses) { - return schema - .min(1, 'Quorum must be at least 1% of member') - .required('Required') - } else { - return schema.min(1, 'Quorum must be at least 1% of member') + .min(1, 'Quorum must be at least 1% of member') + .when( + ['$_programVersion', '$addCouncil'], + // @ts-expect-error yup types are wrong https://github.com/jquense/yup/issues/649 + (_programVersion, addCouncil, schema) => { + if (_programVersion >= 3 && addCouncil) { + return schema.required('Council yes threshold is required') + } } - }), + ), } export interface CouncilYesVotePercentage { @@ -55,6 +56,7 @@ export default function YesVotePercentageForm({ forCommunity = false, onSubmit, onPrevClick, + title, }) { const schema = yup .object( @@ -79,7 +81,8 @@ export default function YesVotePercentageForm({ : forCouncil ? 'councilYesVotePercentage' : 'yesVotePercentage' - const yesVotePercentage = watch(fieldName) || 0 + const percentageValue = !formData.isQuadratic || !forCommunity ? 60 : 5 + const yesVotePercentage = watch(fieldName) || percentageValue useEffect(() => { updateUserInput( @@ -89,12 +92,16 @@ export default function YesVotePercentageForm({ : CouncilYesVotePercentageSchema, setValue ) - }, []) + }, [forCommunity, formData, setValue]) function serializeValues(values) { onSubmit({ step: currentStep, data: values }) } + useEffect(() => { + setValue(fieldName, percentageValue) + }, [fieldName, formData.isQuadratic, percentageValue, setValue]) + return (
( - + )} /> @@ -143,8 +144,9 @@ export default function YesVotePercentageForm({ > {forCommunity ? ( - Typically, newer DAOs start their community approval quorums around - 60% of total token supply. + {!formData.isQuadratic + ? 'Typically, newer DAOs start their community approval quorums around 60% of total token supply.' + : "Setting a high percentage approval quorum may result in proposals never passing in a quadratic voting DAO, as the voting power is influenced by token distribution. It's recomended to start with a low percentage and adjust as needed."} ) : forCouncil && formData?.memberAddresses?.length >= 0 ? ( <> diff --git a/components/NftVotingCountingModal.tsx b/components/NftVotingCountingModal.tsx index 681d2ca6ba..64d3375c5d 100644 --- a/components/NftVotingCountingModal.tsx +++ b/components/NftVotingCountingModal.tsx @@ -1,12 +1,12 @@ +import { useVotingNfts } from '@hooks/queries/plugins/nftVoter' import { usePrevious } from '@hooks/usePrevious' -import { NftVoterClient } from '@solana/governance-program-library' +import useUserOrDelegator from '@hooks/useUserOrDelegator' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' import useNftProposalStore from 'NftVotePlugin/NftProposalStore' -import useNftPluginStore from 'NftVotePlugin/store/nftPluginStore' import { useEffect, useState } from 'react' import useTransactionsStore from 'stores/useTransactionStore' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import useWalletStore from 'stores/useWalletStore' import Modal from './Modal' +import {useNftClient} from "../VoterWeightPlugins/useNftClient"; const NftVotingCountingModal = () => { const votingInProgress = useNftProposalStore((s) => s.votingInProgress) @@ -21,19 +21,18 @@ const NftVotingComponent = () => { countedNftsForProposal, proposal, } = useNftProposalStore() - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const wallet = useWalletStore((s) => s.current) - const { votingNfts } = useNftPluginStore((s) => s.state) + const wallet = useWalletOnePointOh() + const userPk = useUserOrDelegator() + const votingNfts = useVotingNfts(userPk) ?? [] const votingInProgress = useNftProposalStore((s) => s.votingInProgress) const usedNfts = countedNftsForProposal.length - const totalVotingPower = votingNfts.length + const totalVotingPower = votingNfts.length // TODO this is sometimes incorrect, power per nft is determined by config const remainingNftsToCount = totalVotingPower - usedNfts //in last tx there is max of 5 nfts const lastTransactionNftsCount = 5 const maxNftsPerTransaction = 8 + const { nftClient } = useNftClient() const [usedNftsCount, setUsedNftsCount] = useState(0) const [remainingVotingPower, setRemainingVotingPower] = useState(0) const handleCalcCountedNfts = (val: number) => { @@ -47,7 +46,8 @@ const NftVotingComponent = () => { }, [usedNfts, remainingNftsToCount]) useEffect(() => { - const multiplier = processedTransactions - prevProcessedTransactions + const multiplier = + processedTransactions - (prevProcessedTransactions as number) if (processedTransactions !== 0) { if (remainingVotingPower <= lastTransactionNftsCount) { handleCalcCountedNfts(remainingVotingPower) @@ -69,6 +69,7 @@ const NftVotingComponent = () => { ) } } + // 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 }, [processedTransactions]) return votingInProgress ? ( @@ -79,7 +80,7 @@ const NftVotingComponent = () => { wrapperStyle={{ top: '-350px' }} onClose={() => closeNftVotingCountingModal( - client.client as NftVoterClient, + nftClient!, proposal!, wallet!.publicKey! ) diff --git a/components/NotifiIcon.tsx b/components/NotifiIcon.tsx deleted file mode 100644 index 6883c5f639..0000000000 --- a/components/NotifiIcon.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { useTheme } from 'next-themes' -import NotifiIconDark from './NotificationsSwitch/NotifiIconDark' -import NotifiIconLight from './NotificationsSwitch/NotifiIconLight' - -const NotifiIcon = ({ height = '30' }) => { - const { theme } = useTheme() - return theme === 'Dark' ? ( - - ) : ( - - ) -} - -export default NotifiIcon diff --git a/components/NotificationsCard/NotifiFullLogo.tsx b/components/NotificationsCard/NotifiFullLogo.tsx deleted file mode 100644 index b97ddc2c9b..0000000000 --- a/components/NotificationsCard/NotifiFullLogo.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { useTheme } from 'next-themes' -import NotifiLogoFullDark from './NotifiLogoFullDark' -import NotifiLogoFullLight from './NotifiLogoFullLight ' - -const NotifiFullLogo = ({ height = '23', width = '340' }) => { - const { theme } = useTheme() - return theme === 'Dark' ? ( - - ) : ( - - ) -} - -export default NotifiFullLogo diff --git a/components/NotificationsCard/NotifiLogoFullDark.tsx b/components/NotificationsCard/NotifiLogoFullDark.tsx deleted file mode 100644 index 0022f6eabd..0000000000 --- a/components/NotificationsCard/NotifiLogoFullDark.tsx +++ /dev/null @@ -1,63 +0,0 @@ -const NotifiIconDark = ({ height = '40', width = '340' }) => { - return ( - - - - - - - - - - - - - - - - - ) -} - -export default NotifiIconDark diff --git a/components/NotificationsCard/NotifiLogoFullLight .tsx b/components/NotificationsCard/NotifiLogoFullLight .tsx deleted file mode 100644 index 93066a6eeb..0000000000 --- a/components/NotificationsCard/NotifiLogoFullLight .tsx +++ /dev/null @@ -1,63 +0,0 @@ -const NotifiIconDark = ({ height = '50', width = '340' }) => { - return ( - - - - - - - - - - - - - - - - - ) -} - -export default NotifiIconDark diff --git a/components/NotificationsCard/NotifiLogoLightLong.svg b/components/NotificationsCard/NotifiLogoLightLong.svg deleted file mode 100644 index e5edd54c09..0000000000 --- a/components/NotificationsCard/NotifiLogoLightLong.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/components/NotificationsCard/NotifiPreviewCard.tsx b/components/NotificationsCard/NotifiPreviewCard.tsx deleted file mode 100644 index 92ebe782af..0000000000 --- a/components/NotificationsCard/NotifiPreviewCard.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import Switch from './NotifiSwitch' -import { XIcon } from '@heroicons/react/solid' -import { Source, useNotifiClient } from '@notifi-network/notifi-react-hooks' -import React, { - FunctionComponent, - useCallback, - useEffect, - useMemo, - useState, -} from 'react' - -import NotifiFullLogo from './NotifiFullLogo' -type NotifiClientReturnType = ReturnType - -type NotifiPreviewCardProps = { - onClick: () => void - onClose: () => void - telegramEnabled: boolean - email: string - phoneNumber: string - telegram: string - handleDelete: (source: Source) => Promise -} & Pick - -const NotifiPreviewCard: FunctionComponent = ({ - createAlert, - data, - email, - handleDelete, - onClose, - onClick, - phoneNumber, - telegram, - telegramEnabled, - isAuthenticated, -}) => { - const alerts = data?.alerts - const sources = data?.sources - const [isLoading, setLoading] = useState(false) - - const handleEdit = useCallback(() => { - onClick() - }, [onClick]) - - useEffect(() => { - if (!isAuthenticated) { - onClick() - } - }, [isAuthenticated]) - - const handleUnsubscribe = useCallback( - async (source: Source) => { - if (isLoading) { - return - } - handleDelete(source) - }, - [handleDelete, isLoading] - ) - - useEffect(() => { - if (!isAuthenticated) { - onClick() - } - }, [isAuthenticated]) - - const handleSubscribe = useCallback( - async (source: Source) => { - if (isLoading) { - return - } - - if (!source) { - throw new Error('No source provided') - } - const filterId = source.applicableFilters[0].id - - if (!filterId) { - throw new Error('No filter id found') - } - try { - setLoading(true) - const alertResult = await createAlert({ - emailAddress: email === '' ? null : email, - filterId: filterId ?? '', - name: `${source.name} notification`, - phoneNumber: phoneNumber === '' ? null : phoneNumber, - sourceId: source.id ?? '', - telegramId: telegram === '' ? null : telegram, - }) - - if (alertResult) { - if (alertResult.targetGroup?.telegramTargets?.length > 0) { - const target = alertResult.targetGroup?.telegramTargets[0] - if (target && !target.isConfirmed) { - if (target.confirmationUrl) { - window.open(target.confirmationUrl) - } - } - } - } - setLoading(false) - } catch (e) { - throw new Error(e) - } - }, - [createAlert, email, phoneNumber, telegram, isLoading] - ) - - const daoNotifications = useMemo( - () => (source: Source) => { - const handleClick = (source: Source) => { - isChecked ? handleUnsubscribe(source) : handleSubscribe(source) - } - const sourceId = source.id - - const isChecked = Boolean( - alerts?.some((alert) => - alert.sourceGroup.sources.some((source) => source.id === sourceId) - ) - ) - - return ( -
-
- {source.name} Notifications On -
-
- handleClick(source)} /> -
-
- ) - }, - [alerts, handleDelete, handleSubscribe] - ) - - const notificationsToggle = useMemo( - () => - sources - ?.map((source) => { - if (source.type === 'DIRECT_PUSH') { - return - } - return daoNotifications(source) - }) - ?.filter((source) => source), - [daoNotifications, sources] - ) - - return ( -
-
-
-

Notifications

- -
-

{email}

-

{phoneNumber}

- {telegramEnabled &&

{telegram}

} -
- Edit Information -
-
- {notificationsToggle && notificationsToggle.length >= 1 ? ( -
- {notificationsToggle} -
- ) : null} -
-
-

Powered by

- - - -
- -
-
- ) -} - -export default NotifiPreviewCard diff --git a/components/NotificationsCard/NotifiSwitch.tsx b/components/NotificationsCard/NotifiSwitch.tsx deleted file mode 100644 index 1ad9adf671..0000000000 --- a/components/NotificationsCard/NotifiSwitch.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { FunctionComponent } from 'react' - -interface SwitchProps { - checked: boolean - onChange: (x: boolean) => void -} - -const Switch: FunctionComponent = ({ - checked = false, - onChange, -}) => { - const handleClick = () => { - onChange(!checked) - } - - return ( -
- -
- ) -} - -export default Switch diff --git a/components/NotificationsCard/NotifiTextLight.tsx b/components/NotificationsCard/NotifiTextLight.tsx deleted file mode 100644 index 04769ab6c6..0000000000 --- a/components/NotificationsCard/NotifiTextLight.tsx +++ /dev/null @@ -1,34 +0,0 @@ -const NotifiIconDark = ({ height, width }) => { - return ( - - - - - - - - ) -} - -export default NotifiIconDark diff --git a/components/NotificationsCard/NotificationCardContainer.tsx b/components/NotificationsCard/NotificationCardContainer.tsx deleted file mode 100644 index 26856a2e1e..0000000000 --- a/components/NotificationsCard/NotificationCardContainer.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import NotificationsCard from '@components/NotificationsCard' -import NotifiPreviewCard from '@components/NotificationsCard/NotifiPreviewCard' -import { EndpointTypes } from '@models/types' -import { - BlockchainEnvironment, - Source, - useNotifiClient, -} from '@notifi-network/notifi-react-hooks' -import { firstOrNull } from '@utils/helpers' -import { useRouter } from 'next/router' -import { useCallback, useEffect, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' - -type Props = { - onClose: () => void - onBackClick: () => void -} - -const NotificationCardContainer: React.FC = ({ - onClose, - onBackClick, -}) => { - const [showPreview, setPreview] = useState(true) - const router = useRouter() - - const { cluster } = router.query - - const endpoint = cluster ? (cluster as EndpointTypes) : 'mainnet' - const wallet = useWalletStore((s) => s.current) - const connected = useWalletStore((s) => s.connected) - let env = BlockchainEnvironment.MainNetBeta - - switch (endpoint) { - case 'mainnet': - break - case 'devnet': - env = BlockchainEnvironment.DevNet - break - case 'localnet': - env = BlockchainEnvironment.LocalNet - break - } - const notifiClient = useNotifiClient({ - dappAddress: 'solanarealmsdao', - env, - walletPublicKey: wallet?.publicKey?.toString() ?? '', - }) - - const { - data, - isAuthenticated, - getConfiguration, - deleteAlert, - isInitialized, - } = notifiClient - - const [email, setEmail] = useState('') - const [phoneNumber, setPhone] = useState('') - const [telegram, setTelegram] = useState('') - const [telegramEnabled, setTelegramEnabled] = useState(false) - - useEffect(() => { - const targetGroup = firstOrNull(data?.targetGroups) - if (targetGroup) { - setEmail(firstOrNull(targetGroup?.emailTargets)?.emailAddress ?? '') - setPhone(firstOrNull(targetGroup?.smsTargets)?.phoneNumber ?? '') - setTelegram(firstOrNull(targetGroup?.telegramTargets)?.telegramId ?? '') - } else { - setEmail(firstOrNull(data?.emailTargets)?.emailAddress ?? '') - setPhone(firstOrNull(data?.smsTargets)?.phoneNumber ?? '') - setTelegram(firstOrNull(data?.telegramTargets)?.telegramId ?? '') - } - }, [data]) - - const updateTelegramSupported = useCallback(async () => { - const { supportedTargetTypes } = await getConfiguration() - const telegram = supportedTargetTypes.find( - (targetType) => targetType === 'TELEGRAM' - ) - setTelegramEnabled(telegram !== undefined) - }, [getConfiguration, setTelegramEnabled]) - - useEffect(() => { - updateTelegramSupported().catch((e) => { - console.error('Failed to get supported type information: ', e) - }) - }, [updateTelegramSupported]) - - useEffect(() => { - if (isAuthenticated && connected && isInitialized) { - const targetGroup = firstOrNull(data?.targetGroups) - - if (targetGroup) { - setEmail(firstOrNull(targetGroup?.emailTargets)?.emailAddress ?? '') - setPhone(firstOrNull(targetGroup?.smsTargets)?.phoneNumber ?? '') - setTelegram(firstOrNull(targetGroup?.telegramTargets)?.telegramId ?? '') - } else { - setEmail(firstOrNull(data?.emailTargets)?.emailAddress ?? '') - setPhone(firstOrNull(data?.smsTargets)?.phoneNumber ?? '') - setTelegram(firstOrNull(data?.telegramTargets)?.telegramId ?? '') - } - } - - // Handles when the alerts.length is the same as sources - if (data?.alerts && data.alerts.length === data?.sources.length) { - if (email || phoneNumber || telegram) { - setPreview(true) - } - } - }, [ - connected, - data, - email, - isAuthenticated, - setPreview, - isInitialized, - phoneNumber, - telegram, - ]) - - const handleDelete = useCallback( - async (source: Source) => { - try { - if (data?.alerts) { - const sourceId = source.id - const alertToDelete = data.alerts?.find((alert) => - alert.sourceGroup.sources.find((source) => source.id === sourceId) - ) - - alertToDelete?.id && - (await deleteAlert({ - alertId: alertToDelete.id, - keepSourceGroup: true, - keepTargetGroup: true, - })) - } - } catch (e) { - throw new Error(e) - } - }, - [data?.alerts, deleteAlert] - ) - - return ( -
-
-
- {!isInitialized && ( -
-
-
-
-
-
-
-
-
-
-
-
-
-
- )} - {showPreview && isInitialized && ( - setPreview(false)} - /> - )} - {!showPreview && isInitialized && ( - - )} -
-
-
- ) -} - -export default NotificationCardContainer diff --git a/components/NotificationsCard/PhoneInput.tsx b/components/NotificationsCard/PhoneInput.tsx deleted file mode 100644 index 0b78a6eae0..0000000000 --- a/components/NotificationsCard/PhoneInput.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import Input from '@components/inputs/Input' -import { Listbox, Transition } from '@headlessui/react' -import { ChatAltIcon, ChevronDownIcon } from '@heroicons/react/outline' -import { isValidPhoneNumber } from 'libphonenumber-js' -import { Dispatch, SetStateAction } from 'react' -import { Fragment, useCallback, useEffect, useState } from 'react' - -import { InputRow } from '.' -import { countryMap } from './data' -import { splitPhoneNumber } from './phoneUtils' - -type Props = { - handlePhone: (input: string) => void - phoneNumber: string - setErrorMessage: Dispatch> -} - -const PhoneInput = ({ handlePhone, phoneNumber, setErrorMessage }: Props) => { - const [selectedCountryCode, setCountryCode] = useState('US') - const [dialCode, setDialCode] = useState('+1') - const [baseNumber, setBaseNumber] = useState('') - - const selectCountryHandler = useCallback( - (value: string) => { - setCountryCode(value) - const dialCode = countryMap[value].dialCode - setDialCode(dialCode) - - const input = baseNumber !== '' ? dialCode + baseNumber : '' - handlePhone(input) - }, - [baseNumber, handlePhone] - ) - - const splitPhoneNumbers = useCallback( - (phoneNumber: string) => { - const { baseNumber, countryCode } = splitPhoneNumber(phoneNumber) - if (!countryCode || !baseNumber) { - setErrorMessage('Improper phone, please try again') - } - setBaseNumber(baseNumber) - setCountryCode(countryCode) - }, - [setErrorMessage] - ) - - useEffect(() => { - if (phoneNumber && isValidPhoneNumber(phoneNumber)) { - splitPhoneNumbers(phoneNumber) - } - }, [phoneNumber, splitPhoneNumbers, isValidPhoneNumber]) - - const onChange = useCallback( - (event: React.ChangeEvent) => { - const onlyNumberInput = event.target.value.replace(/[^\d]/g, '') - - setBaseNumber(onlyNumberInput) - const input = onlyNumberInput !== '' ? dialCode + onlyNumberInput : '' - handlePhone(input) - }, - [dialCode, handlePhone] - ) - - const validatePhoneNumber = () => { - if (!isValidPhoneNumber(phoneNumber) && phoneNumber !== '') { - setErrorMessage('You have entered an invalid number') - } - } - - return ( - - } - label="phone" - > - setErrorMessage('')} - onBlur={validatePhoneNumber} - placeholder="XXX-XXX-XXXX" - type="tel" - value={baseNumber} - /> -
- -
- - {dialCode} - - - - - - {Object.entries(countryMap).map( - ([countryCode, countryMetadata], idx) => { - const { dialCode, flag, name } = countryMetadata - return ( - - `relative cursor-default select-none py-2 pl-2 pr-4 z-20 ${ - active - ? 'bg-gray-800 text-grey-300' - : 'text-gray-300' - }` - } - key={idx} - value={countryCode} - > - {({ selected }) => ( - <> - -
-
- {flag} - {name} -
-
{dialCode}
-
-
- - )} -
- ) - } - )} -
-
-
-
-
-
- ) -} - -export default PhoneInput diff --git a/components/NotificationsCard/data.tsx b/components/NotificationsCard/data.tsx deleted file mode 100644 index 7e3c3d0a41..0000000000 --- a/components/NotificationsCard/data.tsx +++ /dev/null @@ -1,138 +0,0 @@ -/* eslint-disable sort-keys */ -export type CountryMetadata = { - name: string - dialCode: string - flag: string -} - -type CountryMap = { - [countryCode: string]: CountryMetadata -} - -export const countryMap: CountryMap = { - US: { - dialCode: '+1', - flag: '🇺🇸', - name: 'United States', - }, - AU: { - dialCode: '+61', - flag: '🇦🇺', - name: 'Australia', - }, - AT: { - dialCode: '+43', - flag: '🇦🇹', - name: 'Austria', - }, - BE: { - dialCode: '+32', - flag: '🇧🇪', - name: 'Belgium', - }, - BR: { - dialCode: '+55', - flag: '🇧🇷', - name: 'Brazil', - }, - CA: { - dialCode: '+1', - flag: '🇨🇦', - name: 'Canada', - }, - DK: { - dialCode: '+45', - flag: '🇩🇰', - name: 'Denmark', - }, - FI: { - dialCode: '+358', - flag: '🇫🇮', - name: 'Finland', - }, - FR: { - dialCode: '+33', - flag: '🇫🇷', - name: 'France', - }, - DE: { - dialCode: '+49', - flag: '🇩🇪', - name: 'Germany', - }, - HK: { - dialCode: '+852', - flag: '🇭🇰', - name: 'Hong Kong', - }, - HU: { - dialCode: '+36', - flag: '🇭🇺', - name: 'Hungary', - }, - IS: { - dialCode: '+354', - flag: '🇮🇸', - name: 'Iceland', - }, - MY: { - dialCode: '+60', - flag: '🇲🇾', - name: 'Malaysia', - }, - NO: { - dialCode: '+47', - flag: '🇳🇴', - name: 'Norway', - }, - PH: { - dialCode: '+63', - flag: '🇵🇭', - name: 'Philippines', - }, - PL: { - dialCode: '+48', - flag: '🇵🇱', - name: 'Poland', - }, - PT: { - dialCode: '+351', - flag: '🇵🇹', - name: 'Portugal', - }, - SG: { - dialCode: '+65', - flag: '🇸🇬', - name: 'Singapore', - }, - KR: { - dialCode: '+82', - flag: '🇰🇷', - name: 'Korea, Republic of South Korea', - }, - ES: { - dialCode: '+34', - flag: '🇪🇸', - name: 'Spain', - }, - SE: { - dialCode: '+46', - flag: '🇸🇪', - name: 'Sweden', - }, - CH: { - dialCode: '+41', - flag: '🇨🇭', - name: 'Switzerland', - }, - TW: { - dialCode: '+886', - flag: '🇹🇼', - name: 'Taiwan', - }, - GB: { - dialCode: '+44', - flag: '🇬🇧', - name: 'United Kingdom', - }, -} diff --git a/components/NotificationsCard/index.tsx b/components/NotificationsCard/index.tsx deleted file mode 100644 index 847c63c082..0000000000 --- a/components/NotificationsCard/index.tsx +++ /dev/null @@ -1,438 +0,0 @@ -import { - ArrowLeftIcon, - MailIcon, - PaperAirplaneIcon, -} from '@heroicons/react/solid' -import { - Alert, - GqlError, - MessageSigner, - useNotifiClient, -} from '@notifi-network/notifi-react-hooks' -import { firstOrNull } from '@utils/helpers' -import { isValidPhoneNumber } from 'libphonenumber-js' -import React, { - Dispatch, - FunctionComponent, - SetStateAction, - useEffect, - useState, -} from 'react' -import { useCallback } from 'react' - -import useWalletStore from '../../stores/useWalletStore' -import Button from '../Button' -import Input from '../inputs/Input' -import NotifiFullLogo from './NotifiFullLogo' -import PhoneInput from './PhoneInput' - -type NotifiClientReturnType = ReturnType - -type NotificationCardProps = { - onBackClick: () => void - email: string - - phoneNumber: string - telegram: string - setPreview: Dispatch> - setEmail: Dispatch> - setTelegram: Dispatch> - setPhone: Dispatch> -} & Pick< - NotifiClientReturnType, - | 'createAlert' - | 'logIn' - | 'fetchData' - | 'data' - | 'isAuthenticated' - | 'updateAlert' - | 'getConfiguration' -> - -const NotificationsCard = ({ - createAlert, - data, - email, - getConfiguration, - isAuthenticated, - logIn, - onBackClick, - phoneNumber, - setEmail, - setPhone, - setPreview, - setTelegram, - telegram, - updateAlert, -}: NotificationCardProps) => { - const [isLoading, setLoading] = useState(false) - const [hasUnsavedChanges, setUnsavedChanges] = useState(false) - const [errorMessage, setErrorMessage] = useState('') - const [telegramEnabled, setTelegramEnabled] = useState(false) - - const wallet = useWalletStore((s) => s.current) - const connected = useWalletStore((s) => s.connected) - - const alerts = data?.alerts - const sources = data?.sources - - const [localEmail, setLocalEmail] = useState('') - const [localPhoneNumber, setLocalPhone] = useState('') - const [localTelegram, setLocalTelegram] = useState('') - - const updateTelegramSupported = useCallback(async () => { - const { supportedTargetTypes } = await getConfiguration() - const telegram = supportedTargetTypes.find((it) => it === 'TELEGRAM') - setTelegramEnabled(telegram !== undefined) - }, [getConfiguration, setTelegramEnabled]) - - useEffect(() => { - updateTelegramSupported().catch((e) => { - console.error('Failed to get supported type information: ', e) - }) - }, [updateTelegramSupported]) - - useEffect(() => { - const targetGroup = firstOrNull(data?.targetGroups) - - if (email || telegram || phoneNumber) { - setLocalEmail(email ?? '') - setLocalTelegram(telegram ?? '') - setLocalPhone(phoneNumber ?? '') - setUnsavedChanges(true) - } else if (targetGroup) { - setLocalEmail(firstOrNull(targetGroup?.emailTargets)?.emailAddress ?? '') - setLocalPhone(firstOrNull(targetGroup?.smsTargets)?.phoneNumber ?? '') - setLocalTelegram( - firstOrNull(targetGroup?.telegramTargets)?.telegramId ?? '' - ) - setUnsavedChanges(true) - } else { - setLocalEmail(firstOrNull(data?.emailTargets)?.emailAddress ?? '') - setLocalPhone(firstOrNull(data?.smsTargets)?.phoneNumber ?? '') - setLocalTelegram(firstOrNull(data?.telegramTargets)?.telegramId ?? '') - setUnsavedChanges(true) - } - }, [ - data, - data?.emailTargets, - data?.smsTargets, - data?.telegramTargets, - email, - phoneNumber, - telegram, - ]) - - const checkTelegramUnconfirmed = useCallback((alertsResponse: Alert[]) => { - const hasTelegramAlert = alertsResponse.find( - (alert) => alert.targetGroup.telegramTargets.length >= 0 - ) - const target = hasTelegramAlert?.targetGroup.telegramTargets[0] - - if (target && !target.isConfirmed) { - if (target.confirmationUrl) { - window.open(target.confirmationUrl) - } - } - - return alertsResponse.some((alertResponse) => - alertResponse.targetGroup.telegramTargets.some( - (target) => !target.isConfirmed - ) - ) - }, []) - - const handleError = (errors: { message: string }[]) => { - const error = errors.length > 0 ? errors[0] : null - if (error instanceof GqlError) { - setErrorMessage( - `${error.message}: ${error.getErrorMessages().join(', ')}` - ) - } else { - setErrorMessage(error?.message ?? 'Unknown error') - } - setLoading(false) - } - - const handleRefresh = useCallback( - async function () { - setLoading(true) - setErrorMessage('') - // user is not authenticated - if (!isAuthenticated && wallet && wallet.publicKey) { - try { - await logIn((wallet as unknown) as MessageSigner) - } catch (e) { - handleError([e]) - } - setLoading(false) - } - setLoading(false) - }, - [setLoading, isAuthenticated, wallet, setErrorMessage, logIn] - ) - - const handleSave = useCallback(async () => { - setLoading(true) - if (!isAuthenticated && wallet && wallet.publicKey) { - try { - await logIn((wallet as unknown) as MessageSigner) - setUnsavedChanges(true) - } catch (e) { - handleError([e]) - } - } - if (connected && isAuthenticated) { - try { - if (alerts && alerts.length >= 1) { - const results: Alert[] = [] - - for (const alert of alerts) { - const alertRes = await updateAlert({ - alertId: alert.id ?? '', - emailAddress: localEmail === '' ? null : localEmail, - phoneNumber: isValidPhoneNumber(localPhoneNumber) - ? localPhoneNumber - : null, - telegramId: localTelegram === '' ? null : localTelegram, - }) - if (alertRes) { - results.push(alertRes) - } - } - if (results) { - setEmail( - results[0].targetGroup?.emailTargets[0]?.emailAddress ?? '' - ) - setPhone(results[0].targetGroup?.smsTargets[0]?.phoneNumber ?? '') - setTelegram( - results[0].targetGroup?.telegramTargets[0]?.telegramId ?? '' - ) - setPreview(true) - } - checkTelegramUnconfirmed(results) - if (results) { - setPreview(true) - } - } else { - const results: Alert[] = [] - if (sources && sources.length >= 1) { - for (const source of sources) { - const filterId = source.applicableFilters[0].id - const alertRes = await createAlert({ - emailAddress: localEmail === '' ? null : localEmail, - filterId: filterId ?? '', - name: `${source.name} notification`, - phoneNumber: isValidPhoneNumber(localPhoneNumber) - ? localPhoneNumber - : null, - sourceId: source?.id ?? '', - telegramId: localTelegram === '' ? null : localTelegram, - }) - if (alertRes) { - results.push(alertRes) - } - } - } - if (telegram) { - checkTelegramUnconfirmed(results) - } - if (results && results.length >= 1) { - setPreview(true) - setEmail( - results[0].targetGroup?.emailTargets[0]?.emailAddress ?? '' - ) - setPhone(results[0].targetGroup?.smsTargets[0]?.phoneNumber ?? '') - setTelegram( - results[0].targetGroup?.telegramTargets[0]?.telegramId ?? '' - ) - } - } - setUnsavedChanges(false) - } catch (e) { - handleError([e]) - } - } - setLoading(false) - }, [ - alerts, - checkTelegramUnconfirmed, - connected, - createAlert, - isAuthenticated, - localEmail, - localPhoneNumber, - localTelegram, - logIn, - setEmail, - setPhone, - setPreview, - setTelegram, - sources, - telegram, - updateAlert, - wallet, - ]) - - const handleEmail = (e: React.ChangeEvent) => { - setLocalEmail(e.target.value) - setUnsavedChanges(true) - } - - const handlePhone = (input: string) => { - setLocalPhone(input) - setUnsavedChanges(true) - } - - const handleTelegram = (e: React.ChangeEvent) => { - setLocalTelegram(e.target.value) - setUnsavedChanges(true) - } - - const disabled = - (isAuthenticated && !hasUnsavedChanges) || - (localEmail === '' && localTelegram === '' && localPhoneNumber === '') || - errorMessage !== '' - - return ( -
-
- - -
- {!connected ? ( - <> -
- Connect wallet to see options -
- - ) : ( - <> -
- Get notifications for proposals, voting, and results. Add your email - address, phone number, and/or Telegram. -
-
- {errorMessage.length > 0 ? ( -
{errorMessage}
- ) : ( - !isAuthenticated && ( -
- When prompted, sign the transaction. -
- ) - )} -
-
- - } - label="email" - > - - - - {telegramEnabled && ( - - } - label="Telegram" - > - - - )} -
-
-
- Already Subscribed?{' '} - - Click here to load your alert details. - -
-
-
- - - -
- - )} -
- ) -} - -interface InputRowProps { - label: string - icon: React.ReactNode -} - -export const InputRow: FunctionComponent = ({ - children, - icon, - label, -}) => { - return ( - - ) -} - -export default NotificationsCard diff --git a/components/NotificationsCard/phoneUtils.tsx b/components/NotificationsCard/phoneUtils.tsx deleted file mode 100644 index c746c519ce..0000000000 --- a/components/NotificationsCard/phoneUtils.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { parsePhoneNumber } from 'libphonenumber-js' - -type PhoneData = { - countryCode: string - baseNumber: string -} - -export const splitPhoneNumber = (phoneNumber: string): PhoneData => { - const { country: countryCode, nationalNumber: baseNumber } = parsePhoneNumber( - phoneNumber - ) - if (!countryCode || !baseNumber) { - throw new Error('No country or phone found') - } - - return { baseNumber, countryCode } -} - -export const formatPhoneNumber = (phoneNumber: string) => { - if (!phoneNumber) { - throw new Error('No phone data found!') - } - - return parsePhoneNumber(phoneNumber) - .formatInternational() - .replaceAll(' ', '-') -} diff --git a/components/NotificationsSwitch/NotifiIconDark.tsx b/components/NotificationsSwitch/NotifiIconDark.tsx deleted file mode 100644 index 7e18a4ff2e..0000000000 --- a/components/NotificationsSwitch/NotifiIconDark.tsx +++ /dev/null @@ -1,37 +0,0 @@ -const NotifiIconDark = ({ height, width }) => { - return ( - - - - - - - - - - - ) -} - -export default NotifiIconDark diff --git a/components/NotificationsSwitch/NotifiIconLight.tsx b/components/NotificationsSwitch/NotifiIconLight.tsx deleted file mode 100644 index cfdf44e1cf..0000000000 --- a/components/NotificationsSwitch/NotifiIconLight.tsx +++ /dev/null @@ -1,37 +0,0 @@ -const NotifiIconLight = ({ height, width }) => { - return ( - - - - - - - - - - - ) -} - -export default NotifiIconLight diff --git a/components/NotificationsSwitch/TelegramIcon.tsx b/components/NotificationsSwitch/TelegramIcon.tsx deleted file mode 100644 index 7661c4f62f..0000000000 --- a/components/NotificationsSwitch/TelegramIcon.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import * as React from 'react' -import { SVGProps } from 'react' - -const SvgComponent = (props: SVGProps) => ( - - - -) - -export default SvgComponent diff --git a/components/NotificationsSwitch/index.tsx b/components/NotificationsSwitch/index.tsx deleted file mode 100644 index 8a134c2372..0000000000 --- a/components/NotificationsSwitch/index.tsx +++ /dev/null @@ -1,210 +0,0 @@ -import Button from '@components/Button' -import NotifiIcon from '@components/NotifiIcon' -import { defaultVariables } from '@dialectlabs/react-ui' -import styled from '@emotion/styled' -import { Transition } from '@headlessui/react' -import { DeviceMobileIcon } from '@heroicons/react/outline' -import { BellIcon, KeyIcon, MailIcon } from '@heroicons/react/solid' - -import { useEffect, useRef, useState } from 'react' -import useNotificationStore, { ModalStates } from 'stores/useNotificationStore' - -import DialectNotificationsModal from '@components/DialectNotificationsModal' -import NotificationCardContainer from '@components/NotificationsCard/NotificationCardContainer' -import TelegramIcon from './TelegramIcon' - -export function useOutsideAlerter( - ref: React.MutableRefObject, - bellRef: React.MutableRefObject, - setOpen: CallableFunction -) { - useEffect(() => { - /** - * Alert if clicked on outside of element - */ - function handleClickOutside(event: MouseEvent) { - if ( - ref.current && - !ref?.current.contains(event.target as Element) && - bellRef.current && - !bellRef?.current.contains(event.target as Element) - ) { - setOpen(false) - } - } - - // Bind the event listener - document.addEventListener('mousedown', handleClickOutside) - return () => { - // Unbind the event listener on clean up - document.removeEventListener('mousedown', handleClickOutside) - } - }, [ref, bellRef, setOpen]) -} - -const TagToIcon = { - Email: , - NotifiCenter: , - Telegram: , - Text: , - Wallet: , -} - -type ChannelType = 'Wallet' | 'Email' | 'Text' | 'Telegram' | 'Notifi Center' - -interface NotificationSolutionType { - name: string - channels: ChannelType[] - description: string - modalState: ModalStates -} - -const NotificationSolutions: NotificationSolutionType[] = [ - { - channels: ['Wallet', 'Email', 'Text', 'Telegram'], - description: `Get notifications when new proposals are created & when proposals are completed or canceled. By wallet, email, Telegram or text message.`, - modalState: ModalStates.Dialect, - name: 'Dialect', - }, - { - channels: ['Email', 'Text', 'Telegram', 'Notifi Center'], - description: ` - Get notifications for proposals, voting, and results. Add your email address, phone number, and/or Telegram.`, - modalState: ModalStates.Notifi, - name: 'notifi', - }, -] - -export default function NotificationsSwitch() { - const { modalState, set: setNotificationStore } = useNotificationStore( - (s) => s - ) - - const wrapperRef = useRef(null) - const bellRef = useRef(null) - const [openModal, setOpenModal] = useState(false) - useOutsideAlerter(wrapperRef, bellRef, setOpenModal) - - const StyledChannelName = styled.span` - font-size: 0.8rem; - white-space: nowrap; - ` - - const removeSpaces = (str: string): string => { - return str.split(' ').join('') - } - - const formatName = (str: string): string => { - return str[0].toUpperCase() + str.substring(1) - } - - const Tag = ({ channelName }: { channelName: ChannelType }) => { - return ( - -
- {TagToIcon[removeSpaces(channelName)]} - {channelName} -
-
- ) - } - - const NotificationBox = ({ - channels, - description, - modalState, - name, - }: NotificationSolutionType) => ( -
-
-
- {name === 'notifi' && } -

{name}

-
-
- {channels.map((channel) => ( - - ))} -
- -
-
-

{description}

-
-
- -
- -
-
-
- ) - - const DialectBellIcon = defaultVariables.dark.icons.bell - - return ( -
- - {modalState === ModalStates.Selection && ( -
-
-

Realms Notifications

- {NotificationSolutions.map((solution) => ( - - ))} -
-
- )} - - {modalState === ModalStates.Dialect && ( - { - setOpenModal(false) - }} - onBackClick={() => - setNotificationStore((state) => { - state.modalState = ModalStates.Selection - }) - } - /> - )} - {modalState === ModalStates.Notifi && ( - setOpenModal(!openModal)} - onBackClick={() => - setNotificationStore((state) => { - state.modalState = ModalStates.Selection - }) - } - /> - )} -
- -
- ) -} diff --git a/components/PageBodyContainer.tsx b/components/PageBodyContainer.tsx index 363c3c7dcc..5f3ee13697 100644 --- a/components/PageBodyContainer.tsx +++ b/components/PageBodyContainer.tsx @@ -1,24 +1,33 @@ import { useRouter } from 'next/router' import Footer from '@components/Footer' +import {PluginDebug} from "../VoterWeightPlugins/lib/PluginDebug"; +import React from "react"; const PageBodyContainer = ({ children }) => { - const { pathname } = useRouter() + const { pathname, query } = useRouter() const isNewRealmsWizard = /\/realms\/new\/\w+/.test(pathname) + // TODO TEMP DEBUG - REMOVE BEFORE MERGE + if ( + query['debug'] !== undefined + ) { + return + } + return ( <>
-
+
-
+
{children}
diff --git a/components/Profile/Profile.tsx b/components/Profile/Profile.tsx index 6e34386dc9..396259e1d0 100644 --- a/components/Profile/Profile.tsx +++ b/components/Profile/Profile.tsx @@ -3,7 +3,7 @@ import { useProfile, ProfileImage } from '@components/Profile' import { PublicKey } from '@solana/web3.js' import { LoadingDots } from '@components/Loading' import { CivicIcon } from '@components/icons' -import useWalletStore from '../../stores/useWalletStore' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' const VisitLink: FC<{ address: PublicKey }> = ({ address }) => ( = ({ type Props = { publicKey?: PublicKey; expanded?: boolean } export const Profile: FC = ({ publicKey, expanded }) => { - const connectedWallet = useWalletStore((s) => s.current) + const connectedWallet = useWalletOnePointOh() const { profile, loading } = useProfile(publicKey) if (!profile && loading) return diff --git a/components/Profile/ProfileImage.tsx b/components/Profile/ProfileImage.tsx index edfe21f66c..0c96e872cc 100644 --- a/components/Profile/ProfileImage.tsx +++ b/components/Profile/ProfileImage.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react' -import { useProfile } from '@components/Profile' +import { useProfile } from '@components/Profile/useProfile' import ImgWithLoader from '@components/ImgWithLoader' import { PublicKey } from '@solana/web3.js' import { LoadingDots } from '@components/Loading' @@ -25,14 +25,30 @@ export const ProfileImage: FC = ({ publicKey, expanded, className }) => { if (!profile && loading) return // No civic profile - show placeholder - if (!profile || !profile.image) return + if (!profile || !profile.image) { + return + + + } // Show civic profile image with loader as image loads return ( - + + + ) } diff --git a/components/Profile/ProfileName.tsx b/components/Profile/ProfileName.tsx new file mode 100644 index 0000000000..75c5be6f9e --- /dev/null +++ b/components/Profile/ProfileName.tsx @@ -0,0 +1,40 @@ +import React, { FC } from 'react' +import { useProfile } from '@components/Profile/useProfile'; +import { PublicKey } from '@solana/web3.js'; +import ContentLoader from "react-content-loader"; +import {ShortAddress} from "@components/Profile/ShortAddress"; + +type Props = { publicKey?: PublicKey, height?: string; + width?: string; + dark?: boolean; + style?: React.CSSProperties; } +export const ProfileName: FC = ({ publicKey, height = "13", + width = "300", + dark = false, + style, }) => { + const { profile, loading } = useProfile(publicKey) + + + if (!publicKey) return <>; + return loading ? ( +
+ + + +
+ ) : ( +
+ {profile?.name?.value || } +
+ ); +} diff --git a/components/Profile/ShortAddress.tsx b/components/Profile/ShortAddress.tsx new file mode 100644 index 0000000000..4a4d4ec5ec --- /dev/null +++ b/components/Profile/ShortAddress.tsx @@ -0,0 +1,16 @@ +import {PublicKey} from "@solana/web3.js"; +import React, {FC} from "react"; +import {shortenAddress} from "@utils/address"; + +export const ShortAddress:FC<{address: PublicKey | undefined }> = ({address}) => { + if (!address) return <>; + return ( + + {shortenAddress(address.toString())} + + ); +}; \ No newline at end of file diff --git a/components/Profile/index.ts b/components/Profile/index.ts index 5bd5bc1ddb..906312443d 100644 --- a/components/Profile/index.ts +++ b/components/Profile/index.ts @@ -1,4 +1,5 @@ export { Profile } from './Profile' export { ProfilePopup } from './ProfilePopup' export { ProfileImage } from './ProfileImage' +export { ProfileName } from './ProfileName' export { useProfile } from './useProfile' diff --git a/components/Profile/useProfile.ts b/components/Profile/useProfile.ts index 0118fd2c8f..a2b1acbe92 100644 --- a/components/Profile/useProfile.ts +++ b/components/Profile/useProfile.ts @@ -1,48 +1,39 @@ -import { useEffect, useState } from 'react' -import { Connection, PublicKey } from '@solana/web3.js' +import { PublicKey } from '@solana/web3.js' import { CivicProfile, Profile as BaseProfile } from '@civic/profile' -import useWalletStore from 'stores/useWalletStore' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { useQuery } from '@tanstack/react-query' type Profile = BaseProfile & { exists: boolean } -const getProfile = async ( - publicKey: PublicKey, - connection?: Connection -): Promise => - CivicProfile.get(publicKey.toBase58(), { - solana: { - connection, - }, - }) - const profileIsSet = (profile: BaseProfile): boolean => !!profile.name || !!profile.image || !!profile.headline export const useProfile = ( publicKey?: PublicKey ): { profile: Profile | undefined; loading: boolean } => { - const connection = useWalletStore((s) => s.connection) - const connectedWallet = useWalletStore((s) => s.current) - const [profile, setProfile] = useState() - const [loading, setLoading] = useState(true) + const connection = useLegacyConnectionContext() + const connectedWallet = useWalletOnePointOh() const profileWalletPublicKey = publicKey || connectedWallet?.publicKey + const options = connection + ? { solana: { connection: connection?.current } } + : undefined - useEffect(() => { - if (profileWalletPublicKey) { - getProfile(profileWalletPublicKey, connection?.current).then( - (profile) => { - setProfile({ - ...profile, - exists: profileIsSet(profile), - }) - setLoading(false) - } - ) + const { data: profile, isLoading } = useQuery( + ['Civic Profile', profileWalletPublicKey?.toBase58() + 'Civic'], + // @ts-ignore we won't run this if there is no profileWalletPublicKey + () => CivicProfile.get(profileWalletPublicKey?.toBase58(), options), + { + enabled: !!profileWalletPublicKey, // Only run query if profileWalletPublicKey is available + select: (data) => ({ + ...data, + exists: profileIsSet(data), + }), } - }, [publicKey, connectedWallet?.publicKey, connection.current]) + ) - return { profile, loading } + return { profile, loading: isLoading } } diff --git a/components/ProposalActions.tsx b/components/ProposalActions.tsx index b46f51f6e4..71085a4d26 100644 --- a/components/ProposalActions.tsx +++ b/components/ProposalActions.tsx @@ -1,12 +1,12 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { useEffect, useState } from 'react' import { useHasVoteTimeExpired } from '../hooks/useHasVoteTimeExpired' import useRealm from '../hooks/useRealm' import { getSignatoryRecordAddress, ProposalState, + serializeInstructionToBase64, + SignatoryRecord, } from '@solana/spl-governance' -import useWalletStore from '../stores/useWalletStore' import Button, { SecondaryButton } from './Button' import { RpcContext } from '@solana/spl-governance' @@ -17,44 +17,89 @@ import { Proposal } from '@solana/spl-governance' import { ProgramAccount } from '@solana/spl-governance' import { cancelProposal } from 'actions/cancelProposal' import { getProgramVersionForRealm } from '@models/registry/api' -import useNftPluginStore from 'NftVotePlugin/store/nftPluginStore' +import dayjs from 'dayjs' +import { diffTime } from './ProposalRemainingVotingTime' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { + proposalQueryKeys, + useRouteProposalQuery, +} from '@hooks/queries/proposal' +import { useProposalGovernanceQuery } from '@hooks/useProposal' +import { useTokenOwnerRecordByPubkeyQuery } from '@hooks/queries/tokenOwnerRecord' +import { useAsync } from 'react-async-hook' +import { useGovernanceAccountByPubkeyQuery } from '@hooks/queries/governanceAccount' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import queryClient from '@hooks/queries/queryClient' +import useCreateProposal from '@hooks/useCreateProposal' +import { useSelectedProposalTransactions } from '@hooks/queries/proposalTransaction' +import { InstructionDataWithHoldUpTime } from 'actions/createProposal' +import { TransactionInstruction } from '@solana/web3.js' +import useQueryContext from '@hooks/useQueryContext' +import { useRouter } from 'next/router' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' const ProposalActionsPanel = () => { - const { governance, proposal, proposalOwner } = useWalletStore( - (s) => s.selectedProposal - ) + const { propose } = useCreateProposal() + const { fmtUrlWithCluster } = useQueryContext() + const router = useRouter() const { realmInfo } = useRealm() - const wallet = useWalletStore((s) => s.current) - const connected = useWalletStore((s) => s.connected) + const proposal = useRouteProposalQuery().data?.result + const { data: transactions } = useSelectedProposalTransactions() + const governance = useProposalGovernanceQuery().data?.result + const proposalOwner = useTokenOwnerRecordByPubkeyQuery( + proposal?.account.tokenOwnerRecord + ).data?.result + + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected const hasVoteTimeExpired = useHasVoteTimeExpired(governance, proposal!) - const signatories = useWalletStore((s) => s.selectedProposal.signatories) - const connection = useWalletStore((s) => s.connection) - const refetchProposals = useWalletStore((s) => s.actions.refetchProposals) - const [signatoryRecord, setSignatoryRecord] = useState(undefined) - const maxVoterWeight = - useNftPluginStore((s) => s.state.maxVoteRecord)?.pubkey || undefined + const connection = useLegacyConnectionContext() + + // TODO check the kind to be passed + const { maxVoterWeightPk } = useRealmVoterWeightPlugins() + const canFinalizeVote = hasVoteTimeExpired && proposal?.account.state === ProposalState.Voting + const now = new Date().getTime() / 1000 // unix timestamp in seconds + const mainVotingEndedAt = proposal?.account.signingOffAt + ?.addn(governance?.account.config.baseVotingTime || 0) + .toNumber() - const walletPk = wallet?.publicKey + const votingCoolOffTime = governance?.account.config.votingCoolOffTime || 0 + const canFinalizeAt = mainVotingEndedAt + ? mainVotingEndedAt + votingCoolOffTime + : mainVotingEndedAt - useEffect(() => { - const setup = async () => { - if (proposal && realmInfo && walletPk) { - const signatoryRecordPk = await getSignatoryRecordAddress( - realmInfo.programId, - proposal.pubkey, - walletPk - ) + const canFinalizeNow = canFinalizeAt ? canFinalizeAt <= now : true + const endOfProposalAndCoolOffTime = canFinalizeAt + ? dayjs(1000 * canFinalizeAt!) + : undefined + const coolOffTimeLeft = endOfProposalAndCoolOffTime + ? diffTime(false, dayjs(), endOfProposalAndCoolOffTime) + : undefined - if (signatoryRecordPk && signatories) { - setSignatoryRecord(signatories[signatoryRecordPk.toBase58()]) - } - } - } + const walletPk = wallet?.publicKey - setup() - }, [proposal, realmInfo, walletPk]) + const { result: signatoryRecordPk } = useAsync( + async () => + realmInfo === undefined || + proposal === undefined || + walletPk === undefined || + walletPk === null + ? undefined + : getSignatoryRecordAddress( + realmInfo.programId, + proposal.pubkey, + walletPk + ), + [realmInfo, proposal, walletPk] + ) + + const signatoryRecord = useGovernanceAccountByPubkeyQuery( + SignatoryRecord, + 'SignatoryRecord', + signatoryRecordPk + ).data?.result const canSignOff = signatoryRecord && @@ -72,6 +117,13 @@ const ProposalActionsPanel = () => { wallet.publicKey ) + const canRepropose = + proposal && + governance && + proposalOwner && + wallet?.publicKey && + ProposalState.Defeated === proposal?.account.state + const signOffTooltipContent = !connected ? 'Connect your wallet to sign off this proposal' : !signatoryRecord @@ -106,7 +158,7 @@ const ProposalActionsPanel = () => { : '' const handleFinalizeVote = async () => { try { - if (proposal && realmInfo && governance) { + if (proposal && realmInfo && governance && proposalOwner) { const rpcContext = new RpcContext( proposal.owner, getProgramVersionForRealm(realmInfo), @@ -119,10 +171,13 @@ const ProposalActionsPanel = () => { rpcContext, governance?.account.realm, proposal, - maxVoterWeight + maxVoterWeightPk, + proposalOwner ) - await refetchProposals() } + queryClient.invalidateQueries({ + queryKey: proposalQueryKeys.all(connection.endpoint), + }) } catch (error) { notify({ type: 'error', @@ -136,7 +191,7 @@ const ProposalActionsPanel = () => { const handleSignOffProposal = async () => { try { - if (proposal && realmInfo) { + if (proposal && realmInfo && signatoryRecord) { const rpcContext = new RpcContext( proposal.owner, getProgramVersionForRealm(realmInfo), @@ -151,9 +206,10 @@ const ProposalActionsPanel = () => { proposal, signatoryRecord ) - - await refetchProposals() } + queryClient.invalidateQueries({ + queryKey: proposalQueryKeys.all(connection.endpoint), + }) } catch (error) { notify({ type: 'error', @@ -168,7 +224,7 @@ const ProposalActionsPanel = () => { proposal: ProgramAccount | undefined ) => { try { - if (proposal && realmInfo) { + if (proposal && realmInfo && proposalOwner) { const rpcContext = new RpcContext( proposal.owner, getProgramVersionForRealm(realmInfo), @@ -177,10 +233,16 @@ const ProposalActionsPanel = () => { connection.endpoint ) - await cancelProposal(rpcContext, realmInfo.realmId, proposal) - - await refetchProposals() + await cancelProposal( + rpcContext, + realmInfo.realmId, + proposal, + proposalOwner + ) } + queryClient.invalidateQueries({ + queryKey: proposalQueryKeys.all(connection.endpoint), + }) } catch (error) { notify({ type: 'error', @@ -191,14 +253,77 @@ const ProposalActionsPanel = () => { console.error('error cancelling proposal', error) } } + + const handleRepropose = async () => { + try { + if (proposal && realmInfo) { + const proposalAddress = await propose({ + title: proposal.account.name, + description: proposal.account.descriptionLink, + voteByCouncil: + !realmInfo.communityMint || + !proposal.account.governingTokenMint.equals( + realmInfo.communityMint + ), + instructionsData: transactions + ? [ + ...transactions.flatMap((tx) => + tx.account.getAllInstructions().map( + (inst) => + new InstructionDataWithHoldUpTime({ + instruction: { + serializedInstruction: serializeInstructionToBase64( + new TransactionInstruction({ + keys: inst.accounts, + programId: inst.programId, + data: Buffer.from(inst.data), + }) + ), + isValid: true, + governance: undefined, + customHoldUpTime: tx.account.holdUpTime, + chunkBy: 1, + }, + }) + ) + ), + ] + : [], + governance: proposal.account.governance, + }) + const url = fmtUrlWithCluster( + `/dao/${router.query.symbol}/proposal/${proposalAddress}` + ) + router.push(url) + } + queryClient.invalidateQueries({ + queryKey: proposalQueryKeys.all(connection.endpoint), + }) + } catch (error) { + notify({ + type: 'error', + message: `Error: Could not sign off proposal.`, + description: `${error}`, + }) + + console.error('error sign off', error) + } + } return ( <> {ProposalState.Cancelled === proposal?.account.state || ProposalState.Succeeded === proposal?.account.state || - ProposalState.Defeated === proposal?.account.state || - (!canCancelProposal && !canSignOff && !canFinalizeVote) ? null : ( + (!canCancelProposal && + !canSignOff && + !canFinalizeVote && + !canRepropose) ? null : (
+ {canRepropose && ( + + )} {canSignOff && ( + <> + + {!canFinalizeNow && coolOffTimeLeft && ( +
+ Cool Off Time: {coolOffTimeLeft.days}d   + {coolOffTimeLeft.hours}h   + {coolOffTimeLeft.minutes}m +
+ )} + )}
diff --git a/components/ProposalCard.tsx b/components/ProposalCard.tsx index 8a24a96bbb..f093a3f737 100644 --- a/components/ProposalCard.tsx +++ b/components/ProposalCard.tsx @@ -1,9 +1,9 @@ import styled from '@emotion/styled' import { ChevronRightIcon } from '@heroicons/react/solid' -import ProposalStateBadge from './ProposalStatusBadge' +import ProposalStateBadge from './ProposalStateBadge' import Link from 'next/link' -import { Proposal, ProposalState } from '@solana/spl-governance' -import ApprovalQuorum from './ApprovalQuorum' +import { GovernanceAccountType, Proposal, ProposalState, VoteType } from '@solana/spl-governance' +import { ApprovalProgress, VetoProgress } from './QuorumProgress' import useRealm from '../hooks/useRealm' import useProposalVotes from '../hooks/useProposalVotes' import ProposalTimeStatus from './ProposalTimeStatus' @@ -12,6 +12,7 @@ import ProposalMyVoteBadge from '../components/ProposalMyVoteBadge' import useQueryContext from '../hooks/useQueryContext' import { PublicKey } from '@solana/web3.js' import VoteResults from './VoteResults' +import MultiChoiceVotes from './MultiChoiceVotes' type ProposalCardProps = { proposalPk: PublicKey @@ -31,7 +32,9 @@ const StyledCardWrapper = styled.div` const ProposalCard = ({ proposalPk, proposal }: ProposalCardProps) => { const { symbol } = useRealm() const { fmtUrlWithCluster } = useQueryContext() - const { yesVoteProgress, yesVotesRequired } = useProposalVotes(proposal) + const votesData = useProposalVotes(proposal) + const isMulti = proposal.voteType !== VoteType.SINGLE_CHOICE + && proposal.accountType === GovernanceAccountType.ProposalV2 return (
@@ -48,31 +51,52 @@ const ProposalCard = ({ proposalPk, proposal }: ProposalCardProps) => { {proposal.name}

- {proposal.state === ProposalState.Voting && ( - - )} +
- {proposal.state === ProposalState.Voting && ( -
-
+ {proposal.state === ProposalState.Voting ? + isMulti ? +
+ +
+ : + (
+
-
- +
+
-
- )} + {votesData._programVersion !== undefined && + // @asktree: here is some typescript gore because typescript doesn't know that a number being > 3 means it isn't 1 or 2 + votesData._programVersion !== 1 && + votesData._programVersion !== 2 && + votesData.veto !== undefined && + (votesData.veto.voteProgress ?? 0) > 0 ? ( + <> +
+ +
+ +
+ + ) : undefined} +
) + : ""} diff --git a/components/ProposalExecutionCard.tsx b/components/ProposalExecutionCard.tsx index d15dc4f855..a12d6ed12f 100644 --- a/components/ProposalExecutionCard.tsx +++ b/components/ProposalExecutionCard.tsx @@ -1,4 +1,3 @@ -import { ProgramAccount, ProposalTransaction } from '@solana/spl-governance' import classNames from 'classnames' import { useEffect, useState, useRef } from 'react' import dayjs from 'dayjs' @@ -8,76 +7,69 @@ import { ExecuteAllInstructionButton, PlayState, } from '@components/instructions/ExecuteAllInstructionButton' -import useProposal from '@hooks/useProposal' import { ntext } from '@utils/ntext' import Button from '@components/Button' import { diffTime } from '@components/ProposalRemainingVotingTime' - -function parseTransactions( - transactions: ProgramAccount[] -) { - const executed: ProgramAccount[] = [] - const ready: ProgramAccount[] = [] - const notReady: ProgramAccount[] = [] - let minHoldUpTime: number | null = null - - for (const transaction of transactions) { - const holdUpTime = transaction.account.holdUpTime - - if (transaction.account.executedAt) { - executed.push(transaction) - } else if (!holdUpTime || holdUpTime <= 0) { - ready.push(transaction) - } else { - notReady.push(transaction) - - if (holdUpTime) { - if (minHoldUpTime === null || holdUpTime < minHoldUpTime) { - minHoldUpTime = holdUpTime - } - } - } - } - - return { executed, ready, notReady, minHoldUpTime } -} +import useProposalTransactions from '@hooks/useProposalTransactions' +import { useRouteProposalQuery } from '@hooks/queries/proposal' +import { useSelectedProposalTransactions } from '@hooks/queries/proposalTransaction' interface Props { className?: string } export default function ProposalExecutionCard(props: Props) { - const { instructions, proposal } = useProposal() + const proposal = useRouteProposalQuery().data?.result + const { data: allTransactions } = useSelectedProposalTransactions() const [playState, setPlayState] = useState(PlayState.Unplayed) const [timeLeft, setTimeLeft] = useState< undefined | ReturnType >() const timer = useRef() - - const allTransactions = Object.values(instructions) - const { executed, ready, notReady, minHoldUpTime } = parseTransactions( - allTransactions + const proposalTransactions = useProposalTransactions( + allTransactions, + proposal ) useEffect(() => { - if (typeof window !== 'undefined' && minHoldUpTime) { + if ( + typeof window !== 'undefined' && + proposalTransactions && + proposalTransactions.nextExecuteAt + ) { timer.current = window.setInterval(() => { - const end = dayjs(1000 * (dayjs().unix() + minHoldUpTime)) + const end = dayjs(1000 * proposalTransactions.nextExecuteAt!) setTimeLeft(diffTime(false, dayjs(), end)) }, 1000) } return () => clearInterval(timer.current) - }, [minHoldUpTime]) + // 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 + }, [proposalTransactions?.nextExecuteAt]) if ( + allTransactions === undefined || allTransactions.length === 0 || !proposal || - allTransactions.length === executed.length + !proposalTransactions || + allTransactions.length === proposalTransactions.executed.length ) { return null } + const { ready, notReady, executed, nextExecuteAt } = proposalTransactions + + //Temp solutions for execution of small instructions in one tx until other instructions are not + //rewrite to handle tx separation it self + const isOneTx = () => { + if (!ready || !ready.length || ready.length !== 2) { + return false + } + return true + } + + const executeAllInOneTx = isOneTx() ? true : false + return (

- {minHoldUpTime !== null + {nextExecuteAt !== null ? 'Execution Hold Up Time' : 'Execute Proposal'}

@@ -114,6 +106,7 @@ export default function ProposalExecutionCard(props: Props) { setPlaying={setPlayState} small={false} proposalInstructions={ready} + multiTransactionMode={!executeAllInOneTx} /> ) : (
+ )} diff --git a/components/ProposalMyVoteBadge.tsx b/components/ProposalMyVoteBadge.tsx index 38ed4a42f7..4a32432c4b 100644 --- a/components/ProposalMyVoteBadge.tsx +++ b/components/ProposalMyVoteBadge.tsx @@ -1,50 +1,13 @@ -import { - Proposal, - ProgramAccount, - VoteRecord, - Realm, -} from '@solana/spl-governance' +import { Proposal, ProgramAccount, VoteType, GovernanceAccountType } from '@solana/spl-governance' import classNames from 'classnames' import { ThumbUpIcon, ThumbDownIcon } from '@heroicons/react/solid' - import { isYesVote } from '@models/voteRecords' -import useRealm from '@hooks/useRealm' -import useWalletStore from '../stores/useWalletStore' import Tooltip from './Tooltip' - -interface VoteRecords { - [proposal: string]: ProgramAccount -} - -export function getOwnVoteRecord( - communityDelegateVoteRecords: VoteRecords, - councilDelegateVoteRecords: VoteRecords, - ownVoteRecords: VoteRecords, - proposal: Omit, 'owner'>, - realm?: ProgramAccount -): ProgramAccount | undefined { - const proposalKey = proposal.pubkey.toBase58() - const councilDelegateVote = councilDelegateVoteRecords[proposalKey] - const communityDelegateVote = communityDelegateVoteRecords[proposalKey] - const ownRecord = ownVoteRecords[proposalKey] - const governingTokenMint = proposal.account.governingTokenMint.toBase58() - - if ( - councilDelegateVote && - governingTokenMint === realm?.account?.config?.councilMint?.toBase58() - ) { - return councilDelegateVote - } - - if ( - communityDelegateVote && - governingTokenMint === realm?.account?.communityMint.toBase58() - ) { - return communityDelegateVote - } - - return ownRecord -} +import { useRealmQuery } from '@hooks/queries/realm' +import { useAddressQuery_VoteRecord } from '@hooks/queries/addresses/voteRecord' +import { useAddressQuery_TokenOwnerRecord } from '@hooks/queries/addresses/tokenOwnerRecord' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useVoteRecordByPubkeyQuery } from '@hooks/queries/voteRecord' interface Props { className?: string @@ -52,31 +15,31 @@ interface Props { } export default function ProposalMyVoteBadge(props: Props) { - const { realm } = useRealm() - const communityDelegateVoteRecords = useWalletStore( - (s) => s.communityDelegateVoteRecordsByProposal - ) - const councilDelegateVoteRecords = useWalletStore( - (s) => s.councilDelegateVoteRecordsByProposal - ) - const ownVoteRecords = useWalletStore((s) => s.ownVoteRecordsByProposal) + const realm = useRealmQuery().data?.result + const wallet = useWalletOnePointOh() + const isMulti = props.proposal.account.voteType !== VoteType.SINGLE_CHOICE + && props.proposal.account.accountType === GovernanceAccountType.ProposalV2 - const ownVoteRecord = getOwnVoteRecord( - communityDelegateVoteRecords, - councilDelegateVoteRecords, - ownVoteRecords, - props.proposal, - realm + const { data: tokenOwnerRecordPk } = useAddressQuery_TokenOwnerRecord( + realm?.owner, + realm?.pubkey, + props.proposal.account.governingTokenMint, + wallet?.publicKey ?? undefined + ) + const { data: voteRecordPk } = useAddressQuery_VoteRecord( + realm?.owner, + props.proposal.pubkey, + tokenOwnerRecordPk ) + const { data: ownVoteRecord } = useVoteRecordByPubkeyQuery(voteRecordPk) - if (!ownVoteRecord) { + if (!ownVoteRecord?.result?.account) { return null } - const isYes = isYesVote(ownVoteRecord.account) - + const isYes = isYesVote(ownVoteRecord?.result?.account) return ( - +
{ - const { yesVoteProgress, yesVotesRequired } = useProposalVotes(proposal) + const realm = useRealmQuery().data?.result + const wallet = useWalletOnePointOh() + const { data: tokenOwnerRecordPk } = useAddressQuery_TokenOwnerRecord( + realm?.owner, + realm?.pubkey, + proposal.governingTokenMint, + wallet?.publicKey ?? undefined + ) + const { data: voteRecordPk } = useAddressQuery_VoteRecord( + realm?.owner, + proposalPk, + tokenOwnerRecordPk + ) + const { data: ownVoteRecord } = useVoteRecordByPubkeyQuery(voteRecordPk) + + const votesData = useProposalVotes(proposal) const checked = !!selectedProposals.find( - // @ts-ignore (p) => p.proposalPk.toString() === proposalPk.toString() ) const toggleCheckbox = () => { if (checked) { const proposals = selectedProposals.filter( - // @ts-ignore (p) => p.proposalPk.toString() !== proposalPk.toString() ) setSelectedProposals(proposals) @@ -40,7 +58,9 @@ const ProposalSelectCard = ({ } } - return ( + const myVoteExists = ownVoteRecord?.result !== undefined + + return myVoteExists ? null : (
{proposal.state === ProposalState.Voting && ( -
-
+
+
-
- +
+
+ {votesData._programVersion !== undefined && + // @asktree: here is some typescript gore because typescript doesn't know that a number being > 3 means it isn't 1 or 2 + votesData._programVersion !== 1 && + votesData._programVersion !== 2 && + votesData.veto !== undefined && + (votesData.veto.voteProgress ?? 0) > 0 ? ( + <> +
+
+ +
+ + ) : undefined}
)} diff --git a/components/ProposalSorting.tsx b/components/ProposalSorting.tsx new file mode 100644 index 0000000000..4c7b759868 --- /dev/null +++ b/components/ProposalSorting.tsx @@ -0,0 +1,128 @@ +import { ChevronDownIcon } from '@heroicons/react/solid' +import { Disclosure } from '@headlessui/react' +import classNames from 'classnames' +import { ArrowDown, ArrowsVertical, ArrowUp } from '@carbon/icons-react' +import styled from '@emotion/styled' + +export const PROPOSAL_SORTING_LOCAL_STORAGE_KEY = 'PROPOSALS_SORTING_OPT_V2' + +export enum SORTING_OPTIONS { + ASC, + DESC, + NONE, +} + +export type Sorting = { + completed_at: SORTING_OPTIONS + signedOffAt: SORTING_OPTIONS +} + +export const InitialSorting = { + completed_at: SORTING_OPTIONS.NONE, + signedOffAt: SORTING_OPTIONS.NONE, +} + +const keyToLabel = { + completed_at: 'Voting completed', + signedOffAt: 'Signing time', +} + +const StyledAlertCount = styled.span` + font-size: 0.6rem; +` + +interface Props { + className?: string + disabled?: boolean + sorting: Sorting + onChange(newSorting: Sorting): void +} + +const ProposalSorting = ({ className, disabled, onChange, sorting }: Props) => { + const hiddenCount = Object.values(sorting).filter( + (x) => x !== SORTING_OPTIONS.NONE + ).length + return ( + + {({ open }) => ( + <> + + {hiddenCount > 0 ? ( +
+ + {hiddenCount} + +
+ ) : null} +
+ Sorting + +
+
+ + {Object.keys(InitialSorting).map((x) => ( + + ))} + + + )} +
+ ) +} + +const Option = ({ sorting, objKey, onChange, label }) => { + return ( +
+ {label} +
+ {sorting[objKey] === SORTING_OPTIONS.NONE && ( + + onChange({ + ...sorting, + [objKey]: SORTING_OPTIONS.DESC, + }) + } + > + )} + {sorting[objKey] === SORTING_OPTIONS.DESC && ( + + onChange({ + ...sorting, + [objKey]: SORTING_OPTIONS.ASC, + }) + } + > + )} + {sorting[objKey] === SORTING_OPTIONS.ASC && ( + + onChange({ + ...sorting, + [objKey]: SORTING_OPTIONS.NONE, + }) + } + > + )} +
+
+ ) +} + +export default ProposalSorting diff --git a/components/ProposalStateBadge.tsx b/components/ProposalStateBadge.tsx new file mode 100644 index 0000000000..eba6459008 --- /dev/null +++ b/components/ProposalStateBadge.tsx @@ -0,0 +1,205 @@ +import { Proposal, ProposalState } from '@solana/spl-governance' +import classNames from 'classnames' + +import assertUnreachable from '@utils/typescript/assertUnreachable' +import { isInCoolOffTime } from './VotePanel/hooks' +import { + useUserCommunityTokenOwnerRecord, + useUserCouncilTokenOwnerRecord, +} from '@hooks/queries/tokenOwnerRecord' +import { useGovernanceByPubkeyQuery } from '@hooks/queries/governance' + +export const hasInstructions = (proposal: Proposal) => { + if (proposal.instructionsCount) { + return true + } + + if (proposal.options) { + for (const option of proposal.options) { + if (option.instructionsCount) { + return true + } + } + } + + return false +} + +interface OtherState { + isCreator: boolean + isSignatory: boolean + proposal: Proposal + votingEnded: boolean + coolOff: boolean +} + +function getBorderColor(proposalState: ProposalState, otherState: OtherState) { + switch (proposalState) { + case ProposalState.Cancelled: + case ProposalState.Completed: + case ProposalState.Defeated: + case ProposalState.ExecutingWithErrors: + case ProposalState.Vetoed: + return 'border-transparent' + case ProposalState.Executing: + return 'border-[#5DC9EB]' + case ProposalState.Draft: + return otherState.isCreator ? 'border-white' : 'border-transparent' + case ProposalState.SigningOff: + return otherState.isSignatory ? 'border-[#F5A458]' : 'border-transparent' + case ProposalState.Succeeded: + return !hasInstructions(otherState.proposal) + ? 'border-transparent' + : 'border-[#5DC9EB]' + case ProposalState.Voting: + return otherState.votingEnded ? 'border-[#5DC9EB]' : 'border-[#8EFFDD]' + default: + assertUnreachable(proposalState) + } +} + +function getLabel( + proposalState: ProposalState, + otherState: Pick +) { + switch (proposalState) { + case ProposalState.Cancelled: + return 'Cancelled' + case ProposalState.Completed: + return 'Completed' + case ProposalState.Defeated: + return 'Defeated' + case ProposalState.Draft: + return 'Draft' + case ProposalState.Executing: + return 'Executable' + case ProposalState.ExecutingWithErrors: + return 'Executing w/ errors' + case ProposalState.SigningOff: + return 'Signing off' + case ProposalState.Succeeded: + return !hasInstructions(otherState.proposal) ? 'Completed' : 'Executable' + case ProposalState.Voting: + return otherState.votingEnded + ? 'Finalizing' + : otherState.coolOff + ? 'Cool Off' + : 'Voting' + case ProposalState.Vetoed: + return 'Vetoed' + default: + assertUnreachable(proposalState) + } +} + +function getOpacity( + proposalState: ProposalState, + otherState: Pick +) { + switch (proposalState) { + case ProposalState.Cancelled: + case ProposalState.Completed: + case ProposalState.Defeated: + case ProposalState.ExecutingWithErrors: + case ProposalState.Vetoed: + return 'opacity-70' + case ProposalState.Draft: + return otherState.isCreator ? '' : 'opacity-70' + case ProposalState.SigningOff: + return otherState.isSignatory ? '' : 'opacity-70' + case ProposalState.Succeeded: + return !hasInstructions(otherState.proposal) ? 'opacity-70' : '' + case ProposalState.Voting: + case ProposalState.Executing: + return '' + default: + assertUnreachable(proposalState) + } +} + +function getTextColor( + proposalState: ProposalState, + otherState: Pick +) { + switch (proposalState) { + case ProposalState.Cancelled: + case ProposalState.Draft: + return 'text-white' + case ProposalState.Completed: + return 'text-[#8EFFDD]' + case ProposalState.Defeated: + case ProposalState.Vetoed: + case ProposalState.ExecutingWithErrors: + return 'text-[#FF7C7C]' + case ProposalState.Executing: + return 'text-[#5DC9EB]' + case ProposalState.SigningOff: + return 'text-[#F5A458]' + case ProposalState.Succeeded: + return !hasInstructions(otherState.proposal) + ? 'text-[#8EFFDD]' + : 'text-[#5DC9EB]' + case ProposalState.Voting: + return otherState.votingEnded + ? 'bg-gradient-to-r from-[#00C2FF] via-[#00E4FF] to-[#87F2FF] bg-clip-text text-transparent' + : 'text-[#8EFFDD]' + default: + assertUnreachable(proposalState) + } +} + +interface Props { + className?: string + proposal: Proposal +} + +export default function ProposalStateBadge(props: Props) { + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result + const governance = useGovernanceByPubkeyQuery(props.proposal.governance).data + ?.result + const isCreator = + ownTokenRecord?.pubkey.equals(props.proposal.tokenOwnerRecord) || + ownCouncilTokenRecord?.pubkey.equals(props.proposal.tokenOwnerRecord) || + false + + // For now, we're not going to display any special UI if the user is a signatory + const isSignatory = false + + const votingEnded = + governance !== undefined && + props.proposal.getTimeToVoteEnd(governance.account) < 0 + + const coolOff = isInCoolOffTime(props.proposal, governance?.account) + + const otherState = { + isCreator, + isSignatory, + votingEnded, + proposal: props.proposal, + coolOff, + } + + return ( +
+
+ {getLabel(props.proposal.state, otherState)} +
+
+ ) +} diff --git a/components/ProposalStatusBadge.tsx b/components/ProposalStatusBadge.tsx deleted file mode 100644 index 3521f6e42a..0000000000 --- a/components/ProposalStatusBadge.tsx +++ /dev/null @@ -1,174 +0,0 @@ -import { Proposal, ProposalState } from '@solana/spl-governance' -import classNames from 'classnames' - -import useRealm from '@hooks/useRealm' -import useRealmGovernance from '../hooks/useRealmGovernance' - -export const hasInstructions = (proposal: Proposal) => { - if (proposal.instructionsCount) { - return true - } - - if (proposal.options) { - for (const option of proposal.options) { - if (option.instructionsCount) { - return true - } - } - } - - return false -} - -interface OtherState { - isCreator: boolean - isSignatory: boolean - proposal: Proposal - votingEnded: boolean -} - -function getBorderColor(proposalState: ProposalState, otherState: OtherState) { - switch (proposalState) { - case ProposalState.Cancelled: - case ProposalState.Completed: - case ProposalState.Defeated: - case ProposalState.ExecutingWithErrors: - return 'border-transparent' - case ProposalState.Executing: - return 'border-[#5DC9EB]' - case ProposalState.Draft: - return otherState.isCreator ? 'border-white' : 'border-transparent' - case ProposalState.SigningOff: - return otherState.isSignatory ? 'border-[#F5A458]' : 'border-transparent' - case ProposalState.Succeeded: - return !hasInstructions(otherState.proposal) - ? 'border-transparent' - : 'border-[#5DC9EB]' - case ProposalState.Voting: - return otherState.votingEnded ? 'border-[#5DC9EB]' : 'border-[#8EFFDD]' - } -} - -function getLabel( - proposalState: ProposalState, - otherState: Pick -) { - switch (proposalState) { - case ProposalState.Cancelled: - return 'Cancelled' - case ProposalState.Completed: - return 'Completed' - case ProposalState.Defeated: - return 'Defeated' - case ProposalState.Draft: - return 'Draft' - case ProposalState.Executing: - return 'Executable' - case ProposalState.ExecutingWithErrors: - return 'Executing w/ errors' - case ProposalState.SigningOff: - return 'Signing off' - case ProposalState.Succeeded: - return !hasInstructions(otherState.proposal) ? 'Completed' : 'Executable' - case ProposalState.Voting: - return otherState.votingEnded ? 'Finalizing' : 'Voting' - } -} - -function getOpacity( - proposalState: ProposalState, - otherState: Pick -) { - switch (proposalState) { - case ProposalState.Cancelled: - case ProposalState.Completed: - case ProposalState.Defeated: - case ProposalState.ExecutingWithErrors: - return 'opacity-70' - case ProposalState.Draft: - return otherState.isCreator ? '' : 'opacity-70' - case ProposalState.SigningOff: - return otherState.isSignatory ? '' : 'opacity-70' - case ProposalState.Succeeded: - return !hasInstructions(otherState.proposal) ? 'opacity-70' : '' - default: - return '' - } -} - -function getTextColor( - proposalState: ProposalState, - otherState: Pick -) { - switch (proposalState) { - case ProposalState.Cancelled: - case ProposalState.Draft: - return 'text-white' - case ProposalState.Completed: - return 'text-[#8EFFDD]' - case ProposalState.Defeated: - case ProposalState.ExecutingWithErrors: - return 'text-[#FF7C7C]' - case ProposalState.Executing: - return 'text-[#5DC9EB]' - case ProposalState.SigningOff: - return 'text-[#F5A458]' - case ProposalState.Succeeded: - return !hasInstructions(otherState.proposal) - ? 'text-[#8EFFDD]' - : 'text-[#5DC9EB]' - case ProposalState.Voting: - return otherState.votingEnded - ? 'bg-gradient-to-r from-[#00C2FF] via-[#00E4FF] to-[#87F2FF] bg-clip-text text-transparent' - : 'text-[#8EFFDD]' - } -} - -interface Props { - className?: string - proposal: Proposal -} - -export default function ProposalStateBadge(props: Props) { - const { ownTokenRecord, ownCouncilTokenRecord } = useRealm() - const governance = useRealmGovernance(props.proposal.governance) - - const isCreator = - ownTokenRecord?.pubkey.equals(props.proposal.tokenOwnerRecord) || - ownCouncilTokenRecord?.pubkey.equals(props.proposal.tokenOwnerRecord) || - false - - // For now, we're not going to display any special UI if the user is a signatory - const isSignatory = false - - const votingEnded = - governance && props.proposal.getTimeToVoteEnd(governance) < 0 - - const otherState = { - isCreator, - isSignatory, - votingEnded, - proposal: props.proposal, - } - - return ( -
- {getLabel(props.proposal.state, otherState)} -
- ) -} diff --git a/components/ProposalTimeStatus.tsx b/components/ProposalTimeStatus.tsx index b826271701..bd9c6d3b7f 100644 --- a/components/ProposalTimeStatus.tsx +++ b/components/ProposalTimeStatus.tsx @@ -1,15 +1,15 @@ -import useRealm from '../hooks/useRealm' import { Proposal, ProposalState } from '@solana/spl-governance' import { fmtUnixTime } from '../utils/formatting' -import { VoteCountdown } from './VoteCountdown' +import ProposalTimer from './ProposalTimer' +import { useGovernanceByPubkeyQuery } from '@hooks/queries/governance' type ProposalTimeStatusProps = { proposal: Proposal } const ProposalTimeStatus = ({ proposal }: ProposalTimeStatusProps) => { - const { governances } = useRealm() - const governance = governances[proposal?.governance.toBase58()]?.account + const governance = useGovernanceByPubkeyQuery(proposal.governance).data + ?.result return proposal && governance ? (
@@ -18,7 +18,7 @@ const ProposalTimeStatus = ({ proposal }: ProposalTimeStatusProps) => { proposal.votingCompletedAt )}` ) : proposal.votingAt ? ( - + ) : ( `Drafted ${fmtUnixTime(proposal.draftAt)}` )} diff --git a/components/ProposalTimer.tsx b/components/ProposalTimer.tsx new file mode 100644 index 0000000000..141ca32ec9 --- /dev/null +++ b/components/ProposalTimer.tsx @@ -0,0 +1,247 @@ +import { CaretDown, InformationFilled, Timer } from '@carbon/icons-react' +import { Governance, Proposal } from '@solana/spl-governance' +import clsx from 'clsx' +import dayjs from 'dayjs' +import { useCallback, useEffect, useState } from 'react' +import Tooltip from './Tooltip' + +/** here's a horrible function chatgpt wrote for me :-) */ +function formatDuration(seconds: number) { + const minuteInSeconds = 60 + const hourInSeconds = minuteInSeconds * 60 + const dayInSeconds = hourInSeconds * 24 + + const days = Math.floor(seconds / dayInSeconds) + seconds %= dayInSeconds + const hours = Math.floor(seconds / hourInSeconds) + seconds %= hourInSeconds + const minutes = Math.floor(seconds / minuteInSeconds) + + const parts = [ + days.toString().padStart(2, '0') + 'd', + hours.toString().padStart(2, '0') + 'h', + minutes.toString().padStart(2, '0') + 'm', + ] as const + + return parts +} + +const useCountdown = ({ + proposal, + governance, +}: { + proposal: Proposal + governance: Governance +}) => { + const [countdown, setCountdown] = useState< + ReturnType | undefined + >(undefined) + + const getTimeToVoteEnd = useCallback(() => { + // todo this should probably be made impossible if its not already + if (proposal.isVoteFinalized()) { + return { state: 'done' } as const + } + + const now = dayjs().unix() // TODO remove superfluous dependency + const votingStartedAt = proposal.votingAt?.toNumber() ?? 0 // TODO when and why would this be null ? + + const totalSecondsElapsed = Math.max(0, now - votingStartedAt) + const maxVotingTime = + governance.config.baseVotingTime + governance.config.votingCoolOffTime + + const totalSecondsRemaining = Math.max( + 0, + maxVotingTime - totalSecondsElapsed + ) + if (totalSecondsRemaining <= 0) { + return { state: 'done' } as const + } + + return { + state: 'voting', + total: { + secondsRemaining: totalSecondsRemaining, + secondsElapsed: totalSecondsElapsed, + }, + } as const + }, [ + governance.config.baseVotingTime, + governance.config.votingCoolOffTime, + proposal, + ]) + + useEffect(() => { + const updateCountdown = () => { + const newState = getTimeToVoteEnd() + setCountdown(newState) + } + + const interval = setInterval(() => { + updateCountdown() + }, 1000) + + updateCountdown() + return () => clearInterval(interval) + }, [getTimeToVoteEnd]) + + return countdown +} + +const ProposalTimer = ({ + proposal, + governance, +}: { + proposal: Proposal + governance: Governance +}) => { + const countdown = useCountdown({ proposal, governance }) + + return countdown && countdown.state === 'voting' ? ( +
+
+
+ +
+ {formatDuration(countdown.total.secondsRemaining).map((x, i) => ( +
{x}
+ ))} +
+
+ +
+ +
+
+
+
Unrestricted Voting Time
+
+
+ The amount of time a voter has to approve or deny a proposal. +
+
+ {governance.config.votingCoolOffTime !== 0 && ( +
+
+
+
Cool-Off Voting Time
+
+
+ After the unrestricted voting time, this is the amount of time + a voter has to deny, veto, or withdraw a vote on a proposal. +
+
+ )} +
+ } + > + + +
+ ) : null +} + +export const TimerBar = ({ + proposal, + governance, + size, +}: { + proposal: Proposal + governance: Governance + size: 'xs' | 'lg' +}) => { + const countdown = useCountdown({ proposal, governance }) + + return countdown && countdown.state === 'voting' ? ( +
+
+ governance.config.baseVotingTime + ? 'hidden' + : undefined + } + size={size} + /> +
+
+
+ + +
+
+ ) : null +} + +const Notch = ({ + className, + size, +}: { + className?: string + size: 'xs' | 'lg' +}) => ( +
+ +
+) + +export default ProposalTimer diff --git a/components/ProposalTopVotersBubbleChart.tsx b/components/ProposalTopVotersBubbleChart.tsx index c8fe019b93..6349d4f1bc 100644 --- a/components/ProposalTopVotersBubbleChart.tsx +++ b/components/ProposalTopVotersBubbleChart.tsx @@ -19,8 +19,7 @@ const voteTypeDomain = (type: VoteType) => { const loadD3 = () => import('d3') -type Unpromise

= P extends Promise ? T : never -type D3 = Unpromise> +type D3 = Awaited> interface Props { className?: string @@ -56,7 +55,7 @@ function Content(props: Props) { const hierarchy = d3 .hierarchy({ children: props.data }) - .sum((d: any) => (d.votesCast ? d.votesCast.toNumber() : 0)) + .sum((d: any) => (d.votesCast ? d.votesCast.toString() : 0)) .sort((a, b) => (b.value || 0) - (a.value || 0)) const pack = d3.pack().size([props.width, props.height]).padding(3) @@ -122,6 +121,7 @@ function Content(props: Props) { .attr('y', '0.5em') .text((d) => abbreviateAddress(d.data.name)) } + // 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 }, [ container, props.data, diff --git a/components/ProposalTopVotersList.tsx b/components/ProposalTopVotersList.tsx index c272af1025..3cf3d88bd3 100644 --- a/components/ProposalTopVotersList.tsx +++ b/components/ProposalTopVotersList.tsx @@ -50,14 +50,18 @@ const formatNumber = (value: BN, decimals: number) => { return formatter.format(num.toNumber()) } -const voteTypeText = (type: VoteType) => { +const voteTypeText = (type: VoteType, isMulti: boolean) => { switch (type) { case VoteType.No: return 'Nay' case VoteType.Undecided: return '' case VoteType.Yes: - return 'Yay' + if (isMulti) { + return 'Voted' + } else { + return 'Yay' + } } } @@ -103,6 +107,7 @@ interface Props { className?: string data: VoterDisplayData[] endpoint: string + isMulti: boolean highlighted?: string onHighlight?(key?: string): void } @@ -213,7 +218,7 @@ export default function ProposalTopVotersList(props: Props) { 'text-sm' )} > - {voteTypeText(rowData.voteType)} + {voteTypeText(rowData.voteType, props.isMulti)}

Show: - - + + {!props.isMulti && + + } { + const collection = nft.grouping.find((x) => x.group_key === 'collection') + return ( + collection && + usedCollectionsPks.includes(collection.group_value) && + nft.creators?.filter((x) => x.verified).length > 0 + ) + }) +} + +const ProposalVoterNftChart = (props: Props) => { + const { data: nfts, isLoading } = useDigitalAssetsByOwner( + props.highlighted ? new PublicKey(props.highlighted) : undefined + ) + + const usedCollectionsPks = useNftRegistrarCollection() + const verifiedNfts = useMemo( + () => filterVerifiedCollections(nfts, usedCollectionsPks), + [nfts, usedCollectionsPks] + ) + + return ( +
+

+ Voter's NFTs +

+ {!props.highlighted ? ( +
Move cursor to an account
+ ) : isLoading ? ( +
Loading NFTs...
+ ) : !verifiedNfts || verifiedNfts.length === 0 ? ( +
+ Something went wrong, fail to fetch... +
+ ) : ( +
+ {verifiedNfts && + verifiedNfts.map((nft: any) => { + return ( + {nft.content.metadata.name} + ) + })} +
+ )} +
+ ) +} + +export default ProposalVoterNftChart diff --git a/components/ProposalVotingPower/CommunityVotingPower.tsx b/components/ProposalVotingPower/CommunityVotingPower.tsx deleted file mode 100644 index 935f7e3be9..0000000000 --- a/components/ProposalVotingPower/CommunityVotingPower.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import { BigNumber } from 'bignumber.js' -import { useCallback } from 'react' -import classNames from 'classnames' - -import useRealm from '@hooks/useRealm' -import { calculateMaxVoteScore } from '@models/proposal/calulateMaxVoteScore' -import useProposal from '@hooks/useProposal' -import useWalletStore from 'stores/useWalletStore' -import { SecondaryButton } from '@components/Button' - -import { getMintMetadata } from '../instructions/programs/splToken' -import getNumTokens from './getNumTokens' -import depositTokens from './depositTokens' -import VotingPowerPct from './VotingPowerPct' - -interface Props { - className?: string -} - -export default function CommunityVotingPower(props: Props) { - const { - mint, - ownTokenRecord, - ownVoterWeight, - realm, - realmInfo, - realmTokenAccount, - } = useRealm() - const { proposal } = useProposal() - const fetchWalletTokenAccounts = useWalletStore( - (s) => s.actions.fetchWalletTokenAccounts - ) - const fetchRealm = useWalletStore((s) => s.actions.fetchRealm) - const connection = useWalletStore((s) => s.connection.current) - const wallet = useWalletStore((s) => s.current) - - const depositAmount = realmTokenAccount - ? new BigNumber(realmTokenAccount.account.amount.toString()) - : new BigNumber(0) - - const depositMint = realm?.account.communityMint - const tokenName = - getMintMetadata(depositMint)?.name ?? realm?.account.name ?? '' - - const amount = getNumTokens(ownVoterWeight, ownTokenRecord, mint, realmInfo) - const max = - realm && proposal && mint - ? new BigNumber( - calculateMaxVoteScore(realm, proposal, mint).toString() - ).shiftedBy(-mint.decimals) - : null - - const deposit = useCallback(async () => { - if (depositAmount && realmTokenAccount && realmInfo && realm && wallet) { - await depositTokens({ - connection, - realmInfo, - realm, - wallet, - amount: depositAmount, - depositTokenAccount: realmTokenAccount, - }) - await fetchWalletTokenAccounts() - await fetchRealm(realmInfo.programId, realmInfo.realmId) - } - }, [ - depositAmount, - fetchRealm, - fetchWalletTokenAccounts, - connection, - realmTokenAccount, - realmInfo, - realm, - wallet, - ]) - - if (!(realm && realmInfo)) { - return ( -
- ) - } - - return ( -
- {amount.isZero() ? ( -
- You do not have any voting power in this realm. -
- ) : ( -
-
{tokenName} Votes
-
-
- {amount.toFormat()} -
- {max && !max.isZero() && ( - - )} -
-
- )} - {depositAmount.isGreaterThan(0) && ( - <> -
- You have{' '} - {mint - ? depositAmount.shiftedBy(-mint.decimals).toFormat() - : depositAmount.toFormat()}{' '} - more {tokenName} votes in your wallet. Do you want to deposit them - to increase your voting power in this Realm? -
- - Deposit - - - )} -
- ) -} diff --git a/components/ProposalVotingPower/CouncilVotingPower.tsx b/components/ProposalVotingPower/CouncilVotingPower.tsx deleted file mode 100644 index 2905a2d950..0000000000 --- a/components/ProposalVotingPower/CouncilVotingPower.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import { BigNumber } from 'bignumber.js' -import { useCallback } from 'react' -import classNames from 'classnames' - -import useRealm from '@hooks/useRealm' -import { calculateMaxVoteScore } from '@models/proposal/calulateMaxVoteScore' -import useProposal from '@hooks/useProposal' -import useWalletStore from 'stores/useWalletStore' -import { SecondaryButton } from '@components/Button' - -import { getMintMetadata } from '../instructions/programs/splToken' -import getNumTokens from './getNumTokens' -import depositTokens from './depositTokens' -import VotingPowerPct from './VotingPowerPct' - -interface Props { - className?: string -} - -export default function CouncilVotingPower(props: Props) { - const { - councilMint, - councilTokenAccount, - ownCouncilTokenRecord, - ownVoterWeight, - realm, - realmInfo, - } = useRealm() - const { proposal } = useProposal() - const fetchWalletTokenAccounts = useWalletStore( - (s) => s.actions.fetchWalletTokenAccounts - ) - const fetchRealm = useWalletStore((s) => s.actions.fetchRealm) - const connection = useWalletStore((s) => s.connection.current) - const wallet = useWalletStore((s) => s.current) - - const depositAmount = councilTokenAccount - ? new BigNumber(councilTokenAccount.account.amount.toString()) - : new BigNumber(0) - const depositMint = realm?.account.config.councilMint - const tokenName = - getMintMetadata(depositMint)?.name ?? realm?.account.name ?? '' - - const amount = getNumTokens( - ownVoterWeight, - ownCouncilTokenRecord, - councilMint, - realmInfo - ) - - const max = - realm && proposal && councilMint - ? new BigNumber( - calculateMaxVoteScore(realm, proposal, councilMint).toString() - ).shiftedBy(-councilMint.decimals) - : null - - const deposit = useCallback(async () => { - if (depositAmount && councilTokenAccount && realmInfo && realm && wallet) { - await depositTokens({ - connection, - realmInfo, - realm, - wallet, - amount: depositAmount, - depositTokenAccount: councilTokenAccount, - }) - await fetchWalletTokenAccounts() - await fetchRealm(realmInfo.programId, realmInfo.realmId) - } - }, [ - depositAmount, - fetchRealm, - fetchWalletTokenAccounts, - connection, - councilTokenAccount, - realmInfo, - realm, - wallet, - ]) - - if (!(realm && realmInfo)) { - return ( -
- ) - } - - return ( -
- {amount.isZero() ? ( -
- You do not have any voting power in this realm. -
- ) : ( -
-
{tokenName} Council Votes
-
-
- {amount.toFormat()} -
- {max && !max.isZero() && ( - - )} -
-
- )} - {depositAmount.isGreaterThan(0) && ( - <> -
- You have{' '} - {councilMint - ? depositAmount.shiftedBy(-councilMint.decimals).toFormat() - : depositAmount.toFormat()}{' '} - more {tokenName} council votes in your wallet. Do you want to - deposit them to increase your voting power in this Realm? -
- - Deposit - - - )} -
- ) -} diff --git a/components/ProposalVotingPower/LockedCommunityNFTRecordVotingPower.tsx b/components/ProposalVotingPower/LockedCommunityNFTRecordVotingPower.tsx new file mode 100644 index 0000000000..992d0db0c8 --- /dev/null +++ b/components/ProposalVotingPower/LockedCommunityNFTRecordVotingPower.tsx @@ -0,0 +1,169 @@ +import { useState, useEffect } from 'react' +import { BigNumber } from 'bignumber.js' +import useRealm from '@hooks/useRealm' +import useHeliumVsrStore from 'HeliumVotePlugin/hooks/useHeliumVsrStore' +import { fmtMintAmount, getMintDecimalAmount } from '@tools/sdk/units' +import { getMintMetadata } from '@components/instructions/programs/splToken' +import Tooltip from '@components/Tooltip' +import { ChevronRightIcon, LightningBoltIcon } from '@heroicons/react/solid' +import { BN } from '@coral-xyz/anchor' +import Link from 'next/link' +import useQueryContext from '@hooks/useQueryContext' +import InlineNotification from '@components/InlineNotification' +import { useAddressQuery_CommunityTokenOwner } from '@hooks/queries/addresses/tokenOwnerRecord' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' +import {useVotingClients} from "@hooks/useVotingClients"; + +interface Props { + className?: string +} + +export default function LockedCommunityNFTRecordVotingPower(props: Props) { + const { fmtUrlWithCluster } = useQueryContext() + const [amount, setAmount] = useState(new BigNumber(0)) + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + + const { realmTokenAccount, symbol } = useRealm() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const { data: tokenOwnerRecordPk } = useAddressQuery_CommunityTokenOwner() + // this is only available for the community role as long as the rest of the hooks are hard-coding it + const votingClient = useVotingClients()('community') + const [ + loadingPositions, + votingPower, + amountLocked, + positions, + propagatePositions, + ] = useHeliumVsrStore((s) => [ + s.state.isLoading, + s.state.votingPower, + s.state.amountLocked, + s.state.positions, + s.propagatePositions, + ]) + + useEffect(() => { + if (votingClient.heliumVsrVotingPositions.length !== positions.length) { + propagatePositions({ votingClient }) + } + }, [positions, votingClient, propagatePositions]) + + useEffect(() => { + if (mint && votingPower) { + setAmount(getMintDecimalAmount(mint, votingPower)) + } + }, [mint, votingPower]) + + const isLoading = loadingPositions || !(votingPower && mint) + const communityMint = realm?.account.communityMint + + const tokenName = + getMintMetadata(communityMint)?.name ?? realm?.account.name ?? '' + + const hasTokensInWallet = + realmTokenAccount && realmTokenAccount.account.amount.gt(new BN(0)) + + const availableTokens = + hasTokensInWallet && mint + ? fmtMintAmount(mint, realmTokenAccount?.account.amount as BN) + : '0' + + const multiplier = + !votingPower.isZero() && !amountLocked.isZero() && mint + ? getMintDecimalAmount(mint, votingPower) + .div(getMintDecimalAmount(mint, amountLocked)) + .toFixed(2) + 'x' + : null + + const lockTokensFmt = + amountLocked && mint ? fmtMintAmount(mint, amountLocked) : '0' + + const tokensToShow = + hasTokensInWallet && realmTokenAccount + ? fmtMintAmount(mint, realmTokenAccount.account.amount) + : hasTokensInWallet + ? availableTokens + : 0 + + if (isLoading) { + return ( + <> +
+
+ + ) + } + + const isSameWallet = + (connected && !ownTokenRecord) || + (connected && + ownTokenRecord && + wallet!.publicKey!.equals(ownTokenRecord!.account.governingTokenOwner)) + + return ( +
+
+ + + View + + + +
+ {isSameWallet && hasTokensInWallet && connected ? ( +
+ +
+ ) : null} + {amount.isZero() ? ( +
+ You do not have any voting power in this dao. +
+ ) : ( + <> +
+
Votes
+
+
+ {amount.toFormat(2)}{' '} + {multiplier && ( + +
+ + {multiplier} +
+
+ )} +
+
+
+
+

+ {tokenName} Locked + + {lockTokensFmt} + +

+
+ + )} +
+ ) +} diff --git a/components/ProposalVotingPower/LockedCommunityVotingPower.tsx b/components/ProposalVotingPower/LockedCommunityVotingPower.tsx index 505c8a40cb..d5178139a3 100644 --- a/components/ProposalVotingPower/LockedCommunityVotingPower.tsx +++ b/components/ProposalVotingPower/LockedCommunityVotingPower.tsx @@ -1,59 +1,46 @@ import useRealm from '@hooks/useRealm' import { BigNumber } from 'bignumber.js' -import { LightningBoltIcon } from '@heroicons/react/solid' -import { useCallback } from 'react' import classNames from 'classnames' -import { calculateMaxVoteScore } from '@models/proposal/calulateMaxVoteScore' -import useProposal from '@hooks/useProposal' import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' -import { getMintDecimalAmount } from '@tools/sdk/units' -import Tooltip from '@components/Tooltip' -import { SecondaryButton } from '@components/Button' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import useWalletStore from 'stores/useWalletStore' -import { notify } from '@utils/notifications' import { getMintMetadata } from '../instructions/programs/splToken' -import depositTokensVST from './depositTokensVSR' -import VotingPowerPct from './VotingPowerPct' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmCommunityMintInfoQuery } from '@hooks/queries/mintInfo' +import VSRCommunityVotingPower from 'VoteStakeRegistry/components/TokenBalance/VSRVotingPower' +import DepositCommunityTokensBtn from 'VoteStakeRegistry/components/TokenBalance/DepositCommunityTokensBtn' +import useDelegators from '@components/VotePanel/useDelegators' +import {useRealmVoterWeightPlugins} from "@hooks/useRealmVoterWeightPlugins"; +import {CalculatedWeight, VoterWeightPlugins} from "../../VoterWeightPlugins/lib/types"; +import { BN } from '@coral-xyz/anchor' interface Props { className?: string } -export default function LockedCommunityVotingPower(props: Props) { - const { mint, realm, realmInfo, realmTokenAccount, tokenRecords } = useRealm() - const { proposal } = useProposal() - const client = useVotePluginsClientStore((s) => s.state.vsrClient) - const connection = useWalletStore((s) => s.connection.current) - const deposits = useDepositStore((s) => s.state.deposits) - const endpoint = useWalletStore((s) => s.connection.endpoint) - const fetchRealm = useWalletStore((s) => s.actions.fetchRealm) - const fetchWalletTokenAccounts = useWalletStore( - (s) => s.actions.fetchWalletTokenAccounts - ) - const getOwnedDeposits = useDepositStore((s) => s.getOwnedDeposits) - const votingPower = useDepositStore((s) => s.state.votingPower) - const votingPowerFromDeposits = useDepositStore( - (s) => s.state.votingPowerFromDeposits - ) - const wallet = useWalletStore((s) => s.current) - const isLoading = useDepositStore((s) => s.state.isLoading) +const findVSRVoterWeight = (calculatedVoterWeight: CalculatedWeight | undefined): BN|undefined => + calculatedVoterWeight?.details.find((detail) => detail.pluginName === 'VSR')?.pluginWeight ?? undefined; - const currentTokenOwnerRecord = - wallet && wallet.publicKey - ? tokenRecords[wallet.publicKey.toBase58()] - : null - const tokenOwnerRecordPk = currentTokenOwnerRecord - ? currentTokenOwnerRecord.pubkey - : null +const isVSRLastVoterWeightPlugin = (plugins: VoterWeightPlugins | undefined) => plugins?.voterWeight[plugins.voterWeight.length - 1].name === 'VSR'; - const depositRecord = deposits.find( - (deposit) => - deposit.mint.publicKey.toBase58() === - realm!.account.communityMint.toBase58() && deposit.lockup.kind.none - ) +export default function LockedCommunityVotingPower(props: Props) { + const realm = useRealmQuery().data?.result + const { + data: mintData, + isLoading: mintLoading, + } = useRealmCommunityMintInfoQuery() + const mint = mintData?.result + + const { realmTokenAccount } = useRealm() + const { totalCalculatedVoterWeight, isReady: votingPowerReady, plugins } = useRealmVoterWeightPlugins('community'); + + // in case the VSR plugin is the last plugin, this is the final calculated voter weight. + // however, if it is one in a chain, we are just showing an intermediate calculation here. + // This affects how it appears in the UI + const votingPower = findVSRVoterWeight(totalCalculatedVoterWeight) + const isLastVoterWeightPlugin = isVSRLastVoterWeightPlugin(plugins); + + const isLoading = useDepositStore((s) => s.state.isLoading) const depositMint = realm?.account.communityMint const depositAmount = realmTokenAccount @@ -63,146 +50,31 @@ export default function LockedCommunityVotingPower(props: Props) { const tokenName = getMintMetadata(depositMint)?.name ?? realm?.account.name ?? '' - const amount = - votingPower && mint - ? getMintDecimalAmount(mint, votingPower) - : new BigNumber('0') - - const multiplier = - !votingPower.isZero() && !votingPowerFromDeposits.isZero() - ? (votingPower.toNumber() / votingPowerFromDeposits.toNumber()).toFixed( - 2 - ) + 'x' - : null - - const tokenAmount = - depositRecord && mint - ? new BigNumber( - getMintDecimalAmount(mint, depositRecord.amountDepositedNative) - ) - : new BigNumber('0') - - const lockedTokensAmount = deposits - .filter( - (x) => - typeof x.lockup.kind['none'] === 'undefined' && - x.mint.publicKey.toBase58() === realm?.account.communityMint.toBase58() - ) - .reduce( - (curr, next) => curr.plus(new BigNumber(next.currentlyLocked.toString())), - new BigNumber(0) - ) - - const max = - realm && proposal && mint - ? new BigNumber( - calculateMaxVoteScore(realm, proposal, mint).toString() - ).shiftedBy(-mint.decimals) - : null - - const deposit = useCallback(async () => { - if ( - client && - realm && - realmInfo && - realmTokenAccount && - wallet && - wallet.publicKey - ) { - try { - await depositTokensVST({ - client, - connection, - endpoint, - realm, - realmInfo, - realmTokenAccount, - tokenOwnerRecordPk, - wallet, - }) - - await getOwnedDeposits({ - client, - connection, - communityMintPk: realm.account.communityMint, - realmPk: realm.pubkey, - walletPk: wallet.publicKey, - }) - - await fetchWalletTokenAccounts() - await fetchRealm(realmInfo.programId, realmInfo.realmId) - } catch (e) { - console.error(e) - notify({ message: `Something went wrong ${e}`, type: 'error' }) - } - } - }, [ - client, - connection, - endpoint, - fetchWalletTokenAccounts, - fetchRealm, - getOwnedDeposits, - realm, - realmInfo, - realmTokenAccount, - tokenOwnerRecordPk, - wallet, - ]) + // memoize useAsync inputs to prevent constant refetch + const relevantDelegators = useDelegators('community') - if (isLoading || !(votingPower && mint)) { + if (isLoading || !votingPowerReady || mintLoading) { return (
) } return (
- {amount.isZero() ? ( + {(votingPower === undefined || votingPower.isZero()) && + (relevantDelegators?.length ?? 0) < 1 ? (
- You do not have any voting power in this realm. + You do not have any voting power in this dao.
) : ( - <> -
-
{tokenName} Votes
-
-
- {amount.toFormat()}{' '} - {multiplier && ( - -
- - {multiplier} -
-
- )} -
- {max && !max.isZero() && ( - - )} -
-
-
-

- {tokenName} Deposited - - {tokenAmount.isNaN() ? '0' : tokenAmount.toFormat()} - -

-

- {tokenName} Locked - - {lockedTokensAmount.isNaN() - ? '0' - : lockedTokensAmount.toFormat()} - -

-
- + )} + {depositAmount.isGreaterThan(0) && ( <>
@@ -211,11 +83,9 @@ export default function LockedCommunityVotingPower(props: Props) { ? depositAmount.shiftedBy(-mint.decimals).toFormat() : depositAmount.toFormat()}{' '} more {tokenName} votes in your wallet. Do you want to deposit them - to increase your voting power in this Realm? + to increase your voting power in this Dao?
- - Deposit - + )}
diff --git a/components/ProposalVotingPower/LockedCouncilVotingPower.tsx b/components/ProposalVotingPower/LockedCouncilVotingPower.tsx deleted file mode 100644 index 2f38f93a5d..0000000000 --- a/components/ProposalVotingPower/LockedCouncilVotingPower.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import useRealm from '@hooks/useRealm' -import { BigNumber } from 'bignumber.js' -import classNames from 'classnames' - -import { calculateMaxVoteScore } from '@models/proposal/calulateMaxVoteScore' -import useProposal from '@hooks/useProposal' -import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' -import { fmtMintAmount, getMintDecimalAmount } from '@tools/sdk/units' - -import { getMintMetadata } from '../instructions/programs/splToken' -import VotingPowerPct from './VotingPowerPct' - -interface Props { - className?: string -} - -export default function LockedCouncilVotingPower(props: Props) { - const { councilMint, realm } = useRealm() - const { proposal } = useProposal() - const deposits = useDepositStore((s) => s.state.deposits) - const votingPower = useDepositStore((s) => s.state.votingPower) - const isLoading = useDepositStore((s) => s.state.isLoading) - - const depositRecord = deposits.find( - (deposit) => - deposit.mint.publicKey.toBase58() === - realm!.account.communityMint.toBase58() && deposit.lockup.kind.none - ) - - const depositMint = realm?.account.config.councilMint - const tokenName = - getMintMetadata(depositMint)?.name ?? realm?.account.name ?? '' - - const amount = - votingPower && councilMint - ? getMintDecimalAmount(councilMint, votingPower) - : new BigNumber('0') - - const tokenAmount = - depositRecord && councilMint - ? new BigNumber( - fmtMintAmount(councilMint, depositRecord.amountDepositedNative) - ) - : new BigNumber('0') - - const lockedTokensAmount = deposits - .filter( - (x) => - typeof x.lockup.kind['none'] === 'undefined' && - x.mint.publicKey.toBase58() === realm?.account.communityMint.toBase58() - ) - .reduce( - (curr, next) => curr.plus(new BigNumber(next.currentlyLocked.toString())), - new BigNumber(0) - ) - - const max = - realm && proposal && councilMint - ? new BigNumber( - calculateMaxVoteScore(realm, proposal, councilMint).toString() - ).shiftedBy(-councilMint.decimals) - : null - - if (isLoading || !(votingPower && councilMint)) { - return ( -
- ) - } - - return ( -
- {amount.isZero() ? ( -
- You do not have any voting power in this realm. -
- ) : ( -
-
{tokenName} Council Votes
-
-
- {amount.toFormat()} -
- {max && !max.isZero() && ( - - )} -
-
- )} -
-

- {tokenName} Deposited - - {tokenAmount.isNaN() ? '0' : tokenAmount.toFormat()} - -

-

- {tokenName} Locked - - {lockedTokensAmount.isNaN() ? '0' : lockedTokensAmount.toFormat()} - -

-
-
- ) -} diff --git a/components/ProposalVotingPower/NftVotingPower.tsx b/components/ProposalVotingPower/NftVotingPower.tsx index 33e6d05af6..9ad5c03a43 100644 --- a/components/ProposalVotingPower/NftVotingPower.tsx +++ b/components/ProposalVotingPower/NftVotingPower.tsx @@ -1,95 +1,84 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ import classNames from 'classnames' import { BigNumber } from 'bignumber.js' -import { Transaction, TransactionInstruction } from '@solana/web3.js' -import { - SYSTEM_PROGRAM_ID, - withCreateTokenOwnerRecord, -} from '@solana/spl-governance' -import { NftVoterClient } from '@solana/governance-program-library' - -import useNftPluginStore from 'NftVotePlugin/store/nftPluginStore' -import useWalletStore from 'stores/useWalletStore' -import useRealm from '@hooks/useRealm' +import { Transaction } from '@solana/web3.js' import Button from '@components/Button' -import { getVoterWeightRecord } from '@utils/plugin/accounts' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' import { sendTransaction } from '@utils/send' import VotingPowerPct from './VotingPowerPct' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useUserOrDelegator from '@hooks/useUserOrDelegator' +import { useConnection } from '@solana/wallet-adapter-react' +import { useVotingNfts } from '@hooks/queries/plugins/nftVoter' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import {useJoinRealm} from "@hooks/useJoinRealm"; interface Props { className?: string + inAccountDetails?: boolean + children?: React.ReactNode } -export default function NftVotingPower(props: Props) { - const nfts = useNftPluginStore((s) => s.state.votingNfts) - const votingPower = useNftPluginStore((s) => s.state.votingPower) - const maxWeight = useNftPluginStore((s) => s.state.maxVoteRecord) - const isLoading = useNftPluginStore((s) => s.state.isLoadingNfts) - const connected = useWalletStore((s) => s.connected) - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - const fetchRealm = useWalletStore((s) => s.actions.fetchRealm) - const { ownTokenRecord, realm, realmInfo } = useRealm() - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) +const Join = () => { + const { connection } = useConnection() + const actingAsWalletPk = useUserOrDelegator() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const realm = useRealmQuery().data?.result + const { userNeedsTokenOwnerRecord, userNeedsVoterWeightRecords, handleRegister } = useJoinRealm(); - const displayNfts = nfts.slice(0, 3) - const remainingCount = Math.max(nfts.length - 3, 0) - const max = maxWeight - ? new BigNumber(maxWeight.account.maxVoterWeight.toString()) - : null - const amount = new BigNumber(votingPower.toString()) + const join = async () => { + if (!realm || !wallet?.publicKey) throw new Error() - 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 instructions = await handleRegister(); const transaction = new Transaction() transaction.add(...instructions) await sendTransaction({ - transaction: transaction, - wallet: wallet!, - connection: connection.current, + transaction, + wallet: wallet, + connection: connection, signers: [], sendingMessage: `Registering`, successMessage: `Registered`, }) - await fetchRealm(realm?.owner, realm?.pubkey) } - if (isLoading) { + return ( + (actingAsWalletPk?.toString() === wallet?.publicKey?.toString() && + connected && + (userNeedsTokenOwnerRecord || userNeedsVoterWeightRecords) && ( + + )) || + null + ) +} + +export default function NftVotingPower(props: Props) { + const userPk = useUserOrDelegator() + const nfts = useVotingNfts(userPk) + + const { isReady, totalCalculatedVoterWeight, calculatedMaxVoterWeight } = useRealmVoterWeightPlugins( + 'community', + ) + + const displayNfts = (nfts ?? []).slice(0, 3) + const remainingCount = Math.max((nfts ?? []).length - 3, 0) + const max = calculatedMaxVoterWeight?.value + ? new BigNumber(calculatedMaxVoterWeight.value.toString()) + : null + const amount = new BigNumber((totalCalculatedVoterWeight?.value ?? 0).toString()) + + if (!isReady || nfts === undefined) { return (
) } @@ -97,7 +86,7 @@ export default function NftVotingPower(props: Props) { if (nfts.length === 0) { return (
- You do not have any voting power in this realm. + You do not have any voting power in this dao.
) } @@ -111,8 +100,10 @@ export default function NftVotingPower(props: Props) { {displayNfts.slice(0, 3).map((nft, index) => (
))} {!!remainingCount && ( @@ -126,11 +117,7 @@ export default function NftVotingPower(props: Props) { )}
- {connected && !ownTokenRecord && ( - - )} +
) } diff --git a/components/ProposalVotingPower/PluginVotingPower.tsx b/components/ProposalVotingPower/PluginVotingPower.tsx new file mode 100644 index 0000000000..42e9659939 --- /dev/null +++ b/components/ProposalVotingPower/PluginVotingPower.tsx @@ -0,0 +1,110 @@ +import classNames from 'classnames' +import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' + +import { getMintMetadata } from '@components/instructions/programs/splToken' +import { TokenDeposit } from '@components/TokenBalance/TokenDeposit' +import { useLegacyVoterWeight } from '@hooks/queries/governancePower' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import { useRealmQuery } from '@hooks/queries/realm' +import { useDelegatorAwareVoterWeight } from '@hooks/useDelegatorAwareVoterWeight' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import { GoverningTokenRole } from '@solana/spl-governance' +import { BigNumber } from 'bignumber.js' +import clsx from 'clsx' +import { useMemo } from 'react' + +interface Props { + className?: string + role: 'community' | 'council' + showDepositButton?: boolean +} + +export default function PluginVotingPower({ + role, + className, + showDepositButton = true, +}: Props) { + const realm = useRealmQuery().data?.result + const voterWeight = useDelegatorAwareVoterWeight(role) + + const mintInfo = useMintInfoByPubkeyQuery(realm?.account.communityMint).data + ?.result + + const isLoading = useDepositStore((s) => s.state.isLoading) + const { isReady } = useRealmVoterWeightPlugins(role) + const { result: ownVoterWeight } = useLegacyVoterWeight() + + const formattedTokenAmount = useMemo( + () => + mintInfo && ownVoterWeight?.communityTokenRecord + ? new BigNumber( + ownVoterWeight?.communityTokenRecord?.account?.governingTokenDepositAmount?.toString() + ) + .shiftedBy(-mintInfo.decimals) + .toFixed(2) + .toString() + : undefined, + [mintInfo, ownVoterWeight?.communityTokenRecord] + ) + + const relevantMint = + role === 'community' + ? realm?.account.communityMint + : realm?.account.config.councilMint + + const tokenName = + getMintMetadata(relevantMint)?.name ?? realm?.account.name ?? '' + + const formattedTotal = useMemo( + () => + mintInfo && voterWeight?.value + ? new BigNumber(voterWeight?.value.toString()) + .shiftedBy(-mintInfo.decimals) + .toFixed(2) + .toString() + : undefined, + [mintInfo, voterWeight?.value] + ) + + if (isLoading || !isReady) { + return ( +
+ ) + } + + return ( +
+
+
+
+
+ {tokenName} + {role === 'council' ? ' Council' : ''} votes +
+
+

{formattedTotal ?? '0'}

+

+ ({formattedTokenAmount ?? '0'} tokens) +

+
+
+ {showDepositButton && ( +
+ +
+ )} +
+
+
+ ) +} diff --git a/components/ProposalVotingPower/QuadraticVotingInfoModal.tsx b/components/ProposalVotingPower/QuadraticVotingInfoModal.tsx new file mode 100644 index 0000000000..3f9ee6e488 --- /dev/null +++ b/components/ProposalVotingPower/QuadraticVotingInfoModal.tsx @@ -0,0 +1,90 @@ +import { useState } from 'react' + +import { InformationCircleIcon, UserGroupIcon } from '@heroicons/react/solid' +import Modal from '@components/Modal' + +interface QuadraticVotingInfoModalProps { + voteWeight: string + totalVoteWeight: string + totalMembers: number + tokenAmount: string +} + +export default function QuadraticVotingInfoModal({ + voteWeight, + totalVoteWeight, + totalMembers, + tokenAmount, +}: QuadraticVotingInfoModalProps) { + const [showQuadraticModal, setShowQuadraticModal] = useState(false) + + return ( +
+ + setShowQuadraticModal(true)} + /> + + {showQuadraticModal && ( + setShowQuadraticModal(false)} + isOpen={showQuadraticModal} + > +
+
+
+
+

+ {voteWeight ?? '0'} votes +

+

+ ({tokenAmount ?? '0'} tokens) +

+
+
+ +
+

{totalMembers} DAO members

+

holding {totalVoteWeight} tokens

+
+
+
+
+

What is Quadratic Voting?

+
+ Quadratic voting empowers individual voter groups, lessening + the influence of token-rich whales and giving more of a + proportional vote to smaller token holders. +
+
+
+
+
+

How is it calculated?

+
+ Quadratic voting is based on the square root of the amount of + tokens held by a member. The result is the number of{' '} + actual votes. +
+
+
+
+
+
Example Calculation:
+ +
+ 1 votes = 1 token +
+ 2 votes = 4 tokens +
3 votes = 9 tokens +
+
+
+
+
+ )} +
+ ) +} diff --git a/components/ProposalVotingPower/QuadraticVotingPower.tsx b/components/ProposalVotingPower/QuadraticVotingPower.tsx new file mode 100644 index 0000000000..b212c41949 --- /dev/null +++ b/components/ProposalVotingPower/QuadraticVotingPower.tsx @@ -0,0 +1,126 @@ +import classNames from 'classnames' +import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' + +import { GatewayStatus, useGateway } from '@civic/solana-gateway-react' +import { BN } from '@coral-xyz/anchor' +import { useLegacyVoterWeight } from '@hooks/queries/governancePower' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import { useRealmQuery } from '@hooks/queries/realm' +import { useDelegatorAwareVoterWeight } from '@hooks/useDelegatorAwareVoterWeight' +import { + useRealmVoterWeightPlugins, + useRealmVoterWeights, +} from '@hooks/useRealmVoterWeightPlugins' +import { BigNumber } from 'bignumber.js' +import { useMemo } from 'react' +import PluginVotingPower from './PluginVotingPower' +import QuadraticVotingInfoModal from './QuadraticVotingInfoModal' +import { useTokenOwnerRecordsForRealmQuery } from '@hooks/queries/tokenOwnerRecord' +import { Member } from '@utils/uiTypes/members' + +interface Props { + className?: string + role: 'community' | 'council' +} + +export default function QuadraticVotingPower({ role, className }: Props) { + const realm = useRealmQuery().data?.result + const { data: activeMembersData } = useTokenOwnerRecordsForRealmQuery() + const voterWeight = useDelegatorAwareVoterWeight(role) + + const mintInfo = useMintInfoByPubkeyQuery(realm?.account.communityMint).data + ?.result + + const activeMembers: Member[] | undefined = useMemo(() => activeMembersData?.map(member => ({ + walletAddress: member.account.governingTokenOwner.toBase58(), + communityVotes: new BN(0), + councilVotes: new BN(0) + })), [activeMembersData]) + + const isLoading = useDepositStore((s) => s.state.isLoading) + const { + isReady, + calculatedMaxVoterWeight, + plugins, + } = useRealmVoterWeightPlugins(role) + const { result: ownVoterWeight } = useLegacyVoterWeight() + + const formattedTokenAmount = useMemo( + () => + mintInfo && ownVoterWeight?.communityTokenRecord + ? new BigNumber( + ownVoterWeight?.communityTokenRecord?.account?.governingTokenDepositAmount?.toString() + ) + .shiftedBy(-mintInfo.decimals) + .toFixed(2) + .toString() + : undefined, + [mintInfo, ownVoterWeight?.communityTokenRecord] + ) + + const formattedMax = + mintInfo && calculatedMaxVoterWeight?.value + ? new BigNumber(calculatedMaxVoterWeight?.value.toString()) + .shiftedBy(-mintInfo.decimals) + .toString() + : undefined + + const formattedTotal = useMemo( + () => + mintInfo && voterWeight?.value + ? new BigNumber(voterWeight?.value.toString()) + .shiftedBy(-mintInfo.decimals) + .toFixed(2) + .toString() + : undefined, + [mintInfo, voterWeight?.value] + ) + + const { communityWeight, councilWeight } = useRealmVoterWeights() + const { gatewayStatus } = useGateway() + const isQVEnabled = plugins?.voterWeight.some((p) => p.name === 'QV') + const isGatewayEnabled = plugins?.voterWeight.some( + (p) => p.name === 'gateway' + ) + + const hasAnyVotingPower = + councilWeight?.value?.gt(new BN(0)) && communityWeight?.value?.gt(new BN(0)) + + if (isLoading || !isReady) { + return ( +
+ ) + } + + return ( +
+ {hasAnyVotingPower && isQVEnabled && ( +
+

Quadratic Voting

+ +
+ )} + { + // check if the last plugin is gateway to show the voting power + plugins?.voterWeight[plugins.voterWeight.length - 1].name === 'QV' && ( + + ) + } +
+ ) +} diff --git a/components/ProposalVotingPower/TokenHaverVotingPower.tsx b/components/ProposalVotingPower/TokenHaverVotingPower.tsx new file mode 100644 index 0000000000..6870c7e1a2 --- /dev/null +++ b/components/ProposalVotingPower/TokenHaverVotingPower.tsx @@ -0,0 +1,119 @@ +import classNames from 'classnames' +import useDepositStore from 'VoteStakeRegistry/stores/useDepositStore' + +import { getMintMetadata } from '@components/instructions/programs/splToken' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import { useRealmQuery } from '@hooks/queries/realm' +import { useDelegatorAwareVoterWeight } from '@hooks/useDelegatorAwareVoterWeight' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import { BigNumber } from 'bignumber.js' +import clsx from 'clsx' +import { useMemo } from 'react' +import { useJoinRealm } from '@hooks/useJoinRealm' +import { sendTransaction } from '@utils/send' +import { Transaction } from '@solana/web3.js' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useConnection } from '@solana/wallet-adapter-react' +import Button from '@components/Button' + +interface Props { + className?: string + role: 'community' | 'council' + showDepositButton?: boolean +} + +export default function TokenHaverVotingPower({ role, className }: Props) { + /** ideally this would all be removed and registration would be automatic upon acting */ + const wallet = useWalletOnePointOh() + const { connection } = useConnection() + const { + userNeedsTokenOwnerRecord, + userNeedsVoterWeightRecords, + handleRegister, + } = useJoinRealm() + const join = async () => { + const instructions = await handleRegister() + const transaction = new Transaction() + transaction.add(...instructions) + + await sendTransaction({ + transaction: transaction, + wallet: wallet!, + connection, + signers: [], + sendingMessage: `Registering`, + successMessage: `Registered`, + }) + } + const showJoinButton = + !!wallet?.connected && + (userNeedsTokenOwnerRecord || userNeedsVoterWeightRecords) + + /** */ + + const realm = useRealmQuery().data?.result + const voterWeight = useDelegatorAwareVoterWeight(role) + + const mintInfo = useMintInfoByPubkeyQuery(realm?.account.communityMint).data + ?.result + + const isLoading = useDepositStore((s) => s.state.isLoading) + const { isReady } = useRealmVoterWeightPlugins(role) + + const relevantMint = + role === 'community' + ? realm?.account.communityMint + : realm?.account.config.councilMint + + const tokenName = + getMintMetadata(relevantMint)?.name ?? realm?.account.name ?? '' + + const formattedTotal = useMemo( + () => + mintInfo && voterWeight?.value + ? new BigNumber(voterWeight?.value.toString()) + .shiftedBy(-mintInfo.decimals) + .toFixed(0) + .toString() + : undefined, + [mintInfo, voterWeight?.value] + ) + + if (isLoading || !isReady) { + return ( +
+ ) + } + + return ( +
+
+
+
+
+
+ {tokenName} + {role === 'council' ? ' Council' : ''} votes +
+
+

+ {formattedTotal ?? '0'} +

+
+
+
+
+
+ {showJoinButton && ( + + )} +
+ ) +} diff --git a/components/ProposalVotingPower/VotingPower.tsx b/components/ProposalVotingPower/VotingPower.tsx index 24909627ac..5ffdabeac8 100644 --- a/components/ProposalVotingPower/VotingPower.tsx +++ b/components/ProposalVotingPower/VotingPower.tsx @@ -1,152 +1,11 @@ -import classNames from 'classnames' -import { - ProgramAccount, - RealmConfigAccount, - TokenOwnerRecord, - Realm, - Proposal, -} from '@solana/spl-governance' -import { AccountInfo, MintInfo } from '@solana/spl-token' -import type { PublicKey } from '@solana/web3.js' -import { GoverningTokenRole } from '@solana/spl-governance' - -import { TokenProgramAccount } from '@utils/tokens' -import useRealm from '@hooks/useRealm' -import { nftPluginsPks, vsrPluginsPks } from '@hooks/useVotingPlugins' -import useProposal from '@hooks/useProposal' -import useWalletStore from 'stores/useWalletStore' - -import CommunityVotingPower from './CommunityVotingPower' -import CouncilVotingPower from './CouncilVotingPower' -import LockedCommunityVotingPower from './LockedCommunityVotingPower' -import LockedCouncilVotingPower from './LockedCouncilVotingPower' -import NftVotingPower from './NftVotingPower' - -enum Type { - Council, - LockedCouncil, - LockedCommunity, - NFT, - Community, -} - -function getTypes( - config?: ProgramAccount, - councilMint?: MintInfo, - councilTokenAccount?: TokenProgramAccount, - mint?: MintInfo, - ownCouncilTokenRecord?: ProgramAccount, - ownTokenRecord?: ProgramAccount, - proposal?: ProgramAccount, - realm?: ProgramAccount, - tokenType?: GoverningTokenRole -) { - const types: Type[] = [] - - const currentPluginPk = config?.account?.communityTokenConfig.voterWeightAddin - - if ( - currentPluginPk && - nftPluginsPks.includes(currentPluginPk.toBase58()) && - tokenType === GoverningTokenRole.Community - ) { - types.push(Type.NFT) - } else if ( - currentPluginPk && - vsrPluginsPks.includes(currentPluginPk.toBase58()) - ) { - const isDepositVisible = ( - depositMint: MintInfo | undefined, - realmMint: PublicKey | undefined - ) => - depositMint && - (!proposal || - proposal.account.governingTokenMint.toBase58() === - realmMint?.toBase58()) - - if ( - (!realm?.account.config.councilMint || - isDepositVisible(mint, realm?.account.communityMint)) && - tokenType === GoverningTokenRole.Community - ) { - types.push(Type.LockedCommunity) - } else if ( - isDepositVisible(councilMint, realm?.account.config.councilMint) && - tokenType === GoverningTokenRole.Council - ) { - types.push(Type.LockedCouncil) - } - } else if (tokenType === GoverningTokenRole.Council) { - types.push(Type.Council) - } else if (tokenType === GoverningTokenRole.Community) { - types.push(Type.Community) - } - - return types -} - -interface Props { - className?: string -} - -export default function VotingPower(props: Props) { - const { proposal } = useProposal() - const { - config, - councilMint, - councilTokenAccount, - mint, - ownCouncilTokenRecord, - ownTokenRecord, - realm, - } = useRealm() - const connected = useWalletStore((s) => s.connected) - const tokenType = useWalletStore((s) => s.selectedProposal.tokenType) - - const types = getTypes( - config, - councilMint, - councilTokenAccount, - mint, - ownCouncilTokenRecord, - ownTokenRecord, - proposal, - realm, - tokenType - ) - - if (!connected || !proposal) { - return ( -
- ) - } - - if (connected && types.length === 0) { - return ( -
- You do not have any voting power in this realm. -
- ) - } - - return ( -
- {types.map((type) => { - switch (type) { - case Type.Council: - return - case Type.LockedCommunity: - return - case Type.LockedCouncil: - return - case Type.Community: - return - case Type.NFT: - return - } - })} -
+import { useVotingPop } from '@components/VotePanel/hooks' +import GovernancePowerForRole from '@components/GovernancePower/GovernancePowerForRole' + +export default function VotingPower() { + const votePop = useVotingPop() + return votePop === undefined ? ( +
+ ) : ( + ) } diff --git a/components/ProposalVotingPower/VotingPowerPct.tsx b/components/ProposalVotingPower/VotingPowerPct.tsx index b05897c124..a65707ed19 100644 --- a/components/ProposalVotingPower/VotingPowerPct.tsx +++ b/components/ProposalVotingPower/VotingPowerPct.tsx @@ -27,14 +27,12 @@ export default function VotingPowerPct(props: Props) { className={classNames( props.className, 'leading-[15px]', - 'text-[11px]', + 'text-xs', 'text-right', - 'text-white/70' + 'text-fgd-2' )} > {getPct(props.amount, props.total)}% of total -
- voting power
) } diff --git a/components/ProposalVotingPower/depositTokens.ts b/components/ProposalVotingPower/depositTokens.ts deleted file mode 100644 index 8bd826f8ea..0000000000 --- a/components/ProposalVotingPower/depositTokens.ts +++ /dev/null @@ -1,83 +0,0 @@ -import type BigNumber from 'bignumber.js' -import type { SignerWalletAdapter } from '@solana/wallet-adapter-base' -import { - ProgramAccount, - Realm, - withDepositGoverningTokens, -} from '@solana/spl-governance' -import { - Connection, - Keypair, - Transaction, - TransactionInstruction, -} from '@solana/web3.js' -import BN from 'bn.js' - -import { RealmInfo, getProgramVersionForRealm } from '@models/registry/api' -import { - approveTokenTransfer, - TokenAccount, - TokenProgramAccount, -} from '@utils/tokens' -import { sendTransaction } from '@utils/send' - -interface Args { - amount: BigNumber - connection: Connection - depositTokenAccount: TokenProgramAccount - realm: ProgramAccount - realmInfo: RealmInfo - wallet: SignerWalletAdapter -} - -export default async function depositTokens({ - amount, - connection, - depositTokenAccount, - realm, - realmInfo, - wallet, -}: Args) { - if (!wallet.publicKey) { - throw new Error('Could not complete deposit; wallet missing publicKey') - } - - const instructions: TransactionInstruction[] = [] - const signers: Keypair[] = [] - const amountBN = new BN(amount.toString()) - - const transferAuthority = approveTokenTransfer( - instructions, - [], - depositTokenAccount.publicKey, - wallet.publicKey, - amountBN - ) - - signers.push(transferAuthority) - - await withDepositGoverningTokens( - instructions, - realmInfo.programId, - getProgramVersionForRealm(realmInfo!), - realm.pubkey, - depositTokenAccount.publicKey, - depositTokenAccount.account.mint, - wallet!.publicKey, - transferAuthority.publicKey, - wallet!.publicKey, - amountBN - ) - - const transaction = new Transaction() - transaction.add(...instructions) - - await sendTransaction({ - connection, - signers, - transaction, - wallet, - sendingMessage: 'Depositing tokens', - successMessage: 'Tokens have been deposited', - }) -} diff --git a/components/ProposalVotingPower/getNumTokens.ts b/components/ProposalVotingPower/getNumTokens.ts index fc121e1477..37cad87d77 100644 --- a/components/ProposalVotingPower/getNumTokens.ts +++ b/components/ProposalVotingPower/getNumTokens.ts @@ -1,17 +1,11 @@ import type { ProgramAccount, TokenOwnerRecord } from '@solana/spl-governance' import type { MintInfo } from '@solana/spl-token' -import { - LOCALNET_REALM_ID as PYTH_LOCALNET_REALM_ID, - PythBalance, -} from 'pyth-staking-api' import { BigNumber } from 'bignumber.js' import { getMintDecimalAmount } from '@tools/sdk/units' import type { VoteRegistryVoterWeight, VoteNftWeight, - SwitchboardQueueVoteWeight, - PythVoterWeight, SimpleGatedVoterWeight, VoterWeight, } from '../../models/voteWeights' @@ -20,26 +14,15 @@ import type { RealmInfo } from '../../models/registry/api' type OwnVoterWeight = | VoteRegistryVoterWeight | VoteNftWeight - | SwitchboardQueueVoteWeight - | PythVoterWeight | SimpleGatedVoterWeight | VoterWeight export default function getNumTokens( - ownVoterWeight: OwnVoterWeight, + _ownVoterWeight: OwnVoterWeight, depositTokenRecord?: ProgramAccount, mint?: MintInfo, - realmInfo?: RealmInfo + _realmInfo?: RealmInfo ) { - const isPyth = - realmInfo?.realmId.toBase58() === PYTH_LOCALNET_REALM_ID.toBase58() - - if (isPyth && ownVoterWeight.votingPower) { - return new BigNumber( - new PythBalance(ownVoterWeight.votingPower).toBN().toString() - ) - } - if (depositTokenRecord && mint) { return getMintDecimalAmount( mint, diff --git a/components/ProposalVotingPower/index.tsx b/components/ProposalVotingPower/index.tsx index 19096007a8..d95e95573c 100644 --- a/components/ProposalVotingPower/index.tsx +++ b/components/ProposalVotingPower/index.tsx @@ -1,38 +1,21 @@ import classNames from 'classnames' -import useWalletStore from 'stores/useWalletStore' -import { - gatewayPluginsPks, - switchboardPluginsPks, -} from '@hooks/useVotingPlugins' -import TokenBalanceCardWrapper from '@components/TokenBalance/TokenBalanceCardWrapper' -import useRealm from '@hooks/useRealm' -import useProposal from '@hooks/useProposal' -import { option } from '@tools/core/option' - import VotingPower from './VotingPower' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' interface Props { className?: string } export default function ProposalVotingPower(props: Props) { - const connected = !!useWalletStore((s) => s.current?.connected) - const { config } = useRealm() - const { proposal } = useProposal() - - const currentPluginPk = config?.account?.communityTokenConfig.voterWeightAddin - + const connected = useWalletOnePointOh()?.connected + /* const isUsingGatewayPlugin = - currentPluginPk && gatewayPluginsPks.includes(currentPluginPk.toBase58()) - - const isUsingSwitchboardPlugin = - currentPluginPk && - switchboardPluginsPks.includes(currentPluginPk.toBase58()) + currentPluginPk && GATEWAY_PLUGINS_PKS.includes(currentPluginPk.toBase58()) - if (isUsingGatewayPlugin || isUsingSwitchboardPlugin) { + if (isUsingGatewayPlugin) { return - } + } */ return (
{ + return ( +
+
+
+
+

{quorumTitle} Quorum

+ + + +
+ {typeof progress !== 'undefined' && progress < 100 ? ( +

{`${( + votesRequired ?? 0 + ).toLocaleString(undefined, { + maximumFractionDigits: 0, + })} ${(progress ?? 0) > 0 ? 'more' : ''} ${voteKindTitle} vote${ + //@ts-ignore + (votesRequired ?? 0) > 1 ? 's' : '' + } required`}

+ ) : ( +
+ +

+ Required approval achieved +

+
+ )} +
+
+ {/* {progress < 100 ? ( */} +
+
= 100 ? 'bg-green' : 'bg-fgd-3' + } flex rounded`} + >
+
+ {/* ) : null} */} +
+ ) +} + +export const ApprovalProgress = (props: Props) => ( + +) + +export const VetoProgress = (props: Props) => ( + +) diff --git a/components/RealmHeader.tsx b/components/RealmHeader.tsx index 500f375c09..41f219c657 100644 --- a/components/RealmHeader.tsx +++ b/components/RealmHeader.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import { useEffect, useState } from 'react' import useRealm from 'hooks/useRealm' import { ChartPieIcon, CogIcon, UsersIcon } from '@heroicons/react/outline' import { ChevronLeftIcon } from '@heroicons/react/solid' @@ -6,25 +6,26 @@ import Link from 'next/link' import useQueryContext from 'hooks/useQueryContext' import { ExternalLinkIcon } from '@heroicons/react/outline' import { getRealmExplorerHost } from 'tools/routing' - -import useMembersStore from 'stores/useMembersStore' -import { vsrPluginsPks } from '@hooks/useVotingPlugins' import { tryParsePublicKey } from '@tools/core/pubkey' +import { useRealmQuery } from '@hooks/queries/realm' +import { useConnection } from '@solana/wallet-adapter-react' const RealmHeader = () => { const { fmtUrlWithCluster } = useQueryContext() - const { realm, realmInfo, realmDisplayName, symbol, config } = useRealm() + const realm = useRealmQuery().data?.result const { REALM } = process.env - const activeMembers = useMembersStore((s) => s.compact.activeMembers) - const isLockTokensMode = - config?.account.communityTokenConfig.voterWeightAddin && - vsrPluginsPks.includes( - config?.account.communityTokenConfig.voterWeightAddin?.toBase58() - ) - const isBackNavVisible = realmInfo?.symbol !== REALM // hide backnav for the default realm + const { connection } = useConnection() + + const { realmInfo, symbol, vsrMode } = useRealm() const explorerHost = getRealmExplorerHost(realmInfo) - const realmUrl = `https://${explorerHost}/#/realm/${realmInfo?.realmId.toBase58()}?programId=${realmInfo?.programId.toBase58()}` + const realmUrl = `https://${explorerHost}/account/${realmInfo?.realmId.toBase58()}${connection.rpcEndpoint.includes("devnet") ? "?cluster=devnet" : ""}` + + const [isBackNavVisible, setIsBackNavVisible] = useState(true) + + useEffect(() => { + setIsBackNavVisible(realmInfo?.symbol !== REALM) + }, [realmInfo?.symbol, REALM]) return (
@@ -43,7 +44,7 @@ const RealmHeader = () => { ) : null}
- {realmDisplayName ? ( + {realmInfo?.displayName ? (
{realmInfo?.ogImage ? ( @@ -53,11 +54,11 @@ const RealmHeader = () => { > ) : (
- {realmDisplayName?.charAt(0)} + {realmInfo.displayName.charAt(0)}
)}
-

{realmDisplayName}

+

{realmInfo.displayName}

@@ -65,15 +66,7 @@ const RealmHeader = () => {
)}
- {!config?.account.communityTokenConfig.voterWeightAddin && ( - - - - Members ({activeMembers.length}) - - - )} - {isLockTokensMode && ( + {vsrMode === 'default' && ( @@ -84,6 +77,12 @@ const RealmHeader = () => { )} + + + + Members + + diff --git a/components/ScrollToTop.tsx b/components/ScrollToTop.tsx deleted file mode 100644 index 62fd0206f6..0000000000 --- a/components/ScrollToTop.tsx +++ /dev/null @@ -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 && ( -
- -
- ) - ) -} diff --git a/components/SelectInstructionType.tsx b/components/SelectInstructionType.tsx new file mode 100644 index 0000000000..e22b62f66b --- /dev/null +++ b/components/SelectInstructionType.tsx @@ -0,0 +1,183 @@ +import useGovernanceAssets, { + InstructionType, +} from '@hooks/useGovernanceAssets' +import { Instructions, PackageEnum } from '@utils/uiTypes/proposalCreationTypes' +import { useCallback, useEffect, useState } from 'react' +import ImageTextSelection from './ImageTextSelection' +import TypeaheadSelect from './TypeaheadSelect' + +function sortInstructionTypes( + instructionTypes: InstructionType[] +): InstructionType[] { + return instructionTypes.sort((instructionTypeA, instructionTypeB) => { + // Sort by package id + // Common package always first + if (instructionTypeA.packageId !== instructionTypeB.packageId) { + if (instructionTypeA.packageId === PackageEnum.Common) { + return -1 + } + + if (instructionTypeB.packageId === PackageEnum.Common) { + return 1 + } + + return instructionTypeA.packageId - instructionTypeB.packageId + } + + // Then sort by instruction name + // None transaction always first + if (instructionTypeA.id === Instructions.None) { + return -1 + } + + if (instructionTypeB.id === Instructions.None) { + return 1 + } + + // Alphabetical order + return instructionTypeA.name < instructionTypeB.name ? -1 : 1 + }) +} + +const SelectInstructionType = ({ + instructionTypes, + selectedInstruction, + onChange, +}: { + selectedInstruction?: InstructionType + instructionTypes: InstructionType[] + onChange: (instructionType: InstructionType | null) => void +}) => { + const [packageId, setPackageId] = useState(null) + const { availablePackages, getPackageTypeById } = useGovernanceAssets() + + const [ + filteredAndSortedInstructionTypes, + setFilteredAndSortedInstructionTypes, + ] = useState([]) + + const computeFilteredAndSortedInstructionsTypes = useCallback(() => { + if (packageId === null) { + const sortedInstructionTypes = sortInstructionTypes(instructionTypes) + setFilteredAndSortedInstructionTypes(sortedInstructionTypes) + + // Select first instruction by default + if (instructionTypes.length && !selectedInstruction) { + onChange(instructionTypes[0]) + } + + return + } + + if (selectedInstruction && selectedInstruction.packageId !== packageId) { + onChange(null) + } + + const filteredAndSortedInstructionTypes = sortInstructionTypes( + instructionTypes.filter( + (instructionType) => instructionType.packageId === packageId + ) + ) + + // Select first instruction by default + if (filteredAndSortedInstructionTypes.length && !selectedInstruction) { + onChange(filteredAndSortedInstructionTypes[0]) + } + + setFilteredAndSortedInstructionTypes(filteredAndSortedInstructionTypes) + }, [packageId, selectedInstruction, instructionTypes, onChange]) + + useEffect(() => { + computeFilteredAndSortedInstructionsTypes() + }, [computeFilteredAndSortedInstructionsTypes]) + + const getInstructionDisplayName = (instruction?: InstructionType): string => { + if (!instruction || typeof instruction.packageId === 'undefined') { + return '' + } + + // Only display package name as prefix when no package is selected + return `${ + instruction.packageId !== null && packageId === null + ? `${getPackageTypeById(instruction.packageId)?.name}: ` ?? '' + : '' + }${instruction.name}` + } + + const packages = [ + { + id: null, + name: 'All', + }, + + // Sort the packages in the following order: + // Common always first + // Then packages without images + // Then by alphabetical order (id are sorted by alphabetical order already) + ...availablePackages.sort((packageA, packageB): number => { + if (packageA.id === PackageEnum.Common) { + return -1 + } + + if ( + typeof packageA.image === 'undefined' && + typeof packageB.image !== 'undefined' + ) { + return -1 + } + + if ( + typeof packageA.image !== 'undefined' && + typeof packageB.image === 'undefined' + ) { + return 1 + } + + return packageA.id - packageB.id + }), + ] + + return ( +
+
+ + + ({ + key: instructionType.id.toString(), + text: getInstructionDisplayName(instructionType), + }))} + selected={ + selectedInstruction + ? { + key: selectedInstruction.id.toString(), + } + : undefined + } + onSelect={(option) => { + if (!option?.key) { + return onChange(null) + } + + const id = option.key + + onChange( + filteredAndSortedInstructionTypes.find( + (instructionType) => instructionType.id.toString() === id + ) ?? null + ) + }} + /> +
+
+ ) +} + +export default SelectInstructionType diff --git a/components/SelectPrimaryDelegators.tsx b/components/SelectPrimaryDelegators.tsx new file mode 100644 index 0000000000..6f58515587 --- /dev/null +++ b/components/SelectPrimaryDelegators.tsx @@ -0,0 +1,278 @@ +import Select from '@components/inputs/Select' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useTokenOwnerRecordsDelegatedToUser } from '@hooks/queries/tokenOwnerRecord' +import { useSelectedDelegatorStore } from 'stores/useSelectedDelegatorStore' +import { PublicKey } from '@solana/web3.js' +import { useRealmQuery } from '@hooks/queries/realm' +import { useMemo } from 'react' +import { ProgramAccount, TokenOwnerRecord } from '@solana/spl-governance' +import { capitalize } from '@utils/helpers' +import { ProfileName } from './Profile/ProfileName' +import { useAsync } from 'react-async-hook' +import { determineVotingPowerType } from '@hooks/queries/governancePower' +import { useConnection } from '@solana/wallet-adapter-react' +import useSelectedRealmPubkey from '@hooks/selectedRealm/useSelectedRealmPubkey' +import { DELEGATOR_BATCH_VOTE_SUPPORT_BY_PLUGIN } from '@constants/flags' + +const YOUR_WALLET_VALUE = 'Yourself + all delegators' +const JUST_YOUR_WALLET = 'Yourself only' + +const SelectPrimaryDelegators = () => { + const wallet = useWalletOnePointOh() + const walletId = wallet?.publicKey?.toBase58() + const realm = useRealmQuery().data?.result + + const { data: delegatesArray } = useTokenOwnerRecordsDelegatedToUser() + + // returns array of community tokenOwnerRecords that connected wallet has been delegated + const communityTorsDelegatedToUser = useMemo( + () => + realm === undefined + ? undefined + : delegatesArray?.filter((x) => + x.account.governingTokenMint.equals(realm.account.communityMint) + ), + [delegatesArray, realm] + ) + + const councilMintAddr = realm?.account.config.councilMint + + // returns array of council tokenOwnerRecords that connected wallet has been delegated + const councilTorsDelegatedToUser = useMemo( + () => + councilMintAddr === undefined + ? undefined + : delegatesArray?.filter((x) => + x.account.governingTokenMint.equals(councilMintAddr) + ), + [delegatesArray, councilMintAddr] + ) + + const { + councilDelegator, + communityDelegator, + setCommunityDelegator, + setCouncilDelegator, + } = useSelectedDelegatorStore() + + const handleCouncilSelect = (councilWalletPk: string | undefined) => { + setCouncilDelegator( + councilWalletPk !== undefined ? new PublicKey(councilWalletPk) : undefined + ) + } + + const handleCommunitySelect = (communityWalletPk: string | undefined) => { + setCommunityDelegator( + communityWalletPk ? new PublicKey(communityWalletPk) : undefined + ) + } + + return ( + <> + {((walletId && + communityTorsDelegatedToUser && + communityTorsDelegatedToUser.length > 0) || + communityDelegator) && ( + + )} + {((walletId && + councilTorsDelegatedToUser && + councilTorsDelegatedToUser.length > 0) || + councilDelegator) && ( + + )} + + ) +} + +export default SelectPrimaryDelegators + +const usePluginNameAsync = (kind: 'community' | 'council') => { + const { connection } = useConnection() + const realmPk = useSelectedRealmPubkey() + return useAsync( + async () => + kind && realmPk && determineVotingPowerType(connection, realmPk, kind), + [connection, realmPk, kind] + ) +} + +function PrimaryDelegatorSelectBatchSupported({ + selectedDelegator, + handleSelect, + kind, + tors, +}: { + selectedDelegator: PublicKey | undefined + handleSelect: (tokenRecordPk: string) => void + kind: 'community' | 'council' + tors: ProgramAccount[] +}) { + const wallet = useWalletOnePointOh() + const walletPk = wallet?.publicKey ?? undefined + + const { result: plugin } = usePluginNameAsync(kind) + const batchDelegatorUxSupported = + plugin && DELEGATOR_BATCH_VOTE_SUPPORT_BY_PLUGIN[plugin] + + return ( +
+
+

+ Perform {capitalize(kind)} actions as: +

+ +
+
+ ) +} + +// its a conditional, make it use the old or new component depending on support. thanks. +const PrimaryDelegatorSelect = ( + props: Parameters[0] +) => { + const { result: plugin } = usePluginNameAsync(props.kind) + const batchDelegatorUxSupported = + plugin && DELEGATOR_BATCH_VOTE_SUPPORT_BY_PLUGIN[plugin] + return batchDelegatorUxSupported ? ( + + ) : ( + + ) +} + +/** Used when batched delegator voting is not supported */ +function PrimaryDelegatorSelectOld({ + selectedDelegator, + handleSelect, + + kind, + tors, +}: { + selectedDelegator: PublicKey | undefined + handleSelect: (tokenRecordPk: string) => void + kind: 'community' | 'council' + tors: ProgramAccount[] +}) { + const wallet = useWalletOnePointOh() + const walletPk = wallet?.publicKey ?? undefined + + return ( +
+
+

+ Perform {capitalize(kind)} actions as: +

+ +
+
+ ) +} diff --git a/components/SendNft.tsx b/components/SendNft.tsx new file mode 100644 index 0000000000..255ee4df2b --- /dev/null +++ b/components/SendNft.tsx @@ -0,0 +1,410 @@ +import Button from '@components/Button' +import Input from '@components/inputs/Input' +import { PublicKey } from '@solana/web3.js' +import { tryParseKey } from '@tools/validators/pubkey' +import { abbreviateAddress } from '@utils/formatting' +import React, { useMemo, useState } from 'react' +import { + ArrowCircleDownIcon, + ArrowCircleUpIcon, + CheckCircleIcon, + PhotographIcon, + // InformationCircleIcon, +} from '@heroicons/react/solid' +import { + getInstructionDataFromBase64, + getNativeTreasuryAddress, + serializeInstructionToBase64, +} from '@solana/spl-governance' +import useQueryContext from '@hooks/useQueryContext' +import { useRouter } from 'next/router' +import { notify } from '@utils/notifications' +import Textarea from '@components/inputs/Textarea' +// import { Popover } from '@headlessui/react' +import Tooltip from '@components/Tooltip' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import VoteBySwitch from 'pages/dao/[symbol]/proposal/components/VoteBySwitch' +import useCreateProposal from '@hooks/useCreateProposal' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import NFTAccountSelect from './TreasuryAccount/NFTAccountSelect' +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + Token, +} from '@solana/spl-token' +import { createIx_transferNft } from '@utils/metaplex' +import { + fetchDigitalAssetById, + useRealmDigitalAssetsQuery, +} from '@hooks/queries/digitalAssets' +import { SetStateAction } from 'react' +import ImgWithLoader from './ImgWithLoader' +import useTreasuryAddressForGovernance from '@hooks/useTreasuryAddressForGovernance' +import Loading from './Loading' +import { fetchGovernanceByPubkey } from '@hooks/queries/governance' +import { useConnection } from '@solana/wallet-adapter-react' +import useGovernanceSelect from '@hooks/useGovernanceSelect' +import { SUPPORT_CNFTS } from '@constants/flags' +import clsx from 'clsx' +import { getNetworkFromEndpoint } from '@utils/connection' +import { buildTransferCnftInstruction } from '@hooks/instructions/useTransferCnftInstruction' +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; + +const SendNft = ({ + initialNftAndGovernanceSelected, +}: { + initialNftAndGovernanceSelected?: + | [PublicKey, PublicKey] + | [undefined, PublicKey] +}) => { + const { connection } = useConnection() + const realm = useRealmQuery().data?.result + const { propose } = useCreateProposal() + const { canUseTransferInstruction } = useGovernanceAssets() + const { fmtUrlWithCluster } = useQueryContext() + const wallet = useWalletOnePointOh() + const router = useRouter() + + const [selectedNfts, setSelectedNfts] = useState( + initialNftAndGovernanceSelected?.[0] + ? [initialNftAndGovernanceSelected[0]] + : [] + ) + const [selectedGovernance, setSelectedGovernance] = useGovernanceSelect( + initialNftAndGovernanceSelected?.[1] + ) + const { voteByCouncil, shouldShowVoteByCouncilToggle, setVoteByCouncil } = useVoteByCouncilToggle(); + const [showOptions, setShowOptions] = useState(false) + const [destination, setDestination] = useState('') + const [title, setTitle] = useState('') + const [description, setDescription] = useState('') + const [isLoading, setIsLoading] = useState(false) + const [formErrors, setFormErrors] = useState({}) + + const nftName: string | undefined = undefined + const defaultTitle = `Send ${nftName ? nftName : 'NFT'} to ${ + tryParseKey(destination) + ? abbreviateAddress(new PublicKey(destination)) + : '...' + }` + + const walletPk = wallet?.publicKey ?? undefined + const handleProposeNftSend = async () => { + if (!realm || !selectedGovernance) { + throw new Error() + } + if (walletPk === undefined) { + throw 'connect wallet' + } + + const toOwner = tryParseKey(destination) + if (toOwner === null) + return setFormErrors({ destination: 'invalid destination' }) + + setIsLoading(true) + + let anyCompressed = false + const instructions = await Promise.all( + selectedNfts.map(async (nftMint) => { + const network = getNetworkFromEndpoint(connection.rpcEndpoint) + if (network === 'localnet') throw new Error() + const nft = (await fetchDigitalAssetById(network, nftMint)).result + if (nft === undefined) throw new Error('nft not found') + + if (nft.compression?.compressed) { + anyCompressed = true + const ix = await buildTransferCnftInstruction( + connection, + nftMint, + toOwner + ) + return { + serializedInstruction: serializeInstructionToBase64(ix), + isValid: true, + prerequisiteInstructions: [], + } + } else { + const destinationAtaPk = await Token.getAssociatedTokenAddress( + ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID + TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID + nftMint, // mint + toOwner, // owner + true + ) + const destinationAtaQueried = await connection.getAccountInfo( + destinationAtaPk + ) + + // typically this should just be the same as the account that owns the NFT, but sometimes the governance owns it + const nativeTreasury = await getNativeTreasuryAddress( + realm.owner, + selectedGovernance + ) + + const fromOwnerString = nft.ownership.owner + const fromOwner = tryParseKey(fromOwnerString) + // should be impossible, but stuff isn't typed + if (fromOwner === null) throw new Error() + + const transferIx = await createIx_transferNft( + connection, + fromOwner, + toOwner, + nftMint, + fromOwner, + nativeTreasury + ) + + return { + serializedInstruction: serializeInstructionToBase64(transferIx), + isValid: true, + prerequisiteInstructions: + destinationAtaQueried === null + ? [ + Token.createAssociatedTokenAccountInstruction( + ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID + TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID + nftMint, // mint + destinationAtaPk, // ata + toOwner, // owner of token account + walletPk // fee payer + ), + ] + : [], + } + } + }) + ) + + const governanceFetched = await fetchGovernanceByPubkey( + connection, + selectedGovernance + ) + if (governanceFetched.result === undefined) + throw new Error('governance not found') + + const instructionsData = instructions.map((instruction) => ({ + data: getInstructionDataFromBase64(instruction.serializedInstruction), + holdUpTime: + governanceFetched.result.account.config.minInstructionHoldUpTime, + prerequisiteInstructions: instruction.prerequisiteInstructions ?? [], + chunkBy: 1, + })) + + try { + const proposalAddress = await propose({ + title: title !== '' ? title : defaultTitle, + description, + voteByCouncil, + instructionsData, + governance: selectedGovernance, + utilizeLookupTable: anyCompressed, + }) + const url = fmtUrlWithCluster( + `/dao/${router.query.symbol}/proposal/${proposalAddress}` + ) + router.push(url) + } catch (ex) { + notify({ type: 'error', message: `${ex}` }) + //console.error(ex) + setIsLoading(false) + throw ex + } + setIsLoading(false) + } + + return ( + <> +

+ <>Send NFT +

+ + {selectedGovernance !== undefined && ( + setSelectedGovernance(value)} + selectedGovernance={selectedGovernance} + /> + )} + +
+ { + // TODO use some kind of good wallet pubkey input + } + setDestination(evt.target.value)} + noMaxWidth={true} + error={formErrors['destination']} + /> + + {selectedGovernance !== undefined && ( + + )} +
setShowOptions(!showOptions)} + > + {showOptions ? ( + + ) : ( + + )} + Options +
+ {showOptions && ( + <> + setTitle(evt.target.value)} + /> + + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > + )} + + )} +
+
+ +
+ + ) +} + +/** Select NFTs owned by a given governance */ +function GovernanceNFTSelector({ + governance, + nftWidth = '150px', + nftHeight = '150px', + selectedNfts, + setSelectedNfts, +}: { + governance: PublicKey + selectedNfts: PublicKey[] + setSelectedNfts: React.Dispatch> + nftWidth?: string + nftHeight?: string +}) { + const { result: treasuryAddress } = useTreasuryAddressForGovernance( + governance + ) + + // TODO just query by owner (which should be in cache already) + const { data: allNfts, isLoading } = useRealmDigitalAssetsQuery() + const nfts = useMemo( + () => + allNfts + ?.flat() + .filter((x) => SUPPORT_CNFTS || !x.compression.compressed) + .filter( + (x) => + x.ownership.owner === governance.toString() || + x.ownership.owner === treasuryAddress?.toString() + ), + [allNfts, governance, treasuryAddress] + ) + + return ( + <> +
+ {!isLoading ? ( + nfts?.length ? ( +
+ {nfts.map((nft) => ( +
+ setSelectedNfts((prev) => { + const alreadyIncluded = prev.find( + (x) => x.toString() === nft.id + ) + return alreadyIncluded + ? prev.filter((x) => x.toString() !== nft.id) + : [...prev, new PublicKey(nft.id)] + }) + } + key={nft.id} + className={clsx( + `bg-bkg-2 flex-shrink-0 flex items-center justify-center cursor-pointer default-transition rounded-lg relative overflow-hidden`, + selectedNfts.find((k) => k.toString() === nft.id) + ? 'border-4 border-green' + : 'border border-transparent hover:border-primary-dark ' + )} + style={{ + width: nftWidth, + height: nftHeight, + }} + > + {selectedNfts.find((k) => k.toString() === nft.id) && ( + + )} + + +
+ ))} +
+ ) : ( +
+ {"Account doesn't have any NFTs"} + +
+ ) + ) : ( + + )} +
+ + ) +} + +export default SendNft diff --git a/components/StreamCard.tsx b/components/StreamCard.tsx deleted file mode 100644 index 84de87fb04..0000000000 --- a/components/StreamCard.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import { Connection, PublicKey, SystemProgram } from '@solana/web3.js' -import { AccountMetaData } from '@solana/spl-governance' -import { TOKEN_PROGRAM_ID } from '@solana/spl-token' - -import tokenService from '@utils/services/token' - -import { - StreamClient, - Cluster, - cancelStreamInstruction, - Stream, -} from '@streamflow/stream' -import Button from '@components/Button' - -import { serializeInstructionToBase64 } from '@solana/spl-governance' - -import useWalletStore from 'stores/useWalletStore' -import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes' -import useCreateProposal from '@hooks/useCreateProposal' -import { InstructionDataWithHoldUpTime } from 'actions/createProposal' -import useQueryContext from '@hooks/useQueryContext' -import { useRouter } from 'next/router' -import { notify } from '@utils/notifications' -import useRealm from '@hooks/useRealm' -import { useEffect, useState } from 'react' -import useGovernanceAssets from '@hooks/useGovernanceAssets' - -import { STREAMFLOW_PROGRAM_ID } from 'pages/dao/[symbol]/proposal/components/instructions/Streamflow/CreateStream' - -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 function getMintMetadata( - tokenMintPk: PublicKey | undefined -): TokenMintMetadata { - const tokenMintAddress = tokenMintPk ? tokenMintPk.toBase58() : '' - const tokenInfo = tokenMintAddress - ? tokenService.getTokenInfo(tokenMintAddress) - : null - return tokenInfo - ? { - name: tokenInfo.symbol, - decimals: tokenInfo.decimals, - address: tokenInfo.address, - } - : MINT_METADATA[tokenMintAddress] -} - -export default function StreamCard({ - connection, - accounts, -}: { - connection: Connection - accounts: AccountMetaData[] -}) { - const router = useRouter() - const { realm, symbol } = useRealm() - const { assetAccounts } = useGovernanceAssets() - - const { fmtUrlWithCluster } = useQueryContext() - const wallet = useWalletStore((s) => s.current) - const { handleCreateProposal } = useCreateProposal() - const [voteByCouncil] = useState(false) - const defaultCancelTitle = 'Cancel streamflow contract' - const [creatingProposal, setCreatingProposal] = useState(false) - - const [stream, setStream] = useState() - - useEffect(() => { - async function fetch() { - const cli = new StreamClient( - connection.rpcEndpoint, - Cluster.Devnet, - undefined, - accounts[0].pubkey.toBase58() - ) - const contract_metadata = accounts[2].pubkey - const stream = await cli.getOne(contract_metadata.toBase58()) - setStream(stream) - } - if (!stream) { - fetch() - } - }) - - const contract_metadata = accounts[2].pubkey - if (stream?.createdAt == 0 || !stream?.cancelableBySender) { - return <> - } - const creator_governance = new PublicKey(stream.sender) - - const handleCancel = async () => { - let serializedInstruction = '' - if (wallet?.publicKey && realm) { - setCreatingProposal(true) - const cancelStreamAccounts = { - authority: creator_governance, - sender: creator_governance, - senderTokens: new PublicKey(stream.senderTokens), - recipient: new PublicKey(stream.recipient), - recipientTokens: new PublicKey(stream.recipientTokens), - metadata: new PublicKey(contract_metadata), - escrowTokens: new PublicKey(stream.escrowTokens), - streamflowTreasury: new PublicKey(stream.streamflowTreasury), - streamflowTreasuryTokens: new PublicKey( - stream.streamflowTreasuryTokens - ), - partner: new PublicKey(stream.partner), - partnerTokens: new PublicKey(stream.partnerTokens), - mint: new PublicKey(stream.mint), - tokenProgram: new PublicKey(TOKEN_PROGRAM_ID), - systemProgram: SystemProgram.programId, - } - const instruction = cancelStreamInstruction( - new PublicKey(STREAMFLOW_PROGRAM_ID), - cancelStreamAccounts - ) - const governance = assetAccounts.find( - (account) => account.pubkey.toBase58() === creator_governance.toBase58() - )?.governance - serializedInstruction = serializeInstructionToBase64(instruction) - const obj: UiInstruction = { - serializedInstruction: serializedInstruction, - isValid: true, - governance, - } - const instructionData = new InstructionDataWithHoldUpTime({ - instruction: obj, - governance, - }) - try { - const proposalAddress = await handleCreateProposal({ - title: defaultCancelTitle, - description: '', - voteByCouncil, - instructionsData: [instructionData], - governance: governance!, - }) - const url = fmtUrlWithCluster( - `/dao/${symbol}/proposal/${proposalAddress}` - ) - router.push(url) - } catch (ex) { - notify({ type: 'error', message: `${ex}` }) - } - setCreatingProposal(false) - } - } - - return ( - <> - {} -
- -
- - ) -} diff --git a/components/TableElements.tsx b/components/TableElements.tsx index 744c5556db..364c5e1252 100644 --- a/components/TableElements.tsx +++ b/components/TableElements.tsx @@ -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 }) => ( {children}
@@ -84,24 +83,3 @@ export const ExpandableRow = ({ ) } - -type RowProps = { - children: React.ReactNode -} - -export const Row = ({ children }: RowProps) => { - return ( -
- {children} -
- ) -} - -export const TableDateDisplay = ({ date }: { date: string | number }) => ( - <> -

{dayjs(date).format('DD MMM YYYY')}

-

{dayjs(date).format('h:mma')}

- -) diff --git a/components/TermsPopup.tsx b/components/TermsPopup.tsx new file mode 100644 index 0000000000..a2360e0c6e --- /dev/null +++ b/components/TermsPopup.tsx @@ -0,0 +1,57 @@ +import Modal from "./Modal" +import Button, { SecondaryButton } from './Button' +import { useEffect, useState } from "react" +import { useRouter } from "next/router" + +const TermsPopupModal = () => { + const [openModal, setOpenModal] = useState(true) + const [isClient, setIsClient] = useState(false) + const router = useRouter() + + useEffect(() => { + setIsClient(true) + }, []) + + useEffect(() => { + if (localStorage) { + const isTermAccepted = typeof window !== "undefined" ? + localStorage.getItem("accept-terms") === "true" : + false + + if (isTermAccepted) { + setOpenModal(false) + } + } + }) + + const acceptTerms = () => { + localStorage.setItem("accept-terms", "true") + setOpenModal(false) + } + + const rejectTerms = () => { + localStorage.setItem("accept-terms", "false") + router.push("https://realms.today?terms=rejected") + } + + return ( + <> + {isClient && openModal ? + ( setOpenModal(false)} bgClickClose={false} hideClose={true}> +

+ The operating entity of this site and owner of the related intellectual property has + changed. The new operator is Realms Today Ltd. (the New Operator). We have accordingly + amended the Terms and the Private Policy governing the relationship between our users + and the New Operator. By clicking "accept", you represent and warrant that you agree to + the revised Terms and Private Policy. +

+
+ + Reject +
+
) : null + } + ) +} + +export default TermsPopupModal; \ No newline at end of file diff --git a/components/TokenBalance/ClaimUnreleasedNFTs.tsx b/components/TokenBalance/ClaimUnreleasedNFTs.tsx new file mode 100644 index 0000000000..bc40cfdd23 --- /dev/null +++ b/components/TokenBalance/ClaimUnreleasedNFTs.tsx @@ -0,0 +1,220 @@ +import useRealm from '@hooks/useRealm' +import { useEffect, useState } from 'react' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { SecondaryButton } from '@components/Button' +import { chunks } from '@utils/helpers' +import { + sendTransactionsV3, + SequenceType, + txBatchesToInstructionSetWithSigners, +} from '@utils/sendTransactions' +import { ProgramAccount, Proposal, ProposalState, getProposal } from '@solana/spl-governance' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useAddressQuery_CommunityTokenOwner } from '@hooks/queries/addresses/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { useConnection } from '@solana/wallet-adapter-react' +import queryClient from '@hooks/queries/queryClient' +import asFindable from '@utils/queries/asFindable' +import { + proposalQueryKeys, + useRealmProposalsQuery, +} from '@hooks/queries/proposal' +import {useNftClient} from "../../VoterWeightPlugins/useNftClient"; + +const NFT_SOL_BALANCE = 0.0014616 + +type NftRecordsSet = { + proposal: PublicKey, + records: PublicKey[] +} + +const ClaimUnreleasedNFTs = ({ + inAccountDetails, +}: { + inAccountDetails?: boolean +}) => { + const wallet = useWalletOnePointOh() + const [isLoading, setIsLoading] = useState(false) + const { connection } = useConnection() + const [ownNftVoteRecords, setOwnNftVoteRecords] = useState([]) + const [solToBeClaimed, setSolToBeClaimed] = useState(0) + const ownNftVoteRecordsFilterd = ownNftVoteRecords + const realm = useRealmQuery().data?.result + const { nftClient } = useNftClient(); + const { isNftMode } = useRealm() + + const { data: tokenOwnerRecord } = useAddressQuery_CommunityTokenOwner() + const { data: proposals } = useRealmProposalsQuery() + + const releaseNfts = async (count: number | null = null) => { + if (!wallet?.publicKey) throw new Error('no wallet') + if (!realm) throw new Error() + if (!tokenOwnerRecord) throw new Error() + if (!nftClient) throw new Error("not an NFT realm") + + setIsLoading(true) + const instructions: TransactionInstruction[] = [] + const { registrar } = nftClient.getRegistrarPDA(realm.pubkey, realm.account.communityMint); + + const { voterWeightPk } = await nftClient.getVoterWeightRecordPDA(realm.pubkey, realm.account.communityMint, wallet.publicKey) + + const nfts = ownNftVoteRecordsFilterd.slice( + 0, + count ? count : ownNftVoteRecordsFilterd.length + ) + + const fetchedProposals: ProgramAccount[] = []; + const nftRecordsSet: NftRecordsSet[] = []; + + for (const i of nfts) { + const isProposalFetched = fetchedProposals.find(proposal => proposal.pubkey.equals(i.account.proposal)) + let currentProposal: ProgramAccount | undefined; + + if (isProposalFetched) { + currentProposal = isProposalFetched + } else { + const proposalQuery = await queryClient.fetchQuery({ + queryKey: proposalQueryKeys.byPubkey( + connection.rpcEndpoint, + i.account.proposal + ), + staleTime: 0, + queryFn: () => + asFindable(() => getProposal(connection, i.account.proposal))(), + }) + currentProposal = proposalQuery.result + if (proposalQuery.result) { + fetchedProposals.push(proposalQuery.result) + nftRecordsSet.push({ + proposal: proposalQuery.result.pubkey, + records: [] + }) + } + } + + if ( + currentProposal === undefined || + currentProposal.account.state === ProposalState.Voting + ) { + // ignore this one as it's still in voting + continue + } + const currentRecordsIndex = nftRecordsSet.findIndex(r => r.proposal.equals(currentProposal!.pubkey)) + nftRecordsSet[currentRecordsIndex].records.push(i.publicKey) + } + + for (const r of nftRecordsSet) { + const ixChunks = chunks(r.records, 25) + + for (const ix of ixChunks) { + const proposal = fetchedProposals.find(p => p.pubkey.equals(r.proposal)) + + const relinquishNftVoteIx = await nftClient.program.methods + .relinquishNftVote() + .accounts({ + registrar, + voterWeightRecord: voterWeightPk, + governance: proposal!.account.governance, + proposal: r.proposal, + voterTokenOwnerRecord: tokenOwnerRecord, + voterAuthority: wallet.publicKey!, + voteRecord: ix[0], + beneficiary: wallet!.publicKey!, + }) + .remainingAccounts(ix.map(c => ( + { pubkey: c, isSigner: false, isWritable: true } + ))) + .instruction() + + instructions.push(relinquishNftVoteIx) + } + } + + try { + const insertChunks = chunks(instructions, 1).map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [], + batchIdx + ), + sequenceType: SequenceType.Parallel, + } + }) + + await sendTransactionsV3({ + connection, + wallet: wallet!, + transactionInstructions: insertChunks, + }) + + setIsLoading(false) + getNftsVoteRecord() + } catch (e) { + setIsLoading(false) + console.log(e) + } + } + const getNftsVoteRecord = async () => { + if (!nftClient) throw new Error("not an NFT realm"); + const nftVoteRecords = await nftClient.program.account.nftVoteRecord?.all([ + { + memcmp: { + offset: 72, + bytes: wallet!.publicKey!.toBase58(), + }, + }, + ]) + + const nftVoteRecordsFiltered = nftVoteRecords.filter((x) => { + const proposal = proposals?.find((y) => + y.pubkey.equals(x.account.proposal) + ) + return ( + proposal && + proposal.account.governingTokenMint.toBase58() === + realm?.account.communityMint.toBase58() && + proposal.account.state !== ProposalState.Voting + ) + }) + + setOwnNftVoteRecords(nftVoteRecordsFiltered) + setSolToBeClaimed(nftVoteRecordsFiltered.length * NFT_SOL_BALANCE) + } + useEffect(() => { + if (wallet?.publicKey && isNftMode && nftClient) { + getNftsVoteRecord() + } + // 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 + }, [nftClient, isNftMode, wallet?.publicKey?.toBase58()]) + + if (isNftMode) { + return ( + <> + {((!inAccountDetails && solToBeClaimed > 1) || + (inAccountDetails && solToBeClaimed != 0)) && ( +
+
+
+ You have {solToBeClaimed.toFixed(4)} SOL to reclaim from + proposal voting costs +
+ releaseNfts()} + className="sm:w-1/2 max-w-[200px]" + > + Claim + +
+
+ )} + + ) + } else { + return null + } +} + +export default ClaimUnreleasedNFTs diff --git a/components/TokenBalance/DelegateTokenBalanceCard.tsx b/components/TokenBalance/DelegateTokenBalanceCard.tsx deleted file mode 100644 index 4f2a8c57aa..0000000000 --- a/components/TokenBalance/DelegateTokenBalanceCard.tsx +++ /dev/null @@ -1,248 +0,0 @@ -import useMembersStore from 'stores/useMembersStore' -import useWalletStore from 'stores/useWalletStore' -import Select from '@components/inputs/Select' -import useRealm from 'hooks/useRealm' -import { DisplayAddress } from '@cardinal/namespaces-components' -import { fmtMintAmount } from '@tools/sdk/units' -import { BN } from '@project-serum/anchor' -import { useEffect } from 'react' - -const DelegateBalanceCard = () => { - const delegates = useMembersStore((s) => s.compact.delegates) - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - - const walletId = wallet?.publicKey?.toBase58() - const { - ownDelegateTokenRecords, - ownDelegateCouncilTokenRecords, - ownTokenRecord, - ownCouncilTokenRecord, - mint, - councilMint, - } = useRealm() - const { - actions, - selectedCommunityDelegate, - selectedCouncilDelegate, - } = useWalletStore((s) => s) - - useEffect(() => { - if ( - !ownCouncilTokenRecord && - ownDelegateCouncilTokenRecords && - ownDelegateCouncilTokenRecords.length > 0 - ) { - actions.selectCouncilDelegate( - ownDelegateCouncilTokenRecords[0]?.account?.governingTokenOwner?.toBase58() - ) - } - - if ( - !ownTokenRecord && - ownDelegateTokenRecords && - ownDelegateTokenRecords.length > 0 - ) { - actions.selectCommunityDelegate( - ownDelegateTokenRecords[0]?.account?.governingTokenOwner?.toBase58() - ) - } - }, [walletId]) - - // whenever we change delegate, get that delegates vote record so we can display it - useEffect(() => { - actions.fetchDelegateVoteRecords() - }, [selectedCommunityDelegate, selectedCouncilDelegate]) - - const getCouncilTokenCount = () => { - if (walletId && delegates?.[walletId]) { - return delegates?.[walletId].councilTokenCount || 0 - } - return 0 - } - - const getCouncilDelegateAmt = () => { - if (walletId && delegates?.[walletId]) { - return fmtMintAmount( - councilMint, - new BN(delegates?.[walletId].councilTokenCount || 0) - ) - } - return 0 - } - - const getCommunityTokenCount = () => { - if (walletId && delegates?.[walletId]) { - return fmtMintAmount( - mint, - new BN(delegates?.[walletId].communityTokenCount || 0) - ) - } - return 0 - } - - const getCommunityDelegateAmt = () => { - if (walletId && delegates?.[walletId]) { - return delegates?.[walletId]?.communityMembers?.length || 0 - } - return 0 - } - - const handleCouncilSelect = (councilTokenRecord: string) => { - actions.selectCouncilDelegate(councilTokenRecord) - } - - const handleCommunitySelect = (communityPubKey: string) => { - actions.selectCommunityDelegate(communityPubKey) - } - - if (!walletId || !delegates?.[walletId]) { - return null - } - - return ( - <> -

Your Delegates

- {walletId && delegates?.[walletId]?.councilMembers && ( -
-
-
-
-

Council Votes

-

- {getCouncilTokenCount()} -

-
-
-

Delegate Accounts

-

- {getCouncilDelegateAmt()} -

-
-
- -

Selected Delegate

- -
-
- )} - {walletId && delegates?.[walletId]?.communityMembers && ( -
-
-
-
-

Community Votes

-

- {getCommunityTokenCount()} -

-
-
-

Delegate Accounts

-

- {getCommunityDelegateAmt()} -

-
-
- -

Selected Delegate

- -
-
- )} - - ) -} - -export default DelegateBalanceCard diff --git a/components/TokenBalance/NftBalanceCard.tsx b/components/TokenBalance/NftBalanceCard.tsx deleted file mode 100644 index 4933e1a54d..0000000000 --- a/components/TokenBalance/NftBalanceCard.tsx +++ /dev/null @@ -1,158 +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 { ChevronRightIcon } from '@heroicons/react/outline' -import useQueryContext from '@hooks/useQueryContext' -import useRealm from '@hooks/useRealm' -import { NftVoterClient } from '@solana/governance-program-library' -import { - getTokenOwnerRecordAddress, - SYSTEM_PROGRAM_ID, - withCreateTokenOwnerRecord, -} from '@solana/spl-governance' -import { Transaction, TransactionInstruction } from '@solana/web3.js' -import { sendTransaction } from '@utils/send' -import Link from 'next/link' -import useNftPluginStore from 'NftVotePlugin/store/nftPluginStore' -import { useState, useEffect } from 'react' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import useWalletStore from 'stores/useWalletStore' -import { getVoterWeightRecord } from '@utils/plugin/accounts' - -const NftBalanceCard = () => { - const { fmtUrlWithCluster } = useQueryContext() - const connected = useWalletStore((s) => s.connected) - const wallet = useWalletStore((s) => s.current) - 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() - } - }, [realm?.pubkey.toBase58(), wallet?.connected]) - return ( -
- -
- {!connected ? ( -
Please connect your wallet
- ) : !isLoading ? ( - { - return null - }} - ownersPk={[wallet!.publicKey!]} - nftHeight="50px" - nftWidth="50px" - selectable={false} - predefinedNfts={nfts} - > - ) : ( - - )} -
- {connected && !ownTokenRecord && ( - - )} -
- ) -} -export default NftBalanceCard diff --git a/components/TokenBalance/SwitchboardPermissionCard.tsx b/components/TokenBalance/SwitchboardPermissionCard.tsx deleted file mode 100644 index f2aac0c788..0000000000 --- a/components/TokenBalance/SwitchboardPermissionCard.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import Button from '@components/Button' -//import Loading from '@components/Loading' -//import NFTSelector from '@components/NFTS/NFTSelector' -import { ChevronRightIcon } from '@heroicons/react/outline' -import useQueryContext from '@hooks/useQueryContext' -import useRealm from '@hooks/useRealm' -import { getTokenOwnerRecordAddress } from '@solana/spl-governance' -import Link from 'next/link' -import { useState, useEffect } from 'react' -import useWalletStore from 'stores/useWalletStore' -import useSwitchboardPluginStore from 'SwitchboardVotePlugin/store/switchboardStore' -import { sbRefreshWeight } from '../../actions/switchboardRefreshVoterWeight' - -const SwitchboardPermissionCard = () => { - const { fmtUrlWithCluster } = useQueryContext() - const connected = useWalletStore((s) => s.connected) - const wallet = useWalletStore((s) => s.current) - - const switchboardVoterWeight = useSwitchboardPluginStore( - (s) => s.state.votingPower - ) - const switchboardRefreshInstructions = useSwitchboardPluginStore( - (s) => s.state.instructions - ) - - const [tokenOwnerRecordPk, setTokenOwneRecordPk] = useState('') - const { realm, symbol } = useRealm() - const connection = useWalletStore((s) => s.connection) - - useEffect(() => { - const getTokenOwnerRecord = async () => { - const defaultMint = realm!.account.communityMint - const tokenOwnerRecordAddress = await getTokenOwnerRecordAddress( - realm!.owner, - realm!.pubkey, - defaultMint!, - wallet!.publicKey! - ) - setTokenOwneRecordPk(tokenOwnerRecordAddress.toBase58()) - } - if (realm && wallet?.connected) { - getTokenOwnerRecord() - } - }, [realm?.pubkey.toBase58(), wallet?.connected]) - return ( -
-
-

Your Queue Voting Rights:

- - - View - - - -
-
- {(() => { - if (switchboardVoterWeight.isZero()) { - return You do not have voting rights - } else { - return You have voting rights! - } - })()} -
- -
- ) -} -export default SwitchboardPermissionCard diff --git a/components/TokenBalance/TokenBalanceCard.tsx b/components/TokenBalance/TokenBalanceCard.tsx deleted file mode 100644 index 61c824ffcb..0000000000 --- a/components/TokenBalance/TokenBalanceCard.tsx +++ /dev/null @@ -1,496 +0,0 @@ -import { - ASSOCIATED_TOKEN_PROGRAM_ID, - MintInfo, - Token, - TOKEN_PROGRAM_ID, -} from '@solana/spl-token' -import { - Keypair, - PublicKey, - Transaction, - TransactionInstruction, -} from '@solana/web3.js' -import BN from 'bn.js' -import useRealm from '@hooks/useRealm' -import { - getProposal, - getTokenOwnerRecordAddress, - Proposal, - ProposalState, -} from '@solana/spl-governance' -import { getUnrelinquishedVoteRecords } from '@models/api' -import { withDepositGoverningTokens } from '@solana/spl-governance' -import { withRelinquishVote } from '@solana/spl-governance' -import { withWithdrawGoverningTokens } from '@solana/spl-governance' -import useWalletStore from '../../stores/useWalletStore' -import { sendTransaction } from '@utils/send' -import { approveTokenTransfer } from '@utils/tokens' -import Button from '../Button' -import { Option } from '@tools/core/option' -import { GoverningTokenRole } from '@solana/spl-governance' -import { fmtMintAmount } from '@tools/sdk/units' -import { getMintMetadata } from '../instructions/programs/splToken' -import { withFinalizeVote } from '@solana/spl-governance' -import { chunks } from '@utils/helpers' -import { getProgramVersionForRealm } from '@models/registry/api' -import { notify } from '@utils/notifications' -import { ChevronRightIcon } from '@heroicons/react/solid' -import { ExclamationIcon } from '@heroicons/react/outline' -import useQueryContext from '@hooks/useQueryContext' -import { FC, useEffect, useState } from 'react' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import Link from 'next/link' -import useNftPluginStore from 'NftVotePlugin/store/nftPluginStore' -import { vsrPluginsPks } from '@hooks/useVotingPlugins' -import { - LOCALNET_REALM_ID as PYTH_LOCALNET_REALM_ID, - PythBalance, -} from 'pyth-staking-api' -import DelegateTokenBalanceCard from '@components/TokenBalance/DelegateTokenBalanceCard' - -type Props = { proposal?: Option } -const TokenBalanceCard: FC = ({ proposal, children }) => { - const { councilMint, mint, realm, symbol } = useRealm() - const connected = useWalletStore((s) => s.connected) - const wallet = useWalletStore((s) => s.current) - const [tokenOwnerRecordPk, setTokenOwneRecordPk] = useState('') - const { fmtUrlWithCluster } = useQueryContext() - const isDepositVisible = ( - depositMint: MintInfo | undefined, - realmMint: PublicKey | undefined - ) => - depositMint && - (!proposal || - (proposal.isSome() && - proposal.value.governingTokenMint.toBase58() === realmMint?.toBase58())) - - const communityDepositVisible = - // If there is no council then community deposit is the only option to show - !realm?.account.config.councilMint || - isDepositVisible(mint, realm?.account.communityMint) - - const councilDepositVisible = isDepositVisible( - councilMint, - realm?.account.config.councilMint - ) - useEffect(() => { - const getTokenOwnerRecord = async () => { - const defaultMint = !mint?.supply.isZero() - ? 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() - } - }, [realm?.pubkey.toBase58(), wallet?.connected]) - const hasLoaded = mint || councilMint - - return ( -
-
-

Your account

- - - View - - - -
- {hasLoaded ? ( -
- {communityDepositVisible && ( - - )} - {councilDepositVisible && ( - - )} - -
- ) : ( - <> -
-
- - )} - {children} -
- ) -} - -export const TokenDeposit = ({ - mint, - tokenType, - councilVote, -}: { - mint: MintInfo | undefined - tokenType: GoverningTokenRole - councilVote?: boolean -}) => { - const wallet = useWalletStore((s) => s.current) - const connected = useWalletStore((s) => s.connected) - const connection = useWalletStore((s) => s.connection.current) - const { fetchWalletTokenAccounts, fetchRealm } = useWalletStore( - (s) => s.actions - ) - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const maxVoterWeight = - useNftPluginStore((s) => s.state.maxVoteRecord)?.pubkey || undefined - const { - realm, - realmInfo, - realmTokenAccount, - ownTokenRecord, - ownCouncilTokenRecord, - ownVoterWeight, - councilTokenAccount, - proposals, - governances, - toManyCommunityOutstandingProposalsForUser, - toManyCouncilOutstandingProposalsForUse, - config, - } = useRealm() - // Do not show deposits for mints with zero supply because nobody can deposit anyway - if (!mint || mint.supply.isZero()) { - return null - } - - const depositTokenRecord = - tokenType === GoverningTokenRole.Community - ? ownTokenRecord - : ownCouncilTokenRecord - - const depositTokenAccount = - tokenType === GoverningTokenRole.Community - ? realmTokenAccount - : councilTokenAccount - - const depositMint = - tokenType === GoverningTokenRole.Community - ? realm?.account.communityMint - : realm?.account.config.councilMint - - const tokenName = getMintMetadata(depositMint)?.name ?? realm?.account.name - - const depositTokenName = `${tokenName} ${ - tokenType === GoverningTokenRole.Community ? '' : 'Council' - }` - - const depositTokens = async function (amount: BN) { - const instructions: TransactionInstruction[] = [] - const signers: Keypair[] = [] - - const transferAuthority = approveTokenTransfer( - instructions, - [], - depositTokenAccount!.publicKey, - wallet!.publicKey!, - amount - ) - - signers.push(transferAuthority) - - await withDepositGoverningTokens( - instructions, - realmInfo!.programId, - getProgramVersionForRealm(realmInfo!), - realm!.pubkey, - depositTokenAccount!.publicKey, - depositTokenAccount!.account.mint, - wallet!.publicKey!, - transferAuthority.publicKey, - wallet!.publicKey!, - amount - ) - - const transaction = new Transaction() - transaction.add(...instructions) - - await sendTransaction({ - connection, - wallet: wallet!, - transaction, - signers, - sendingMessage: 'Depositing tokens', - successMessage: 'Tokens have been deposited', - }) - - await fetchWalletTokenAccounts() - await fetchRealm(realmInfo!.programId, realmInfo!.realmId) - } - - const depositAllTokens = async () => - await depositTokens(depositTokenAccount!.account.amount) - - const withdrawAllTokens = async function () { - const instructions: TransactionInstruction[] = [] - // If there are unrelinquished votes for the voter then let's release them in the same instruction as convenience - if (depositTokenRecord!.account!.unrelinquishedVotesCount > 0) { - const voteRecords = await getUnrelinquishedVoteRecords( - connection, - realmInfo!.programId, - depositTokenRecord!.account!.governingTokenOwner - ) - - for (const voteRecord of Object.values(voteRecords)) { - let proposal = proposals[voteRecord.account.proposal.toBase58()] - if (!proposal) { - continue - } - - if (proposal.account.state === ProposalState.Voting) { - // If the Proposal is in Voting state refetch it to make sure we have the latest state to avoid false positives - proposal = await getProposal(connection, proposal.pubkey) - if (proposal.account.state === ProposalState.Voting) { - const governance = - governances[proposal.account.governance.toBase58()] - if (proposal.account.getTimeToVoteEnd(governance.account) > 0) { - // Note: It's technically possible to withdraw the vote here but I think it would be confusing and people would end up unconsciously withdrawing their votes - notify({ - type: 'error', - message: `Can't withdraw tokens while Proposal ${proposal.account.name} is being voted on. Please withdraw your vote first`, - }) - throw new Error( - `Can't withdraw tokens while Proposal ${proposal.account.name} is being voted on. Please withdraw your vote first` - ) - } else { - // finalize proposal before withdrawing tokens so we don't stop the vote from succeeding - await withFinalizeVote( - instructions, - realmInfo!.programId, - getProgramVersionForRealm(realmInfo!), - realm!.pubkey, - proposal.account.governance, - proposal.pubkey, - proposal.account.tokenOwnerRecord, - proposal.account.governingTokenMint, - maxVoterWeight - ) - } - } - } - // Note: We might hit single transaction limits here (accounts and size) if user has too many unrelinquished votes - // It's not going to be an issue for now due to the limited number of proposals so I'm leaving it for now - // As a temp. work around I'm leaving the 'Release Tokens' button on finalized Proposal to make it possible to release the tokens from one Proposal at a time - await withRelinquishVote( - instructions, - realmInfo!.programId, - realmInfo!.programVersion!, - realmInfo!.realmId, - proposal.account.governance, - proposal.pubkey, - depositTokenRecord!.pubkey, - proposal.account.governingTokenMint, - voteRecord.pubkey, - depositTokenRecord!.account.governingTokenOwner, - wallet!.publicKey! - ) - await client.withRelinquishVote( - instructions, - proposal, - voteRecord.pubkey - ) - } - } - let ata: PublicKey | null = null - if (!depositTokenAccount) { - ata = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID - TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID - depositMint!, // mint - wallet!.publicKey!, // owner - true - ) - const ataIx = Token.createAssociatedTokenAccountInstruction( - ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID - TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID - depositMint!, // mint - ata, // ata - wallet!.publicKey!, // owner of token account - wallet!.publicKey! // fee payer - ) - instructions.push(ataIx) - } - - await withWithdrawGoverningTokens( - instructions, - realmInfo!.programId, - realmInfo!.programVersion!, - realm!.pubkey, - depositTokenAccount?.publicKey - ? depositTokenAccount!.publicKey - : new PublicKey(ata!), - depositTokenRecord!.account.governingTokenMint, - wallet!.publicKey! - ) - - try { - // use chunks of 8 here since we added finalize, - // because previously 9 withdraws used to fit into one tx - const ixChunks = chunks(instructions, 8) - for (const [index, chunk] of ixChunks.entries()) { - const transaction = new Transaction().add(...chunk) - await sendTransaction({ - connection, - wallet: wallet!, - transaction, - sendingMessage: - index == ixChunks.length - 1 - ? 'Withdrawing tokens' - : `Releasing tokens (${index}/${ixChunks.length - 2})`, - successMessage: - index == ixChunks.length - 1 - ? 'Tokens have been withdrawn' - : `Released tokens (${index}/${ixChunks.length - 2})`, - }) - } - await fetchWalletTokenAccounts() - await fetchRealm(realmInfo!.programId, realmInfo!.realmId) - } catch (ex) { - //TODO change to more friendly notification - notify({ type: 'error', message: `${ex}` }) - console.error("Can't withdraw tokens", ex) - } - } - - const hasTokensInWallet = - depositTokenAccount && depositTokenAccount.account.amount.gt(new BN(0)) - - const hasTokensDeposited = - depositTokenRecord && - depositTokenRecord.account.governingTokenDepositAmount.gt(new BN(0)) - - const depositTooltipContent = !connected - ? 'Connect your wallet to deposit' - : !hasTokensInWallet - ? "You don't have any governance tokens in your wallet to deposit." - : '' - const withdrawTooltipContent = !connected - ? 'Connect your wallet to withdraw' - : !hasTokensDeposited - ? "You don't have any tokens deposited to withdraw." - : !councilVote && - (toManyCouncilOutstandingProposalsForUse || - toManyCommunityOutstandingProposalsForUser) - ? 'You have to many outstanding proposals to withdraw.' - : '' - - //Todo: move to own components with refactor to dao folder structure - const isPyth = - realmInfo?.realmId.toBase58() === PYTH_LOCALNET_REALM_ID.toBase58() - - const availableTokens = isPyth - ? new PythBalance(ownVoterWeight.votingPower!).toString() - : depositTokenRecord && mint - ? fmtMintAmount( - mint, - depositTokenRecord.account.governingTokenDepositAmount - ) - : '0' - - const canShowAvailableTokensMessage = - !hasTokensDeposited && hasTokensInWallet && connected - const canExecuteAction = !hasTokensDeposited ? 'deposit' : 'withdraw' - const canDepositToken = !hasTokensDeposited && hasTokensInWallet - const tokensToShow = - canDepositToken && depositTokenAccount - ? fmtMintAmount(mint, depositTokenAccount.account.amount) - : canDepositToken - ? availableTokens - : 0 - - return ( - <> -
-
-
-

{depositTokenName} Votes

-

- {availableTokens} -

-
-
-
- - {!isPyth && ( - <> -

- You have {tokensToShow} tokens available to {canExecuteAction}. -

- -
- - - -
- - )} - {config?.account.communityTokenConfig.voterWeightAddin && - vsrPluginsPks.includes( - config?.account.communityTokenConfig.voterWeightAddin.toBase58() - ) && - tokenType === GoverningTokenRole.Community && ( - - - Please withdraw your tokens and deposit again to get governance - power - - )} - - ) -} - -export default TokenBalanceCard diff --git a/components/TokenBalance/TokenBalanceCardWrapper.tsx b/components/TokenBalance/TokenBalanceCardWrapper.tsx index b9c6ddd51d..75de2f2fa9 100644 --- a/components/TokenBalance/TokenBalanceCardWrapper.tsx +++ b/components/TokenBalance/TokenBalanceCardWrapper.tsx @@ -1,14 +1,24 @@ -import { Proposal } from '@solana/spl-governance' -import { Option } from 'tools/core/option' import useRealm from '@hooks/useRealm' import dynamic from 'next/dynamic' -import { - gatewayPluginsPks, - nftPluginsPks, - vsrPluginsPks, - switchboardPluginsPks, -} from '@hooks/useVotingPlugins' +import { ChevronRightIcon } from '@heroicons/react/solid' +import useQueryContext from '@hooks/useQueryContext' import GatewayCard from '@components/Gateway/GatewayCard' +import ClaimUnreleasedNFTs from './ClaimUnreleasedNFTs' +import Link from 'next/link' +import { useAddressQuery_CommunityTokenOwner } from '@hooks/queries/addresses/tokenOwnerRecord' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useUserCommunityTokenOwnerRecord } from '@hooks/queries/tokenOwnerRecord' +import ClaimUnreleasedPositions from 'HeliumVotePlugin/components/ClaimUnreleasedPositions' +import VanillaAccountDetails from './VanillaAccountDetails' +import GovernancePowerCard from '@components/GovernancePower/GovernancePowerCard' +import SelectPrimaryDelegators from '@components/SelectPrimaryDelegators' +import PythAccountDetails from 'PythVotePlugin/components/PythAccountDetails' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import { ReactNode } from 'react' +import QuadraticVotingPower from '@components/ProposalVotingPower/QuadraticVotingPower' +import VanillaVotingPower from '@components/GovernancePower/Power/Vanilla/VanillaVotingPower' +import React from 'react' +import ParclAccountDetails from 'ParclVotePlugin/components/ParclAccountDetails' const LockPluginTokenBalanceCard = dynamic( () => @@ -16,76 +26,160 @@ const LockPluginTokenBalanceCard = dynamic( 'VoteStakeRegistry/components/TokenBalance/LockPluginTokenBalanceCard' ) ) -const TokenBalanceCard = dynamic(() => import('./TokenBalanceCard')) -const NftBalanceCard = dynamic(() => import('./NftBalanceCard')) -const SwitchboardPermissionCard = dynamic( - () => import('./SwitchboardPermissionCard') + +const HeliumVotingPowerCard = dynamic(() => + import('HeliumVotePlugin/components/VotingPowerCard').then((module) => { + const { VotingPowerCard } = module + return VotingPowerCard + }) ) -const TokenBalanceCardWrapper = ({ - proposal, +const NftVotingPower = dynamic( + () => import('../ProposalVotingPower/NftVotingPower') +) + +export const GovernancePowerTitle = () => { + const { symbol } = useRealm() + const { fmtUrlWithCluster } = useQueryContext() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const { data: tokenOwnerRecordPk } = useAddressQuery_CommunityTokenOwner() + + return ( +
+

My governance power

+ + + View + + + +
+ ) +} + +const TokenBalanceCardInner = ({ + inAccountDetails, }: { - proposal?: Option + inAccountDetails?: boolean }) => { - const { - ownTokenRecord, - config, - ownCouncilTokenRecord, - councilTokenAccount, - } = useRealm() - const currentPluginPk = config?.account?.communityTokenConfig.voterWeightAddin - const getTokenBalanceCard = () => { - //based on realm config it will provide proper tokenBalanceCardComponent - const isLockTokensMode = - currentPluginPk && vsrPluginsPks.includes(currentPluginPk?.toBase58()) - const isNftMode = - currentPluginPk && nftPluginsPks.includes(currentPluginPk?.toBase58()) - const isGatewayMode = - currentPluginPk && gatewayPluginsPks.includes(currentPluginPk?.toBase58()) - const isSwitchboardMode = - currentPluginPk && - switchboardPluginsPks.includes(currentPluginPk?.toBase58()) - - if ( - isLockTokensMode && - (!ownTokenRecord || - ownTokenRecord.account.governingTokenDepositAmount.isZero()) - ) { - return - } - if ( - isNftMode && - (!ownTokenRecord || - ownTokenRecord.account.governingTokenDepositAmount.isZero()) - ) { - return ( - <> - - {((ownCouncilTokenRecord && - !ownCouncilTokenRecord?.account.governingTokenDepositAmount.isZero()) || - (councilTokenAccount && - !councilTokenAccount?.account.amount.isZero())) && ( - - )} - - ) - } - if ( - isSwitchboardMode && - (!ownTokenRecord || - ownTokenRecord.account.governingTokenDepositAmount.isZero()) - ) { - return - } - //Default - return ( - - {/*Add the gateway card if this is a gated DAO*/} - {isGatewayMode && } - + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const { plugins } = useRealmVoterWeightPlugins('community') + const requiredCards = plugins?.voterWeight.map((plugin) => plugin.name) + + const showHeliumCard = requiredCards?.includes('HeliumVSR') + const showDefaultVSRCard = requiredCards?.includes('VSR') + const showPythCard = requiredCards?.includes('pyth') + const showNftCard = requiredCards?.includes('NFT') + const showGatewayCard = requiredCards?.includes('gateway') + const showQvCard = requiredCards?.includes('QV') + const showParclCard = requiredCards?.includes('parcl'); + + if (showDefaultVSRCard && inAccountDetails) { + return // does this ever actually occur in the component hierarchy? + } + + const cards: ReactNode[] = [] + + if ( + showHeliumCard && + (!ownTokenRecord || + ownTokenRecord.account.governingTokenDepositAmount.isZero()) + ) { + cards.push( + + {!inAccountDetails && } + + + + ) + } + + if (showNftCard && inAccountDetails) { + cards.push( +
+
+ + +
+ +
+ ) + } + + if (showPythCard) { + cards.push( + + {inAccountDetails ? : } + ) } - return getTokenBalanceCard() + + if (showGatewayCard) { + cards.push( + + {inAccountDetails ? ( + + ) : ( + + )} + + ) + } + + if (showQvCard) { + cards.push( + + {inAccountDetails && ( + <> + + + + )} + + ) + } + + if (showParclCard) { + cards.push( + + {!inAccountDetails && } + + + ) + } + + //Default + if (cards.length === 0) { + cards.push( + + {inAccountDetails ? : } + + ) + } + + return <>{cards} +} + +const TokenBalanceCardWrapper = ({ + inAccountDetails, +}: { + inAccountDetails?: boolean +}) => { + return ( +
+ + +
+ ) } export default TokenBalanceCardWrapper diff --git a/components/TokenBalance/TokenDeposit.tsx b/components/TokenBalance/TokenDeposit.tsx new file mode 100644 index 0000000000..ce6d35a150 --- /dev/null +++ b/components/TokenBalance/TokenDeposit.tsx @@ -0,0 +1,190 @@ +import { MintInfo } from '@solana/spl-token' +import BN from 'bn.js' +import useRealm from '@hooks/useRealm' +import { GoverningTokenType } from '@solana/spl-governance' +import { GoverningTokenRole } from '@solana/spl-governance' +import { fmtMintAmount } from '@tools/sdk/units' +import { getMintMetadata } from '../instructions/programs/splToken' +import { useEffect } from 'react' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { + useUserCommunityTokenOwnerRecord, + useUserCouncilTokenOwnerRecord, +} from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import VanillaVotingPower from '@components/GovernancePower/Power/Vanilla/VanillaVotingPower' +import { DepositTokensButton } from '@components/DepositTokensButton' +import VanillaWithdrawTokensButton from './VanillaWithdrawTokensButton' +import Button from '@components/Button' +import { useJoinRealm } from '@hooks/useJoinRealm' +import { Transaction } from '@solana/web3.js' +import { sendTransaction } from '@utils/send' +import { useConnection } from '@solana/wallet-adapter-react' + +/** deposit + withdraw for vanilla govtokens, used only in account view. plugin views still use this for council. */ +export const TokenDeposit = ({ + mint, + tokenRole, + inAccountDetails, + setHasGovPower, + hideVotes, +}: { + mint: MintInfo | undefined + tokenRole: GoverningTokenRole + inAccountDetails?: boolean + setHasGovPower?: (hasGovPower: boolean) => void + hideVotes?: boolean +}) => { + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const { + userNeedsTokenOwnerRecord, + userNeedsVoterWeightRecords, + handleRegister, + } = useJoinRealm() + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result + const realm = useRealmQuery().data?.result + const config = useRealmConfigQuery().data?.result + const { connection } = useConnection() + + const relevantTokenConfig = + tokenRole === GoverningTokenRole.Community + ? config?.account.communityTokenConfig + : config?.account.councilTokenConfig + const isMembership = + relevantTokenConfig?.tokenType === GoverningTokenType.Membership + + const { realmTokenAccount, councilTokenAccount } = useRealm() + + const depositTokenRecord = + tokenRole === GoverningTokenRole.Community + ? ownTokenRecord + : ownCouncilTokenRecord + + const depositTokenAccount = + tokenRole === GoverningTokenRole.Community + ? realmTokenAccount + : councilTokenAccount + + const depositMint = + tokenRole === GoverningTokenRole.Community + ? realm?.account.communityMint + : realm?.account.config.councilMint + + const tokenName = getMintMetadata(depositMint)?.name ?? realm?.account.name + + const depositTokenName = `${tokenName} ${ + tokenRole === GoverningTokenRole.Community ? '' : 'Council' + }` + + const hasTokensInWallet = + depositTokenAccount && depositTokenAccount.account.amount.gt(new BN(0)) + + const hasTokensDeposited = + depositTokenRecord && + depositTokenRecord.account.governingTokenDepositAmount.gt(new BN(0)) + + const availableTokens = + depositTokenRecord && mint + ? fmtMintAmount( + mint, + depositTokenRecord.account.governingTokenDepositAmount + ) + : '0' + + const join = async () => { + const instructions = await handleRegister() + const transaction = new Transaction() + transaction.add(...instructions) + + await sendTransaction({ + transaction: transaction, + wallet: wallet!, + connection, + signers: [], + sendingMessage: `Registering`, + successMessage: `Registered`, + }) + } + + useEffect(() => { + if (availableTokens != '0' || hasTokensDeposited || hasTokensInWallet) { + if (setHasGovPower) setHasGovPower(true) + } + }, [availableTokens, hasTokensDeposited, hasTokensInWallet, setHasGovPower]) + + const canShowAvailableTokensMessage = hasTokensInWallet && connected + const tokensToShow = + hasTokensInWallet && depositTokenAccount + ? fmtMintAmount(mint, depositTokenAccount.account.amount) + : hasTokensInWallet + ? availableTokens + : 0 + + // There are two buttons available on this UI: + // The Deposit button - available if you have tokens to deposit + // The Join button - available if you have already deposited tokens (you have a Token Owner Record) + // but you may not have all your Voter Weight Records yet. + // This latter case may occur if the DAO changes its configuration and new Voter Weight Records are required. + // For example if a new plugin is added. + const showJoinButton = + !userNeedsTokenOwnerRecord && userNeedsVoterWeightRecords + + // Do not show deposits for mints with zero supply because nobody can deposit anyway + if (!mint || mint.supply.isZero()) { + return null + } + + return ( +
+ {(availableTokens != '0' || inAccountDetails) && !hideVotes && ( +
+ {tokenRole === GoverningTokenRole.Community ? ( + + ) : ( + + )} +
+ )} + +
+ You have {tokensToShow} {hasTokensDeposited ? `more ` : ``} + {depositTokenName} tokens available to deposit. +
+ +
+ {connected && showJoinButton ? ( + + ) : hasTokensInWallet || inAccountDetails ? ( + + ) : null} + {!isMembership && // Membership tokens can't be withdrawn (that is their whole point, actually) + inAccountDetails && ( + + )} +
+
+ ) +} diff --git a/components/TokenBalance/VanillaAccountDetails.tsx b/components/TokenBalance/VanillaAccountDetails.tsx new file mode 100644 index 0000000000..0004c0bea2 --- /dev/null +++ b/components/TokenBalance/VanillaAccountDetails.tsx @@ -0,0 +1,58 @@ +import { GoverningTokenRole } from '@solana/spl-governance' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { + useRealmCommunityMintInfoQuery, + useRealmCouncilMintInfoQuery, +} from '@hooks/queries/mintInfo' +import { TokenDeposit } from './TokenDeposit' + +const VanillaAccountDetails = () => { + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + + const communityDepositVisible = + // If there is no council then community deposit is the only option to show + !realm?.account.config.councilMint || + realm?.account.communityMint !== undefined + const councilDepositVisible = realm?.account.config.councilMint !== undefined + const hasLoaded = mint || councilMint + + return ( + <> + {hasLoaded ? ( +
+ {!connected && ( +
+ Connect your wallet to see governance power +
+ )} + {communityDepositVisible && ( + + )} + {councilDepositVisible && ( + + )} +
+ ) : ( + <> +
+
+ + )} + + ) +} + +export default VanillaAccountDetails diff --git a/components/TokenBalance/VanillaWithdrawTokensButton.tsx b/components/TokenBalance/VanillaWithdrawTokensButton.tsx new file mode 100644 index 0000000000..eb4fc438ee --- /dev/null +++ b/components/TokenBalance/VanillaWithdrawTokensButton.tsx @@ -0,0 +1,331 @@ +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + Token, + TOKEN_PROGRAM_ID, +} from '@solana/spl-token' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import BN from 'bn.js' +import useRealm from '@hooks/useRealm' +import { + getProposal, + Governance, + GoverningTokenType, + ProgramAccount, +} from '@solana/spl-governance' +import { getProposalsAtVotingStateByTOR, getUnrelinquishedVoteRecords } from '@models/api' +import { withRelinquishVote } from '@solana/spl-governance' +import { withWithdrawGoverningTokens } from '@solana/spl-governance' +import { SecondaryButton } from '../Button' +import { withFinalizeVote } from '@solana/spl-governance' +import { chunks } from '@utils/helpers' +import { getProgramVersionForRealm } from '@models/registry/api' +import { notify } from '@utils/notifications' +import { useMaxVoteRecord } from '@hooks/useMaxVoteRecord' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { + useUserCommunityTokenOwnerRecord, + useUserCouncilTokenOwnerRecord, +} from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmConfigQuery } from '@hooks/queries/realmConfig' +import { fetchGovernanceByPubkey } from '@hooks/queries/governance' +import { useConnection } from '@solana/wallet-adapter-react' +import queryClient from '@hooks/queries/queryClient' +import { proposalQueryKeys } from '@hooks/queries/proposal' +import asFindable from '@utils/queries/asFindable' +import { fetchTokenAccountByPubkey } from '@hooks/queries/tokenAccount' +import {useVotingClients} from "@hooks/useVotingClients"; +import { sendTransactionsV3, SequenceType } from '@utils/sendTransactions' +import { useState } from 'react' + +// TODO make this have reasonable props +// TODO, also just refactor it +const VanillaWithdrawTokensButton = ({ + role, +}: { + role: 'community' | 'council' +}) => { + const [disableButton, setDisableButton] = useState(false) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const { connection } = useConnection() + const maxVoterWeight = useMaxVoteRecord()?.pubkey || undefined + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result + const realm = useRealmQuery().data?.result + const config = useRealmConfigQuery().data?.result + const votingClient = useVotingClients()(role); + + const relevantTokenConfig = + role === 'community' + ? config?.account.communityTokenConfig + : config?.account.councilTokenConfig + const isMembership = + relevantTokenConfig?.tokenType === GoverningTokenType.Membership + + const { + realmInfo, + realmTokenAccount, + councilTokenAccount, + toManyCommunityOutstandingProposalsForUser, + toManyCouncilOutstandingProposalsForUse, + } = useRealm() + + const depositTokenRecord = + role === 'community' ? ownTokenRecord : ownCouncilTokenRecord + + const depositTokenAccount = + role === 'community' ? realmTokenAccount : councilTokenAccount + + const depositMint = + role === 'community' + ? realm?.account.communityMint + : realm?.account.config.councilMint + + const vetoMint = + role === 'community' + ? realm?.account.config.councilMint + : realm?.account.communityMint + + const withdrawAllTokens = async function () { + const instructions: TransactionInstruction[] = [] + setDisableButton(true) + + try { + if (depositTokenRecord!.account!.unrelinquishedVotesCount > 0) { + const voteRecords = await getUnrelinquishedVoteRecords( + connection, + realmInfo!.programId, + depositTokenRecord!.account!.governingTokenOwner + ) + + for (const voteRecord of Object.values(voteRecords)) { + const proposalQuery = await queryClient.fetchQuery({ + queryKey: proposalQueryKeys.byPubkey( + connection.rpcEndpoint, + voteRecord.account.proposal + ), + staleTime: 0, + queryFn: () => + asFindable(() => + getProposal(connection, voteRecord.account.proposal) + )(), + }) + + const proposal = proposalQuery.result + if (!proposal) { + continue + } + + if (voteRecord.account.vote?.veto) { + if (vetoMint && !proposal.account.governingTokenMint.equals(vetoMint)) { + continue; + } + } else { + if (!proposal.account.governingTokenMint.equals(depositMint!)) { + continue; + } + } + + const governance = ( + await fetchGovernanceByPubkey( + connection, + proposal.account.governance + ) + ).result + + if (!governance) throw new Error('failed to fetch governance') + + if (!governance.account.realm.equals(realm!.pubkey)) { + continue + } + + if (proposal.account.getTimeToVoteEnd(governance.account) > 0) { + notify({ + type: 'error', + message: `Can't withdraw tokens while Proposal ${proposal.account.name} is being voted on. Please withdraw your vote first`, + }) + throw new Error( + `Can't withdraw tokens while Proposal ${proposal.account.name} is being voted on. Please withdraw your vote first` + ) + } else { + await withRelinquishVote( + instructions, + realmInfo!.programId, + realmInfo!.programVersion!, + realmInfo!.realmId, + proposal.account.governance, + proposal.pubkey, + depositTokenRecord!.pubkey, + depositMint!, + voteRecord.pubkey, + depositTokenRecord!.account.governingTokenOwner, + wallet!.publicKey! + ) + await votingClient.withRelinquishVote( + instructions, + proposal, + voteRecord.pubkey, + depositTokenRecord!.pubkey + ) + } + } + } + + if (depositTokenRecord!.account.outstandingProposalCount > 0) { + const activeProposals = await getProposalsAtVotingStateByTOR( + connection, + realmInfo!.programId, + depositTokenRecord!.pubkey + ) + + for (const proposal of Object.values(activeProposals)) { + const fetchedGovernances: ProgramAccount[] = [] + const isGovernanceFetched = fetchedGovernances.find(governance => governance.pubkey.equals(proposal.pubkey)) + + const currentGovernance = isGovernanceFetched ? isGovernanceFetched : ( + await fetchGovernanceByPubkey( + connection, + proposal.account.governance + ) + ).result + + if (!currentGovernance) throw new Error('failed to fetch governance') + + if(fetchedGovernances.indexOf(currentGovernance) === -1) { + fetchedGovernances.push(currentGovernance) + } + + if (proposal.account.getTimeToVoteEnd(currentGovernance.account) > 0) { + notify({ + type: 'error', + message: `Can't withdraw tokens while Proposal ${proposal.account.name} is being voted on.`, + }) + throw new Error( + `Can't withdraw tokens while Proposal ${proposal.account.name} is being voted on.` + ) + } else { + await withFinalizeVote( + instructions, + realmInfo!.programId, + getProgramVersionForRealm(realmInfo!), + realm!.pubkey, + proposal.account.governance, + proposal.pubkey, + proposal.account.tokenOwnerRecord, + proposal.account.governingTokenMint, + maxVoterWeight + ) + } + } + } + + const ataPk = await Token.getAssociatedTokenAddress( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + depositMint!, + wallet!.publicKey!, + true + ) + const ata = await fetchTokenAccountByPubkey(connection, ataPk) + + if (!ata.found) { + const ataIx = Token.createAssociatedTokenAccountInstruction( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + depositMint!, + ataPk, + wallet!.publicKey!, + wallet!.publicKey! // fee payer + ) + instructions.push(ataIx) + } + + await withWithdrawGoverningTokens( + instructions, + realmInfo!.programId, + realmInfo!.programVersion!, + realm!.pubkey, + depositTokenAccount?.publicKey + ? depositTokenAccount!.publicKey + : new PublicKey(ataPk), + depositTokenRecord!.account.governingTokenMint, + wallet!.publicKey! + ) + + // Force the UI to recalculate voter weight + queryClient.invalidateQueries({ + queryKey: ['calculateVoterWeight'], + }) + + + try { + const ixChunks = chunks(instructions, 8) + for (const chunk of ixChunks.values()) { + const txes = [chunk].map((txBatch) => { + return { + instructionsSet: txBatch.map((x) => { + return { + transactionInstruction: x, + } + }), + sequenceType: SequenceType.Sequential, + } + }) + + await sendTransactionsV3({ + connection, + wallet: wallet!, + transactionInstructions: txes + }) + } + setDisableButton(false) + } catch (ex) { + setDisableButton(false) + //TODO change to more friendly notification + notify({ type: 'error', message: `${ex}` }) + console.error("Can't withdraw tokens", ex) + } + } catch(e) { + setDisableButton(false) + notify({ type: 'error', message: `${e}` }) + console.error("Can't withdraw tokens", e) + } + } + + + const hasTokensDeposited = + depositTokenRecord && + depositTokenRecord.account.governingTokenDepositAmount.gt(new BN(0)) + + const withdrawTooltipContent = !connected + ? 'Connect your wallet to withdraw' + : !hasTokensDeposited + ? "You don't have any tokens deposited to withdraw." + : role === 'community' && + (toManyCouncilOutstandingProposalsForUse || + toManyCommunityOutstandingProposalsForUser) + ? 'You have to many outstanding proposals to withdraw.' + : '' + + return ( + + Withdraw + + ) +} +export default VanillaWithdrawTokensButton diff --git a/components/Tooltip.tsx b/components/Tooltip.tsx index 73542f2de0..7fd30fa7aa 100644 --- a/components/Tooltip.tsx +++ b/components/Tooltip.tsx @@ -1,9 +1,9 @@ -import React, { ReactNode } from 'react' +import { ReactNode } from 'react' import Tippy from '@tippyjs/react' import 'tippy.js/animations/scale.css' type TooltipProps = { - content: ReactNode + content: ReactNode | undefined placement?: any className?: string children?: ReactNode diff --git a/components/TransactionLoader.tsx b/components/TransactionLoader.tsx index f19a230c8d..ca01c57f53 100644 --- a/components/TransactionLoader.tsx +++ b/components/TransactionLoader.tsx @@ -1,10 +1,10 @@ import { ExternalLinkIcon } from '@heroicons/react/outline' import useTransactionsStore from 'stores/useTransactionStore' -import useWalletStore from 'stores/useWalletStore' import Button from './Button' import { getExplorerUrl } from './explorer/tools' import Loading from './Loading' import Modal from './Modal' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' const TransactionLoader = () => { const { @@ -17,7 +17,7 @@ const TransactionLoader = () => { hasErrors, closeTransactionProcess, } = useTransactionsStore() - const connection = useWalletStore((s) => s.connection) + const connection = useLegacyConnectionContext() const currentlyProcessing = processedTransactions + 1 return isProcessing ? ( {
Error
-
{error}
+
+ {error} +
diff --git a/components/TreasuryAccount/AccountHeader.tsx b/components/TreasuryAccount/AccountHeader.tsx index ba78d1df12..a3bc325b44 100644 --- a/components/TreasuryAccount/AccountHeader.tsx +++ b/components/TreasuryAccount/AccountHeader.tsx @@ -1,17 +1,32 @@ import useTotalTokenValue from '@hooks/useTotalTokenValue' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { getMintDecimalAmountFromNatural } from '@tools/sdk/units' import BigNumber from 'bignumber.js' import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' import BaseAccountHeader from './BaseAccountHeader' +import { useRealmDigitalAssetsQuery } from '@hooks/queries/digitalAssets' +import { useMemo } from 'react' const AccountHeader = () => { const currentAccount = useTreasuryAccountStore((s) => s.currentAccount) - const nftsPerPubkey = useTreasuryAccountStore((s) => s.governanceNfts) - const nftsCount = - currentAccount?.governance && currentAccount.isNft - ? nftsPerPubkey[currentAccount?.governance?.pubkey.toBase58()]?.length - : 0 + const { data: nfts } = useRealmDigitalAssetsQuery() + const nftsCount = useMemo( + () => + nfts + ?.flat() + .filter( + (x) => + x.ownership.owner === + currentAccount?.governance.pubkey.toString() || + x.ownership.owner === + currentAccount?.extensions.transferAddress?.toString() + ).length ?? 0, + [ + currentAccount?.extensions.transferAddress, + currentAccount?.governance.pubkey, + nfts, + ] + ) const isNFT = currentAccount?.isNft const tokenInfo = useTreasuryAccountStore((s) => s.tokenInfo) const amount = diff --git a/components/TreasuryAccount/AccountItem.tsx b/components/TreasuryAccount/AccountItem.tsx index 6561e0db81..4fdd1e30c1 100644 --- a/components/TreasuryAccount/AccountItem.tsx +++ b/components/TreasuryAccount/AccountItem.tsx @@ -1,10 +1,8 @@ +import { useMemo } from 'react' import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools' import { AssetAccount } from '@utils/uiTypes/assets' -import { Metadata } from '@metaplex-foundation/mpl-token-metadata' -import { useEffect, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' -import { findMetadataPda } from '@metaplex-foundation/js' -import { PublicKey } from '@solana/web3.js' +import TokenIcon from '@components/treasuryV2/icons/TokenIcon' +import { useTokenMetadata } from '@hooks/queries/tokenMetadata' const AccountItem = ({ governedAccountTokenAccount, @@ -19,46 +17,14 @@ const AccountItem = ({ displayPrice, } = getTreasuryAccountItemInfoV2(governedAccountTokenAccount) - const [logoFromMeta, setLogoFromMeta] = useState( - undefined + const { data } = useTokenMetadata( + governedAccountTokenAccount.extensions.mint?.publicKey, + !logo ) - const [symbolFromMeta, setSymbolFromMeta] = useState( - undefined - ) - const connection = useWalletStore((s) => s.connection) - - useEffect(() => { - const getTokenMetadata = async (mintAddress: string) => { - try { - const mintPubkey = new PublicKey(mintAddress) - const metadataAccount = findMetadataPda(mintPubkey) - const accountData = await connection.current.getAccountInfo( - metadataAccount - ) - - const state = Metadata.deserialize(accountData!.data) - const jsonUri = state[0].data.uri.slice( - 0, - state[0].data.uri.indexOf('\x00') - ) - - const data = await (await fetch(jsonUri)).json() - setLogoFromMeta(data.image) - setSymbolFromMeta(data.symbol) - } catch (e) { - console.log(e) - } - } - if ( - !logo && - governedAccountTokenAccount.extensions.mint?.publicKey.toBase58() - ) { - getTokenMetadata( - governedAccountTokenAccount.extensions.mint?.publicKey.toBase58() - ) - } - }, [governedAccountTokenAccount.extensions.mint?.publicKey.toBase58()]) + const symbolFromMeta = useMemo(() => { + return data?.symbol + }, [data?.symbol]) return (
@@ -73,18 +39,11 @@ const AccountItem = ({ currentTarget.hidden = true }} /> - ) : logoFromMeta ? ( - { - currentTarget.onerror = null // prevents looping - currentTarget.hidden = true - }} - /> - ) : undefined} + ) : ( + + )}
{name}
diff --git a/components/TreasuryAccount/AccountItemNFT.tsx b/components/TreasuryAccount/AccountItemNFT.tsx index 1c20e59346..70a924cd62 100644 --- a/components/TreasuryAccount/AccountItemNFT.tsx +++ b/components/TreasuryAccount/AccountItemNFT.tsx @@ -1,72 +1,57 @@ import { PublicKey } from '@solana/web3.js' import { abbreviateAddress } from '@utils/formatting' -import useWalletStore from '../../stores/useWalletStore' -import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' -import { AssetAccount } from '@utils/uiTypes/assets' -import tokenService from '@utils/services/token' -import { WSOL_MINT } from '@components/instructions/tools' +import useTreasuryAddressForGovernance from '@hooks/useTreasuryAddressForGovernance' +import { useRealmDigitalAssetsQuery } from '@hooks/queries/digitalAssets' +import { useMemo } from 'react' + +/** this is just an item in the NFTAccountSelect */ const AccountItemNFT = ({ - governedAccountTokenAccount, + governance, className, - onClick, border = false, }: { - governedAccountTokenAccount: AssetAccount + governance: PublicKey className?: string - onClick?: () => void border?: boolean }) => { - const connection = useWalletStore((s) => s.connection) - const nftsPerPubkey = useTreasuryAccountStore((s) => s.governanceNfts) - const { setCurrentAccount } = useTreasuryAccountStore() + const { result: treasuryAddress } = useTreasuryAddressForGovernance( + governance + ) - const accountPublicKey = governedAccountTokenAccount - ? governedAccountTokenAccount.extensions.transferAddress - : null - //TODO move to outside component - async function handleGoToAccountOverview() { - setCurrentAccount(governedAccountTokenAccount, connection) - } - const info = governedAccountTokenAccount.isSol - ? tokenService.getTokenInfo(WSOL_MINT) - : undefined - const nftsCount = governedAccountTokenAccount.isSol - ? nftsPerPubkey[governedAccountTokenAccount.governance.pubkey.toBase58()] - ?.length + - nftsPerPubkey[ - governedAccountTokenAccount.extensions.transferAddress!.toBase58() - ]?.length - : nftsPerPubkey[governedAccountTokenAccount.governance.pubkey.toBase58()] - ?.length + const { data: nfts } = useRealmDigitalAssetsQuery() + + const nftsCount = useMemo( + () => + nfts + ?.flat() + .filter( + (x) => + x.ownership.owner === governance.toString() || + x.ownership.owner === treasuryAddress?.toString() + ).length, + [governance, nfts, treasuryAddress] + ) return (
- {governedAccountTokenAccount.isSol ? ( - - ) : ( - - )} +
- {abbreviateAddress(accountPublicKey as PublicKey)} + {treasuryAddress ? abbreviateAddress(treasuryAddress) : ''}
- {governedAccountTokenAccount.governance ? nftsCount : 0} NFTS + {nftsCount ?? '...'} NFTS
diff --git a/components/TreasuryAccount/AccountOverview.tsx b/components/TreasuryAccount/AccountOverview.tsx index d2ccdea0b7..1507657273 100644 --- a/components/TreasuryAccount/AccountOverview.tsx +++ b/components/TreasuryAccount/AccountOverview.tsx @@ -1,659 +1,6 @@ -import Button, { LinkButton } from '@components/Button' -import { getExplorerUrl } from '@components/explorer/tools' -import { - getAccountName, - WSOL_MINT, - WSOL_MINT_PK, -} from '@components/instructions/tools' -import Modal from '@components/Modal' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import useQueryContext from '@hooks/useQueryContext' -import useRealm from '@hooks/useRealm' -import { PublicKey } from '@solana/web3.js' -import { abbreviateAddress, fmtUnixTime } from '@utils/formatting' -import BN from 'bn.js' -import { useRouter } from 'next/router' -import React, { useEffect, useState } from 'react' -import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' -import useWalletStore from 'stores/useWalletStore' -import AccountHeader from './AccountHeader' -import DepositNFT from './DepositNFT' -import SendTokens from './SendTokens' -import { - ExternalLinkIcon, - PlusCircleIcon, - XCircleIcon, -} from '@heroicons/react/outline' -import Tooltip from '@components/Tooltip' -import ConvertToMsol from './ConvertToMsol' -import ConvertToStSol from './ConvertToStSol' -import useStrategiesStore from 'Strategies/store/useStrategiesStore' -import DepositModal from 'Strategies/components/DepositModal' -import { SolendStrategy, TreasuryStrategy } from 'Strategies/types/types' +import Button from '@components/Button' +import { TreasuryStrategy } from 'Strategies/types/types' import BigNumber from 'bignumber.js' -import { MangoAccount } from '@blockworks-foundation/mango-client' -import { - calculateAllDepositsInMangoAccountsForMint, - MANGO, - tryGetMangoAccountsForOwner, -} from 'Strategies/protocols/mango/tools' -import useMarketStore from 'Strategies/store/marketStore' -import LoadingRows from './LoadingRows' -import TradeOnSerum, { TradeOnSerumProps } from './TradeOnSerum' -import { AccountType } from '@utils/uiTypes/assets' -import CreateAta from './CreateAta' -import { - cTokenExchangeRate, - getReserveData, - SOLEND, -} from 'Strategies/protocols/solend' -import tokenService from '@utils/services/token' -import { EVERLEND } from '../../Strategies/protocols/everlend/tools' -import { findAssociatedTokenAccount } from '@everlend/common' - -type InvestmentType = TreasuryStrategy & { - investedAmount: number -} - -const AccountOverview = () => { - const router = useRouter() - const { ownTokenRecord, ownCouncilTokenRecord } = useRealm() - const { - governedTokenAccounts, - auxiliaryTokenAccounts, - } = useGovernanceAssets() - const currentAccount = useTreasuryAccountStore((s) => s.currentAccount) - const nftsPerPubkey = useTreasuryAccountStore((s) => s.governanceNfts) - const nftsCount = - currentAccount?.governance && currentAccount.isNft - ? nftsPerPubkey[currentAccount?.governance?.pubkey.toBase58()]?.length - : 0 - const { symbol } = useRealm() - const { fmtUrlWithCluster } = useQueryContext() - const isNFT = currentAccount?.isNft - const isSol = currentAccount?.isSol - const [loading, setLoading] = useState(true) - const isSplToken = currentAccount?.type === AccountType.TOKEN - const isAuxiliaryAccount = currentAccount?.type === AccountType.AuxiliaryToken - const { canUseTransferInstruction } = useGovernanceAssets() - const { connection, connected } = useWalletStore((s) => s) - const recentActivity = useTreasuryAccountStore((s) => s.recentActivity) - const isLoadingRecentActivity = useTreasuryAccountStore( - (s) => s.isLoadingRecentActivity - ) - const market = useMarketStore((s) => s) - const [mngoAccounts, setMngoAccounts] = useState([]) - const [openNftDepositModal, setOpenNftDepositModal] = useState(false) - const [openCommonSendModal, setOpenCommonSendModal] = useState(false) - const [openMsolConvertModal, setOpenMsolConvertModal] = useState(false) - const [openStSolConvertModal, setOpenStSolConvertModal] = useState(false) - const [openAtaModal, setOpenAtaModal] = useState(false) - const accountPublicKey = currentAccount?.extensions.transferAddress - const strategies = useStrategiesStore((s) => s.strategies) - const [accountInvestments, setAccountInvestments] = useState< - InvestmentType[] - >([]) - const [showStrategies, setShowStrategies] = useState(false) - const [ - proposedInvestment, - setProposedInvestment, - ] = useState(null) - const [isCopied, setIsCopied] = useState(false) - const [ - tradeSerumInfo, - setTradeSerumInfo, - ] = useState(null) - const strategyMint = currentAccount?.isSol - ? WSOL_MINT - : currentAccount?.extensions.token?.account.mint.toString() - const visibleInvestments = strategies.filter( - (strat) => strat.handledMint === strategyMint - ) - const visibleAccounts = accountInvestments.filter( - (strat) => strat.handledMint === strategyMint - ) - useEffect(() => { - const getSlndCTokens = async () => { - const accounts = [ - ...governedTokenAccounts, - ...auxiliaryTokenAccounts, - ...(currentAccount?.isSol ? [currentAccount] : []), - ] - - const solendStrategy = visibleInvestments.filter( - (strat) => strat.protocolName === SOLEND - )[0] - - const relevantAccs = accounts - .map((acc) => { - const reserve = (solendStrategy as SolendStrategy)?.reserves.find( - (reserve) => - reserve.mintAddress === strategyMint && - reserve.collateralMintAddress === - acc.extensions.mint?.publicKey.toBase58() - ) - if (!reserve || !solendStrategy) return null - - return { - acc, - reserve, - } - }) - .filter(Boolean) - - const reserveStats = await getReserveData( - relevantAccs.map((data) => data!.reserve.reserveAddress) - ) - - return relevantAccs.map((data) => { - const reserve = data!.reserve - const account = data!.acc - - const stat = reserveStats.find( - (stat) => stat.reserve.lendingMarket === reserve.marketAddress - )! - - return { - ...solendStrategy, - apy: `${reserve.supplyApy.toFixed(2)}%`, - protocolName: solendStrategy.protocolName, - strategySubtext: `${reserve.marketName} Pool`, - investedAmount: - ((account.extensions.amount?.toNumber() ?? 0) * - cTokenExchangeRate(stat)) / - 10 ** reserve.decimals, - } - }) as Array - } - - const handleGetMangoAccounts = async () => { - const currentAccountMint = currentAccount?.isSol - ? WSOL_MINT_PK - : currentAccount?.extensions.token?.account.mint - const currentPositions = calculateAllDepositsInMangoAccountsForMint( - mngoAccounts, - currentAccountMint!, - market - ) - if (currentPositions > 0) { - return strategies - .map((invest) => ({ - ...invest, - investedAmount: currentPositions, - })) - .filter((x) => x.protocolName === MANGO) - } - return [] - } - - const handleEverlendAccounts = async (): Promise => { - const everlendStrategy = visibleInvestments.filter( - (strat) => strat.protocolName === EVERLEND - )[0] - - const tokenMintATA = await findAssociatedTokenAccount( - isSol - ? currentAccount!.pubkey - : currentAccount!.extensions!.token!.account.owner, - - new PublicKey( - (everlendStrategy as TreasuryStrategy & { poolMint: string }).poolMint - ) - ) - const tokenMintATABalance = await connection.current.getTokenAccountBalance( - tokenMintATA - ) - - return [ - { - ...everlendStrategy, - investedAmount: Number(tokenMintATABalance.value.uiAmount), - }, - ].filter((strat) => strat.investedAmount !== 0) - } - - const loadData = async () => { - const requests = [] as Array>> - if (visibleInvestments.filter((x) => x.protocolName === MANGO).length) { - requests.push(handleGetMangoAccounts()) - } - if (visibleInvestments.filter((x) => x.protocolName === SOLEND).length) { - requests.push(getSlndCTokens()) - } - - if ( - visibleInvestments.filter((x) => x.protocolName === EVERLEND).length - ) { - requests.push(handleEverlendAccounts()) - } - - const results = (await Promise.allSettled(requests)) - .filter((x) => x.status === 'fulfilled') - //@ts-ignore - .map((x) => x.value) - - setLoading(false) - - setAccountInvestments(results.flatMap((x) => x)) - } - - loadData() - }, [currentAccount, mngoAccounts, visibleInvestments.length]) - useEffect(() => { - const getMangoAcccounts = async () => { - const accounts = await tryGetMangoAccountsForOwner( - market, - currentAccount!.governance!.pubkey - ) - setMngoAccounts(accounts ? accounts : []) - } - if (currentAccount) { - getMangoAcccounts() - } - }, [currentAccount, market]) - - useEffect(() => { - if (isCopied) { - const timer = setTimeout(() => { - setIsCopied(false) - }, 1500) - return () => clearTimeout(timer) - } - }, [isCopied]) - - useEffect(() => { - if (visibleInvestments.length && visibleAccounts.length === 0) { - setShowStrategies(true) - } else { - setShowStrategies(false) - } - }, [currentAccount, visibleAccounts.length, visibleInvestments.length]) - - const handleCopyAddress = (address: string) => { - navigator.clipboard.writeText(address) - setIsCopied(true) - } - - if (!currentAccount) { - return null - } - - const deposits = visibleAccounts.reduce( - (acc, account) => ({ - ...acc, - [account.protocolName]: - (acc[account.protocolName] ?? 0) + account.investedAmount, - }), - {} - ) - - const StaticInvestmentsComponent = () => { - const currentTokenImg = currentAccount.isToken - ? tokenService.getTokenInfo( - currentAccount.extensions.mint!.publicKey.toBase58() - )?.logoURI || '' - : '' - const marinadeStrategy = { - liquidity: 0, - protocolSymbol: '', - apy: '', - protocolName: 'Marinade', - handledMint: '', - handledTokenSymbol: '', - handledTokenImgSrc: - 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png', - protocolLogoSrc: - 'https://raw.githubusercontent.com/LP-Finance-Inc/token-image/main/msol.png', - strategyName: 'Stake', - strategyDescription: '', - createProposalFcn: () => null, - } - const lidoStrategy = { - liquidity: 0, - protocolSymbol: '', - apy: '', - protocolName: 'Lido', - handledMint: '', - handledTokenSymbol: '', - handledTokenImgSrc: - 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png', - protocolLogoSrc: - 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj/logo.png', - strategyName: 'Stake', - strategyDescription: '', - createProposalFcn: () => null, - } - const serumStrategy = { - liquidity: 0, - protocolSymbol: '', - apy: '', - protocolName: 'Serum', - handledMint: '', - handledTokenSymbol: '', - handledTokenImgSrc: currentTokenImg, - protocolLogoSrc: - 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt/logo.png', - strategyName: 'Trade', - strategyDescription: '', - createProposalFcn: () => null, - } - return ( - <> - {isSol && ( - setOpenMsolConvertModal(true)} - currentDeposits={0} - strat={marinadeStrategy} - > - )} - {isSol && ( - setOpenStSolConvertModal(true)} - currentDeposits={0} - strat={lidoStrategy} - > - )} - {isSplToken && ( - setTradeSerumInfo({ tokenAccount: currentAccount })} - currentDeposits={0} - strat={serumStrategy} - > - )} - - ) - } - const NoInvestmentsIndicator = () => { - return ( - <> -
-

- {loading ? 'Loading...' : 'No investments for this account'} -

-
- - ) - } - return ( - <> -
-

- {currentAccount?.extensions.transferAddress && - getAccountName(currentAccount.extensions.transferAddress) - ? getAccountName(currentAccount.extensions.transferAddress) - : accountPublicKey && - abbreviateAddress(accountPublicKey as PublicKey)} -

-
- {isNFT && ( -

{ - const url = fmtUrlWithCluster(`/dao/${symbol}/gallery`) - router.push(url) - }} - > - View Collection -

- )} - e.stopPropagation()} - > - Explorer - - -
-
- -
-
- {isCopied && ( -
- Copied to Clipboard -
- )} - -
- {!isAuxiliaryAccount && ( - - )} - {isSol ? ( - - ) : null} -
- {!isAuxiliaryAccount && ( -
-
-

- {showStrategies ? 'Available Investments' : 'Current Investments'} -

- setShowStrategies(!showStrategies)} - > - {showStrategies ? ( - <> - - Cancel - - ) : ( - <> - - Investments - - )} - -
- {showStrategies ? ( - <> - {visibleInvestments.length > 0 && - visibleInvestments.map((strat, i) => ( - { - setProposedInvestment({ - ...strat, - investedAmount: deposits[strat.protocolName] ?? 0, - }) - }} - strat={strat} - /> - ))} - - - ) : visibleAccounts.length > 0 ? ( - visibleAccounts.map((strat, i) => ( - - )) - ) : ( - - )} -
- )} -

Recent Activity

-
- {isLoadingRecentActivity ? ( - - ) : recentActivity.length > 0 ? ( - recentActivity.map((activity) => ( - -
{activity.signature.substring(0, 12)}...
-
-
- {activity.blockTime - ? fmtUnixTime(new BN(activity.blockTime)) - : null} -
- -
-
- )) - ) : ( -
-

No recent activity

-
- )} -
- {proposedInvestment && ( - { - setProposedInvestment(null) - }} - proposedInvestment={proposedInvestment} - protocolName={proposedInvestment.protocolName} - protocolLogoSrc={proposedInvestment.protocolLogoSrc} - handledTokenName={proposedInvestment.handledTokenSymbol} - strategyName={proposedInvestment.strategyName} - createProposalFcn={proposedInvestment.createProposalFcn} - /> - )} - {openNftDepositModal && ( - { - setOpenNftDepositModal(false) - }} - isOpen={openNftDepositModal} - > - { - setOpenNftDepositModal(false) - }} - > - - )} - {openCommonSendModal && ( - { - setOpenCommonSendModal(false) - }} - isOpen={openCommonSendModal} - > - - - )} - {openMsolConvertModal && ( - { - setOpenMsolConvertModal(false) - }} - isOpen={openMsolConvertModal} - > - - - )} - {openStSolConvertModal && ( - { - setOpenStSolConvertModal(false) - }} - isOpen={openStSolConvertModal} - > - - - )} - {openAtaModal && isSol && ( - { - setOpenAtaModal(false) - }} - isOpen={openAtaModal} - > - setOpenAtaModal(false)} - owner={currentAccount.extensions.transferAddress!} - governancePk={currentAccount.governance.pubkey} - /> - - )} - {tradeSerumInfo && ( - { - setTradeSerumInfo(null) - }} - isOpen={!!tradeSerumInfo} - > - - - )} - - ) -} interface StrategyCardProps { onClick?: () => void @@ -673,6 +20,8 @@ export const StrategyCard = ({ strategySubtext, handledTokenSymbol, apy, + apyHeader, + noProtocol, } = strat const currentPositionFtm = new BigNumber( currentDeposits.toFixed(2) @@ -698,9 +47,9 @@ export const StrategyCard = ({
)}
-

{`${strategyName} ${handledTokenSymbol} on ${protocolName}${ - strategySubtext ? ` - ${strategySubtext}` : '' - }`}

+

{`${strategyName} ${handledTokenSymbol} ${ + noProtocol ? '' : `on ${protocolName}` + }${strategySubtext ? ` - ${strategySubtext}` : ''}`}

{(handledTokenSymbol || currentPositionFtm !== '0') && (

{`${currentPositionFtm} ${handledTokenSymbol}`}

)} @@ -708,7 +57,7 @@ export const StrategyCard = ({
- {apy &&

Interest Rate

} + {apy &&

{apyHeader ?? 'Interest Rate'}

}

{apy}

{onClick ? : null} @@ -716,5 +65,3 @@ export const StrategyCard = ({
) } - -export default AccountOverview diff --git a/components/TreasuryAccount/AccountsCompactWrapper.tsx b/components/TreasuryAccount/AccountsCompactWrapper.tsx index 512d12f0d4..09659bb0eb 100644 --- a/components/TreasuryAccount/AccountsCompactWrapper.tsx +++ b/components/TreasuryAccount/AccountsCompactWrapper.tsx @@ -20,9 +20,7 @@ const AccountsCompactWrapper = () => { ] const { symbol } = useRealm() const { fmtUrlWithCluster } = useQueryContext() - const isLoadingAccounts = useGovernanceAssetsStore( - (s) => s.loadGovernedAccounts - ) + const isLoadingAccounts = useGovernanceAssetsStore((s) => s.loadTokenAccounts) return (
diff --git a/components/TreasuryAccount/AccountsItems.tsx b/components/TreasuryAccount/AccountsItems.tsx index 535012d825..04d4afbbde 100644 --- a/components/TreasuryAccount/AccountsItems.tsx +++ b/components/TreasuryAccount/AccountsItems.tsx @@ -12,11 +12,16 @@ const AccountsItems = () => { ...governedTokenAccountsWithoutNfts, ...auxiliaryTokenAccounts, ] - const accountsSorted = accounts.sort((a, b) => { - const infoA = getTreasuryAccountItemInfoV2(a) - const infoB = getTreasuryAccountItemInfoV2(b) - return infoB.totalPrice - infoA.totalPrice - }) + const accountsSorted = accounts + .sort((a, b) => { + const infoA = getTreasuryAccountItemInfoV2(a) + const infoB = getTreasuryAccountItemInfoV2(b) + return infoB.totalPrice - infoA.totalPrice + }) + .splice( + 0, + Number(process?.env?.MAIN_VIEW_SHOW_MAX_TOP_TOKENS_NUM || accounts.length) + ) return (
{accountsSorted.map((account) => { diff --git a/components/TreasuryAccount/AccountsTabs.tsx b/components/TreasuryAccount/AccountsTabs.tsx deleted file mode 100644 index 62da98a89f..0000000000 --- a/components/TreasuryAccount/AccountsTabs.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import { FunctionComponent, useEffect, useState } from 'react' -import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools' -import { AssetAccount } from '@utils/uiTypes/assets' -import useWalletStore from 'stores/useWalletStore' -import { findMetadataPda } from '@metaplex-foundation/js' -import { PublicKey } from '@solana/web3.js' -import { Metadata } from '@metaplex-foundation/mpl-token-metadata' - -interface AccountsTabsProps { - activeTab: AssetAccount | null - onChange: (x) => void - tabs: Array -} - -const AccountsTabs: FunctionComponent = ({ - activeTab, - onChange, - tabs, -}) => { - return ( -
-
- t.extensions.transferAddress === - activeTab?.extensions.transferAddress - ) * 100 - }%)`, - height: `${100 / tabs.length}%`, - }} - /> - {tabs.map((x) => { - return ( - - ) - })} -
- ) -} - -interface AccountTabProps { - assetAccount: AssetAccount - activeTab: AssetAccount | null - onChange: (x) => void -} - -const AccountTab: FunctionComponent = ({ - assetAccount, - activeTab, - onChange, -}) => { - const { - amountFormatted, - logo, - name, - symbol, - displayPrice, - } = getTreasuryAccountItemInfoV2(assetAccount) - - const [logoFromMeta, setLogoFromMeta] = useState( - undefined - ) - const [symbolFromMeta, setSymbolFromMeta] = useState( - undefined - ) - const connection = useWalletStore((s) => s.connection) - - useEffect(() => { - const getTokenMetadata = async (mintAddress: string) => { - try { - const mintPubkey = new PublicKey(mintAddress) - const metadataAccount = findMetadataPda(mintPubkey) - const accountData = await connection.current.getAccountInfo( - metadataAccount - ) - - const state = Metadata.deserialize(accountData!.data) - const jsonUri = state[0].data.uri.slice( - 0, - state[0].data.uri.indexOf('\x00') - ) - - const data = await (await fetch(jsonUri)).json() - - setLogoFromMeta(data.image) - setSymbolFromMeta(data.symbol) - } catch (e) { - console.log(e) - } - } - if (!logo && assetAccount.extensions.mint?.publicKey.toBase58()) { - getTokenMetadata(assetAccount.extensions.mint?.publicKey.toBase58()) - } - }, [assetAccount.extensions.mint?.publicKey.toBase58()]) - return ( - - ) -} - -export default AccountsTabs diff --git a/components/TreasuryAccount/BaseAccountHeader.tsx b/components/TreasuryAccount/BaseAccountHeader.tsx index 6d9d94381e..c44630a114 100644 --- a/components/TreasuryAccount/BaseAccountHeader.tsx +++ b/components/TreasuryAccount/BaseAccountHeader.tsx @@ -1,14 +1,12 @@ -import { TokenInfo } from '@solana/spl-token-registry' import React from 'react' import { useEffect, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' -import { findMetadataPda } from '@metaplex-foundation/js' import { PublicKey } from '@solana/web3.js' -import { Metadata } from '@metaplex-foundation/mpl-token-metadata' +import { TokenInfoWithoutDecimals } from '@utils/services/tokenPrice' +import { useTokenMetadata } from '@hooks/queries/tokenMetadata' const BaseAccountHeader: React.FC<{ isNFT?: boolean - tokenInfo?: TokenInfo + tokenInfo?: TokenInfoWithoutDecimals amountFormatted: string totalPrice?: string mintAddress: string @@ -16,38 +14,20 @@ const BaseAccountHeader: React.FC<{ const [logo, setLogo] = useState(tokenInfo?.logoURI) const [symbol, setSymbol] = useState(tokenInfo?.symbol) - const connection = useWalletStore((s) => s.connection) + const { data } = useTokenMetadata( + new PublicKey(mintAddress), + !tokenInfo?.symbol + ) useEffect(() => { - const getTokenMetadata = async (mintAddress: string) => { - try { - const mintPubkey = new PublicKey(mintAddress) - const metadataAccount = findMetadataPda(mintPubkey) - const accountData = await connection.current.getAccountInfo( - metadataAccount - ) - - const state = Metadata.deserialize(accountData!.data) - const jsonUri = state[0].data.uri.slice( - 0, - state[0].data.uri.indexOf('\x00') - ) - - const data = await (await fetch(jsonUri)).json() - - setLogo(data.image) - setSymbol(data.symbol) - } catch (e) { - console.log(e) - } - } if (tokenInfo?.address) { setLogo(tokenInfo?.logoURI) setSymbol(tokenInfo?.symbol) - } else { - getTokenMetadata(mintAddress) } - }) + if (data?.symbol) { + setSymbol(data?.symbol) + } + }, [data, tokenInfo]) return (
{(logo || isNFT) && ( diff --git a/components/TreasuryAccount/ConvertToMsol.tsx b/components/TreasuryAccount/ConvertToMsol.tsx index ba06d41592..15ec4be60f 100644 --- a/components/TreasuryAccount/ConvertToMsol.tsx +++ b/components/TreasuryAccount/ConvertToMsol.tsx @@ -3,7 +3,7 @@ import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' import AccountLabel from './AccountHeader' import GovernedAccountSelect from 'pages/dao/[symbol]/proposal/components/GovernedAccountSelect' import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { useEffect, useState } from 'react' +import React, { useEffect, useState } from 'react' import { StakingViewForm, UiInstruction, @@ -16,30 +16,29 @@ import useRealm from '@hooks/useRealm' import VoteBySwitch from 'pages/dao/[symbol]/proposal/components/VoteBySwitch' import Button from '@components/Button' import Tooltip from '@components/Tooltip' -import useWalletStore from 'stores/useWalletStore' import { getStakeSchema } from '@utils/validations' import { getConvertToMsolInstruction } from '@utils/instructionTools' -import { - getInstructionDataFromBase64, - Governance, - ProgramAccount, -} from '@solana/spl-governance' +import { getInstructionDataFromBase64 } from '@solana/spl-governance' import useQueryContext from '@hooks/useQueryContext' import { useRouter } from 'next/router' import { notify } from '@utils/notifications' import useCreateProposal from '@hooks/useCreateProposal' import { AssetAccount } from '@utils/uiTypes/assets' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; const ConvertToMsol = () => { - const { canChooseWhoVote, realm, symbol } = useRealm() + const realm = useRealmQuery().data?.result + const {symbol } = useRealm() const { canUseTransferInstruction } = useGovernanceAssets() const { governedTokenAccounts } = useGovernanceAssets() const { fmtUrlWithCluster } = useQueryContext() const router = useRouter() const { handleCreateProposal } = useCreateProposal() - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const { fetchRealmGovernance } = useWalletStore((s) => s.actions) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() const currentAccount = useTreasuryAccountStore((s) => s.currentAccount) const notConnectedMessage = 'You need to be connected to your wallet to have the ability to create a staking proposal' @@ -53,7 +52,7 @@ const ConvertToMsol = () => { description: '', }) const [showOptions, setShowOptions] = useState(false) - const [voteByCouncil, setVoteByCouncil] = useState(false) + const { voteByCouncil, shouldShowVoteByCouncilToggle, setVoteByCouncil } = useVoteByCouncilToggle(); const [isLoading, setIsLoading] = useState(false) const mSolTokenAccounts = governedTokenAccounts.filter( @@ -75,6 +74,8 @@ const ConvertToMsol = () => { } const handlePropose = async () => { + if (currentAccount?.governance === undefined) throw new Error() + setIsLoading(true) const instruction: UiInstruction = await getConvertToMsolInstruction({ schema, @@ -102,15 +103,10 @@ const ConvertToMsol = () => { } try { - // Fetch governance to get up to date proposalCount - const selectedGovernance = (await fetchRealmGovernance( - currentAccount?.governance?.pubkey - )) as ProgramAccount - const proposalAddress = await handleCreateProposal({ title: form.title ? form.title : proposalTitle, description: form.description ? form.description : '', - governance: selectedGovernance, + governance: currentAccount?.governance, instructionsData: [instructionData], voteByCouncil, isDraft: false, @@ -131,6 +127,7 @@ const ConvertToMsol = () => { value: currentAccount, propertyName: 'governedTokenAccount', }) + // 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 }, [currentAccount, form.destinationAccount]) return ( @@ -227,13 +224,13 @@ const ConvertToMsol = () => { }) } > - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - > + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > )} )} diff --git a/components/TreasuryAccount/ConvertToStSol.tsx b/components/TreasuryAccount/ConvertToStSol.tsx index 84e3ab8d3b..0fdef041b7 100644 --- a/components/TreasuryAccount/ConvertToStSol.tsx +++ b/components/TreasuryAccount/ConvertToStSol.tsx @@ -3,7 +3,7 @@ import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' import AccountLabel from './AccountHeader' import GovernedAccountSelect from 'pages/dao/[symbol]/proposal/components/GovernedAccountSelect' import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { useEffect, useState } from 'react' +import React, { useEffect, useState } from 'react' import { StakingViewForm, UiInstruction, @@ -16,20 +16,23 @@ import useRealm from '@hooks/useRealm' import VoteBySwitch from 'pages/dao/[symbol]/proposal/components/VoteBySwitch' import Button from '@components/Button' import Tooltip from '@components/Tooltip' -import useWalletStore from 'stores/useWalletStore' import { getStakeSchema } from '@utils/validations' import { getConvertToStSolInstruction } from '@utils/instructionTools' -import { - getInstructionDataFromBase64, - Governance, - ProgramAccount, -} from '@solana/spl-governance' +import { getInstructionDataFromBase64 } from '@solana/spl-governance' import useQueryContext from '@hooks/useQueryContext' import { useRouter } from 'next/router' import { notify } from '@utils/notifications' import useCreateProposal from '@hooks/useCreateProposal' import { AssetAccount } from '@utils/uiTypes/assets' import { PublicKey } from '@solana/web3.js' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { + LIDO_PROGRAM_ID, + LIDO_PROGRAM_ID_DEVNET, +} from '@constants/pubkeys/lido' +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; const defaultFormState = { destinationAccount: undefined, @@ -47,24 +50,21 @@ const getProposalText = (amount) => { const LIDO_ADDRESS = '49Yi1TKkNyYjPAFdR9LBvoHcUjuPX4Df5T5yv39w2XTn' const STSOL_MINT = '7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj' -export const LIDO_PROGRAM_ID = 'CrX7kMhLC3cSsXJdT7JDgqrRVWGnUpX3gfEfxxU2NVLi' const LIDO_ADDRESS_DEVNET = '8sqs4Jzs8uq7CEtimhXf32gioVUN3n5Qk65YMkNU5E4F' const STSOL_MINT_DEVNET = '5nnLCgZn1EQaLj1ub8vYbQgBhkWi97x4JC5ARVPhci4V' -export const LIDO_PROGRAM_ID_DEVNET = - 'CbxVmURN74QZGuFj6qKjM8VDM8b8KKZrbPFLM2CC2hC8' const ConvertToStSol = () => { - const { canChooseWhoVote, realm, symbol } = useRealm() + const realm = useRealmQuery().data?.result + const {symbol } = useRealm() const { canUseTransferInstruction } = useGovernanceAssets() const { governedTokenAccounts } = useGovernanceAssets() const { fmtUrlWithCluster } = useQueryContext() const router = useRouter() const { handleCreateProposal } = useCreateProposal() - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const { fetchRealmGovernance } = useWalletStore((s) => s.actions) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() const currentAccount = useTreasuryAccountStore((s) => s.currentAccount) const [formErrors, setFormErrors] = useState({}) @@ -73,7 +73,7 @@ const ConvertToStSol = () => { ) const [form, setForm] = useState(defaultFormState) const [showOptions, setShowOptions] = useState(false) - const [voteByCouncil, setVoteByCouncil] = useState(false) + const { voteByCouncil, shouldShowVoteByCouncilToggle, setVoteByCouncil } = useVoteByCouncilToggle(); const [isLoading, setIsLoading] = useState(false) const mintMinAmount = form.governedTokenAccount?.extensions?.mint @@ -130,15 +130,10 @@ const ConvertToStSol = () => { } try { - // Fetch governance to get up to date proposalCount - const selectedGovernance = (await fetchRealmGovernance( - currentAccount?.governance?.pubkey - )) as ProgramAccount - const proposalAddress = await handleCreateProposal({ title: form.title ? form.title : getProposalText(form.amount), description: form.description ? form.description : '', - governance: selectedGovernance, + governance: currentAccount!.governance!, instructionsData: [instructionData], voteByCouncil, isDraft: false, @@ -159,6 +154,7 @@ const ConvertToStSol = () => { value: currentAccount, propertyName: 'governedTokenAccount', }) + // 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 }, [currentAccount, form.destinationAccount]) useEffect(() => { @@ -168,6 +164,7 @@ const ConvertToStSol = () => { return acc.extensions.mint?.publicKey.toString() === stSolMint }) setStSolTokenAccounts(stSolAccounts) + // 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 }, [connection.cluster]) return ( @@ -264,13 +261,13 @@ const ConvertToStSol = () => { }) } /> - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - /> + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > )} )} diff --git a/components/TreasuryAccount/CreateAta.tsx b/components/TreasuryAccount/CreateAta.tsx index 766e36284d..e3b5304831 100644 --- a/components/TreasuryAccount/CreateAta.tsx +++ b/components/TreasuryAccount/CreateAta.tsx @@ -1,5 +1,4 @@ import { useState } from 'react' -import useWalletStore from 'stores/useWalletStore' import { Keypair, PublicKey, @@ -10,11 +9,13 @@ import Button from '@components/Button' import { createATA } from '@utils/ataTools' import { tryGetAta } from '@utils/validations' import { sendTransaction } from '@utils/send' -import useRealm from '@hooks/useRealm' import useGovernanceAssetsStore from 'stores/useGovernanceAssetsStore' import * as serum from '@project-serum/common' import TokenMintInput from '@components/inputs/TokenMintInput' -import { TokenInfo } from '@solana/spl-token-registry' +import { TokenInfoWithoutDecimals } from '@utils/services/tokenPrice' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' const CreateAta = ({ owner, @@ -25,20 +26,21 @@ const CreateAta = ({ governancePk: PublicKey createCallback: () => void }) => { - const { realm } = useRealm() + const realm = useRealmQuery().data?.result const refetchGovernanceAccounts = useGovernanceAssetsStore( (s) => s.refetchGovernanceAccounts ) - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() const [isLoading, setIsLoading] = useState(false) const [validatedTypedMint, setValidatedTypedMint] = useState< string | undefined >() const [foundByNameToken, setFoundByNameToken] = useState< - TokenInfo | undefined + TokenInfoWithoutDecimals | undefined >() const handleCreate = async () => { + if (!realm) throw new Error() const mintPk = validatedTypedMint ? new PublicKey(validatedTypedMint) : new PublicKey(foundByNameToken!.address) @@ -56,7 +58,7 @@ const CreateAta = ({ wallet, mintPk, owner, - wallet!.publicKey! + wallet.publicKey! ) } else { const instructions: TransactionInstruction[] = [] @@ -81,15 +83,16 @@ const CreateAta = ({ await sendTransaction({ transaction, - wallet: wallet!, - connection: connection.current!, + wallet: wallet, + connection: connection.current, signers, }) } - await refetchGovernanceAccounts(connection, realm!, governancePk) + await refetchGovernanceAccounts(connection, realm, governancePk) setIsLoading(false) createCallback() } + return (

Create token account

diff --git a/components/TreasuryAccount/DepositNFT.tsx b/components/TreasuryAccount/DepositNFT.tsx deleted file mode 100644 index 051617c375..0000000000 --- a/components/TreasuryAccount/DepositNFT.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import React, { useState } from 'react' -import useWalletStore from 'stores/useWalletStore' -import Button, { SecondaryButton } from '@components/Button' -import Tooltip from '@components/Tooltip' -import DepositNFTFromWallet from './DepositNFTFromWallet' -import DepositNFTAddress from './DepositNFTAddress' -import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' -import { ArrowLeftIcon, ExternalLinkIcon } from '@heroicons/react/solid' -import { getExplorerUrl } from '@components/explorer/tools' - -enum DepositState { - DepositNFTFromWallet, - DepositNFTAddress, -} - -const DepositNFT = ({ onClose }) => { - const currentAccount = useTreasuryAccountStore((s) => s.currentAccount) - const connection = useWalletStore((s) => s.connection) - const connected = useWalletStore((s) => s.connected) - const [ - currentDepositView, - setCurrentDepositView, - ] = useState(null) - - return ( - <> -

- {currentDepositView !== null && ( - setCurrentDepositView(null)} - /> - )} - Deposit NFT - e.stopPropagation()} - > - - -

- {currentDepositView === null && ( -
- - -
- )} - {currentDepositView === DepositState.DepositNFTFromWallet && ( - - )} - {currentDepositView === DepositState.DepositNFTAddress && ( - Close - } - > - )} - - ) -} - -export default DepositNFT diff --git a/components/TreasuryAccount/DepositNFTAddress.tsx b/components/TreasuryAccount/DepositNFTAddress.tsx deleted file mode 100644 index f56e2a4f69..0000000000 --- a/components/TreasuryAccount/DepositNFTAddress.tsx +++ /dev/null @@ -1,227 +0,0 @@ -import React, { useEffect, useState } from 'react' -import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' -import Input from '@components/inputs/Input' -import { tryParseKey } from '@tools/validators/pubkey' -import { debounce } from '@utils/debounce' -import useWalletStore from 'stores/useWalletStore' -import { deprecated } from '@metaplex-foundation/mpl-token-metadata' -import axios from 'axios' -import { notify } from '@utils/notifications' -import Loading from '@components/Loading' -import Button, { LinkButton } from '@components/Button' -import { PublicKey } from '@solana/web3.js' -import { - ASSOCIATED_TOKEN_PROGRAM_ID, - Token, - TOKEN_PROGRAM_ID, -} from '@solana/spl-token' -import Tooltip from '@components/Tooltip' -import { tryGetAta } from '@utils/validations' -import useRealm from '@hooks/useRealm' -import { createATA } from '@utils/ataTools' -import { abbreviateAddress } from '@utils/formatting' -import { DuplicateIcon, ExclamationIcon } from '@heroicons/react/outline' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import DepositLabel from './DepositLabel' -import NFTAccountSelect from './NFTAccountSelect' -import ImgWithLoader from '@components/ImgWithLoader' -const DepositNFTAddress = ({ additionalBtns }: { additionalBtns?: any }) => { - const currentAccount = useTreasuryAccountStore((s) => s.currentAccount) - - const wallet = useWalletStore((s) => s.current) - const { realm } = useRealm() - const connected = useWalletStore((s) => s.connected) - const [form, setForm] = useState({ - mint: '', - }) - const [isLoading, setIsLoading] = useState(false) - const [nftMetaData, setNftMetaData] = useState( - null - ) - const [isInvalidMint, setIsInvalidMint] = useState(false) - const [formErrors, setFormErrors] = useState({}) - const [imgUrl, setImgUrl] = useState('') - const [ataAddress, setAtaAddress] = useState('') - const { nftsGovernedTokenAccounts } = useGovernanceAssets() - const { setCurrentAccount } = useTreasuryAccountStore() - const connection = useWalletStore((s) => s.connection) - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - const handleGenerateATAAddress = async () => { - setAtaAddress('') - if (!currentAccount) { - throw 'No governance selected' - } - if (!realm) { - throw 'no realm selected' - } - const mintPK = new PublicKey(form.mint) - const owner = currentAccount?.isSol - ? currentAccount.extensions.transferAddress! - : currentAccount!.governance!.pubkey - const ataPk = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID - TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID - mintPK, // mint - owner!, // owner - true - ) - const ata = ataPk.toBase58() - const isExistingAta = await tryGetAta(connection.current, mintPK, owner) - if (!isExistingAta) { - try { - await createATA( - connection.current, - wallet, - mintPK, - owner, - wallet!.publicKey! - ) - setAtaAddress(ata) - } catch (e) { - notify({ - type: 'error', - message: 'Unable to create address', - }) - setAtaAddress('') - } - } else { - setAtaAddress(ata) - } - } - useEffect(() => { - setIsInvalidMint(false) - if (form.mint) { - debounce.debounceFcn(async () => { - const pubKey = tryParseKey(form.mint) - if (pubKey) { - setIsLoading(true) - try { - const metadataPDA = await deprecated.Metadata.getPDA(pubKey) - const tokenMetadata = await deprecated.Metadata.load( - connection.current, - metadataPDA - ) - setNftMetaData(tokenMetadata) - } catch (e) { - notify({ - type: 'error', - message: 'Unable to fetch nft', - }) - setNftMetaData(null) - } - setIsLoading(false) - } else { - setIsInvalidMint(true) - setNftMetaData(null) - } - }) - } else { - setNftMetaData(null) - } - }, [form.mint]) - useEffect(() => { - const uri = nftMetaData?.data?.data?.uri - const getNftData = async (uri) => { - if (uri) { - setIsLoading(true) - try { - const nftResponse = (await axios.get(uri)).data - setImgUrl(nftResponse.image) - } catch (e) { - notify({ - type: 'error', - message: 'Unable to fetch nft', - }) - } - setIsLoading(false) - } else { - setImgUrl('') - } - } - setAtaAddress('') - getNftData(uri) - }, [JSON.stringify(nftMetaData)]) - return ( - <> - setCurrentAccount(value, connection)} - currentAccount={currentAccount} - nftsGovernedTokenAccounts={nftsGovernedTokenAccounts} - > - -
-
-
- - { - "If your wallet doesn't support sending nfts to shared wallets please generate address using the nft mint" - } -
-
- - handleSetForm({ - value: evt.target.value, - propertyName: 'mint', - }) - } - noMaxWidth={true} - error={formErrors['mint']} - /> - - {isInvalidMint && ( -
Invalid mint address
- )} - {isLoading ? ( - - ) : ( - imgUrl && ( -
- -
- ) - )} -
- {ataAddress && ( -
-
-
- {abbreviateAddress(new PublicKey(ataAddress))} -
-
-
- { - navigator.clipboard.writeText(ataAddress) - }} - > - - -
-
- )} -
-
{additionalBtns}
-
- - ) -} - -export default DepositNFTAddress diff --git a/components/TreasuryAccount/DepositNFTFromWallet.tsx b/components/TreasuryAccount/DepositNFTFromWallet.tsx index f5f59621b8..80a87cf84e 100644 --- a/components/TreasuryAccount/DepositNFTFromWallet.tsx +++ b/components/TreasuryAccount/DepositNFTFromWallet.tsx @@ -1,126 +1,162 @@ -import React, { useEffect, useRef, useState } from 'react' -import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' -import useWalletStore from 'stores/useWalletStore' +import { useState } from 'react' import Button from '@components/Button' import Tooltip from '@components/Tooltip' -import { NFTWithMint } from '@utils/uiTypes/nfts' +import { PublicKey } from '@solana/web3.js' +import NFTSelector from '@components/NFTS/NFTSelector' +import NFTAccountSelect from './NFTAccountSelect' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' import { notify } from '@utils/notifications' -import { web3 } from '@project-serum/anchor' import { ASSOCIATED_TOKEN_PROGRAM_ID, - Token, TOKEN_PROGRAM_ID, + Token, } from '@solana/spl-token' -import { PublicKey } from '@solana/web3.js' import { createATA } from '@utils/ataTools' -import { getTokenAccountsByMint } from '@utils/tokens' -import { sendTransaction } from '@utils/send' -import NFTSelector, { NftSelectorFunctions } from '@components/NFTS/NFTSelector' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import NFTAccountSelect from './NFTAccountSelect' +import { createIx_transferNft } from '@utils/metaplex' +import { SequenceType, sendTransactionsV3 } from '@utils/sendTransactions' +import { getNativeTreasuryAddress } from '@solana/spl-governance' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import useGovernanceSelect from '@hooks/useGovernanceSelect' +import queryClient from '@hooks/queries/queryClient' +import { + digitalAssetsQueryKeys, + fetchDigitalAssetById, +} from '@hooks/queries/digitalAssets' +import { getNetworkFromEndpoint } from '@utils/connection' +import { buildTransferCnftInstruction } from '@hooks/instructions/useTransferCnftInstruction' +import { useRealmQuery } from '@hooks/queries/realm' +import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' + +const useMetaplexDeposit = () => { + const wallet = useWalletOnePointOh() + const connection = useLegacyConnectionContext() + const realm = useRealmQuery().data?.result + + return async (nftId: PublicKey, governance: PublicKey) => { + if (!wallet?.publicKey) throw new Error() + if (realm === undefined) throw new Error() + + // ostensibly currentAccount should in fact be a native treasury, but I haven't verified this. + const toOwner = await getNativeTreasuryAddress(realm.owner, governance) + const network = getNetworkFromEndpoint(connection.current.rpcEndpoint) + if (network === 'localnet') throw new Error() + const nft = (await fetchDigitalAssetById(network, nftId)).result + if (nft === undefined) throw new Error('nft not found') + + const ix = nft.compression?.compressed + ? await buildTransferCnftInstruction(connection.current, nftId, toOwner) + : await createIx_transferNft( + connection.current, + wallet.publicKey, + toOwner, + nftId, + wallet.publicKey, + wallet.publicKey + ) + + await sendTransactionsV3({ + connection: connection.current, + wallet, + transactionInstructions: [ + { + instructionsSet: [{ transactionInstruction: ix }], + sequenceType: SequenceType.Parallel, + }, + ], + }) + } +} const DepositNFTFromWallet = ({ additionalBtns }: { additionalBtns?: any }) => { - const nftSelectorRef = useRef(null) - const { setCurrentAccount } = useTreasuryAccountStore() const currentAccount = useTreasuryAccountStore((s) => s.currentAccount) - const { getNfts } = useTreasuryAccountStore() - const [selectedNfts, setSelectedNfts] = useState([]) - const wallet = useWalletStore((s) => s.current) - const connected = useWalletStore((s) => s.connected) - const connection = useWalletStore((s) => s.connection) + const [selectedNfts, setSelectedNfts] = useState([]) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const connection = useLegacyConnectionContext() const [isLoading, setIsLoading] = useState(false) - const [sendingSuccess, setSendingSuccess] = useState(false) - const { nftsGovernedTokenAccounts } = useGovernanceAssets() + + const deposit = useMetaplexDeposit() + + const [selectedGovernance, setSelectedGovernance] = useGovernanceSelect( + currentAccount?.governance.pubkey + ) + const realm = useRealmQuery().data?.result const handleDeposit = async () => { - for (const i of selectedNfts) { + if (selectedGovernance === undefined) throw new Error() + if (realm === undefined) throw new Error() + + // really these should probably get batched into one TX or whatever. + for (const nftMint of selectedNfts) { setIsLoading(true) - setSendingSuccess(false) - try { - const owner = currentAccount?.isSol - ? currentAccount.extensions.transferAddress! - : currentAccount!.governance!.pubkey - const ConnectedWalletAddress = wallet?.publicKey - const selectedNft = i - const nftMintPk = new PublicKey(selectedNft.mintAddress) - const tokenAccountsWithNftMint = await getTokenAccountsByMint( - connection.current, - nftMintPk.toBase58() - ) - //we find ata from connected wallet that holds the nft - const fromAddress = tokenAccountsWithNftMint.find( - (x) => - x.account.owner.toBase58() === ConnectedWalletAddress?.toBase58() - )?.publicKey - //we check is there ata created for nft before - const doseAtaForReciverAddressExisit = tokenAccountsWithNftMint.find( - (x) => x.account.owner.toBase58() === owner.toBase58() + + const network = getNetworkFromEndpoint(connection.current.rpcEndpoint) + if (network === 'localnet') throw new Error() + + const nft = (await fetchDigitalAssetById(network, nftMint)).result + if (nft === undefined) throw new Error('nft not found') + if (nft.compression.compressed === false) { + const owner = await getNativeTreasuryAddress( + realm.owner, + selectedGovernance ) const ataPk = await Token.getAssociatedTokenAddress( ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID - nftMintPk, // mint + nftMint, // mint owner!, // owner true ) - if (!doseAtaForReciverAddressExisit) { + + const ataQueried = await connection.current.getAccountInfo(ataPk) + + if (ataQueried === null) { await createATA( connection.current, wallet, - nftMintPk, + nftMint, owner!, wallet!.publicKey! ) } - const transaction = new web3.Transaction().add( - Token.createTransferInstruction( - TOKEN_PROGRAM_ID, - fromAddress!, - ataPk, - wallet!.publicKey!, - [], - 1 - ) - ) - await sendTransaction({ - connection: connection.current, - wallet: wallet!, - transaction, - sendingMessage: 'Depositing NFT', - successMessage: 'NFT has been deposited', + } + + await deposit(new PublicKey(nftMint), selectedGovernance) + .then(() => { + queryClient.invalidateQueries(digitalAssetsQueryKeys.all(network)) }) - setSendingSuccess(true) - nftSelectorRef.current?.handleGetNfts() - getNfts(nftsGovernedTokenAccounts, connection) - } catch (e) { - notify({ - type: 'error', - message: 'Unable to send selected nft', + .catch((e) => { + notify({ + type: 'error', + message: 'Unable to send selected nft', + }) + throw e }) - } + setIsLoading(false) } } - useEffect(() => { - if (sendingSuccess) { - setCurrentAccount(currentAccount!, connection) - } - }, [connected, sendingSuccess]) + const walletPk = wallet?.publicKey return ( <> - setCurrentAccount(value, connection)} - currentAccount={currentAccount} - nftsGovernedTokenAccounts={nftsGovernedTokenAccounts} - > - setSelectedNfts(selected)} - > + {selectedGovernance && ( + + )} + {walletPk ? ( + + ) : ( + 'Please connect your wallet' + )}
{additionalBtns} diff --git a/components/TreasuryAccount/HoldTokensTotalPrice.tsx b/components/TreasuryAccount/HoldTokensTotalPrice.tsx index 040ed1ca7e..963a41c543 100644 --- a/components/TreasuryAccount/HoldTokensTotalPrice.tsx +++ b/components/TreasuryAccount/HoldTokensTotalPrice.tsx @@ -1,11 +1,14 @@ import { useTotalTreasuryPrice } from '@hooks/useTotalTreasuryPrice' +import { formatNumber } from '@utils/formatNumber' + const HoldTokensTotalPrice = () => { - const { totalPriceFormatted } = useTotalTreasuryPrice() + const { totalPriceFormatted, isFetching } = useTotalTreasuryPrice() + return (

Treasury Balance

- ${totalPriceFormatted ? totalPriceFormatted : 0} + {isFetching ? 'Fetching ...' : `$${formatNumber(totalPriceFormatted)}`}
) diff --git a/components/TreasuryAccount/LoadingRows.tsx b/components/TreasuryAccount/LoadingRows.tsx deleted file mode 100644 index 0dddaabbe1..0000000000 --- a/components/TreasuryAccount/LoadingRows.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react' - -const LoadingRows = () => { - return ( -
-
-
-
-
- ) -} - -export default LoadingRows diff --git a/components/TreasuryAccount/MangoModal.tsx b/components/TreasuryAccount/MangoModal.tsx new file mode 100644 index 0000000000..fec0b5f447 --- /dev/null +++ b/components/TreasuryAccount/MangoModal.tsx @@ -0,0 +1,770 @@ +import { + Group, + MangoAccount, + USDC_MINT, + toUiDecimals, + toNative, +} from '@blockworks-foundation/mango-v4' +import AdditionalProposalOptions from '@components/AdditionalProposalOptions' +import Button, { LinkButton } from '@components/Button' +import Input from '@components/inputs/Input' +import Select from '@components/inputs/Select' +import { BN } from '@coral-xyz/anchor' +import useCreateProposal from '@hooks/useCreateProposal' +import UseMangoV4 from '@hooks/useMangoV4' +import useQueryContext from '@hooks/useQueryContext' +import useRealm from '@hooks/useRealm' +import { + getInstructionDataFromBase64, + serializeInstructionToBase64, +} from '@solana/spl-governance' +import { AccountMeta, PublicKey } from '@solana/web3.js' +import { AssetAccount } from '@utils/uiTypes/assets' +import { useRouter } from 'next/router' +import { useEffect, useState } from 'react' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import Tooltip from '@components/Tooltip' +import { + getMintDecimalAmount, + getMintMinAmountAsDecimal, +} from '@tools/sdk/units' +import BigNumber from 'bignumber.js' +import { precision } from '@utils/formatting' +import * as yup from 'yup' +import tokenPriceService from '@utils/services/tokenPrice' +import { validateInstruction } from '@utils/instructionTools' +import Switch from '@components/Switch' +import { InstructionDataWithHoldUpTime } from 'actions/createProposal' +import ProgramSelector from '@components/Mango/ProgramSelector' +import useProgramSelector from '@components/Mango/useProgramSelector' +import ButtonGroup from '@components/ButtonGroup' + +enum ProposalType { + DEPOSIT = 'Deposit', + WITHDRAW = 'Withdraw', +} +import { useVoteByCouncilToggle } from '@hooks/useVoteByCouncilToggle' + +const MangoModal = ({ account }: { account: AssetAccount }) => { + const { canUseTransferInstruction } = useGovernanceAssets() + const programSelectorHook = useProgramSelector() + const { mangoClient, mangoGroup, getMaxWithdrawForBank } = UseMangoV4( + programSelectorHook.program?.val, + programSelectorHook.program?.group + ) + const { fmtUrlWithCluster } = useQueryContext() + const { handleCreateProposal } = useCreateProposal() + const router = useRouter() + const { symbol } = useRealm() + const [isProposing, setIsProposing] = useState(false) + const { voteByCouncil, setVoteByCouncil } = useVoteByCouncilToggle() + const [isLoadingMangoAccount, setIsLoadingMangoAccount] = useState( + true + ) + const [mangoAccounts, setMangoAccounts] = useState([]) + const tabs = [ProposalType.DEPOSIT, ProposalType.WITHDRAW] + const [proposalType, setProposalType] = useState(ProposalType.DEPOSIT) + const [form, setForm] = useState<{ + mangoAccount: MangoAccount | null | undefined + accountName: string + amount: number + title: string + description: string + delegate: boolean + delegateWallet: string + }>({ + accountName: '', + title: '', + description: '', + amount: 0, + mangoAccount: undefined, + delegate: false, + delegateWallet: '', + }) + + const [formErrors, setFormErrors] = useState({}) + const [maxWithdrawBalance, setMaxWithdrawBalance] = useState(0) + + const handleSetForm = ({ propertyName, value }) => { + setForm({ ...form, [propertyName]: value }) + setFormErrors({}) + } + + useEffect(() => { + setForm({ ...form, mangoAccount: undefined }) + }, [programSelectorHook.program?.val.toBase58()]) + + useEffect(() => { + setFormErrors({}) + setForm({ + ...form, + accountName: '', + amount: 0, + mangoAccount: undefined, + title: `${proposalType} ${ + tokenPriceService.getTokenInfo( + account.extensions.mint!.publicKey.toBase58() + )?.symbol || 'tokens' + } ${proposalType === 'Withdraw' ? 'from' : 'to'} Mango`, + }) + }, [proposalType]) + + const SOL_BUFFER = 0.02 + + const treasuryAmount = new BN( + account.isSol + ? account.extensions.amount!.toNumber() + : account.extensions.token!.account.amount + ) + const mintInfo = account.extensions.mint!.account! + const mintMinAmount = mintInfo ? getMintMinAmountAsDecimal(mintInfo) : 1 + let maxAmount = mintInfo + ? getMintDecimalAmount(mintInfo, treasuryAmount) + : new BigNumber(0) + if (account.isSol) { + maxAmount = maxAmount.minus(SOL_BUFFER) + } + const maxAmountFtm = maxAmount.toNumber().toFixed(4) + const currentPrecision = precision(mintMinAmount) + + const schema = yup.object().shape({ + mangoAccount: yup + .object() + .nullable(true) + .test( + 'is-not-undefined', + 'Please select an Account', + (value) => value !== undefined + ), + accountName: yup.string().when('mangoAccount', { + is: null, + then: yup.string().required('Account name is required'), + otherwise: yup.string().notRequired(), + }), + title: yup.string().required('Title is required'), + amount: yup + .number() + .required('Amount is required') + .min(mintMinAmount) + .max( + proposalType === ProposalType.DEPOSIT + ? maxAmount.toNumber() + : maxWithdrawBalance + ), + delegate: yup.boolean().required('Delegate is required'), + delegateWallet: yup + .string() + .nullable() + .when('delegate', { + is: true, + then: yup.string().required('Delegate Wallet is required'), + otherwise: yup.string().notRequired(), + }), + }) + + useEffect(() => { + setMangoAccounts([]) + }, [programSelectorHook.program?.val]) + + useEffect(() => { + const getMangoAccounts = async () => { + const accounts = await mangoClient?.getMangoAccountsForOwner( + mangoGroup!, + account.extensions.token!.account.owner! + ) + + if (accounts) { + setMangoAccounts(accounts) + } + } + if (mangoClient && mangoGroup) { + setMangoAccounts([]) + setIsLoadingMangoAccount(true) + getMangoAccounts().then(() => setIsLoadingMangoAccount(false)) + } + }, [account.extensions.token, mangoClient, mangoGroup]) + + useEffect(() => { + if (proposalType === ProposalType.DEPOSIT) return + if (!mangoGroup || !form.mangoAccount) return + const bank = mangoGroup!.getFirstBankByMint( + account.extensions.mint!.publicKey! + ) + const maxWithdrawForBank = getMaxWithdrawForBank( + mangoGroup, + bank, + form.mangoAccount + ) + setMaxWithdrawBalance(maxWithdrawForBank.toNumber()) + }, [proposalType, mangoGroup, form]) + + const handleCreateAccount = async () => { + const isValid = await validateInstruction({ schema, form, setFormErrors }) + if (!isValid) return + + try { + setIsProposing(true) + const instructions: InstructionDataWithHoldUpTime[] = [] + let mangoAccountPk = form.mangoAccount?.publicKey + const bank = mangoGroup!.getFirstBankByMint( + account.extensions.mint!.publicKey! + ) + + if (form.mangoAccount === null) { + const newAccountNum = getNextAccountNumber(mangoAccounts) + const createAccIx = await mangoClient!.program.methods + .accountCreate( + newAccountNum, + 8, + 4, + 4, + 32, + form.accountName || `Account ${newAccountNum + 1}` + ) + .accounts({ + group: mangoGroup!.publicKey, + owner: account.extensions.token!.account.owner!, + payer: account.extensions.token!.account.owner!, + }) + .instruction() + + const createAccInstData = { + data: getInstructionDataFromBase64( + serializeInstructionToBase64(createAccIx) + ), + holdUpTime: + account?.governance.account?.config.minInstructionHoldUpTime, + prerequisiteInstructions: [], + chunkBy: 1, + } + + instructions.push(createAccInstData) + + const acctNumBuffer = Buffer.alloc(4) + acctNumBuffer.writeUInt32LE(newAccountNum) + + const [mangoAccount] = PublicKey.findProgramAddressSync( + [ + Buffer.from('MangoAccount'), + mangoGroup!.publicKey.toBuffer(), + account.extensions.token!.account.owner!.toBuffer(), + acctNumBuffer, + ], + mangoClient!.programId + ) + mangoAccountPk = mangoAccount + } + + const tokens = toNative( + form.amount, + account.extensions.mint!.account!.decimals + ) + + if (proposalType === ProposalType.DEPOSIT) { + const methodByProposal = mangoClient!.program.methods.tokenDeposit + const methodByProposalInstruction = await methodByProposal( + tokens, + false + ) + .accounts({ + group: mangoGroup!.publicKey, + account: mangoAccountPk, + owner: account.extensions.token!.account.owner!, + bank: bank.publicKey, + vault: bank.vault, + oracle: bank.oracle, + tokenAccount: account.pubkey, + tokenAuthority: account.extensions.token!.account.owner!, + }) + .remainingAccounts( + [bank.publicKey, bank.oracle].map( + (pk) => + ({ + pubkey: pk, + isWritable: false, + isSigner: false, + } as AccountMeta) + ) + ) + .instruction() + + const depositAccInstData = { + data: getInstructionDataFromBase64( + serializeInstructionToBase64(methodByProposalInstruction!) + ), + holdUpTime: + account?.governance.account?.config.minInstructionHoldUpTime, + prerequisiteInstructions: [], + chunkBy: 1, + } + + instructions.push(depositAccInstData) + } + + if (proposalType === ProposalType.WITHDRAW) { + const withdrawTxs = await mangoClient!.tokenWithdrawNativeIx( + mangoGroup!, + form.mangoAccount!, + account.extensions.mint!.publicKey!, + tokens, + false + ) + + for (const withdrawTx of withdrawTxs) { + const withdrawAccInsData = { + data: getInstructionDataFromBase64( + serializeInstructionToBase64(withdrawTx) + ), + holdUpTime: + account?.governance.account?.config.minInstructionHoldUpTime, + prerequisiteInstructions: [], + chunkBy: 1, + } + + instructions.push(withdrawAccInsData) + } + } + + if (form.delegate) { + const delegateIx = await mangoClient!.program.methods + .accountEdit(null, new PublicKey(form.delegateWallet), null, null) + .accounts({ + group: mangoGroup!.publicKey, + account: mangoAccountPk, + owner: account.extensions.token!.account.owner!, + }) + .instruction() + + const delegateAccInstData = { + data: getInstructionDataFromBase64( + serializeInstructionToBase64(delegateIx!) + ), + holdUpTime: + account?.governance.account?.config.minInstructionHoldUpTime, + prerequisiteInstructions: [], + chunkBy: 1, + } + + instructions.push(delegateAccInstData) + } + + const proposalAddress = await handleCreateProposal({ + title: form.title, + description: form.description, + voteByCouncil, + instructionsData: instructions, + governance: account.governance!, + }) + const url = fmtUrlWithCluster( + `/dao/${symbol}/proposal/${proposalAddress}` + ) + router.push(url) + } catch (e) { + console.log(e) + } + setIsProposing(false) + } + + return ( +
+
+ +
+

Mango

+
+
+
+
+ setProposalType(v)} + values={tabs} + /> +
+ {proposalType === ProposalType.WITHDRAW && ( +
+ {account.extensions.mint?.publicKey.toBase58() === + USDC_MINT.toBase58() && ( + + )} + + + {form.mangoAccount === null && ( + + handleSetForm({ + propertyName: 'accountName', + value: e.target.value, + }) + } + /> + )} +
+ Amount +
+ {maxWithdrawBalance} + { + handleSetForm({ + propertyName: 'amount', + value: maxWithdrawBalance, + }) + }} + > + Max + +
+
+ + handleSetForm({ + propertyName: 'amount', + value: e.target.value, + }) + } + onBlur={() => { + handleSetForm({ + propertyName: 'amount', + value: parseFloat( + Math.max( + Number(mintMinAmount), + Math.min( + Number(Number.MAX_SAFE_INTEGER), + Number(form.amount) + ) + ).toFixed(currentPrecision) + ), + }) + }} + /> +
+

Delegate

+ + handleSetForm({ + propertyName: 'delegate', + value: !form.delegate, + }) + } + /> +
+ {form.delegate && ( + + handleSetForm({ + propertyName: 'delegateWallet', + value: e.target.value, + }) + } + /> + )} + { + handleSetForm({ + propertyName: 'title', + value: evt.target.value, + }) + }} + setDescription={(evt) => { + handleSetForm({ + propertyName: 'description', + value: evt.target.value, + }) + }} + voteByCouncil={voteByCouncil} + setVoteByCouncil={setVoteByCouncil} + /> +
+ +
+
+ )} + {proposalType === ProposalType.DEPOSIT && ( +
+ {account.extensions.mint?.publicKey.toBase58() === + USDC_MINT.toBase58() && ( + + )} + + + {form.mangoAccount === null && ( + + handleSetForm({ + propertyName: 'accountName', + value: e.target.value, + }) + } + /> + )} +
+ Amount +
+ {maxAmountFtm} + { + handleSetForm({ + propertyName: 'amount', + value: maxAmount.toNumber(), + }) + }} + > + Max + +
+
+ + handleSetForm({ + propertyName: 'amount', + value: e.target.value, + }) + } + onBlur={() => { + handleSetForm({ + propertyName: 'amount', + value: parseFloat( + Math.max( + Number(mintMinAmount), + Math.min( + Number(Number.MAX_SAFE_INTEGER), + Number(form.amount) + ) + ).toFixed(currentPrecision) + ), + }) + }} + /> +
+

Delegate

+ + handleSetForm({ + propertyName: 'delegate', + value: !form.delegate, + }) + } + /> +
+ {form.delegate && ( + + handleSetForm({ + propertyName: 'delegateWallet', + value: e.target.value, + }) + } + /> + )} + { + handleSetForm({ + propertyName: 'title', + value: evt.target.value, + }) + }} + setDescription={(evt) => { + handleSetForm({ + propertyName: 'description', + value: evt.target.value, + }) + }} + voteByCouncil={voteByCouncil} + setVoteByCouncil={setVoteByCouncil} + /> +
+ +
+
+ )} +
+
+ ) +} + +const MangoAccountItem = ({ + account, + group, +}: { + account: MangoAccount | null + group: Group | null +}) => { + return account && group ? ( +
+
Name: {account.name}
+
{account.publicKey.toBase58()}
+
+ Account Value: ${toUiDecimals(account.getAssetsValue(group), 6)} +
+
+ ) : ( +
Create new account
+ ) +} + +const getNextAccountNumber = (accounts: MangoAccount[]): number => { + if (accounts.length > 1) { + return ( + accounts + .map((a) => a.accountNum) + .reduce((a, b) => Math.max(a, b), -Infinity) + 1 + ) + } else if (accounts.length === 1) { + return accounts[0].accountNum + 1 + } + return 0 +} + +export default MangoModal diff --git a/components/TreasuryAccount/NFTAccountSelect.tsx b/components/TreasuryAccount/NFTAccountSelect.tsx index 9eb5385e84..598170ee71 100644 --- a/components/TreasuryAccount/NFTAccountSelect.tsx +++ b/components/TreasuryAccount/NFTAccountSelect.tsx @@ -1,36 +1,39 @@ import Select from '@components/inputs/Select' import AccountItemNFT from './AccountItemNFT' +import { PublicKey } from '@solana/web3.js' +import { useRealmGovernancesQuery } from '@hooks/queries/governance' +/** Governance selector with NFT counts */ const NFTAccountSelect = ({ onChange, - nftsGovernedTokenAccounts, - currentAccount, + selectedGovernance, +}: { + onChange: (x: PublicKey) => void + selectedGovernance: PublicKey }) => { + const { data: governances } = useRealmGovernancesQuery() + return ( - {filteredTypes.map((x) => { - return ( - - {x.name} - - ) - })} - - )} - - {treasuryType?.value === OTHER && ( - <> - - handleSetForm({ - value: evt.target.value, - propertyName: 'mintAddress', - }) - } - error={formErrors['mintAddress']} - /> - {tokenInfo ? ( -
- {tokenInfo?.logoURI && ( - - )} -
- {tokenInfo.name} -

{tokenInfo?.symbol}

-
-
- ) : mint ? ( -
Mint found
- ) : null} - - )} - -
- -
-
- ) -} - -export default NewAccountForm diff --git a/components/TreasuryAccount/ProposalOptions.tsx b/components/TreasuryAccount/ProposalOptions.tsx index acd48ed0cf..f5597a7559 100644 --- a/components/TreasuryAccount/ProposalOptions.tsx +++ b/components/TreasuryAccount/ProposalOptions.tsx @@ -6,13 +6,13 @@ import React from 'react' const ProposalOptions: React.FC<{ handleSetForm: (obj: { propertyName: string; value: any }) => void form: any - canChooseWhoVote?: boolean + shouldShowVoteByCouncilToggle?: boolean voteByCouncil: boolean setVoteByCouncil: React.Dispatch> }> = ({ handleSetForm, form, - canChooseWhoVote, + shouldShowVoteByCouncilToggle, voteByCouncil, setVoteByCouncil, }) => { @@ -46,14 +46,14 @@ const ProposalOptions: React.FC<{ }) } > - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - > - )} + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > + )} ) } diff --git a/components/TreasuryAccount/SendTokens.tsx b/components/TreasuryAccount/SendTokens.tsx index bb85a458f4..5955daf8bd 100644 --- a/components/TreasuryAccount/SendTokens.tsx +++ b/components/TreasuryAccount/SendTokens.tsx @@ -11,28 +11,24 @@ import { } from '@tools/sdk/units' import { tryParseKey } from '@tools/validators/pubkey' import { debounce } from '@utils/debounce' -import { abbreviateAddress, precision } from '@utils/formatting' +import { precision } from '@utils/formatting' import { TokenProgramAccount, tryGetTokenAccount } from '@utils/tokens' import { SendTokenCompactViewForm, UiInstruction, } from '@utils/uiTypes/proposalCreationTypes' -import React, { useEffect, useState } from 'react' +import React, { ChangeEvent, useEffect, useState } from 'react' import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' -import useWalletStore from 'stores/useWalletStore' -import { getTokenTransferSchema } from '@utils/validations' +import { getBatchTokenTransferSchema } from '@utils/validations' import { ArrowCircleDownIcon, ArrowCircleUpIcon, // InformationCircleIcon, } from '@heroicons/react/solid' -import tokenService from '@utils/services/token' import BigNumber from 'bignumber.js' import { getInstructionDataFromBase64 } from '@solana/spl-governance' import useQueryContext from '@hooks/useQueryContext' -import { Governance } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' import { useRouter } from 'next/router' import { notify } from '@utils/notifications' import Textarea from '@components/inputs/Textarea' @@ -41,59 +37,56 @@ import AccountLabel from './AccountHeader' import Tooltip from '@components/Tooltip' import useGovernanceAssets from '@hooks/useGovernanceAssets' import { - getSolTransferInstruction, - getTransferInstruction, - getTransferNftInstruction, + getBatchSolTransferInstruction, + getBatchTransferInstruction, } from '@utils/instructionTools' import VoteBySwitch from 'pages/dao/[symbol]/proposal/components/VoteBySwitch' -import NFTSelector from '@components/NFTS/NFTSelector' -import { NFTWithMint } from '@utils/uiTypes/nfts' import useCreateProposal from '@hooks/useCreateProposal' -import NFTAccountSelect from './NFTAccountSelect' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { fetchJupiterPrice } from '@hooks/queries/jupiterPrice' +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; +import { AddAlt } from '@carbon/icons-react' +import { StyledLabel } from '@components/inputs/styles' -const SendTokens = ({ - isNft = false, - selectedNft, -}: { - isNft?: boolean - selectedNft?: NFTWithMint | null -}) => { +const SendTokens = () => { const currentAccount = useTreasuryAccountStore((s) => s.currentAccount) - const connection = useWalletStore((s) => s.connection) - const { nftsGovernedTokenAccounts } = useGovernanceAssets() - const { setCurrentAccount } = useTreasuryAccountStore() - const { realmInfo, symbol, realm, canChooseWhoVote } = useRealm() + const connection = useLegacyConnectionContext() + const realm = useRealmQuery().data?.result + const { realmInfo, symbol} = useRealm() const { handleCreateProposal } = useCreateProposal() const { canUseTransferInstruction } = useGovernanceAssets() const tokenInfo = useTreasuryAccountStore((s) => s.tokenInfo) - const isNFT = isNft || currentAccount?.isNft const isSol = currentAccount?.isSol const { fmtUrlWithCluster } = useQueryContext() - const wallet = useWalletStore((s) => s.current) + const wallet = useWalletOnePointOh() const router = useRouter() - const { fetchRealmGovernance } = useWalletStore((s) => s.actions) const programId: PublicKey | undefined = realmInfo?.programId const [form, setForm] = useState({ - destinationAccount: '', - amount: isNFT ? 1 : undefined, + destinationAccount: [''], + txDollarAmount: [undefined], + amount: [undefined], governedTokenAccount: undefined, programId: programId?.toString(), mintInfo: undefined, title: '', description: '', }) - const [selectedNfts, setSelectedNfts] = useState([]) - const [voteByCouncil, setVoteByCouncil] = useState(false) + const { voteByCouncil, shouldShowVoteByCouncilToggle, setVoteByCouncil } = useVoteByCouncilToggle(); const [showOptions, setShowOptions] = useState(false) const [ destinationAccount, setDestinationAccount, - ] = useState | null>(null) + ] = useState<(TokenProgramAccount | null)[]>([null]) + const [isLoading, setIsLoading] = useState(false) const [formErrors, setFormErrors] = useState({}) - const destinationAccountName = - destinationAccount?.publicKey && - getAccountName(destinationAccount?.account.address) + const destinationAccountName = destinationAccount.map(acc => ( + acc?.publicKey && + getAccountName(acc?.account.address) + )) + const mintMinAmount = form.governedTokenAccount?.extensions?.mint ? getMintMinAmountAsDecimal( form.governedTokenAccount.extensions.mint.account @@ -105,109 +98,64 @@ const SendTokens = ({ setFormErrors({}) setForm({ ...form, [propertyName]: value }) } - const setAmount = (event) => { - const value = event.target.value - handleSetForm({ - value: value, - propertyName: 'amount', + + const handleSetMultipleProps = ( + {destinationAccount, amount, txDollarAmount} : + {amount: any, txDollarAmount: any, destinationAccount?: any} + ) => { + setFormErrors({}) + + setForm({ ...form, + destinationAccount : destinationAccount ? destinationAccount : form.destinationAccount, + amount, + txDollarAmount }) } - const validateAmountOnBlur = () => { - const value = form.amount + + const setAmount = (idx: number, event: ChangeEvent) => { + const value = event.target.value + const newAmounts: any[] = [...form.amount] + newAmounts[idx] = value handleSetForm({ - value: parseFloat( - Math.max( - Number(mintMinAmount), - Math.min(Number(Number.MAX_SAFE_INTEGER), Number(value)) - ).toFixed(currentPrecision) - ), + value: newAmounts, propertyName: 'amount', }) } - const calcTransactionDolarAmount = (amount) => { - const price = tokenService.getUSDTokenPrice( - currentAccount!.extensions.mint!.publicKey.toBase58() + + const validateAmountOnBlur = async(idx: number) => { + const value = form.amount[idx] + const newAmounts = [...form.amount] + const newTxDollars = [...form.txDollarAmount] + + const newVal = parseFloat( + Math.max( + Number(mintMinAmount), + Math.min(Number(Number.MAX_SAFE_INTEGER), Number(value)) + ).toFixed(currentPrecision) ) - const totalPrice = amount * price - const totalPriceFormatted = - amount && price ? new BigNumber(totalPrice).toFormat(2) : '' - return totalPriceFormatted - } + + newAmounts[idx] = newVal - async function getNftInstruction(x: NFTWithMint): Promise { - const selectedNftMint = x.mintAddress - const defaultProps = { - schema, - form, - programId, - connection, - wallet, - currentAccount, - setFormErrors, + const mint = currentAccount?.extensions.mint?.publicKey + if (mint === undefined) { + newTxDollars[idx] = undefined + } else { + const priceData = await fetchJupiterPrice(mint) + const price = priceData.result?.price ?? 0 + + const totalPrice = newVal * price + const totalPriceFormatted = newVal && price ? new BigNumber(totalPrice).toFormat(2) : '' + newTxDollars[idx] = totalPriceFormatted } - return getTransferNftInstruction({ - ...defaultProps, - nftMint: selectedNftMint, + + handleSetMultipleProps({ + amount: newAmounts, + txDollarAmount: newTxDollars }) } - const handleProposeNftSend = async () => { - for (const x of selectedNfts) { - const nftName = x?.name - const nftTitle = `Send ${nftName ? nftName : 'NFT'} to ${ - tryParseKey(form.destinationAccount) - ? abbreviateAddress(new PublicKey(form.destinationAccount)) - : '' - }` - const proposalTitle = isNFT - ? nftTitle - : `Pay ${form.amount}${tokenInfo ? ` ${tokenInfo?.symbol} ` : ' '}to ${ - tryParseKey(form.destinationAccount) - ? abbreviateAddress(new PublicKey(form.destinationAccount)) - : '' - }` - setIsLoading(true) - const instruction: UiInstruction = await getNftInstruction(x) - if (instruction.isValid) { - const governance = currentAccount?.governance - let proposalAddress: PublicKey | null = null - if (!realm) { - setIsLoading(false) - throw 'No realm selected' - } - const instructionData = { - data: instruction.serializedInstruction - ? getInstructionDataFromBase64(instruction.serializedInstruction) - : null, - holdUpTime: governance?.account?.config.minInstructionHoldUpTime, - prerequisiteInstructions: instruction.prerequisiteInstructions || [], - } - try { - // Fetch governance to get up to date proposalCount - const selectedGovernance = (await fetchRealmGovernance( - governance?.pubkey - )) as ProgramAccount - proposalAddress = await handleCreateProposal({ - title: form.title ? form.title : proposalTitle, - description: form.description ? form.description : '', - voteByCouncil, - instructionsData: [instructionData], - governance: selectedGovernance!, - }) - const url = fmtUrlWithCluster( - `/dao/${symbol}/proposal/${proposalAddress}` - ) - router.push(url) - } catch (ex) { - notify({ type: 'error', message: `${ex}` }) - } - } - setIsLoading(false) - } - } - - async function getInstruction(): Promise { + async function getInstruction(): Promise { const defaultProps = { schema, form, @@ -218,39 +166,38 @@ const SendTokens = ({ setFormErrors, } if (isSol) { - return getSolTransferInstruction(defaultProps) + return getBatchSolTransferInstruction(defaultProps) } - return getTransferInstruction(defaultProps) + return getBatchTransferInstruction(defaultProps) } const handleProposeTransfer = async () => { setIsLoading(true) - const instruction: UiInstruction = await getInstruction() - if (instruction.isValid) { + const instruction: UiInstruction[] = await getInstruction() + + if (instruction.every(ix => ix.isValid)) { const governance = currentAccount?.governance let proposalAddress: PublicKey | null = null if (!realm) { setIsLoading(false) throw 'No realm selected' } - const instructionData = { - data: instruction.serializedInstruction - ? getInstructionDataFromBase64(instruction.serializedInstruction) + const instructionsData = instruction.map(ix => ({ + data: ix.serializedInstruction + ? getInstructionDataFromBase64(ix.serializedInstruction) : null, holdUpTime: governance?.account?.config.minInstructionHoldUpTime, - prerequisiteInstructions: instruction.prerequisiteInstructions || [], - } + prerequisiteInstructions: ix.prerequisiteInstructions || [], + chunkBy: 4 + })) + try { - // Fetch governance to get up to date proposalCount - const selectedGovernance = (await fetchRealmGovernance( - governance?.pubkey - )) as ProgramAccount proposalAddress = await handleCreateProposal({ title: form.title ? form.title : proposalTitle, description: form.description ? form.description : '', voteByCouncil, - instructionsData: [instructionData], - governance: selectedGovernance!, + instructionsData, + governance: governance!, }) const url = fmtUrlWithCluster( `/dao/${symbol}/proposal/${proposalAddress}` @@ -263,18 +210,19 @@ const SendTokens = ({ setIsLoading(false) } - const IsAmountNotHigherThenBalance = () => { - const mintValue = getMintNaturalAmountFromDecimalAsBN( - form.amount!, - form.governedTokenAccount!.extensions.mint!.account.decimals - ) - let gte: boolean | undefined = false + const IsAmountNotHigherThenBalance = (idx: number) => { try { + const mintValue = getMintNaturalAmountFromDecimalAsBN( + form.amount[idx]!, + form.governedTokenAccount!.extensions.mint!.account.decimals + ) + let gte: boolean | undefined = false gte = form.governedTokenAccount!.extensions.amount?.gte(mintValue) + return gte } catch (e) { //silent fail + return true } - return gte } useEffect(() => { if (currentAccount) { @@ -283,122 +231,132 @@ const SendTokens = ({ propertyName: 'governedTokenAccount', }) } + // 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 }, [currentAccount]) - useEffect(() => { - if (form.destinationAccount) { - debounce.debounceFcn(async () => { - const pubKey = tryParseKey(form.destinationAccount) - if (pubKey) { - const account = await tryGetTokenAccount(connection.current, pubKey) - setDestinationAccount(account ? account : null) - } else { - setDestinationAccount(null) - } - }) - } else { - setDestinationAccount(null) - } - }, [form.destinationAccount]) - const schema = getTokenTransferSchema({ form, connection, nftMode: isNft }) - const transactionDolarAmount = calcTransactionDolarAmount(form.amount) - const nftName: string | undefined = undefined - const nftTitle = `Send ${nftName ? nftName : 'NFT'} to ${ - tryParseKey(form.destinationAccount) - ? abbreviateAddress(new PublicKey(form.destinationAccount)) - : '' - }` - const proposalTitle = isNFT - ? nftTitle - : `Pay ${form.amount}${tokenInfo ? ` ${tokenInfo?.symbol} ` : ' '}to ${ - tryParseKey(form.destinationAccount) - ? abbreviateAddress(new PublicKey(form.destinationAccount)) - : '' - }` + const schema = getBatchTokenTransferSchema({ form, connection, nftMode: false }) + + const proposalTitle = `Transfer tokens` + // ${ + // tokenInfo ? ` ${tokenInfo?.symbol} ` : ' ' + // }to ${ + // tryParseKey(form.destinationAccount) + // ? abbreviateAddress(new PublicKey(form.destinationAccount)) + // : '' + // }` if (!currentAccount) { return null } + const addRecipient = () => { + const newAddresses = [...form.destinationAccount] + const newAmounts = [...form.amount] + const newTxDollars = [...form.txDollarAmount] + + newAddresses.push("") + newAmounts.push(undefined) + newTxDollars.push(undefined) + + handleSetMultipleProps({ + destinationAccount: newAddresses, + amount: newAmounts, + txDollarAmount: newTxDollars + }) + + const currentAccounts = [...destinationAccount] + currentAccounts.push(null) + setDestinationAccount(currentAccounts) + } + + const setAddress = (idx: number, address: string) => { + const newAddresses = [...form.destinationAccount] + newAddresses[idx] = address + + handleSetForm({ + value: newAddresses, + propertyName: 'destinationAccount', + }) + + const currentAccounts = [...destinationAccount] + + debounce.debounceFcn(async () => { + const pubKey = tryParseKey(address) + if (pubKey) { + const account = await tryGetTokenAccount(connection.current, pubKey) + currentAccounts[idx] = account ? account : null + setDestinationAccount(currentAccounts) + } else { + currentAccounts[idx] = null + setDestinationAccount(currentAccounts) + } + }) + } + return ( <>

- <> - Send {!isNft && tokenInfo && tokenInfo?.symbol} {isNFT && 'NFT'} - + <>Send {tokenInfo && tokenInfo?.symbol}

- {isNFT ? ( - setCurrentAccount(value, connection)} - currentAccount={currentAccount} - nftsGovernedTokenAccounts={nftsGovernedTokenAccounts} - > - ) : ( - - )} +
- - handleSetForm({ - value: evt.target.value, - propertyName: 'destinationAccount', - }) - } - noMaxWidth={true} - error={formErrors['destinationAccount']} - /> - {destinationAccount && ( -
-
Account owner
-
- {destinationAccount.account.owner.toString()} -
-
- )} - {destinationAccountName && ( -
-
Account name
-
{destinationAccountName}
-
- )} - {isNFT ? ( - <> - setSelectedNfts(nfts)} - ownersPk={ - currentAccount.isSol - ? [ - currentAccount.extensions.transferAddress!, - currentAccount.governance.pubkey, - ] - : [currentAccount.governance.pubkey] + {form.destinationAccount.map((acc, idx) => ( +
+ Recipient {idx+1} + setAddress(idx, e.target.value)} + noMaxWidth={true} + error={ + formErrors['destinationAccount'] && formErrors['destinationAccount'][idx] ? + formErrors['destinationAccount'][idx] : "" } - > - - ) : ( - - )} - - {transactionDolarAmount && !isNft - ? IsAmountNotHigherThenBalance() - ? `~$${transactionDolarAmount}` - : 'Insufficient balance' - : null} - + /> + {destinationAccount[idx] && ( +
+
Account owner
+
+ {destinationAccount[idx]!.account.owner.toString()} +
+
+ )} + {destinationAccountName[idx] && ( +
+
Account name
+
{destinationAccountName[idx]}
+
+ )} + + setAmount(idx, e)} + step={mintMinAmount} + error={formErrors['amount'] && formErrors['amount'][idx] ? formErrors['amount'][idx] : ""} + onBlur={() => validateAmountOnBlur(idx)} + noMaxWidth={true} + /> + + + {form.txDollarAmount[idx] + ? IsAmountNotHigherThenBalance(idx) + ? `~$${form.txDollarAmount[idx]}` + : 'Insufficient balance' + : null} + +
+ ))} +
+ +
Add another recipient
+
setShowOptions(!showOptions)} @@ -458,34 +416,27 @@ const SendTokens = ({ }) } > - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - > + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > )} )}
+
+ + ) +} + +export default Trade diff --git a/components/TreasuryAccount/TradeOnSerum.tsx b/components/TreasuryAccount/TradeOnSerum.tsx deleted file mode 100644 index eb87e24c03..0000000000 --- a/components/TreasuryAccount/TradeOnSerum.tsx +++ /dev/null @@ -1,607 +0,0 @@ -import * as yup from 'yup' -import Input from '@components/inputs/Input' -import Select from '@components/inputs/Select' -import useTotalTokenValue from '@hooks/useTotalTokenValue' -import { - fmtTokenInfoWithMint, - getMintDecimalAmountFromNatural, - getMintNaturalAmountFromDecimalAsBN, -} from '@tools/sdk/units' -import { Market as SerumMarket } from '@project-serum/serum' -import tokenService from '@utils/services/token' -import React, { useCallback, useState } from 'react' -import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' -import AccountLabel from './BaseAccountHeader' -import { - Bound, - boundOptions, - OrderSide, - orderSideOptions, - getProgramId, - instructions as serumRemoteInstructions, - getDexId, - IDL as SerumRemoteIDL, - SerumRemote, -} from '@mithraic-labs/serum-remote' -import useWalletStore from 'stores/useWalletStore' -import { - ArrowCircleDownIcon, - ArrowCircleUpIcon, - ExternalLinkIcon, -} from '@heroicons/react/solid' -import ProposalOptions from './ProposalOptions' -import useRealm from '@hooks/useRealm' -import Button from '@components/Button' -import Tooltip from '@components/Tooltip' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { - BN, - Program, - AnchorProvider, - Wallet, - web3, -} from '@project-serum/anchor' -import { getValidatedPublickKey } from '@utils/validations' -import { validateInstruction } from '@utils/instructionTools' -import { - getInstructionDataFromBase64, - Governance, - ProgramAccount, - serializeInstructionToBase64, -} from '@solana/spl-governance' -import { notify } from '@utils/notifications' -import { useRouter } from 'next/router' -import useCreateProposal from '@hooks/useCreateProposal' -import useQueryContext from '@hooks/useQueryContext' -import { - AccountInfo, - ASSOCIATED_TOKEN_PROGRAM_ID, - MintInfo, - Token, - TOKEN_PROGRAM_ID, -} from '@solana/spl-token' -import { InstructionDataWithHoldUpTime } from 'actions/createProposal' -import { AssetAccount } from '@utils/uiTypes/assets' -import { TokenProgramAccount } from '@utils/tokens' -import { Keypair } from '@solana/web3.js' - -export type TradeOnSerumProps = { tokenAccount: AssetAccount } - -type TradeOnSerumForm = { - amount: number - boundedPrice: number - serumRemoteProgramId: string - serumProgramId: string - serumMarketId: string - assetMint: string - reclaimDate: Date - reclaimAddress: string - orderSide: number - bound: Bound - description: string - title: string -} - -const formSchema = ( - mintInfo: TokenProgramAccount, - token: TokenProgramAccount -) => { - return ( - yup - .object() - .shape({ - title: yup.string(), - description: yup.string(), - amount: yup - .number() - .typeError('Amount is required') - .test( - 'amount', - "Transfer amount must be less than the source account's available amount", - function (val: number) { - const mintValue = getMintNaturalAmountFromDecimalAsBN( - val, - mintInfo.account.decimals - ) - return token.account.amount.gte(mintValue) - } - ) - .test( - 'amount', - 'Transfer amount must be greater than 0', - function (val: number) { - return val > 0 - } - ), - boundedPrice: yup - .number() - .typeError('boundedPrice is required') - .test( - 'boundedPrice', - 'Bounded price must be greater than 0', - function (val: number) { - return val > 0 - } - ), - serumRemoteProgramId: yup - .string() - .test( - 'serumRemoteProgramId', - 'serumRemoteProgramId must be valid PublicKey', - function (serumRemoteProgramId: string) { - try { - getValidatedPublickKey(serumRemoteProgramId) - } catch (err) { - return false - } - return true - } - ), - serumProgramId: yup - .string() - .test( - 'serumProgramId', - 'serumProgramId must be valid PublicKey', - function (serumProgramId: string) { - try { - getValidatedPublickKey(serumProgramId) - } catch (err) { - return false - } - return true - } - ), - serumMarketId: yup - .string() - .test( - 'serumMarketId', - 'serumMarketId must be valid PublicKey', - function (serumMarketId: string) { - try { - getValidatedPublickKey(serumMarketId) - } catch (err) { - return false - } - return true - } - ), - assetMint: yup - .string() - .test( - 'assetMint', - 'assetMint must be valid PublicKey', - function (assetMint: string) { - try { - getValidatedPublickKey(assetMint) - } catch (err) { - return false - } - return true - } - ), - // TODO: [nice to have] Validate the date is at least min voting period ahead - reclaimDate: yup.date().typeError('reclaimDate must be a valid date'), - reclaimAddress: yup - .string() - .test( - 'reclaimAddress', - 'reclaimAddress must be valid PublicKey', - function (reclaimAddress: string) { - try { - getValidatedPublickKey(reclaimAddress) - } catch (err) { - return false - } - return true - } - ), - orderSide: yup - .number() - .typeError('orderSide is required') - .test( - 'orderSide', - 'orderSide must be 0 (Bid) or 1 (Ask)', - function (orderSide: number) { - return orderSide === 0 || orderSide === 1 - } - ), - bound: yup - .number() - .typeError('bound is required') - .test( - 'bound', - 'bound must be 0 (Lower) or 1 (Upper)', - function (bound: number) { - return bound === 0 || bound === 1 - } - ), - }) - // Check the Bound and Order Side are viable - .test('bound', 'Some check against other values', function (val) { - if (!val.bound) { - return true - } - if (val.bound === val.orderSide) { - return new yup.ValidationError( - `Bound cannot be ${Bound[val.bound]} when Order Side is ${ - OrderSide[val.orderSide] - }`, - undefined, - 'bound' - ) - } - return true - }) - ) -} - -const TradeOnSerum: React.FC = ({ tokenAccount }) => { - const currentAccount = useTreasuryAccountStore((s) => s.currentAccount) - const router = useRouter() - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const { fetchRealmGovernance } = useWalletStore((s) => s.actions) - const { handleCreateProposal } = useCreateProposal() - const serumRemoteProgramId = getProgramId(connection.cluster) - const serumProgramKey = getDexId(connection.cluster) - const { canUseTransferInstruction } = useGovernanceAssets() - const { canChooseWhoVote, symbol } = useRealm() - const { fmtUrlWithCluster } = useQueryContext() - const [form, setForm] = useState({ - amount: 0, - boundedPrice: 0, - title: 'Diversify treasury with Serum', - description: - 'A proposal to trade some asset for another using Serum. PLEASE EXPLAIN IN MORE DETAIL', - serumRemoteProgramId: serumRemoteProgramId.toString(), - serumProgramId: serumProgramKey.toString(), - serumMarketId: '', - assetMint: tokenAccount.extensions.mint!.publicKey.toString(), - orderSide: 0, - bound: 1, - // Default reclaim date of 10 days - reclaimDate: new Date(new Date().getTime() + 1_000 * 3600 * 24 * 10), - // The reclaim address must be the same account where the initial assets come from - reclaimAddress: tokenAccount.pubkey.toString(), - }) - const [formErrors, setFormErrors] = useState({}) - const [showOptions, setShowOptions] = useState(false) - const [voteByCouncil, setVoteByCouncil] = useState(false) - const [isLoading, setIsLoading] = useState(false) - - if (!tokenAccount.extensions.mint || !tokenAccount.extensions.token) { - throw new Error('No mint information on the tokenAccount') - } - const mintAccount = tokenAccount.extensions.mint - const token = tokenAccount.extensions.token - const schema = formSchema(mintAccount, token) - - const tokenInfo = tokenService.getTokenInfo(mintAccount.publicKey.toString()) - - const totalValue = useTotalTokenValue({ - amount: getMintDecimalAmountFromNatural( - mintAccount.account, - token.account.amount - ).toNumber(), - mintAddress: mintAccount.publicKey.toString(), - }) - - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - - const handlePropose = useCallback(async () => { - setIsLoading(true) - const isValid = await validateInstruction({ schema, form, setFormErrors }) - if (!currentAccount || !currentAccount!.extensions!.token!.account.owner) { - throw new Error('currentAccount is null or undefined') - } - if (wallet && wallet.publicKey && isValid) { - // create the anchor Program - // @ts-ignore: Wallet compatability issues - const options = AnchorProvider.defaultOptions() - const provider = new AnchorProvider( - connection.current, - new Wallet(Keypair.generate()), - options - ) - const program = new Program( - SerumRemoteIDL, - serumRemoteProgramId, - provider - ) - // convert amount to mintAmount - const mintValue = getMintNaturalAmountFromDecimalAsBN( - form.amount, - mintAccount.account.decimals - ) - const dexProgramId = new web3.PublicKey(form.serumProgramId) - const serumMarketId = new web3.PublicKey(form.serumMarketId) - // Load the serumMarket - let market: SerumMarket - try { - market = await SerumMarket.load( - connection.current, - serumMarketId, - {}, - dexProgramId - ) - } catch (err) { - setFormErrors((e) => ({ - ...e, - serumMarketId: 'Error loading the SerumMarket', - })) - setIsLoading(false) - return - } - // Convert the form's numerical bounded price to market lots - const boundPrice = market.priceNumberToLots(form.boundedPrice) - // Validate the market and information - if ( - form.assetMint !== market.quoteMintAddress.toString() && - form.assetMint !== market.baseMintAddress.toString() - ) { - setFormErrors((e) => ({ - ...e, - serumMarketId: - "The asset you're looking to trade with does not exist on this Serum Market", - })) - setIsLoading(false) - return - } - if ( - (form.orderSide === 0 && - form.assetMint !== market.quoteMintAddress.toString()) || - (form.orderSide === 1 && - form.assetMint !== market.baseMintAddress.toString()) - ) { - setFormErrors((e) => ({ - ...e, - orderSide: `order side of ${ - OrderSide[form.orderSide] - } does not match the expected serum market mint`, - })) - setIsLoading(false) - return - } - - const proposalInstructions: InstructionDataWithHoldUpTime[] = [] - const prerequisiteInstructions: web3.TransactionInstruction[] = [] - // Check if an associated token account for the other side of the - // market is required. If so, add the create associated token account ix - const aTADepositAddress = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - form.orderSide === 0 ? market.baseMintAddress : market.quoteMintAddress, - currentAccount!.extensions!.token!.account.owner - ) - const depositAccountInfo = await connection.current.getAccountInfo( - aTADepositAddress - ) - if (!depositAccountInfo) { - // generate the instruction for creating the ATA - const createAtaIx = Token.createAssociatedTokenAccountInstruction( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - form.orderSide === 0 - ? market.baseMintAddress - : market.quoteMintAddress, - aTADepositAddress, - currentAccount!.extensions!.token!.account.owner, - wallet.publicKey - ) - prerequisiteInstructions.push(createAtaIx) - } - - const instruction = await serumRemoteInstructions.initBoundedStrategyIx( - //@ts-ignore: differing anchor versions - program, - dexProgramId, - serumMarketId, - new web3.PublicKey(form.assetMint), - { - transferAmount: mintValue, - boundPrice, - reclaimDate: new BN(form.reclaimDate.getTime() / 1_000), - reclaimAddress: new web3.PublicKey(form.reclaimAddress), - depositAddress: aTADepositAddress, - orderSide: form.orderSide, - bound: form.bound, - }, - { owner: currentAccount!.extensions!.token!.account.owner } - ) - - const serializedIx = serializeInstructionToBase64(instruction) - - const instructionData = { - data: getInstructionDataFromBase64(serializedIx), - holdUpTime: - currentAccount?.governance?.account?.config.minInstructionHoldUpTime, - prerequisiteInstructions, - shouldSplitIntoSeparateTxs: true, - } - proposalInstructions.push(instructionData) - - try { - // Fetch governance to get up to date proposalCount - const selectedGovernance = (await fetchRealmGovernance( - currentAccount?.governance?.pubkey - )) as ProgramAccount - - const proposalAddress = await handleCreateProposal({ - title: form.title, - description: form.description, - governance: selectedGovernance, - instructionsData: proposalInstructions, - voteByCouncil, - isDraft: false, - }) - const url = fmtUrlWithCluster( - `/dao/${symbol}/proposal/${proposalAddress}` - ) - - router.push(url) - } catch (ex) { - notify({ type: 'error', message: `${ex}` }) - } - } - - setIsLoading(false) - }, [schema, form, setFormErrors, connection, currentAccount, symbol, wallet]) - return ( - <> -
-

Trade on Serum!

-
- -
- Serum Remote{' '} - -
-
-  is open sourced, yet unaudited. Do your own research. -
- - {/* Add Serum Remote form */} -
- - handleSetForm({ - value: evt.target.value, - propertyName: 'serumMarketId', - }) - } - noMaxWidth={true} - error={formErrors['serumMarketId']} - /> - - handleSetForm({ - value: evt.target.value, - propertyName: 'amount', - }) - } - error={formErrors['amount']} - noMaxWidth={true} - /> - - - {/* TODO: Add reclaim date picker */} - - handleSetForm({ - value: evt.target.value, - propertyName: 'boundedPrice', - }) - } - error={formErrors['boundedPrice']} - noMaxWidth={true} - /> -
- -
setShowOptions(!showOptions)} - > - {showOptions ? ( - - ) : ( - - )} - Options -
- {showOptions && ( - - )} -
-
- -
- - ) -} - -export default TradeOnSerum diff --git a/components/VoteCommentModal.tsx b/components/VoteCommentModal.tsx index b74fcc34e6..6f0e337782 100644 --- a/components/VoteCommentModal.tsx +++ b/components/VoteCommentModal.tsx @@ -1,111 +1,48 @@ import React, { FunctionComponent, useState } from 'react' -import { ThumbDownIcon, ThumbUpIcon } from '@heroicons/react/solid' -import { - ChatMessageBody, - ChatMessageBodyType, - YesNoVote, -} from '@solana/spl-governance' -import { RpcContext } from '@solana/spl-governance' -import useWalletStore from '../stores/useWalletStore' -import useRealm from '../hooks/useRealm' -import { castVote } from '../actions/castVote' +import { BanIcon, ThumbDownIcon, ThumbUpIcon } from '@heroicons/react/solid' +import { VoteKind } from '@solana/spl-governance' import Button, { SecondaryButton } from './Button' -// import { notify } from '../utils/notifications' import Loading from './Loading' import Modal from './Modal' import Input from './inputs/Input' import Tooltip from './Tooltip' -import { TokenOwnerRecord } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import { getProgramVersionForRealm } from '@models/registry/api' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import { nftPluginsPks } from '@hooks/useVotingPlugins' -import useNftProposalStore from 'NftVotePlugin/NftProposalStore' -import { NftVoterClient } from '@solana/governance-program-library' +import { useSubmitVote } from '@hooks/useSubmitVote' interface VoteCommentModalProps { onClose: () => void isOpen: boolean - vote: YesNoVote - voterTokenRecord: ProgramAccount + vote: VoteKind + isMulti?: number[] +} + +const VOTE_STRINGS = { + [VoteKind.Approve]: 'Yes', + [VoteKind.Deny]: 'No', + [VoteKind.Veto]: 'Veto', + [VoteKind.Abstain]: 'Abstain', } const VoteCommentModal: FunctionComponent = ({ onClose, isOpen, vote, - voterTokenRecord, + isMulti, }) => { - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const [submitting, setSubmitting] = useState(false) const [comment, setComment] = useState('') - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - const { proposal } = useWalletStore((s) => s.selectedProposal) - const { fetchChatMessages } = useWalletStore((s) => s.actions) - const { realm, realmInfo, config } = useRealm() - const { refetchProposals } = useWalletStore((s) => s.actions) - const isNftPlugin = - config?.account.communityTokenConfig.voterWeightAddin && - nftPluginsPks.includes( - config?.account.communityTokenConfig.voterWeightAddin?.toBase58() - ) - const { closeNftVotingCountingModal } = useNftProposalStore.getState() - const submitVote = async (vote: YesNoVote) => { - setSubmitting(true) - const rpcContext = new RpcContext( - proposal!.owner, - getProgramVersionForRealm(realmInfo!), - wallet!, - connection.current, - connection.endpoint - ) + const { submitting, submitVote , error } = useSubmitVote() - const msg = comment - ? new ChatMessageBody({ - type: ChatMessageBodyType.Text, - value: comment, - }) - : undefined + const voteString = VOTE_STRINGS[vote] - try { - await castVote( - rpcContext, - realm!, - proposal!, - voterTokenRecord, - vote, - msg, - client, - refetchProposals - ) - if (!isNftPlugin) { - await refetchProposals() - } - } catch (ex) { - if (isNftPlugin) { - closeNftVotingCountingModal( - client.client as NftVoterClient, - proposal!, - wallet!.publicKey! - ) - } - //TODO: How do we present transaction errors to users? Just the notification? - console.error("Can't cast vote", ex) - onClose() - } finally { - setSubmitting(false) - onClose() - } - - fetchChatMessages(proposal!.pubkey) + const handleSubmit = async () => { + await submitVote({ + vote, + comment, + voteWeights: isMulti, + }).then(() => onClose()) + .catch(console.log) } - const voteString = vote === YesNoVote.Yes ? 'Yes' : 'No' - return (

Confirm your vote

@@ -124,6 +61,7 @@ const VoteCommentModal: FunctionComponent = ({ onChange={(e) => setComment(e.target.value)} // placeholder={`Let the DAO know why you vote '${voteString}'`} /> + {error &&

{error.message}

}
@@ -132,16 +70,23 @@ const VoteCommentModal: FunctionComponent = ({
diff --git a/components/VoteCountdown.tsx b/components/VoteCountdown.tsx deleted file mode 100644 index e05c3b6952..0000000000 --- a/components/VoteCountdown.tsx +++ /dev/null @@ -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.maxVotingTime - : (proposal.votingAt?.toNumber() ?? 0) + - governance.config.maxVotingTime - - 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) ? ( -
Voting ended
- ) : ( -
-
Ends
- {countdown && countdown.days > 0 && ( - <> -
- {countdown.days}d -
- : - - )} -
{countdown.hours}h
- : -
- {countdown.minutes}m -
- {!countdown.days && ( - <> - : -
- {countdown.seconds}s -
- - )} -
- )} - - ) -} diff --git a/components/VotePanel.tsx b/components/VotePanel.tsx deleted file mode 100644 index 44c1f60c51..0000000000 --- a/components/VotePanel.tsx +++ /dev/null @@ -1,312 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { withFinalizeVote, YesNoVote } from '@solana/spl-governance' -import { TransactionInstruction } from '@solana/web3.js' -import { useCallback, useState } from 'react' -import { relinquishVote } from '../actions/relinquishVote' -import { useHasVoteTimeExpired } from '../hooks/useHasVoteTimeExpired' -import useRealm from '../hooks/useRealm' -import { ProposalState } from '@solana/spl-governance' -import { RpcContext } from '@solana/spl-governance' -import { GoverningTokenRole } from '@solana/spl-governance' -import { BanIcon, ThumbUpIcon, ThumbDownIcon } from '@heroicons/react/solid' - -import useWalletStore from '../stores/useWalletStore' -import Button, { SecondaryButton } from './Button' -import VoteCommentModal from './VoteCommentModal' -import { getProgramVersionForRealm } from '@models/registry/api' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import { useRouter } from 'next/router' -import useNftPluginStore from 'NftVotePlugin/store/nftPluginStore' -import { LOCALNET_REALM_ID as PYTH_LOCALNET_REALM_ID } from 'pyth-staking-api' -import { isYesVote } from '@models/voteRecords' -import Tooltip from '@components/Tooltip' -import { VotingClientType } from '@utils/uiTypes/VotePlugin' - -const VotePanel = () => { - const [showVoteModal, setShowVoteModal] = useState(false) - const [vote, setVote] = useState(null) - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const [isLoading, setIsLoading] = useState(false) - const router = useRouter() - const { pk } = router.query - const { - governance, - proposal, - voteRecordsByVoter, - tokenType, - } = useWalletStore((s) => s.selectedProposal) - const { - ownTokenRecord, - ownCouncilTokenRecord, - realm, - realmInfo, - ownVoterWeight, - } = useRealm() - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - const connected = useWalletStore((s) => s.connected) - const refetchProposals = useWalletStore((s) => s.actions.refetchProposals) - const fetchProposal = useWalletStore((s) => s.actions.fetchProposal) - const hasVoteTimeExpired = useHasVoteTimeExpired(governance, proposal!) - const maxVoterWeight = - useNftPluginStore((s) => s.state.maxVoteRecord)?.pubkey || undefined - - // Handle state based on if a delegated wallet has already voted or not - const ownVoteRecord = - tokenType === GoverningTokenRole.Community && ownTokenRecord - ? voteRecordsByVoter[ - ownTokenRecord.account.governingTokenOwner.toBase58() - ] - : ownCouncilTokenRecord - ? voteRecordsByVoter[ - ownCouncilTokenRecord.account.governingTokenOwner.toBase58() - ] - : wallet?.publicKey && voteRecordsByVoter[wallet.publicKey.toBase58()] - - const voterTokenRecord = - tokenType === GoverningTokenRole.Community - ? ownTokenRecord - : ownCouncilTokenRecord - - const isVoteCast = ownVoteRecord !== undefined - const isVoting = - proposal?.account.state === ProposalState.Voting && !hasVoteTimeExpired - - const hasMinAmountToVote = - voterTokenRecord && - ownVoterWeight.hasMinAmountToVote( - voterTokenRecord.account.governingTokenMint - ) - - const isVoteEnabled = - connected && isVoting && !isVoteCast && hasMinAmountToVote - - const isWithdrawEnabled = - connected && - ownVoteRecord && - !ownVoteRecord?.account.isRelinquished && - proposal && - (proposal!.account.state === ProposalState.Voting || - proposal!.account.state === ProposalState.Completed || - proposal!.account.state === ProposalState.Cancelled || - proposal!.account.state === ProposalState.Succeeded || - proposal!.account.state === ProposalState.Executing || - proposal!.account.state === ProposalState.Defeated) - - const submitRelinquishVote = async () => { - const rpcContext = new RpcContext( - proposal!.owner, - getProgramVersionForRealm(realmInfo!), - wallet!, - connection.current, - connection.endpoint - ) - try { - setIsLoading(true) - const instructions: TransactionInstruction[] = [] - - if ( - proposal?.account.state === ProposalState.Voting && - hasVoteTimeExpired - ) { - await withFinalizeVote( - instructions, - realmInfo!.programId, - getProgramVersionForRealm(realmInfo!), - realm!.pubkey, - proposal.account.governance, - proposal.pubkey, - proposal.account.tokenOwnerRecord, - proposal.account.governingTokenMint, - maxVoterWeight - ) - } - - await relinquishVote( - rpcContext, - realm!.pubkey, - proposal!, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - voterTokenRecord!.pubkey, - ownVoteRecord!.pubkey, - instructions, - client - ) - await refetchProposals() - if (pk) { - fetchProposal(pk) - } - } catch (ex) { - console.error("Can't relinquish vote", ex) - } - setIsLoading(false) - } - - const handleShowVoteModal = (vote: YesNoVote) => { - setVote(vote) - setShowVoteModal(true) - } - - const handleCloseShowVoteModal = useCallback(() => { - setShowVoteModal(false) - }, []) - - const actionLabel = - !isVoteCast || !connected - ? `Cast your ${ - tokenType === GoverningTokenRole.Community ? 'community' : 'council' - } vote` - : 'Your vote' - - const withdrawTooltipContent = !connected - ? 'You need to connect your wallet' - : !isWithdrawEnabled - ? !ownVoteRecord?.account.isRelinquished - ? 'Owner vote record is not relinquished' - : 'The proposal is not in a valid state to execute this action.' - : '' - - const voteTooltipContent = !connected - ? 'You need to connect your wallet to be able to vote' - : !isVoting && isVoteCast - ? 'Proposal is not in a voting state anymore.' - : client.clientType === VotingClientType.NftVoterClient && !voterTokenRecord - ? 'You must join the Realm to be able to vote' - : !voterTokenRecord || - !ownVoterWeight.hasMinAmountToVote( - voterTokenRecord.account.governingTokenMint - ) - ? 'You don’t have governance power to vote in this realm' - : '' - - const notVisibleStatesForNotConnectedWallet = [ - ProposalState.Cancelled, - ProposalState.Succeeded, - ProposalState.Draft, - ProposalState.Completed, - ] - - const isVisibleToWallet = !connected - ? !hasVoteTimeExpired && - typeof notVisibleStatesForNotConnectedWallet.find( - (x) => x === proposal?.account.state - ) === 'undefined' - : !ownVoteRecord?.account.isRelinquished - - const isPanelVisible = (isVoting || isVoteCast) && isVisibleToWallet - const didNotVote = - !!proposal && - !isVoting && - proposal.account.state !== ProposalState.Cancelled && - proposal.account.state !== ProposalState.Draft && - !isVoteCast && - isVisibleToWallet - - //Todo: move to own components with refactor to dao folder structure - const isPyth = - realmInfo?.realmId.toBase58() === PYTH_LOCALNET_REALM_ID.toBase58() - - const isRelinquishVotePanelVisible = !( - isPyth && - isVoteCast && - connected && - !isVoting - ) - - return ( - <> - {isPanelVisible && isRelinquishVotePanelVisible && ( -
-
-

{actionLabel}

- {isVoteCast && - connected && - ownVoteRecord && - (isYesVote(ownVoteRecord.account) ? ( - -
- -
-
- ) : ( - -
- -
-
- ))} -
- -
- {isVoteCast && connected ? ( -
- {isVoting && ( - submitRelinquishVote()} - disabled={!isWithdrawEnabled || isLoading} - > - Withdraw - - )} -
- ) : ( - <> - {isVoting && ( -
- - - -
- )} - - )} -
- - {showVoteModal ? ( - - ) : null} -
- )} - {didNotVote && ( -
-

You did not vote

- - - -
- )} - - ) -} - -export default VotePanel diff --git a/components/VotePanel/CastMultiVoteButtons.tsx b/components/VotePanel/CastMultiVoteButtons.tsx new file mode 100644 index 0000000000..8fd6511780 --- /dev/null +++ b/components/VotePanel/CastMultiVoteButtons.tsx @@ -0,0 +1,150 @@ +import { Proposal, VoteKind } from '@solana/spl-governance' +import { CheckCircleIcon } from '@heroicons/react/solid' +import { useState } from 'react' +import Button, { SecondaryButton } from '../Button' +import VoteCommentModal from '../VoteCommentModal' +import { useIsVoting, useVotingPop } from './hooks' +import { useProposalVoteRecordQuery } from '@hooks/queries/voteRecord' +import { useSubmitVote } from '@hooks/useSubmitVote' +import { useSelectedRealmInfo } from '@hooks/selectedRealm/useSelectedRealmRegistryEntry' +import { useCanVote } from './useCanVote' + +export const CastMultiVoteButtons = ({ proposal }: { proposal: Proposal }) => { + const [showVoteModal, setShowVoteModal] = useState(false) + const [vote, setVote] = useState<'yes' | 'no' | null>(null) + const realmInfo = useSelectedRealmInfo() + const allowDiscussion = realmInfo?.allowDiscussion ?? true + const { submitting, submitVote } = useSubmitVote() + const votingPop = useVotingPop() + const [canVote, tooltipContent] = useCanVote() + const { data: ownVoteRecord } = useProposalVoteRecordQuery('electoral') + const [selectedOptions, setSelectedOptions] = useState([]) + const [optionStatus, setOptionStatus] = useState( + new Array(proposal.options.length).fill(false) + ) + const isVoteCast = !!ownVoteRecord?.found + const isVoting = useIsVoting() + + const nota = '$$_NOTA_$$' + const last = proposal.options.length - 1 + + const handleVote = async (vote: 'yes' | 'no') => { + setVote(vote) + + if (allowDiscussion) { + setShowVoteModal(true) + } else { + await submitVote({ + vote: vote === 'yes' ? VoteKind.Approve : VoteKind.Deny, + voteWeights: selectedOptions, + }) + } + } + + const handleOption = (index: number) => { + let options = [...selectedOptions] + let status = [...optionStatus] + const isNota = proposal.options[last].label === nota + + const selected = status[index] + + if (selected) { + options = options.filter((option) => option !== index) + status[index] = false + } else { + if (isNota) { + if (index === last) { + // if nota is clicked, unselect all other options + status = status.map(() => false) + status[index] = true + options = [index] + } else { + // remove nota from the selected if any other option is clicked + status[last] = false + options = options.filter((option) => option !== last) + if (!options.includes(index)) { + options.push(index) + } + status[index] = true + } + } else { + if (!options.includes(index)) { + options.push(index) + } + status[index] = true + } + } + + setSelectedOptions(options) + setOptionStatus(status) + } + + return isVoting && !isVoteCast ? ( +
+
+

Cast your {votingPop} vote

+
+ +
+
+ {proposal.options.map((option, index) => { + return ( +
+ handleOption(index)} + disabled={!canVote || submitting} + isLoading={submitting} + > + {optionStatus[index] && ( + + )} + {option.label === nota && index === last + ? 'None of the Above' + : option.label} + +
+ ) + })} +
+ Note: You can select one or more options +
+ +
+
+ + {showVoteModal && vote ? ( + setShowVoteModal(false)} + vote={VoteKind.Approve} + isMulti={selectedOptions} + /> + ) : null} +
+ ) : null +} diff --git a/components/VotePanel/CastVoteButtons.tsx b/components/VotePanel/CastVoteButtons.tsx new file mode 100644 index 0000000000..e4c8e03471 --- /dev/null +++ b/components/VotePanel/CastVoteButtons.tsx @@ -0,0 +1,156 @@ +import { VoteKind, getVoteRecordAddress } from '@solana/spl-governance' +import { useState } from 'react' +import { ThumbUpIcon, ThumbDownIcon } from '@heroicons/react/solid' +import Button from '../Button' +import VoteCommentModal from '../VoteCommentModal' +import { useIsInCoolOffTime, useIsVoting, useVotingPop } from './hooks' +import { + fetchVoteRecordByPubkey, + useProposalVoteRecordQuery, +} from '@hooks/queries/voteRecord' +import { useSubmitVote } from '@hooks/useSubmitVote' +import { useSelectedRealmInfo } from '@hooks/selectedRealm/useSelectedRealmRegistryEntry' +import { useCanVote } from './useCanVote' +import { useConnection } from '@solana/wallet-adapter-react' +import { useAsync } from 'react-async-hook' +import { useRouteProposalQuery } from '@hooks/queries/proposal' +import { useBatchedVoteDelegators } from './useDelegators' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' + +export const CastVoteButtons = () => { + const [showVoteModal, setShowVoteModal] = useState(false) + const [vote, setVote] = useState<'yes' | 'no' | null>(null) + const realmInfo = useSelectedRealmInfo() + const allowDiscussion = realmInfo?.allowDiscussion ?? true + const { submitting, submitVote } = useSubmitVote() + const votingPop = useVotingPop() + const [canVote, tooltipContent] = useCanVote() + const { data: ownVoteRecord } = useProposalVoteRecordQuery('electoral') + + const isVoteCast = !!ownVoteRecord?.found + const isVoting = useIsVoting() + const isInCoolOffTime = useIsInCoolOffTime() + + const proposal = useRouteProposalQuery().data?.result + const connection = useConnection() + const communityDelegators = useBatchedVoteDelegators('community') + const councilDelegators = useBatchedVoteDelegators('council') + + const wallet = useWalletOnePointOh() + + const { voterWeightForWallet } = useRealmVoterWeightPlugins(votingPop) + + const ownVoterWeight = wallet?.publicKey + ? voterWeightForWallet(wallet?.publicKey) + : undefined + const hasVotingPower = !!( + ownVoterWeight?.value && ownVoterWeight.value?.gtn(0) + ) + + const isDelegatorsVoteCast = useAsync(async () => { + const relevantDelegators = + votingPop === 'community' ? communityDelegators : councilDelegators + + if ( + !hasVotingPower && + proposal && + relevantDelegators && + relevantDelegators.length > 0 + ) { + const delegatorisVoteCastList = await Promise.all( + relevantDelegators.map(async (delegator) => { + const pda = await getVoteRecordAddress( + proposal.owner, + proposal.pubkey, + delegator.pubkey + ) + const voteRecord = await fetchVoteRecordByPubkey( + connection.connection, + pda + ) + return !!voteRecord.found + }) + ) + + // check if there is any delegator without a vote. If so, return false + const voted = !delegatorisVoteCastList.includes(false) + setVote(voted ? 'yes' : 'no') + return voted + } + }, [ + communityDelegators?.length, + connection.connection, + councilDelegators?.length, + hasVotingPower, + proposal?.pubkey, + votingPop, + ]) + + const handleVote = async (vote: 'yes' | 'no') => { + setVote(vote) + + if (allowDiscussion) { + setShowVoteModal(true) + } else { + await submitVote({ + vote: vote === 'yes' ? VoteKind.Approve : VoteKind.Deny, + }) + } + } + const isFinalVoteCast = + isVoteCast || hasVotingPower ? isVoteCast : isDelegatorsVoteCast.result + + return (isVoting && !isFinalVoteCast) || + (isInCoolOffTime && !isFinalVoteCast) ? ( +
+
+

Cast your {votingPop} vote

+
+ +
+
+ {(isVoting || !isInCoolOffTime) && ( + + )} + + +
+
+ + {showVoteModal && vote ? ( + setShowVoteModal(false)} + vote={vote === 'yes' ? VoteKind.Approve : VoteKind.Deny} + /> + ) : null} +
+ ) : null +} diff --git a/components/VotePanel/VetoButtons.tsx b/components/VotePanel/VetoButtons.tsx new file mode 100644 index 0000000000..97bf924cd2 --- /dev/null +++ b/components/VotePanel/VetoButtons.tsx @@ -0,0 +1,124 @@ +import Button from '@components/Button' +import VoteCommentModal from '@components/VoteCommentModal' +import { BanIcon } from '@heroicons/react/solid' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { VoteKind } from '@solana/spl-governance' +import { useState } from 'react' +import { + useIsInCoolOffTime, + useIsVoting, + useUserVetoTokenRecord, + useVetoingPop, +} from './hooks' +import { useProposalVoteRecordQuery } from '@hooks/queries/voteRecord' +import { useSubmitVote } from '@hooks/useSubmitVote' +import { useSelectedRealmInfo } from '@hooks/selectedRealm/useSelectedRealmRegistryEntry' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' + +const useIsVetoable = (): undefined | boolean => { + const vetoingPop = useVetoingPop() + const isVoting = useIsVoting() + const isInCoolOffTime = useIsInCoolOffTime() + // TODO is this accurate? + if (isVoting === false && isInCoolOffTime === false) return false + if (vetoingPop === undefined) return undefined + return !!vetoingPop +} + +const useCanVeto = (): + | undefined + | { canVeto: true } + | { canVeto: false; message: string } => { + const vetoPop = useVetoingPop() + const { calculatedMaxVoterWeight, isReady } = useRealmVoterWeightPlugins( + vetoPop + ) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const isVetoable = useIsVetoable() + const { data: userVetoRecord } = useProposalVoteRecordQuery('veto') + const voterTokenRecord = useUserVetoTokenRecord() + + if (isVetoable === false) + return { + canVeto: false, + // (Note that users should never actually see this) + message: 'This proposal is not vetoable', + } + + // Are you connected? + if (connected === false) + return { canVeto: false, message: 'You must connect your wallet' } + + // Did you already veto? + if (userVetoRecord?.found) + return { canVeto: false, message: 'You already voted' } + + // Do you have any voting power? + const hasMinAmountToVote = + voterTokenRecord && isReady && calculatedMaxVoterWeight?.value?.gtn(0) + if (hasMinAmountToVote === undefined) return undefined + if (hasMinAmountToVote === false) + return { + canVeto: false, + message: 'You don’t have governance power to vote in this dao', + } + + return { canVeto: true } +} + +const VetoButtons = () => { + const realmInfo = useSelectedRealmInfo() + const allowDiscussion = realmInfo?.allowDiscussion ?? true + const vetoable = useIsVetoable() + const vetoingPop = useVetoingPop() + const canVeto = useCanVeto() + const [openModal, setOpenModal] = useState(false) + const { data: userVetoRecord } = useProposalVoteRecordQuery('veto') + const { submitting, submitVote } = useSubmitVote() + + const handleVeto = async () => { + if (allowDiscussion) { + setOpenModal(true) + } else { + submitVote({ + vote: VoteKind.Veto, + }) + } + } + + return vetoable && vetoingPop && !userVetoRecord?.found ? ( + <> +
+
+

Cast your {vetoingPop} veto vote

+
+
+ +
+
+ {openModal ? ( + setOpenModal(false)} + isOpen={openModal} + vote={VoteKind.Veto} + /> + ) : null} + + ) : null +} + +export default VetoButtons diff --git a/components/VotePanel/VotePanel.tsx b/components/VotePanel/VotePanel.tsx new file mode 100644 index 0000000000..c67f6b9576 --- /dev/null +++ b/components/VotePanel/VotePanel.tsx @@ -0,0 +1,63 @@ +import { GovernanceAccountType, ProposalState, VoteType } from '@solana/spl-governance' +import { BanIcon } from '@heroicons/react/solid' + +import Tooltip from '@components/Tooltip' +import VetoButtons from './VetoButtons' +import { CastVoteButtons } from './CastVoteButtons' +import { CastMultiVoteButtons } from './CastMultiVoteButtons' +import { YouVoted } from './YouVoted' +import { useIsVoting } from './hooks' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRouteProposalQuery } from '@hooks/queries/proposal' +import { useProposalVoteRecordQuery } from '@hooks/queries/voteRecord' + +const VotePanel = () => { + const proposal = useRouteProposalQuery().data?.result + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + + const { data: ownVoteRecord } = useProposalVoteRecordQuery('electoral') + + const isVoteCast = ownVoteRecord?.result !== undefined + const isVoting = useIsVoting() + + const didNotVote = + connected && + !!proposal && + !isVoting && + proposal.account.state !== ProposalState.Cancelled && + proposal.account.state !== ProposalState.Draft && + !isVoteCast + + const isMulti = proposal?.account.voteType !== VoteType.SINGLE_CHOICE + && proposal?.account.accountType === GovernanceAccountType.ProposalV2 + + return ( + <> + {didNotVote && ( +
+

+ {isMulti + ? 'You did not vote on this proposal' + : 'You did not vote electorally'} +

+ + + +
+ )} + {/* START: Note that these components control for themselves whether they are displayed and may not be visible */} + + {proposal && isMulti ? ( + + ) : ( + + )} + + {!isMulti && } + {/* END */} + + ) +} + +export default VotePanel diff --git a/components/VotePanel/YouVoted.tsx b/components/VotePanel/YouVoted.tsx new file mode 100644 index 0000000000..99dc5893e8 --- /dev/null +++ b/components/VotePanel/YouVoted.tsx @@ -0,0 +1,328 @@ +import { + GovernanceAccountType, + VoteKind, + VoteType, + getVoteRecordAddress, + withFinalizeVote, +} from '@solana/spl-governance' +import { TransactionInstruction } from '@solana/web3.js' +import { useState } from 'react' +import { relinquishVote } from '../../actions/relinquishVote' +import useRealm from '../../hooks/useRealm' +import { ProposalState } from '@solana/spl-governance' +import { RpcContext } from '@solana/spl-governance' +import { + ThumbUpIcon, + ThumbDownIcon, + BanIcon, + MinusCircleIcon, +} from '@heroicons/react/solid' +import Button from '../Button' +import { getProgramVersionForRealm } from '@models/registry/api' +import Tooltip from '@components/Tooltip' +import { + useVoterTokenRecord, + useIsVoting, + useIsInCoolOffTime, + useUserVetoTokenRecord, + useVotingPop, +} from './hooks' +import assertUnreachable from '@utils/typescript/assertUnreachable' +import { useHasVoteTimeExpired } from '@hooks/useHasVoteTimeExpired' +import { useMaxVoteRecord } from '@hooks/useMaxVoteRecord' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { + proposalQueryKeys, + useRouteProposalQuery, +} from '@hooks/queries/proposal' +import { useProposalGovernanceQuery } from '@hooks/useProposal' +import { + fetchVoteRecordByPubkey, + useProposalVoteRecordQuery, +} from '@hooks/queries/voteRecord' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import queryClient from '@hooks/queries/queryClient' +import { CheckmarkFilled } from '@carbon/icons-react' +import { useVotingClientForGoverningTokenMint } from '@hooks/useVotingClients' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' +import { useAsync } from 'react-async-hook' +import { useBatchedVoteDelegators } from './useDelegators' +import { useSelectedDelegatorStore } from 'stores/useSelectedDelegatorStore' + +export const YouVoted = ({ quorum }: { quorum: 'electoral' | 'veto' }) => { + const proposal = useRouteProposalQuery().data?.result + const realm = useRealmQuery().data?.result + const { realmInfo } = useRealm() + const wallet = useWalletOnePointOh() + const connection = useLegacyConnectionContext() + const connected = !!wallet?.connected + + const governance = useProposalGovernanceQuery().data?.result + const maxVoterWeight = useMaxVoteRecord()?.pubkey || undefined + const hasVoteTimeExpired = useHasVoteTimeExpired(governance, proposal!) + const isVoting = useIsVoting() + const isInCoolOffTime = useIsInCoolOffTime() + const [isLoading, setIsLoading] = useState(false) + + const { data } = useProposalVoteRecordQuery(quorum) + const ownVoteRecord = data?.result + const electoralVoterTokenRecord = useVoterTokenRecord() + const vetoVotertokenRecord = useUserVetoTokenRecord() + const voterTokenRecord = + quorum === 'electoral' ? electoralVoterTokenRecord : vetoVotertokenRecord + const votingClient = useVotingClientForGoverningTokenMint( + proposal?.account.governingTokenMint + ) + + const isWithdrawEnabled = + connected && + ownVoteRecord && + !ownVoteRecord?.account.isRelinquished && + proposal && + (proposal!.account.state === ProposalState.Voting || + proposal!.account.state === ProposalState.Completed || + proposal!.account.state === ProposalState.Cancelled || + proposal!.account.state === ProposalState.Succeeded || + proposal!.account.state === ProposalState.Executing || + proposal!.account.state === ProposalState.Defeated) + + const withdrawTooltipContent = !connected + ? 'You need to connect your wallet' + : !isWithdrawEnabled + ? !ownVoteRecord?.account.isRelinquished + ? 'Owner vote record is not relinquished' + : 'The proposal is not in a valid state to execute this action.' + : '' + + const submitRelinquishVote = async () => { + if ( + realm === undefined || + proposal === undefined || + voterTokenRecord === undefined || + ownVoteRecord === undefined || + ownVoteRecord === null + ) + return + + const rpcContext = new RpcContext( + proposal!.owner, + getProgramVersionForRealm(realmInfo!), + wallet!, + connection.current, + connection.endpoint + ) + + try { + setIsLoading(true) + const instructions: TransactionInstruction[] = [] + + //we want to finalize only if someone try to withdraw after voting time ended + //but its before finalize state + if ( + proposal !== undefined && + proposal?.account.state === ProposalState.Voting && + hasVoteTimeExpired && + !isInCoolOffTime + ) { + await withFinalizeVote( + instructions, + realmInfo!.programId, + getProgramVersionForRealm(realmInfo!), + realm!.pubkey, + proposal.account.governance, + proposal.pubkey, + proposal.account.tokenOwnerRecord, + proposal.account.governingTokenMint, + maxVoterWeight + ) + } + + await relinquishVote( + rpcContext, + realm.pubkey, + proposal, + voterTokenRecord.pubkey, + ownVoteRecord.pubkey, + instructions, + votingClient + ) + queryClient.invalidateQueries({ + queryKey: proposalQueryKeys.all(connection.endpoint), + }) + } catch (ex) { + console.error("Can't relinquish vote", ex) + } + setIsLoading(false) + } + + const selectedCommunityDelegator = useSelectedDelegatorStore( + (s) => s.communityDelegator + ) + const selectedCouncilDelegator = useSelectedDelegatorStore( + (s) => s.councilDelegator + ) + + const communityDelegators = useBatchedVoteDelegators('community') + const councilDelegators = useBatchedVoteDelegators('council') + const votingPop = useVotingPop() + const { voterWeightForWallet } = useRealmVoterWeightPlugins(votingPop) + + const relevantSelectedDelegator = + votingPop === 'community' + ? selectedCommunityDelegator + : selectedCouncilDelegator + + const ownVoterWeight = relevantSelectedDelegator + ? voterWeightForWallet(relevantSelectedDelegator) + : wallet?.publicKey + ? voterWeightForWallet(wallet?.publicKey) + : undefined + const hasVotingPower = !!( + ownVoterWeight?.value && ownVoterWeight.value?.gtn(0) + ) + + const delegatorVote = useAsync(async () => { + const relevantDelegators = + votingPop === 'community' ? communityDelegators : councilDelegators + + if ( + !hasVotingPower && + proposal && + relevantDelegators && + relevantDelegators.length > 0 + ) { + const delegatorisVoteList = await Promise.all( + relevantDelegators.map(async (delegator) => { + const pda = await getVoteRecordAddress( + proposal.owner, + proposal.pubkey, + delegator.pubkey + ) + const voteRecord = await fetchVoteRecordByPubkey( + connection.current, + pda + ) + return voteRecord + }) + ) + + const allVoted = !delegatorisVoteList + .map((vote) => !!vote.found) + .includes(false) + return allVoted ? delegatorisVoteList[0].result : null + } + }, [ + communityDelegators?.length, + connection.current, + councilDelegators?.length, + hasVotingPower, + proposal?.pubkey, + votingPop, + ]) + + const getDelegatorVoteForQuorum = () => { + if ( + // yes/no vote + (quorum === 'electoral' && !delegatorVote?.result?.account.vote?.veto) || + // veto vote + (quorum === 'veto' && delegatorVote?.result?.account.vote?.veto) + ) { + return delegatorVote?.result?.account.vote + } + return undefined + } + + const vote = hasVotingPower + ? ownVoteRecord?.account.vote + : getDelegatorVoteForQuorum() + + const isMulti = + proposal?.account.voteType !== VoteType.SINGLE_CHOICE && + proposal?.account.accountType === GovernanceAccountType.ProposalV2 + + const nota = '$$_NOTA_$$' + + return vote !== undefined ? ( +
+
+

+ {quorum === 'electoral' ? 'Your vote' : 'You voted to veto'} +

+ {vote.voteType === VoteKind.Approve ? ( + isMulti ? ( + vote.approveChoices?.map((choice, index) => + choice.weightPercentage ? ( +
+ +
+ ) : null + ) + ) : ( + +
+ +
+
+ ) + ) : vote.voteType === VoteKind.Deny ? ( + +
+ +
+
+ ) : vote.voteType === VoteKind.Veto ? ( + +
+ +
+
+ ) : vote.voteType === VoteKind.Abstain ? ( + +
+ +
+
+ ) : ( + assertUnreachable(vote.voteType as never) + )} +
+ {(isVoting || isInCoolOffTime) && ( +
+
+ + + {isInCoolOffTime && ( +
+ Warning: If you withdraw your vote now you can only deny the + proposal its not possible to vote yes during cool off time +
+ )} +
+
+ )} +
+ ) : null +} diff --git a/components/VotePanel/hooks.ts b/components/VotePanel/hooks.ts new file mode 100644 index 0000000000..dd6a39a1be --- /dev/null +++ b/components/VotePanel/hooks.ts @@ -0,0 +1,113 @@ +import { useRouteProposalQuery } from '@hooks/queries/proposal' +import { useRealmQuery } from '@hooks/queries/realm' +import { + useUserCommunityTokenOwnerRecord, + useUserCouncilTokenOwnerRecord, +} from '@hooks/queries/tokenOwnerRecord' +import useRoleOfGovToken from '@hooks/selectedRealm/useRoleOfToken' +import { useHasVoteTimeExpired } from '@hooks/useHasVoteTimeExpired' +import { useProposalGovernanceQuery } from '@hooks/useProposal' +import { + ProposalState, + Proposal, + Governance, + VoteThresholdType, +} from '@solana/spl-governance' +import dayjs from 'dayjs' +import { useMemo } from 'react' + +export const useIsVoting = () => { + const proposal = useRouteProposalQuery().data?.result + const governance = useProposalGovernanceQuery().data?.result + const hasVoteTimeExpired = useHasVoteTimeExpired(governance, proposal!) + + const isVoting = + proposal?.account.state === ProposalState.Voting && !hasVoteTimeExpired + return isVoting +} + +export const useIsInCoolOffTime = () => { + const proposal = useRouteProposalQuery().data?.result + const governance = useProposalGovernanceQuery().data?.result + + return isInCoolOffTime(proposal?.account, governance?.account) +} + +export const isInCoolOffTime = ( + proposal: Proposal | undefined, + governance: Governance | undefined +) => { + const mainVotingEndedAt = proposal?.signingOffAt + ?.addn(governance?.config.baseVotingTime || 0) + .toNumber() + + const votingCoolOffTime = governance?.config.votingCoolOffTime || 0 + const canFinalizeAt = mainVotingEndedAt + ? mainVotingEndedAt + votingCoolOffTime + : mainVotingEndedAt + + const endOfProposalAndCoolOffTime = canFinalizeAt + ? dayjs(1000 * canFinalizeAt!) + : undefined + + const isInCoolOffTime = endOfProposalAndCoolOffTime + ? dayjs().isBefore(endOfProposalAndCoolOffTime) && + mainVotingEndedAt && + dayjs().isAfter(mainVotingEndedAt * 1000) + : undefined + + return !!isInCoolOffTime && proposal!.state !== ProposalState.Defeated +} + +export const useVotingPop = () => { + const proposal = useRouteProposalQuery().data?.result + const role = useRoleOfGovToken(proposal?.account.governingTokenMint) + + return role !== 'not found' ? role : undefined +} + +export const useVoterTokenRecord = () => { + const votingPop = useVotingPop() + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result + + const voterTokenRecord = + votingPop === 'community' ? ownTokenRecord : ownCouncilTokenRecord + return voterTokenRecord +} + +/* + returns: undefined if loading, false if nobody can veto, 'council' if council can veto, 'community' if community can veto +*/ +export const useVetoingPop = () => { + const tokenRole = useVotingPop() + const governance = useProposalGovernanceQuery().data?.result + const realm = useRealmQuery().data?.result + const vetoingPop = useMemo(() => { + if (governance === undefined) return undefined + + return tokenRole === 'community' + ? governance?.account.config.councilVetoVoteThreshold.type !== + VoteThresholdType.Disabled && + // if there is no council then there's not actually a vetoing population, in my opinion + realm?.account.config.councilMint !== undefined + ? 'council' + : undefined + : governance?.account.config.communityVetoVoteThreshold.type !== + VoteThresholdType.Disabled + ? 'community' + : undefined + }, [governance, tokenRole, realm?.account.config.councilMint]) + + return vetoingPop +} + +export const useUserVetoTokenRecord = () => { + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result + + const vetoingPop = useVetoingPop() + const voterTokenRecord = + vetoingPop === 'community' ? ownTokenRecord : ownCouncilTokenRecord + return voterTokenRecord +} diff --git a/components/VotePanel/index.ts b/components/VotePanel/index.ts new file mode 100644 index 0000000000..dc432d7cac --- /dev/null +++ b/components/VotePanel/index.ts @@ -0,0 +1 @@ +export { default } from './VotePanel' diff --git a/components/VotePanel/useCanVote.ts b/components/VotePanel/useCanVote.ts new file mode 100644 index 0000000000..80bb661c33 --- /dev/null +++ b/components/VotePanel/useCanVote.ts @@ -0,0 +1,45 @@ +import {useVoterTokenRecord, useVotingPop} from './hooks' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import {useProposalVoteRecordQuery} from '@hooks/queries/voteRecord' +import {useRealmVoterWeightPlugins} from '@hooks/useRealmVoterWeightPlugins' +import {useDelegatorAwareVoterWeight} from "@hooks/useDelegatorAwareVoterWeight"; + +const useHasAnyVotingPower = (role: 'community' | 'council' | undefined) => { + const voterWeight = useDelegatorAwareVoterWeight(role ?? 'community'); + const {isReady } = useRealmVoterWeightPlugins(role) + return isReady && !!voterWeight?.value && voterWeight.value?.isZero() === false +} + +export const useCanVote = () => { + const { isReady, includesPlugin } = useRealmVoterWeightPlugins() + const votingPop = useVotingPop() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + + const { data: ownVoteRecord } = useProposalVoteRecordQuery('electoral') + const voterTokenRecord = useVoterTokenRecord() + const { plugins } = useRealmVoterWeightPlugins(votingPop); + + const hasAllVoterWeightRecords = (plugins?.voterWeight ?? []).every((plugin) => plugin.weights !== undefined) + const isVoteCast = !!ownVoteRecord?.found + + const hasMinAmountToVote = useHasAnyVotingPower(votingPop) + + const canVote = + connected && + !(isReady && includesPlugin('NFT') && !voterTokenRecord) && + !(isReady && includesPlugin('HeliumVSR') && !voterTokenRecord) && + hasAllVoterWeightRecords && + !isVoteCast && + hasMinAmountToVote + + const voteTooltipContent = !connected + ? 'You need to connect your wallet to be able to vote' + : isReady && includesPlugin('NFT') && !voterTokenRecord + ? 'You must join the Realm to be able to vote' + : !hasMinAmountToVote + ? 'You don’t have governance power to vote in this dao' + : '' + + return [canVote, voteTooltipContent] as const +} diff --git a/components/VotePanel/useDelegators.ts b/components/VotePanel/useDelegators.ts new file mode 100644 index 0000000000..d8fb8e3761 --- /dev/null +++ b/components/VotePanel/useDelegators.ts @@ -0,0 +1,71 @@ +import { DELEGATOR_BATCH_VOTE_SUPPORT_BY_PLUGIN } from '@constants/flags' +import { determineVotingPowerType } from '@hooks/queries/governancePower' +import { useRealmQuery } from '@hooks/queries/realm' +import { useTokenOwnerRecordsDelegatedToUser } from '@hooks/queries/tokenOwnerRecord' +import useSelectedRealmPubkey from '@hooks/selectedRealm/useSelectedRealmPubkey' +import { useConnection } from '@solana/wallet-adapter-react' +import { useAsync } from 'react-async-hook' +import { useSelectedDelegatorStore } from 'stores/useSelectedDelegatorStore' + +const useDelegators = (role: 'community' | 'council' | undefined) => { + const realm = useRealmQuery().data?.result + const relevantMint = + role && role === 'community' + ? realm?.account.communityMint + : realm?.account.config.councilMint + + const { data: torsDelegatedToUser } = useTokenOwnerRecordsDelegatedToUser() + const relevantDelegators = + relevantMint && + torsDelegatedToUser?.filter((x) => + x.account.governingTokenMint.equals(relevantMint) + ) + return relevantDelegators +} +/* +const fetchDelegators = async (connection: Connection, walletPk: PublicKey, realmPk: PublicKey, role: 'community' | 'council' | undefined) => { + const realm = (await fetchRealmByPubkey(connection, realmPk)).result + if (realm === undefined) {throw new Error('Realm not found')} + + const relevantMint = + role && role === 'community' + ? realm.account.communityMint + : realm.account.config.councilMint + +} */ + +/** + * if batched voting is enabled for the plugin, and by the user, then this returns array of delegators. + * otherwise, returns [] + **/ +export const useBatchedVoteDelegators = ( + role: 'community' | 'council' | undefined +) => { + const { connection } = useConnection() + const realmPk = useSelectedRealmPubkey() + const delegators = useDelegators(role) + const { result: plugin } = useAsync( + async () => + role && realmPk && determineVotingPowerType(connection, realmPk, role), + [connection, realmPk, role] + ) + const batchVoteSupported = + plugin && DELEGATOR_BATCH_VOTE_SUPPORT_BY_PLUGIN[plugin] + + // empty array if not supported + const delegatorsIfSupported = + batchVoteSupported === undefined + ? undefined + : batchVoteSupported === false + ? [] + : delegators + + // If the user is selecting a specific delegator, we want to just use that and not count the other delegators + const selectedDelegator = useSelectedDelegatorStore((s) => + role === 'community' ? s.communityDelegator : s.councilDelegator + ) + + return selectedDelegator ? [] : delegatorsIfSupported +} + +export default useDelegators diff --git a/components/VoteResultStatus.tsx b/components/VoteResultStatus.tsx index d9e1fd2f21..1d75af696d 100644 --- a/components/VoteResultStatus.tsx +++ b/components/VoteResultStatus.tsx @@ -1,47 +1,94 @@ import { XCircleIcon, CheckCircleIcon } from '@heroicons/react/outline' +import { BanIcon } from '@heroicons/react/solid' +import useProposalVotes from '@hooks/useProposalVotes' +import { GovernanceAccountType, ProposalState, VoteType } from '@solana/spl-governance' +import { useRouteProposalQuery } from '@hooks/queries/proposal' +import { useVetoingPop } from './VotePanel/hooks' -type VoteResultStatusProps = { - progress: number - votePassed: boolean | undefined - yesVotesRequired: number -} - -const VoteResultStatus = ({ - progress, - votePassed, - yesVotesRequired, -}: VoteResultStatusProps) => { - return votePassed ? ( +const VetoResult = () => { + const vetoingPop = useVetoingPop() + return (
- -

The proposal has passed

+ +

Vetoed by the {vetoingPop}

- ) : ( + ) +} + +const ApprovalResult = () => ( +
+ +

The proposal has passed

+
+) + +const MultiChoiceResult = () => ( +
+ +

The proposal is completed

+
+) + +const FailResult = () => { + const proposal = useRouteProposalQuery().data?.result + const voteData = useProposalVotes(proposal?.account) + + return voteData.yesVotesRequired === undefined ? null : (

The proposal has failed

-

{`${yesVotesRequired?.toLocaleString( +

{`${voteData.yesVotesRequired.toLocaleString( undefined, { maximumFractionDigits: 0, } - )} more Yes vote${yesVotesRequired > 1 ? 's' : ''} were needed`}

+ )} more Yes vote${ + voteData.yesVotesRequired > 1 ? 's' : '' + } were needed`}

= 100 ? 'bg-green' : 'bg-fgd-3' - } flex rounded`} + className={`bg-fgd-3 flex rounded`} >
) } +const VoteResultStatus = () => { + const proposal = useRouteProposalQuery().data?.result + + const status = + proposal && + (proposal.account.state === ProposalState.Completed || + proposal.account.state === ProposalState.Executing || + proposal.account.state === ProposalState.SigningOff || + proposal.account.state === ProposalState.Succeeded || + proposal.account.state === ProposalState.ExecutingWithErrors + ? 'approved' + : proposal.account.state === ProposalState.Vetoed + ? 'vetoed' + : 'denied') + + const isMulti = proposal?.account.voteType !== VoteType.SINGLE_CHOICE + && proposal?.account.accountType === GovernanceAccountType.ProposalV2 + + return status === undefined ? null : status === 'approved' ? isMulti ? + ( + + ) : ( + + ) : status === 'vetoed' ? ( + + ) : ( + + ) +} + export default VoteResultStatus diff --git a/components/VoteResults.tsx b/components/VoteResults.tsx index f9c94f7825..887195e20e 100644 --- a/components/VoteResults.tsx +++ b/components/VoteResults.tsx @@ -1,12 +1,13 @@ import VoteResultsBar from './VoteResultsBar' -import useProposalVotes from '@hooks/useProposalVotes' import { Proposal } from '@solana/spl-governance' +import useProposalVotes from '@hooks/useProposalVotes' type VoteResultsProps = { isListView?: boolean proposal: Proposal } +// TODO make component display well when data is loading const VoteResults = ({ isListView, proposal }: VoteResultsProps) => { const { yesVoteCount, @@ -14,6 +15,7 @@ const VoteResults = ({ isListView, proposal }: VoteResultsProps) => { relativeNoVotes, relativeYesVotes, } = useProposalVotes(proposal) + return (
{proposal ? ( @@ -28,7 +30,7 @@ const VoteResults = ({ isListView, proposal }: VoteResultsProps) => { !isListView ? 'hero-text' : '' }`} > - {yesVoteCount.toLocaleString()} + {(yesVoteCount ?? 0).toLocaleString()} {isListView ? ( {relativeYesVotes?.toFixed(1)}% @@ -48,7 +50,7 @@ const VoteResults = ({ isListView, proposal }: VoteResultsProps) => { !isListView ? 'hero-text' : '' }`} > - {noVoteCount.toLocaleString()} + {(noVoteCount ?? 0).toLocaleString()} {isListView ? ( {relativeNoVotes?.toFixed(1)}% diff --git a/components/VoteResultsForRealmProposal.tsx b/components/VoteResultsForRealmProposal.tsx new file mode 100644 index 0000000000..b53e975791 --- /dev/null +++ b/components/VoteResultsForRealmProposal.tsx @@ -0,0 +1,92 @@ +import VoteResultsBar from './VoteResultsBar' +import { + Governance, + ProgramAccount, + Proposal, + Realm, +} from '@solana/spl-governance' +import useProposalVotesForRealm from '@hooks/useProposalVotesForRealm' + +type VoteResultsForRealmProps = { + isListView?: boolean + proposal: Proposal + realm: ProgramAccount + governance?: ProgramAccount +} + +const VoteResultsForRealmProposal = ({ + isListView, + proposal, + realm, + governance, +}: VoteResultsForRealmProps) => { + const { + yesVoteCount, + noVoteCount, + relativeNoVotes, + relativeYesVotes, + } = useProposalVotesForRealm(realm, proposal, governance) + + return ( +
+ {proposal ? ( +
+
+
+

Yes Votes

+

+ {yesVoteCount.toLocaleString()} + {isListView ? ( + + {relativeYesVotes?.toFixed(1)}% + + ) : null} +

+ {!isListView ? ( +
+ {relativeYesVotes?.toFixed(1)}% +
+ ) : null} +
+
+

No Votes

+

+ {noVoteCount.toLocaleString()} + {isListView ? ( + + {relativeNoVotes?.toFixed(1)}% + + ) : null} +

+ {!isListView ? ( +
+ {relativeNoVotes?.toFixed(1)}% +
+ ) : null} +
+
+ +
+ ) : ( + <> +
+ + )} +
+ ) +} + +export default VoteResultsForRealmProposal diff --git a/components/VotingRules.tsx b/components/VotingRules.tsx new file mode 100644 index 0000000000..8c4c30cfe5 --- /dev/null +++ b/components/VotingRules.tsx @@ -0,0 +1,242 @@ +import { useState } from 'react' +import { useVetoingPop, useVotingPop } from './VotePanel/hooks' +import { + ChevronRight, + ChevronUp, + Events, + InformationFilled, + Scales, + ScalesTipped, + Time, +} from '@carbon/icons-react' +import { capitalize } from '@utils/helpers' +import { useProposalGovernanceQuery } from '@hooks/useProposal' +import { VoteTipping, getNativeTreasuryAddress } from '@solana/spl-governance' +import { secondsInDay } from 'date-fns' +import clsx from 'clsx' +import { TimerBar } from './ProposalTimer' +import { useAsync } from 'react-async-hook' +import useRealm from '@hooks/useRealm' +import { ACCOUNT_NAMES } from './instructions/tools' +import { ExploreButton } from './treasuryV2/Details/ExploreLink' +import Tooltip from './Tooltip' +import { useRouteProposalQuery } from '@hooks/queries/proposal' +import {ShortAddress} from "@components/Profile/ShortAddress"; + +const formatOneDecimal = (x: number) => x.toFixed(1).replace(/[.,]0$/, '') + +const formatDays = (x: number) => + formatOneDecimal(x) + ' ' + (x === 1 ? 'day' : 'days') + +// I love enums! +const TIPPING = { + [VoteTipping.Disabled]: 'Disabled', + [VoteTipping.Early]: 'Early', + [VoteTipping.Strict]: 'Strict', +} as const + +const VotingRules = () => { + const proposal = useRouteProposalQuery().data?.result + const governance = useProposalGovernanceQuery().data?.result + const votingPop = useVotingPop() + const vetoVotePop = useVetoingPop() + const { symbol } = useRealm() + + const [showMore, setShowMore] = useState(false) + + const threshold = + votingPop === 'community' + ? governance?.account.config.communityVoteThreshold + : governance?.account.config.councilVoteThreshold + + const vetoVoteThreshold = + !!vetoVotePop && vetoVotePop === 'community' + ? governance?.account.config.communityVetoVoteThreshold + : governance?.account.config.councilVetoVoteThreshold + + const tipping = + votingPop === 'community' + ? governance?.account.config.communityVoteTipping + : governance?.account.config.councilVoteTipping + + const voteDurationDays = + governance?.account.config.baseVotingTime !== undefined && + governance?.account.config.votingCoolOffTime !== undefined + ? (governance.account.config.baseVotingTime + + governance?.account.config.votingCoolOffTime) / + secondsInDay + : undefined + + const treasuryAddress = useAsync( + async () => + governance !== undefined + ? getNativeTreasuryAddress(governance.owner, governance.pubkey) + : undefined, + [governance] + ) + + return ( +
+
setShowMore((prev) => !prev)} + > +

Voting Rules

+ +
+
+
+ {capitalize(votingPop)} +
+ {voteDurationDays !== undefined && ( +
+
+ )} + {threshold?.value !== undefined && ( +
+ {threshold.value}% +
+ )} +
+ {tipping !== undefined ? TIPPING[tipping] : null} +
+
+
+
+
+
+ window.open(`/dao/${symbol}/treasury/v2`, '_blank') + } + > +
Wallet
+ +
+ {treasuryAddress.result && ( +
+
+ {ACCOUNT_NAMES[treasuryAddress.result.toString()] + ? ACCOUNT_NAMES[treasuryAddress.result.toString()] + : } +
+ +
+ )} +
+
+
Vote Type
+
{capitalize(votingPop)}
+
+
+
Approval Quorum
+ {threshold?.value !== undefined &&
{threshold.value}%
} +
+ {vetoVotePop && vetoVoteThreshold?.value && ( + <> +
+
Veto Power
+
{capitalize(vetoVotePop)}
+
+
+
Veto Quorum
+
{vetoVoteThreshold.value}%
+
+ + )} +
+
Vote Tipping
+
{tipping !== undefined ? TIPPING[tipping] : null}
+
+
+
+
+
+
Total Voting Duration
+ {voteDurationDays !== undefined && ( +
{formatDays(voteDurationDays)}
+ )} +
+ {(governance?.account.config.votingCoolOffTime ?? 0) !== 0 && ( + <> +
+
+ Unrestricted
+
+
Voting Time
+
+ + + +
+
+
+
+
+
+ {governance?.account.config.baseVotingTime !== undefined + ? formatDays( + governance.account.config.baseVotingTime / + secondsInDay + ) + : null} +
+
+
+ +
+
+ Cool-off
+
+
Voting Time
+
+ + + +
+
+
+
+
+
+ {governance?.account.config.votingCoolOffTime !== undefined + ? formatDays( + governance.account.config.votingCoolOffTime / + secondsInDay + ) + : null} +
+
+
+ + )} +
+ {governance?.account !== undefined && + proposal?.account !== undefined ? ( + + ) : null} +
+
+ ) +} + +export default VotingRules diff --git a/components/WalletQRCode.tsx b/components/WalletQRCode.tsx index eb1f4e34f3..339cb6677d 100644 --- a/components/WalletQRCode.tsx +++ b/components/WalletQRCode.tsx @@ -35,6 +35,7 @@ function WalletQRCode(props: Props & { width: number }) { ) }) } + // 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 }, []) useEffect(() => { @@ -60,6 +61,7 @@ function WalletQRCode(props: Props & { width: number }) { image: props.logoSrc || LogoRealms.src, }) } + // 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 }, [props.logoSrc, props.walletAddress, code]) return ( diff --git a/components/chat/Comment.tsx b/components/chat/Comment.tsx index 73162fe2b9..4c5fe9862b 100644 --- a/components/chat/Comment.tsx +++ b/components/chat/Comment.tsx @@ -1,36 +1,65 @@ -import React from 'react' -import { VoteRecord } from '@solana/spl-governance' +import { + getTokenOwnerRecordAddress, + getVoteRecordAddress, + GovernanceAccountType, + VoteType +} from '@solana/spl-governance' import { ThumbUpIcon, ThumbDownIcon } from '@heroicons/react/solid' import { ExternalLinkIcon } from '@heroicons/react/solid' import { ChatMessage } from '@solana/spl-governance' import { abbreviateAddress, fmtTokenAmount } from '../../utils/formatting' import useRealm from '../../hooks/useRealm' -import { MintInfo } from '@solana/spl-token' import { isPublicKey } from '@tools/core/pubkey' import { getVoteWeight, isYesVote } from '@models/voteRecords' import dayjs from 'dayjs' import { ProfilePopup, ProfileImage, useProfile } from '@components/Profile' +import { useRouteProposalQuery } from '@hooks/queries/proposal' +import { useMintInfoByPubkeyQuery } from '@hooks/queries/mintInfo' +import { useAsync } from 'react-async-hook' +import useSelectedRealmPubkey from '@hooks/selectedRealm/useSelectedRealmPubkey' +import { useVoteRecordByPubkeyQuery } from '@hooks/queries/voteRecord' + const relativeTime = require('dayjs/plugin/relativeTime') -const Comment = ({ - chatMessage, - voteRecord, - proposalMint, -}: { - chatMessage: ChatMessage - voteRecord: VoteRecord | undefined - proposalMint: MintInfo | undefined -}) => { +const Comment = ({ chatMessage }: { chatMessage: ChatMessage }) => { dayjs.extend(relativeTime) const { author, postedAt, body } = chatMessage const { realmInfo } = useRealm() const { profile } = useProfile(author) const voteSymbol = !realmInfo ? '' + : realmInfo.voteSymbol + ? realmInfo.voteSymbol : isPublicKey(realmInfo.symbol) ? realmInfo.displayName : realmInfo.symbol + //@ts-ignore const fromNow = dayjs(postedAt.toNumber() * 1000).fromNow() + + const proposal = useRouteProposalQuery().data?.result + const proposalMint = useMintInfoByPubkeyQuery( + proposal?.account.governingTokenMint + ).data?.result + + const realmPk = useSelectedRealmPubkey() + + const { result: voteRecordPk } = useAsync(async () => { + if (!proposal || !realmPk) return undefined + const tokenPk = proposal.account.governingTokenMint + const torPk = await getTokenOwnerRecordAddress( + proposal.owner, + realmPk, + tokenPk, + author + ) + return getVoteRecordAddress(proposal.owner, proposal.pubkey, torPk) + }, [proposal, realmPk, author]) + const voteRecord = useVoteRecordByPubkeyQuery(voteRecordPk).data?.result + ?.account + + const isMulti = proposal?.account.voteType !== VoteType.SINGLE_CHOICE + && proposal?.account.accountType === GovernanceAccountType.ProposalV2 + return (
@@ -70,7 +99,7 @@ const Comment = ({ ) : ( )} - {isYesVote(voteRecord) ? 'Yes' : 'No'} + {isYesVote(voteRecord) ? isMulti ? 'Voted' : 'Yes' : 'No'}
| diff --git a/components/chat/DiscussionForm.tsx b/components/chat/DiscussionForm.tsx index 33dc00133c..966f385287 100644 --- a/components/chat/DiscussionForm.tsx +++ b/components/chat/DiscussionForm.tsx @@ -1,48 +1,63 @@ import { useState } from 'react' import Button from '../Button' import Input from '../inputs/Input' -import useWalletStore from '../../stores/useWalletStore' import useRealm from '../../hooks/useRealm' -import { RpcContext, GoverningTokenRole } from '@solana/spl-governance' +import { RpcContext } from '@solana/spl-governance' import { ChatMessageBody, ChatMessageBodyType } from '@solana/spl-governance' import { postChatMessage } from '../../actions/chat/postMessage' import Loading from '../Loading' import Tooltip from '@components/Tooltip' import { getProgramVersionForRealm } from '@models/registry/api' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { + useUserCommunityTokenOwnerRecord, + useUserCouncilTokenOwnerRecord, +} from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRouteProposalQuery } from '@hooks/queries/proposal' +import { useVotingPop } from '@components/VotePanel/hooks' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { useLegacyVoterWeight } from '@hooks/queries/governancePower' +import {useVotingClients} from "@hooks/useVotingClients"; const DiscussionForm = () => { const [comment, setComment] = useState('') - const connected = useWalletStore((s) => s.connected) - const { - ownVoterWeight, - realmInfo, - realm, - ownTokenRecord, - ownCouncilTokenRecord, - } = useRealm() - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result + const realm = useRealmQuery().data?.result + const { result: ownVoterWeight } = useLegacyVoterWeight() + const { realmInfo } = useRealm() + const votingClients = useVotingClients(); const [submitting, setSubmitting] = useState(false) + const [error, setError] = useState('') - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - const { proposal } = useWalletStore((s) => s.selectedProposal) - const { fetchChatMessages } = useWalletStore((s) => s.actions) - const { tokenType } = useWalletStore((s) => s.selectedProposal) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const connection = useLegacyConnectionContext() + const proposal = useRouteProposalQuery().data?.result + const tokenRole = useVotingPop() const commenterVoterTokenRecord = - tokenType === GoverningTokenRole.Community - ? ownTokenRecord - : ownCouncilTokenRecord + tokenRole === 'community' ? + ownTokenRecord ?? ownCouncilTokenRecord : + ownCouncilTokenRecord + const votingClient = votingClients(tokenRole ?? 'community');// default to community if no role is provided const submitComment = async () => { setSubmitting(true) + setError('') + if ( + !realm || + !proposal || + !commenterVoterTokenRecord || + !wallet || + !realmInfo + ) + throw new Error() const rpcContext = new RpcContext( - proposal!.owner, - getProgramVersionForRealm(realmInfo!), - wallet!, + proposal.owner, + getProgramVersionForRealm(realmInfo), + wallet, connection.current, connection.endpoint ) @@ -55,31 +70,30 @@ const DiscussionForm = () => { try { await postChatMessage( rpcContext, - realm!, - proposal!, - commenterVoterTokenRecord!, + realm, + proposal, + commenterVoterTokenRecord, msg, undefined, - client + ownTokenRecord ? votingClient : undefined // use votingClient only if the community TOR is used for commenting ) setComment('') } catch (ex) { console.error("Can't post chat message", ex) + setError(ex.message); //TODO: How do we present transaction errors to users? Just the notification? } finally { setSubmitting(false) } - - fetchChatMessages(proposal!.pubkey) } const postEnabled = - proposal && connected && ownVoterWeight.hasAnyWeight() && comment + proposal && connected && ownVoterWeight?.hasAnyWeight() && comment const tooltipContent = !connected ? 'Connect your wallet to send a comment' - : !ownVoterWeight.hasAnyWeight() + : !ownVoterWeight?.hasAnyWeight() ? 'You need to have deposited some tokens to submit your comment.' : !comment ? 'Write a comment to submit' @@ -107,6 +121,7 @@ const DiscussionForm = () => {
+ {error &&

{error}

} ) } diff --git a/components/chat/DiscussionPanel.tsx b/components/chat/DiscussionPanel.tsx index b732dbddfa..aaf49322a0 100644 --- a/components/chat/DiscussionPanel.tsx +++ b/components/chat/DiscussionPanel.tsx @@ -1,38 +1,64 @@ +import { useMemo } from 'react' import DiscussionForm from './DiscussionForm' -import Comment from './Comment' -import useWalletStore from '../../stores/useWalletStore' +import { useQuery } from '@tanstack/react-query' +import { + GOVERNANCE_CHAT_PROGRAM_ID, + getGovernanceChatMessages, +} from '@solana/spl-governance' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { useSelectedProposalPk } from '@hooks/queries/proposal' +import LazyLoadComment from './LazyLoadComment' + +export const useChatMessagesQuery = () => { + const connection = useLegacyConnectionContext() + const proposalPk = useSelectedProposalPk() + + const enabled = proposalPk !== undefined + const query = useQuery({ + queryKey: enabled + ? [connection.cluster, 'ChatMessages', 'by Proposal', proposalPk] + : undefined, + queryFn: async () => { + if (!enabled) throw new Error() + return getGovernanceChatMessages( + connection.current, + GOVERNANCE_CHAT_PROGRAM_ID, + proposalPk + ) + }, + enabled, + }) + + return query +} const DiscussionPanel = () => { - const { chatMessages, voteRecordsByVoter, proposalMint } = useWalletStore( - (s) => s.selectedProposal + const { data: chatMessages } = useChatMessagesQuery() + + const sortedMessages = useMemo( + () => + chatMessages?.sort( + (m1, m2) => + m2.account.postedAt.toNumber() - m1.account.postedAt.toNumber() + ), + [chatMessages] ) return (

Discussion{' '} - - ({Object.keys(chatMessages).length}) - + {chatMessages !== undefined && ( + ({chatMessages.length}) + )}

- {Object.values(chatMessages) - .sort( - (m1, m2) => - m2.account.postedAt.toNumber() - m1.account.postedAt.toNumber() - ) - .map((cm) => ( - - ))} + + {sortedMessages?.map((cm) => ( + + ))}
) } diff --git a/components/chat/LazyLoadComment.tsx b/components/chat/LazyLoadComment.tsx new file mode 100644 index 0000000000..773c441727 --- /dev/null +++ b/components/chat/LazyLoadComment.tsx @@ -0,0 +1,19 @@ +import React from 'react' +import { useInView } from 'react-intersection-observer' +import Comment from './Comment' +import { ChatMessage } from '@solana/spl-governance' + +const LazyLoadComment = ({ chatMessage }: { chatMessage: ChatMessage }) => { + const { ref, inView } = useInView({ + /* Optional options */ + triggerOnce: true, + }) + + return ( +
+
{inView && }
+
+ ) +} + +export default LazyLoadComment diff --git a/components/explorer/inspectorButton.tsx b/components/explorer/inspectorButton.tsx index 1d98e83daa..7d13c6e2cc 100644 --- a/components/explorer/inspectorButton.tsx +++ b/components/explorer/inspectorButton.tsx @@ -4,36 +4,44 @@ import { ProgramAccount, ProposalTransaction, } from '@solana/spl-governance' -import useWalletStore from '../../stores/useWalletStore' import { getExplorerInspectorUrl, getExplorerUrl } from './tools' import { SecondaryButton } from '../Button' import { notify } from '@utils/notifications' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import dayjs from 'dayjs' export default function InspectorButton({ proposalInstruction, }: { proposalInstruction: ProgramAccount }) { - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const connected = useWalletStore((s) => s.connected) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const wasExecuted = proposalInstruction.account.executionStatus === InstructionExecutionStatus.Success + const executedAtFormatted = proposalInstruction.account.executedAt + ? dayjs(proposalInstruction.account.executedAt.toNumber() * 1000).format( + 'DD-MM-YYYY HH:mm' + ) + : '' + const showInspector = async () => { let inspectUrl = '' if (!wasExecuted) { - const instructionData = proposalInstruction.account.getSingleInstruction() + const instructionData = proposalInstruction.account.getAllInstructions() const result = await dryRunInstruction( connection.current, wallet!, - instructionData + null, + [], + [...instructionData] ) - inspectUrl = getExplorerInspectorUrl( - connection.endpoint, - result.transaction - ) + inspectUrl = await getExplorerInspectorUrl(connection, result.transaction) } else { try { const recentActivity = await connection.current.getConfirmedSignaturesForAddress2( @@ -65,7 +73,9 @@ export default function InspectorButton({ disabled={!connected && !wasExecuted} onClick={() => showInspector()} > - {!wasExecuted ? 'Inspect' : 'View transaction'} + {!wasExecuted + ? 'Inspect' + : `Execution date: ${executedAtFormatted} - View transaction`} ) } diff --git a/components/explorer/tools.ts b/components/explorer/tools.ts index 82cf129f6f..d8e6c33690 100644 --- a/components/explorer/tools.ts +++ b/components/explorer/tools.ts @@ -1,4 +1,6 @@ -import { PublicKey, Transaction } from '@solana/web3.js' +import { TransactionOrVersionedTransaction } from '@solana/wallet-adapter-base' +import { PublicKey, Transaction, TransactionVersion } from '@solana/web3.js' +import { ConnectionContext } from '@utils/connection' import base58 from 'bs58' export function getExplorerUrl( @@ -27,21 +29,32 @@ export function getExplorerUrl( } /// Returns explorer inspector URL for the given transaction -export function getExplorerInspectorUrl( - endpoint: string, - transaction: Transaction +export async function getExplorerInspectorUrl( + connection: ConnectionContext, + transaction: TransactionOrVersionedTransaction< + ReadonlySet + > ) { const SIGNATURE_LENGTH = 64 - const explorerUrl = new URL(getExplorerUrl(endpoint, 'inspector', 'tx')) + const explorerUrl = new URL( + getExplorerUrl(connection.endpoint, 'inspector', 'tx') + ) const signatures = transaction.signatures.map((s) => base58.encode(s.signature ?? Buffer.alloc(SIGNATURE_LENGTH)) ) explorerUrl.searchParams.append('signatures', JSON.stringify(signatures)) - const message = transaction.serializeMessage() - explorerUrl.searchParams.append('message', message.toString('base64')) + const message = + transaction instanceof Transaction + ? transaction.serializeMessage().toString('base64') + : Buffer.from(transaction.message.serialize()).toString('base64') + explorerUrl.searchParams.append('message', message) + + if (connection.cluster === 'devnet') { + explorerUrl.searchParams.append('cluster', 'devnet') + } return explorerUrl.toString() } diff --git a/components/inputs/Checkbox.tsx b/components/inputs/Checkbox.tsx index 5ef8f57aeb..1a24cf1627 100644 --- a/components/inputs/Checkbox.tsx +++ b/components/inputs/Checkbox.tsx @@ -1,7 +1,15 @@ -import React from 'react' import { CheckIcon } from '@heroicons/react/solid' -const Checkbox = ({ checked, label = '', disabled = false, ...props }) => ( +const Checkbox = ({ + checked, + label = '', + disabled = false, + ...props +}: { + checked: boolean + label?: string + disabled?: boolean +} & React.ComponentProps<'input'>) => (
) } - function getProgramAccountLabel(val: ProgramAccount) { - const name = val ? getProgramName(val.account.governedAccount) : '' + function getProgramAccountLabel(val: AssetAccount) { + const name = val ? getProgramName(val.pubkey) : '' return (
{name &&
{name}
} -
{val?.account?.governedAccount?.toBase58()}
+
{val?.pubkey?.toBase58()}
) } useEffect(() => { - if (governedAccounts.length == 1 && autoselectFirst) { + if (governedAccounts.length == 1 && autoSelectFirst) { //wait for microtask queue to be empty setTimeout(() => { onChange(governedAccounts[0]) }) } + // 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 }, [JSON.stringify(governedAccounts)]) return ( {label && {label}} + {subtitle &&

{subtitle}

}
{({ open }) => ( @@ -58,7 +66,7 @@ const Select = ({ > {componentLabel ? componentLabel - : value + : typeof value === 'string' ? value : placeholder} {label && {label}} - + {subtitle &&

{subtitle}

} - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - > - )} - -
-
- -
- - ) -} - -export default GovernanceConfigModal diff --git a/pages/dao/[symbol]/params/MetadataCreationModal.tsx b/pages/dao/[symbol]/params/MetadataCreationModal.tsx index 2fd4c7addb..aa4ec56b87 100644 --- a/pages/dao/[symbol]/params/MetadataCreationModal.tsx +++ b/pages/dao/[symbol]/params/MetadataCreationModal.tsx @@ -8,7 +8,6 @@ import { getUpdateTokenMetadataInstruction, validateInstruction, } from '@utils/instructionTools' -import useWalletStore from 'stores/useWalletStore' import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes' import useCreateProposal from '@hooks/useCreateProposal' import { InstructionDataWithHoldUpTime } from 'actions/createProposal' @@ -16,7 +15,7 @@ import useQueryContext from '@hooks/useQueryContext' import { useRouter } from 'next/router' import { notify } from '@utils/notifications' import useRealm from '@hooks/useRealm' -import { useEffect, useState } from 'react' +import React, { useEffect, useState } from 'react' import Button from '@components/Button' import * as yup from 'yup' import { useDropzone } from 'react-dropzone' @@ -26,8 +25,12 @@ import useGovernanceAssets from '@hooks/useGovernanceAssets' import { AccountType } from '@utils/uiTypes/assets' import { WebBundlr } from '@bundlr-network/client' import { LAMPORTS_PER_SOL } from '@solana/web3.js' -import { deprecated } from '@metaplex-foundation/mpl-token-metadata' import { PublicKey } from '@solana/web3.js' +import { Metaplex } from '@metaplex-foundation/js' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import {useVoteByCouncilToggle} from "@hooks/useVoteByCouncilToggle"; interface GovernanceConfigForm { mintAccount: AssetAccount | undefined @@ -48,21 +51,22 @@ const MetadataCreationModal = ({ initialMintAccount?: AssetAccount | undefined }) => { const router = useRouter() - const { realm, canChooseWhoVote, symbol, realmInfo } = useRealm() + const realm = useRealmQuery().data?.result + const {symbol, realmInfo } = useRealm() const programId: PublicKey | undefined = realmInfo?.programId const { assetAccounts } = useGovernanceAssets() - const connection = useWalletStore((s) => s.connection) + const connection = useLegacyConnectionContext() const mintGovernancesWithMintInfo = assetAccounts.filter((x) => { return x.type === AccountType.MINT }) const shouldBeGoverned = false const { fmtUrlWithCluster } = useQueryContext() - const wallet = useWalletStore((s) => s.current) + const wallet = useWalletOnePointOh() const { handleCreateProposal } = useCreateProposal() const [formErrors, setFormErrors] = useState({}) const [creatingProposal, setCreatingProposal] = useState(false) - const [voteByCouncil, setVoteByCouncil] = useState(false) + const { voteByCouncil, shouldShowVoteByCouncilToggle, setVoteByCouncil } = useVoteByCouncilToggle(); const [selectedImage, setSelectedImage] = useState(null) const [imageFile, setImageFile] = useState(null) const [mintAuthority, setMintAuthority] = useState< @@ -178,11 +182,9 @@ const MetadataCreationModal = ({ : 'https://node1.bundlr.network', 'solana', wallet, - connection.cluster == 'devnet' - ? { - providerUrl: connection.current.rpcEndpoint, - } - : undefined + { + providerUrl: connection.current.rpcEndpoint, + } ) try { await bundlr.utils.getBundlerAddress('solana') @@ -265,15 +267,15 @@ const MetadataCreationModal = ({ const checkCurrentMetadataExist = async () => { if (form.mintAccount) { try { - const tokenMetaPubkey = await deprecated.Metadata.getPDA( - form.mintAccount.pubkey - ) - - const tokenMeta = await deprecated.Metadata.load( - connection.current, - tokenMetaPubkey - ) - if (tokenMeta) return true + const metaplex = new Metaplex(connection.current) + const metadataPDA = await metaplex + .nfts() + .pdas() + .metadata({ mint: form.mintAccount.pubkey }) + const tokenMetadata = await metaplex.nfts().findByMetadata({ + metadata: metadataPDA, + }) + if (tokenMetadata) return true return false } catch (e) { return false @@ -297,6 +299,7 @@ const MetadataCreationModal = ({ setShouldMakeSolTreasury(true) setPayerSolTreasury(undefined) } + // 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, setMintAuthority, @@ -398,13 +401,13 @@ const MetadataCreationModal = ({ } > - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - > + {shouldShowVoteByCouncilToggle && ( + { + setVoteByCouncil(!voteByCouncil) + }} + > )}
diff --git a/pages/dao/[symbol]/params/RealmConfigModal.tsx b/pages/dao/[symbol]/params/RealmConfigModal.tsx deleted file mode 100644 index fbd0e06632..0000000000 --- a/pages/dao/[symbol]/params/RealmConfigModal.tsx +++ /dev/null @@ -1,211 +0,0 @@ -import { parseMintNaturalAmountFromDecimalAsBN } from '@tools/sdk/units' -import Modal from '@components/Modal' -import Input from '@components/inputs/Input' -import VoteBySwitch from '../proposal/components/VoteBySwitch' -import Textarea from '@components/inputs/Textarea' -import { - createSetRealmConfig, - GoverningTokenConfigAccountArgs, - GoverningTokenType, - serializeInstructionToBase64, - tryGetRealmConfig, -} from '@solana/spl-governance' -import { validateInstruction } from '@utils/instructionTools' -import { getRealmCfgSchema } from '@utils/validations' -import useWalletStore from 'stores/useWalletStore' -import { PublicKey } from '@solana/web3.js' -import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes' -import { parseMintSupplyFraction } from '@utils/tokens' -import useCreateProposal from '@hooks/useCreateProposal' -import { InstructionDataWithHoldUpTime } from 'actions/createProposal' -import useQueryContext from '@hooks/useQueryContext' -import { useRouter } from 'next/router' -import { notify } from '@utils/notifications' -import useRealm from '@hooks/useRealm' -import { useState } from 'react' -import Button from '@components/Button' -import RealmConfigFormComponent, { - RealmConfigForm, -} from '../proposal/components/forms/RealmConfigFormComponent' -import { abbreviateAddress } from '@utils/formatting' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { DISABLED_VOTER_WEIGHT } from '@tools/constants' -import { isDisabledVoterWeight } from '@tools/governance/units' - -interface RealmConfigProposal extends RealmConfigForm { - title: string - description: string -} - -const RealmConfigModal = ({ closeProposalModal, isProposalModalOpen }) => { - const router = useRouter() - const { realm, mint, canChooseWhoVote, realmInfo, symbol } = useRealm() - const { assetAccounts } = useGovernanceAssets() - - const realmAuthorityGovernance = assetAccounts.find( - (x) => - x.governance.pubkey.toBase58() === realm?.account.authority?.toBase58() - ) - const { fmtUrlWithCluster } = useQueryContext() - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - const { handleCreateProposal } = useCreateProposal() - const defaultCfgTitle = 'Change realm config' - const [formErrors, setFormErrors] = useState({}) - const [voteByCouncil, setVoteByCouncil] = useState(false) - const [creatingProposal, setCreatingProposal] = useState(false) - const [form, setForm] = useState() - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form!, [propertyName]: value }) - } - const schema = getRealmCfgSchema({ form }) - const handleCreate = async () => { - const isValid = await validateInstruction({ schema, form, setFormErrors }) - let serializedInstruction = '' - if ( - isValid && - form!.governedAccount?.governance?.account && - wallet?.publicKey && - realm - ) { - setCreatingProposal(true) - const governance = form!.governedAccount.governance - - const mintAmount = isDisabledVoterWeight( - form!.minCommunityTokensToCreateGovernance - ) - ? DISABLED_VOTER_WEIGHT - : parseMintNaturalAmountFromDecimalAsBN( - form!.minCommunityTokensToCreateGovernance!, - mint!.decimals! - ) - - const realmConfig = await tryGetRealmConfig( - connection.current, - realmInfo!.programId, - realm.pubkey - ) - - const instruction = await createSetRealmConfig( - realmInfo!.programId, - realmInfo!.programVersion!, - realm.pubkey, - realm.account.authority!, - form?.removeCouncil ? undefined : realm?.account.config.councilMint, - parseMintSupplyFraction(form!.communityMintSupplyFactor.toString()), - mintAmount, - new GoverningTokenConfigAccountArgs({ - voterWeightAddin: form!.communityVoterWeightAddin - ? new PublicKey(form!.communityVoterWeightAddin) - : undefined, - maxVoterWeightAddin: form?.maxCommunityVoterWeightAddin - ? new PublicKey(form.maxCommunityVoterWeightAddin) - : undefined, - tokenType: GoverningTokenType.Liquid, - }), - undefined, - // Pass the payer only if RealmConfigAccount doens't exist and needs to be created - // TODO: If payer is passed then only the payer can execute the proposal - // We should use the DAO Wallet instead, and top it up if there is not enough SOL there - !realmConfig ? wallet.publicKey : undefined - ) - serializedInstruction = serializeInstructionToBase64(instruction) - const obj: UiInstruction = { - serializedInstruction: serializedInstruction, - isValid, - governance, - } - const instructionData = new InstructionDataWithHoldUpTime({ - instruction: obj, - governance, - }) - try { - const proposalAddress = await handleCreateProposal({ - title: form!.title ? form!.title : defaultCfgTitle, - description: form!.description ? form!.description : '', - voteByCouncil, - instructionsData: [instructionData], - governance: governance!, - }) - const url = fmtUrlWithCluster( - `/dao/${symbol}/proposal/${proposalAddress}` - ) - router.push(url) - } catch (ex) { - notify({ type: 'error', message: `${ex}` }) - } - setCreatingProposal(false) - } - } - return ( - -
-

- Change Realm Config:{' '} - {realmAuthorityGovernance && - abbreviateAddress(realmAuthorityGovernance!.governance.pubkey)} -

- - handleSetForm({ - value: evt.target.value, - propertyName: 'title', - }) - } - /> - - {canChooseWhoVote && ( - { - setVoteByCouncil(!voteByCouncil) - }} - > - )} - {realmAuthorityGovernance && ( - - )} -
-
- -
-
- ) -} - -export default RealmConfigModal diff --git a/pages/dao/[symbol]/params/SetRealmAuthorityModal.tsx b/pages/dao/[symbol]/params/SetRealmAuthorityModal.tsx index bb7118e0b1..d13eeb2807 100644 --- a/pages/dao/[symbol]/params/SetRealmAuthorityModal.tsx +++ b/pages/dao/[symbol]/params/SetRealmAuthorityModal.tsx @@ -8,11 +8,13 @@ import { withSetRealmAuthority, } from '@solana/spl-governance' import useRealm from '@hooks/useRealm' -import useWalletStore from 'stores/useWalletStore' import { Transaction, TransactionInstruction } from '@solana/web3.js' import { sendTransaction } from '@utils/send' import useGovernanceAssets from '@hooks/useGovernanceAssets' import GovernanceAccountSelect from '../proposal/components/GovernanceAccountSelect' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' const SetRealmAuthorityModal = ({ closeModal, @@ -21,10 +23,10 @@ const SetRealmAuthorityModal = ({ closeModal: () => void isOpen: boolean }) => { - const { realmInfo, realm } = useRealm() - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - const { fetchRealm, fetchAllRealms } = useWalletStore((s) => s.actions) + const realm = useRealmQuery().data?.result + const { realmInfo } = useRealm() + const wallet = useWalletOnePointOh() + const connection = useLegacyConnectionContext() const { governancesArray } = useGovernanceAssets() const [account, setAccount] = useState | null>( null @@ -52,8 +54,6 @@ const SetRealmAuthorityModal = ({ sendingMessage: `Setting authority`, successMessage: `Authority set`, }) - await fetchAllRealms(realmInfo!.programId) - await fetchRealm(realmInfo!.programId, realmInfo!.realmId) setSettingAuthority(false) closeModal() } diff --git a/pages/dao/[symbol]/params/components/AccountsView.tsx b/pages/dao/[symbol]/params/components/AccountsView.tsx index 65f2463e5f..46005357eb 100644 --- a/pages/dao/[symbol]/params/components/AccountsView.tsx +++ b/pages/dao/[symbol]/params/components/AccountsView.tsx @@ -2,6 +2,7 @@ import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools' import { AccountType } from '@utils/uiTypes/assets' import { AddressField } from '../index' import useGovernanceAssets from '@hooks/useGovernanceAssets' +import { fmtTokenAmount } from '@utils/formatting' const AccountsView = ({ activeGovernance, @@ -21,7 +22,7 @@ const AccountsView = ({ ) .map((x) => { const info = getTreasuryAccountItemInfoV2(x) - if (x.isToken || x.isSol || x.type === AccountType.AuxiliaryToken) { + if (x.isToken || x.isSol || x.type === AccountType.AUXILIARY_TOKEN) { return (
- + {x.extensions.mint?.account.supply && ( + + )} { - const { realm, mint, councilMint, ownVoterWeight } = useRealm() - +const ParamsView = ({ activeGovernance }) => { + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const councilMint = useRealmCouncilMintInfoQuery().data?.result + const { result: ownVoterWeight } = useLegacyVoterWeight() + const programVersion = useProgramVersion() const realmAccount = realm?.account const communityMint = realmAccount?.communityMint.toBase58() + const router = useRouter() + const { symbol } = router.query + const { fmtUrlWithCluster } = useQueryContext() const minCommunityTokensToCreateProposal = activeGovernance?.account?.config ?.minCommunityTokensToCreateProposal @@ -28,6 +40,19 @@ const ParamsView = ({ activeGovernance, openGovernanceProposalModal }) => { ) : 'calculating...' + const minCouncilTokensToCreateProposal = activeGovernance?.account?.config + ?.minCouncilTokensToCreateProposal + ? mint && + DISABLED_VOTER_WEIGHT.eq( + activeGovernance.account.config.minCouncilTokensToCreateProposal + ) + ? 'Disabled' + : fmtMintAmount( + mint, + activeGovernance?.account?.config?.minCouncilTokensToCreateProposal + ) + : 'calculating...' + return ( <> {activeGovernance && ( @@ -40,7 +65,7 @@ const ParamsView = ({ activeGovernance, openGovernanceProposalModal }) => { label="Max Voting Time" padding val={getFormattedStringFromDays( - activeGovernance.account.config.maxVotingTime / SECS_PER_DAY + activeGovernance.account.config.baseVotingTime / SECS_PER_DAY )} /> {communityMint && ( @@ -54,10 +79,7 @@ const ParamsView = ({ activeGovernance, openGovernanceProposalModal }) => { )} { padding val={activeGovernance.account.config.minInstructionHoldUpTime} /> - {/* NOT NEEDED RIGHT NOW */} - {/* */} - - + {(programVersion ?? DEFAULT_GOVERNANCE_PROGRAM_VERSION) >= 3 && ( + <> + + + + )} + {activeGovernance.account.config?.communityVoteThreshold?.value && ( + + )} + {activeGovernance.account.config?.councilVoteThreshold?.value && ( + + )} + {(programVersion ?? DEFAULT_GOVERNANCE_PROGRAM_VERSION) >= 3 ? ( + <> + + + + ) : ( + + )} +
-

Top Voters

+

Number of Voters: {voterCount}

+
+

Top Voters

+
setHighlighted(undefined)} > - +
+ + {/* when hovering over a top voter, ProposalVoterNftChart shows he/her NFTs when isNftMode */} + {isNftMode ? ( + x.key === highlighted)?.voteType + : undefined + } + /> + ) : undefined} +
- + {isMulti ? ( +
+

Vote Result

+ +
+ ) : ( + + )} { const { realmInfo, symbol } = useRealm() - const { proposal, descriptionLink, governance } = useProposal() + const proposal = useRouteProposalQuery().data?.result + const governance = useProposalGovernanceQuery().data?.result + const tor = useTokenOwnerRecordByPubkeyQuery(proposal?.account.tokenOwnerRecord).data?.result + const { connection } = useConnection() + const descriptionLink = proposal?.account.descriptionLink + const allowDiscussion = realmInfo?.allowDiscussion ?? true + const isMulti = + proposal?.account.voteType !== VoteType.SINGLE_CHOICE && + proposal?.account.accountType === GovernanceAccountType.ProposalV2 + + const [openCalendarModal, setOpenCalendarModal] = useState(false) const [description, setDescription] = useState('') - const { yesVoteProgress, yesVotesRequired } = useProposalVotes( - proposal?.account - ) - const currentWallet = useWalletStore((s) => s.current) + const voteData = useProposalVotes(proposal?.account) + const currentWallet = useWalletOnePointOh() const showResults = proposal && proposal.account.state !== ProposalState.Cancelled && proposal.account.state !== ProposalState.Draft - const votePassed = - proposal && - (proposal.account.state === ProposalState.Completed || - proposal.account.state === ProposalState.Executing || - proposal.account.state === ProposalState.SigningOff || - proposal.account.state === ProposalState.Succeeded || - proposal.account.state === ProposalState.ExecutingWithErrors) - const votingEnded = !!governance && !!proposal && @@ -67,6 +81,10 @@ const Proposal = () => { } }, [descriptionLink]) + const proposedBy = + proposal && + tor?.account.governingTokenOwner.toBase58() + const { fmtUrlWithCluster } = useQueryContext() const showTokenBalance = proposal ? proposal.account.state === ProposalState.Draft || @@ -79,8 +97,21 @@ const Proposal = () => { proposal.account.state === ProposalState.Executing || proposal.account.state === ProposalState.ExecutingWithErrors) + const votingTimeEnds = + proposal?.account.signingOffAt && + governance && + proposal.account.signingOffAt.toNumber() + + governance.account.config.baseVotingTime + + const coolOffTimeEnds = + proposal?.account.signingOffAt && + governance && + proposal.account.signingOffAt.toNumber() + + governance.account.config.baseVotingTime + + governance.account.config.votingCoolOffTime + return ( - )} - - - {isTwoCol && } + {proposal.account && ( + + )} + + {isTwoCol && allowDiscussion && } ) : ( <> @@ -134,36 +177,119 @@ const Proposal = () => {
+ {showTokenBalance && } {showResults ? (
{proposal?.account.state === ProposalState.Voting ? (
-

Voting Now

+

+ Voting Now + setOpenCalendarModal(true)} + className="w-5" + > + {openCalendarModal && ( + setOpenCalendarModal(false)} + isOpen={openCalendarModal} + > +
+

Remind me about voting time end

+ {votingTimeEnds && ( + + )} +
+ {governance?.account.config.votingCoolOffTime && ( +
+

Remind me about cool off time end

+ {coolOffTimeEnds && ( + + )} +
+ )} +
+ )} +

) : (

Results

)} - {proposal?.account.state === ProposalState.Voting ? ( -
- -
+ {proposal?.account.state === ProposalState.Voting && !isMulti ? ( + <> +
+ +
+ {voteData._programVersion !== undefined && + // @asktree: here is some typescript gore because typescript doesn't know that a number being > 3 means it isn't 1 or 2 + voteData._programVersion !== 1 && + voteData._programVersion !== 2 && + voteData.veto !== undefined && + (voteData.veto.voteProgress ?? 0) > 0 ? ( +
+ +
+ ) : undefined} + ) : (
- +
)} - + + {isMulti ? ( + + ) : ( + + )} {proposal && (
{
) : null} - + {proposal && currentWallet && showProposalExecution && ( )} - {!isTwoCol && proposal && ( + {!isTwoCol && proposal && allowDiscussion && (
diff --git a/pages/dao/[symbol]/proposal/components/DryRunInstructionBtn.tsx b/pages/dao/[symbol]/proposal/components/DryRunInstructionBtn.tsx index e3474487c9..207ac30925 100644 --- a/pages/dao/[symbol]/proposal/components/DryRunInstructionBtn.tsx +++ b/pages/dao/[symbol]/proposal/components/DryRunInstructionBtn.tsx @@ -2,13 +2,14 @@ import Button, { LinkButton, SecondaryButton } from '@components/Button' import { getExplorerInspectorUrl } from '@components/explorer/tools' import Loading from '@components/Loading' import Modal from '@components/Modal' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' import { getInstructionDataFromBase64 } from '@solana/spl-governance' import { SimulatedTransactionResponse, Transaction } from '@solana/web3.js' import { notify } from '@utils/notifications' import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes' import { dryRunInstruction } from 'actions/dryRunInstruction' import React, { useState } from 'react' -import useWalletStore from 'stores/useWalletStore' const DryRunInstructionBtn = ({ getInstructionDataFcn, @@ -17,8 +18,8 @@ const DryRunInstructionBtn = ({ getInstructionDataFcn: (() => Promise) | undefined btnClassNames: string }) => { - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() const [isPending, setIsPending] = useState(false) const [result, setResult] = useState<{ response: SimulatedTransactionResponse @@ -26,10 +27,10 @@ const DryRunInstructionBtn = ({ } | null>(null) const [isOpen, setIsOpen] = useState(false) - const onInspect = () => { + const onInspect = async () => { if (result) { - const inspectUrl = getExplorerInspectorUrl( - connection.endpoint, + const inspectUrl = await getExplorerInspectorUrl( + connection, result.transaction ) window.open(inspectUrl, '_blank') @@ -103,7 +104,7 @@ const DryRunInstructionBtn = ({ {result?.response && ( - +

{result?.response.err ? 'Simulation error' diff --git a/pages/dao/[symbol]/proposal/components/GovernanceAccountSelect.tsx b/pages/dao/[symbol]/proposal/components/GovernanceAccountSelect.tsx index 28fa9f828f..b6df24eb84 100644 --- a/pages/dao/[symbol]/proposal/components/GovernanceAccountSelect.tsx +++ b/pages/dao/[symbol]/proposal/components/GovernanceAccountSelect.tsx @@ -10,7 +10,7 @@ const GovernanceAccountSelect = ({ governanceAccounts = [], label, noMaxWidth, - autoselectFirst = true, + autoSelectFirst = true, }: { onChange value @@ -18,15 +18,16 @@ const GovernanceAccountSelect = ({ governanceAccounts: ProgramAccount[] label? noMaxWidth?: boolean - autoselectFirst?: boolean + autoSelectFirst?: boolean }) => { useEffect(() => { - if (governanceAccounts.length == 1 && autoselectFirst) { + if (governanceAccounts.length == 1 && autoSelectFirst) { //wait for microtask queue to be empty setTimeout(() => { onChange(governanceAccounts[0]) }) } + // 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 }, [JSON.stringify(governanceAccounts)]) return ( - {governedAccounts - .filter((x) => - !shouldBeGoverned - ? !shouldBeGoverned - : x?.governance?.pubkey.toBase58() === - governance?.pubkey?.toBase58() - ) - .map((acc) => { - return ( - - {getLabel(acc)} - - ) - })} - +
+ + {value && walletInfo && ( +
+
+ {walletInfo.rules.common?.maxVotingTime && ( + } + label="Max Voting Time" + value={durationStr(walletInfo.rules.common.maxVotingTime, true)} + /> + )} + {voteByCouncil && exists(walletInfo.rules.council) ? ( + } + label="Council Vote Threshold" + value={walletInfo.rules.council.voteThresholdPercentage + '%'} + /> + ) : !voteByCouncil && exists(walletInfo.rules.community) ? ( + } + label="Community Vote Threshold" + value={walletInfo.rules.community.voteThresholdPercentage + '%'} + /> + ) : null} + {voteByCouncil && exists(walletInfo.rules.council) ? ( + } + label="Council Vote Tipping" + value={voteTippingText(walletInfo.rules.council.voteTipping)} + /> + ) : !voteByCouncil && exists(walletInfo.rules.community) ? ( + } + label="Community Vote Tipping" + value={voteTippingText(walletInfo.rules.community.voteTipping)} + /> + ) : null} +
+
+ )} +
) } diff --git a/pages/dao/[symbol]/proposal/components/MinimumApprovalThreshold.tsx b/pages/dao/[symbol]/proposal/components/MinimumApprovalThreshold.tsx deleted file mode 100644 index 41f50c9899..0000000000 --- a/pages/dao/[symbol]/proposal/components/MinimumApprovalThreshold.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import ProgressBar from '@components/ProgressBar' - -import { Governance } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import React from 'react' - -const MinimumApprovalThreshold = ({ - governance, -}: { - governance: ProgramAccount | null -}) => { - const info = governance?.account - // const info = { config: { voteThresholdPercentage: { value: 50 } } } - return info ? ( - - ) : null -} - -export default MinimumApprovalThreshold diff --git a/pages/dao/[symbol]/proposal/components/MyProposalsBtn.tsx b/pages/dao/[symbol]/proposal/components/MyProposalsBtn.tsx index e56300be12..022deb0494 100644 --- a/pages/dao/[symbol]/proposal/components/MyProposalsBtn.tsx +++ b/pages/dao/[symbol]/proposal/components/MyProposalsBtn.tsx @@ -1,12 +1,16 @@ import useRealm from '@hooks/useRealm' -import React, { useEffect, useMemo, useState } from 'react' -import useWalletStore from 'stores/useWalletStore' +import { useCallback, useEffect, useMemo, useState } from 'react' import { + getProposalDepositsByDepositPayer, + getVoteRecord, + getVoteRecordAddress, ProgramAccount, Proposal, + ProposalDeposit, ProposalState, withCancelProposal, withFinalizeVote, + withRefundProposalDeposit, withRelinquishVote, } from '@solana/spl-governance' import { Transaction, TransactionInstruction } from '@solana/web3.js' @@ -16,49 +20,87 @@ import useGovernanceAssets from '@hooks/useGovernanceAssets' import dayjs from 'dayjs' import { notify } from '@utils/notifications' import Loading from '@components/Loading' -import useVotePluginsClientStore from 'stores/useVotePluginsClientStore' -import useNftPluginStore from 'NftVotePlugin/store/nftPluginStore' -import { sleep } from '@project-serum/common' -import { NftVoterClient } from '@solana/governance-program-library' import { chunks } from '@utils/helpers' import { sendSignedTransaction } from '@utils/send' -import { getRegistrarPDA, getVoterWeightRecord } from '@utils/plugin/accounts' import { - sendTransactionsV2, + sendTransactionsV3, SequenceType, - transactionInstructionsToTypedInstructionsSets, + txBatchesToInstructionSetWithSigners, } from '@utils/sendTransactions' +import useQueryContext from '@hooks/useQueryContext' +import { useMaxVoteRecord } from '@hooks/useMaxVoteRecord' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useAddressQuery_CommunityTokenOwner } from '@hooks/queries/addresses/tokenOwnerRecord' +import { + tokenOwnerRecordQueryKeys, + useUserCommunityTokenOwnerRecord, + useUserCouncilTokenOwnerRecord, +} from '@hooks/queries/tokenOwnerRecord' +import { useRealmQuery } from '@hooks/queries/realm' +import { + useVoteRecordsByOwnerQuery, + voteRecordQueryKeys, +} from '@hooks/queries/voteRecord' +import useProgramVersion from '@hooks/useProgramVersion' +import { DEFAULT_GOVERNANCE_PROGRAM_VERSION } from '@components/instructions/tools' +import { useConnection } from '@solana/wallet-adapter-react' +import { + proposalQueryKeys, + useRealmProposalsQuery, +} from '@hooks/queries/proposal' +import queryClient from '@hooks/queries/queryClient' +import { getFeeEstimate } from '@tools/feeEstimate' +import { createComputeBudgetIx } from '@blockworks-foundation/mango-v4' +import {useVotingClients} from "@hooks/useVotingClients"; +import {useNftClient} from "../../../../../VoterWeightPlugins/useNftClient"; const MyProposalsBn = () => { const [modalIsOpen, setModalIsOpen] = useState(false) - const wallet = useWalletStore((s) => s.current) - const connected = useWalletStore((s) => s.connected) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected const [isLoading, setIsLoading] = useState(false) const { governancesArray } = useGovernanceAssets() - const { current: connection } = useWalletStore((s) => s.connection) - const ownVoteRecordsByProposal = useWalletStore( - (s) => s.ownVoteRecordsByProposal - ) + const { connection } = useConnection() + const myVoteRecords = useVoteRecordsByOwnerQuery( + wallet?.publicKey ?? undefined + ).data + + const ownVoteRecordsByProposal = useMemo(() => { + return myVoteRecords !== undefined + ? (Object.fromEntries( + myVoteRecords.map((x) => [x.account.proposal.toString(), x] as const) + ) as Record) + : undefined + }, [myVoteRecords]) + const [ownNftVoteRecords, setOwnNftVoteRecords] = useState([]) const ownNftVoteRecordsFilterd = ownNftVoteRecords - const maxVoterWeight = - useNftPluginStore((s) => s.state.maxVoteRecord)?.pubkey || undefined - const { realm, programId } = useWalletStore((s) => s.selectedRealm) - const { refetchProposals } = useWalletStore((s) => s.actions) - const client = useVotePluginsClientStore( - (s) => s.state.currentRealmVotingClient - ) - const { - proposals, - ownTokenRecord, - ownCouncilTokenRecord, - realmInfo, - isNftMode, - } = useRealm() + + const { data: tokenOwnerRecord } = useAddressQuery_CommunityTokenOwner() + + const maxVoterWeight = useMaxVoteRecord()?.pubkey || undefined + const realm = useRealmQuery().data?.result + const programId = realm?.owner + + const programVersion = + useProgramVersion() ?? DEFAULT_GOVERNANCE_PROGRAM_VERSION + + const votingClients = useVotingClients(); + const { nftClient } = useNftClient(); + + const [ + proposalsWithDepositedTokens, + setProposalsWithDepositedTokens, + ] = useState[]>([]) + const ownTokenRecord = useUserCommunityTokenOwnerRecord().data?.result + const ownCouncilTokenRecord = useUserCouncilTokenOwnerRecord().data?.result + + const { realmInfo, isNftMode } = useRealm() + const { data: proposals } = useRealmProposalsQuery() const myProposals = useMemo( () => connected - ? Object.values(proposals).filter( + ? proposals?.filter( (p) => p.account.tokenOwnerRecord.toBase58() === ownTokenRecord?.pubkey.toBase58() || @@ -66,13 +108,18 @@ const MyProposalsBn = () => { ownCouncilTokenRecord?.pubkey.toBase58() ) : [], - [proposals, ownVoteRecordsByProposal, connected] + [ + connected, + proposals, + ownTokenRecord?.pubkey, + ownCouncilTokenRecord?.pubkey, + ] ) - const drafts = myProposals.filter((x) => { + const drafts = myProposals?.filter((x) => { return x.account.state === ProposalState.Draft }) - const notfinalized = myProposals.filter((x) => { - const governance = governancesArray.find( + const notfinalized = myProposals?.filter((x) => { + const governance = governancesArray?.find( (gov) => gov.pubkey.toBase58() === x.account.governance.toBase58() ) const now = dayjs().unix() @@ -81,7 +128,7 @@ const MyProposalsBn = () => { ? 0 // If vote is finalized then set the timestamp to 0 to make it expired : x.account.votingAt && governance ? x.account.votingAt.toNumber() + - governance.account.config.maxVotingTime + governance.account.config.baseVotingTime : undefined : undefined return ( @@ -91,7 +138,7 @@ const MyProposalsBn = () => { now > timestamp ) }) - const unReleased = [...Object.values(proposals)].filter( + const unReleased = proposals?.filter( (x) => (x.account.state === ProposalState.Completed || x.account.state === ProposalState.Executing || @@ -99,12 +146,13 @@ const MyProposalsBn = () => { x.account.state === ProposalState.Succeeded || x.account.state === ProposalState.ExecutingWithErrors || x.account.state === ProposalState.Defeated || + x.account.state === ProposalState.Vetoed || x.account.state === ProposalState.Cancelled) && - ownVoteRecordsByProposal[x.pubkey.toBase58()] && - !ownVoteRecordsByProposal[x.pubkey.toBase58()]?.account.isRelinquished + ownVoteRecordsByProposal?.[x.pubkey.toBase58()] && + !ownVoteRecordsByProposal?.[x.pubkey.toBase58()]?.account.isRelinquished ) - const createdVoting = myProposals.filter((x) => { + const createdVoting = myProposals?.filter((x) => { return ( x.account.state === ProposalState.Voting && !x.account.isVoteFinalized() ) @@ -117,23 +165,25 @@ const MyProposalsBn = () => { if (!wallet || !programId || !realm) return setIsLoading(true) try { - const { - blockhash: recentBlockhash, - } = await connection.getLatestBlockhash() + const [{ blockhash: recentBlockhash }, fee] = await Promise.all([ + connection.getLatestBlockhash(), + getFeeEstimate(connection), + ]) const transactions: Transaction[] = [] + const instructions: TransactionInstruction[] = [] for (let i = 0; i < proposalsArray.length; i++) { const proposal = proposalsArray[i] - const instructions: TransactionInstruction[] = [] - await withInstruction(instructions, proposal) - + } + const instructionChunks = chunks(instructions, 8) + for (const chunk of instructionChunks) { const transaction = new Transaction({ recentBlockhash, feePayer: wallet.publicKey!, }) - transaction.add(...instructions) + transaction.add(...[createComputeBudgetIx(fee), ...chunk]) transaction.recentBlockhash = recentBlockhash transaction.setSigners( // fee payed by the wallet owner @@ -147,21 +197,31 @@ const MyProposalsBn = () => { sendSignedTransaction({ signedTransaction: transaction, connection }) ) ) - await sleep(500) - await refetchProposals() + queryClient.invalidateQueries({ + queryKey: proposalQueryKeys.all(connection.rpcEndpoint), + }) + queryClient.invalidateQueries({ + queryKey: tokenOwnerRecordQueryKeys.all(connection.rpcEndpoint), + }) + queryClient.invalidateQueries({ + queryKey: voteRecordQueryKeys.all( + connection.rpcEndpoint.includes('devnet') ? 'devnet' : 'mainnet' + ), + }) } catch (e) { console.log(e) - notify({ type: 'error', message: 'Something wnet wrong' }) + notify({ type: 'error', message: `Something went wrong ${e}` }) } setIsLoading(false) } const cleanDrafts = (toIndex = null) => { + if (!drafts) throw new Error() const withInstruction = (instructions, proposal) => { return withCancelProposal( instructions, realm!.owner!, - realmInfo!.programVersion!, + programVersion, realm!.pubkey!, proposal!.account.governance, proposal!.pubkey, @@ -172,17 +232,49 @@ const MyProposalsBn = () => { cleanSelected(drafts.slice(0, toIndex || drafts.length), withInstruction) } const releaseAllTokens = (toIndex = null) => { + if (unReleased === undefined) throw new Error() const withInstruction = async ( instructions, proposal: ProgramAccount ) => { - const voterTokenRecord = + let voterTokenRecord = proposal.account.governingTokenMint.toBase58() === realm?.account.communityMint.toBase58() ? ownTokenRecord : ownCouncilTokenRecord + const role = proposal.account.governingTokenMint.toBase58() === + realm?.account.communityMint.toBase58() + ? 'community' + : 'council' const governanceAuthority = wallet!.publicKey! const beneficiary = wallet!.publicKey! + + let voteRecordPk = await getVoteRecordAddress( + realm!.owner, + proposal.pubkey, + voterTokenRecord!.pubkey + ) + + let governingTokenMint = proposal.account.governingTokenMint + + try { + await getVoteRecord(connection, voteRecordPk) + } catch { + voterTokenRecord = role === "community" ? + ownCouncilTokenRecord : + ownTokenRecord + + voteRecordPk = await getVoteRecordAddress( + realm!.owner, + proposal.pubkey, + voterTokenRecord!.pubkey + ) + + governingTokenMint = role === "community" && realm?.account.config.councilMint ? + realm.account.config.councilMint : + realm?.account.communityMint! + } + const inst = await withRelinquishVote( instructions, realm!.owner, @@ -191,15 +283,16 @@ const MyProposalsBn = () => { proposal.account.governance, proposal.pubkey, voterTokenRecord!.pubkey, - proposal.account.governingTokenMint, - ownVoteRecordsByProposal[proposal.pubkey.toBase58()].pubkey, + governingTokenMint, + voteRecordPk, governanceAuthority, beneficiary ) - await client.withRelinquishVote( + await votingClients(role).withRelinquishVote( instructions, proposal, - ownVoteRecordsByProposal[proposal.pubkey.toBase58()].pubkey + voteRecordPk, + voterTokenRecord!.pubkey ) return inst } @@ -209,6 +302,7 @@ const MyProposalsBn = () => { ) } const finalizeAll = (toIndex = null) => { + if (notfinalized === undefined) throw new Error() const withInstruction = ( instructions, proposal: ProgramAccount @@ -216,8 +310,8 @@ const MyProposalsBn = () => { return withFinalizeVote( instructions, realm!.owner, - realmInfo!.programVersion!, - realm!.pubkey!, + programVersion, + realm!.pubkey, proposal.account.governance, proposal.pubkey, proposal.account.tokenOwnerRecord, @@ -231,33 +325,34 @@ const MyProposalsBn = () => { ) } const releaseNfts = async (count: number | null = null) => { + if (proposals === undefined) throw new Error() + if (!realm) throw new Error() + if (!wallet?.publicKey) throw new Error('no wallet') + + if (!nftClient) throw new Error('no nft client') + setIsLoading(true) const instructions: TransactionInstruction[] = [] - const { registrar } = await getRegistrarPDA( - realm!.pubkey, - realm!.account.communityMint, - client.client!.program.programId - ) - const { voterWeightPk } = await getVoterWeightRecord( - realm!.pubkey, - realm!.account.communityMint, - wallet!.publicKey!, - client.client!.program.programId - ) + const { registrar } = nftClient.getRegistrarPDA(realm.pubkey, realm.account.communityMint); + const { voterWeightPk } = await nftClient.getVoterWeightRecordPDA(realm.pubkey, realm.account.communityMint, wallet.publicKey); + const nfts = ownNftVoteRecordsFilterd.slice( 0, count ? count : ownNftVoteRecordsFilterd.length ) for (const i of nfts) { - const relinquishNftVoteIx = await (client.client as NftVoterClient).program.methods + const proposal = proposals.find((p) => + p.pubkey.equals(i.account.proposal) + ) + const relinquishNftVoteIx = await nftClient.program.methods .relinquishNftVote() .accounts({ registrar, voterWeightRecord: voterWeightPk, - governance: - proposals[i.account.proposal.toBase58()].account.governance, + governance: proposal?.account.governance, proposal: i.account.proposal, - governingTokenOwner: wallet!.publicKey!, + voterTokenOwnerRecord: tokenOwnerRecord, + voterAuthority: wallet!.publicKey!, voteRecord: i.publicKey, beneficiary: wallet!.publicKey!, }) @@ -268,19 +363,20 @@ const MyProposalsBn = () => { instructions.push(relinquishNftVoteIx) } try { - const insertChunks = chunks(instructions, 10) - const signerChunks = Array(insertChunks.length).fill([]) - await sendTransactionsV2({ + const insertChunks = chunks(instructions, 5).map((txBatch, batchIdx) => { + return { + instructionsSet: txBatchesToInstructionSetWithSigners( + txBatch, + [], + batchIdx + ), + sequenceType: SequenceType.Parallel, + } + }) + await sendTransactionsV3({ connection, - showUiComponent: true, wallet: wallet!, - signersSet: [...signerChunks], - TransactionInstructions: insertChunks.map((x) => - transactionInstructionsToTypedInstructionsSets( - x, - SequenceType.Parallel - ) - ), + transactionInstructions: insertChunks, }) setIsLoading(false) getNftsVoteRecord() @@ -289,8 +385,9 @@ const MyProposalsBn = () => { console.log(e) } } - const getNftsVoteRecord = async () => { - const nftClient = client.client as NftVoterClient + + const getNftsVoteRecord = useCallback(async () => { + if (!nftClient) throw new Error('no nft client'); const nftVoteRecords = await nftClient.program.account.nftVoteRecord.all([ { memcmp: { @@ -300,21 +397,89 @@ const MyProposalsBn = () => { }, ]) - const nftVoteRecordsFiltered = nftVoteRecords.filter( - (x) => - proposals[x.account.proposal.toBase58()] && - proposals[ - x.account.proposal.toBase58() - ].account.governingTokenMint.toBase58() === + const nftVoteRecordsFiltered = nftVoteRecords.filter((x) => { + const proposal = proposals?.find((p) => + p.pubkey.equals(x.account.proposal) + ) + + return ( + proposal && + proposal.account.governingTokenMint.toBase58() === realm?.account.communityMint.toBase58() - ) + ) + }) setOwnNftVoteRecords(nftVoteRecordsFiltered) + }, [nftClient, proposals, realm?.account.communityMint, wallet]) + + const releaseSol = async () => { + const instructions: TransactionInstruction[] = [] + for (const proposalDeposit of proposalsWithDepositedTokens) { + await withRefundProposalDeposit( + instructions, + programId!, + programVersion, + proposalDeposit.account.proposal, + proposalDeposit.account.depositPayer + ) + } + await sendTransactionsV3({ + connection, + wallet: wallet!, + transactionInstructions: instructions.map((x, idx) => ({ + instructionsSet: txBatchesToInstructionSetWithSigners([x], [], idx), + sequenceType: SequenceType.Parallel, + })), + }) + getSolDeposits() } + const getSolDeposits = useCallback(async () => { + const solDeposits = await getProposalDepositsByDepositPayer( + connection, + realm!.owner, + wallet!.publicKey! + ) + const filterdSolDeposits = solDeposits.filter((x) => { + const proposal = proposals?.find((p) => + p.pubkey.equals(x.account.proposal) + ) + const proposalState = proposal?.account.state + return ( + proposalState !== ProposalState.Draft && + proposalState !== ProposalState.Voting && + proposalState !== ProposalState.SigningOff + ) + }) + setProposalsWithDepositedTokens(filterdSolDeposits) + }, [connection, proposals, realm, wallet]) useEffect(() => { - if (wallet?.publicKey && isNftMode && client.client && modalIsOpen) { + if ( + wallet?.publicKey && + modalIsOpen && + realmInfo?.programVersion && + realmInfo?.programVersion > 2 && + proposals?.length + ) { + getSolDeposits() + } + }, [ + getSolDeposits, + modalIsOpen, + proposals, + realmInfo, + realmInfo?.programVersion, + wallet?.publicKey, + ]) + useEffect(() => { + if (wallet?.publicKey && isNftMode && nftClient && modalIsOpen) { getNftsVoteRecord() } - }, [client.clientType, isNftMode, wallet?.publicKey?.toBase58(), modalIsOpen]) + }, [ + nftClient, + getNftsVoteRecord, + isNftMode, + modalIsOpen, + wallet?.publicKey, + ]) return ( <> @@ -333,32 +498,42 @@ const MyProposalsBn = () => {

Your proposals {isLoading && }

+ {proposalsWithDepositedTokens.length !== 0 && ( +
+
+ You have some sol to be released from proposals deposits +
+ +
+ )} null} btnName="" - proposals={createdVoting} + proposals={createdVoting ?? []} isLoading={isLoading} > {isNftMode && ownNftVoteRecordsFilterd.length !== 0 && ( @@ -406,6 +581,8 @@ const ProposalList = ({ proposals: ProgramAccount[] isLoading: boolean }) => { + const { fmtUrlWithCluster } = useQueryContext() + const { symbol } = useRealm() return ( <> {' '} @@ -439,7 +616,16 @@ const ProposalList = ({ className="text-xs border-fgd-4 border px-3 py-2 mb-3 rounded-lg" key={x.pubkey.toBase58()} > - {x.account.name} +
+ {x.account.name} +

))}
diff --git a/pages/dao/[symbol]/proposal/components/NewProposalBtn.tsx b/pages/dao/[symbol]/proposal/components/NewProposalBtn.tsx index 851bce8452..5c1e0bbf93 100644 --- a/pages/dao/[symbol]/proposal/components/NewProposalBtn.tsx +++ b/pages/dao/[symbol]/proposal/components/NewProposalBtn.tsx @@ -2,41 +2,47 @@ import Link from 'next/link' import { PlusCircleIcon } from '@heroicons/react/outline' import useQueryContext from '@hooks/useQueryContext' import useRealm from '@hooks/useRealm' -import React from 'react' -import useWalletStore from 'stores/useWalletStore' import Tooltip from '@components/Tooltip' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import { useRealmVoterWeightPlugins } from '@hooks/useRealmVoterWeightPlugins' const NewProposalBtn = () => { const { fmtUrlWithCluster } = useQueryContext() - const connected = useWalletStore((s) => s.connected) + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected + const realm = useRealmQuery().data?.result + // const { result: ownVoterWeight } = useLegacyVoterWeight() + const { + ownVoterWeight: communityOwnVoterWeight, + } = useRealmVoterWeightPlugins('community') + const { + isReady, + ownVoterWeight: councilOwnVoterWeight, + } = useRealmVoterWeightPlugins('council') const { symbol, - realm, - governances, - ownVoterWeight, toManyCommunityOutstandingProposalsForUser, toManyCouncilOutstandingProposalsForUse, } = useRealm() - const governanceItems = Object.values(governances) + const hasVotingPower = + (communityOwnVoterWeight && communityOwnVoterWeight.value?.gtn(0)) || + (councilOwnVoterWeight && councilOwnVoterWeight.value?.gtn(0)) const canCreateProposal = realm && - governanceItems.some((g) => - ownVoterWeight.canCreateProposal(g.account.config) - ) && + hasVotingPower && !toManyCommunityOutstandingProposalsForUser && !toManyCouncilOutstandingProposalsForUse const tooltipContent = !connected ? 'Connect your wallet to create new proposal' - : governanceItems.length === 0 + : isReady && !communityOwnVoterWeight && !councilOwnVoterWeight ? 'There is no governance configuration to create a new proposal' - : !governanceItems.some((g) => - ownVoterWeight.canCreateProposal(g.account.config) - ) + : !hasVotingPower ? "You don't have enough governance power to create a new proposal" : toManyCommunityOutstandingProposalsForUser ? 'Too many community outstanding proposals. You need to finalize them before creating a new one.' diff --git a/pages/dao/[symbol]/proposal/components/StakeAccountSelect.tsx b/pages/dao/[symbol]/proposal/components/StakeAccountSelect.tsx index 0e5a530f83..4dec2e3573 100644 --- a/pages/dao/[symbol]/proposal/components/StakeAccountSelect.tsx +++ b/pages/dao/[symbol]/proposal/components/StakeAccountSelect.tsx @@ -1,11 +1,11 @@ import Select from '@components/inputs/Select' import { Governance } from '@solana/spl-governance' import { ProgramAccount } from '@solana/spl-governance' -import React, { useEffect } from 'react' -import { web3 } from '@project-serum/anchor' +import { useEffect } from 'react' +import { web3 } from '@coral-xyz/anchor' import { StakeAccount, StakeState } from '@utils/uiTypes/assets' -export function getStakeAccountLabelInfo(acc: StakeAccount | undefined) { +function getStakeAccountLabelInfo(acc: StakeAccount | undefined) { let stakeAccount = '' let accountStatus = '' let delegatedValidator = '' @@ -34,7 +34,7 @@ const StakeAccountSelect = ({ stakeAccounts = [], label, noMaxWidth, - autoselectFirst = true, + autoSelectFirst = true, }: { onChange value @@ -44,7 +44,7 @@ const StakeAccountSelect = ({ governance?: ProgramAccount | null | undefined label? noMaxWidth?: boolean - autoselectFirst?: boolean + autoSelectFirst?: boolean }) => { function getLabel(value: StakeAccount) { if (value) { @@ -81,12 +81,13 @@ const StakeAccountSelect = ({ ) } useEffect(() => { - if (stakeAccounts.length == 1 && autoselectFirst) { + if (stakeAccounts.length == 1 && autoSelectFirst) { //wait for microtask queue to be empty setTimeout(() => { onChange(stakeAccounts[0]) }) } + // 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 }, [JSON.stringify(stakeAccounts)]) return ( + + ) +} + +export default BurnTokens diff --git a/pages/dao/[symbol]/proposal/components/instructions/Castle/CastleDeposit.tsx b/pages/dao/[symbol]/proposal/components/instructions/Castle/CastleDeposit.tsx deleted file mode 100644 index b012e2ac2d..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Castle/CastleDeposit.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import React, { useContext, useEffect, useState } from 'react' -import Input from '@components/inputs/Input' -import useRealm from '@hooks/useRealm' -import { getMintMinAmountAsDecimal } from '@tools/sdk/units' -import { PublicKey } from '@solana/web3.js' -import { precision } from '@utils/formatting' -import useWalletStore from 'stores/useWalletStore' -import { - CastleDepositForm, - UiInstruction, -} from '@utils/uiTypes/proposalCreationTypes' -import { NewProposalContext } from '../../../new' -import { getCastleDepositSchema } from '@utils/validations' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { Governance } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import GovernedAccountSelect from '../../GovernedAccountSelect' -import Select from '@components/inputs/Select' -import { - Clusters, - DeploymentEnvs, - VaultConfig, -} from '@castlefinance/vault-core' -import { - getCastleVaults, - getCastleDepositInstruction, -} from '@utils/instructions/Castle' - -const CastleDeposit = ({ - index, - governance, -}: { - index: number - governance: ProgramAccount | null -}) => { - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const { realmInfo } = useRealm() - const { governedTokenAccountsWithoutNfts } = useGovernanceAssets() - const shouldBeGoverned = index !== 0 && governance - const programId: PublicKey | undefined = realmInfo?.programId - - // Store CastleDepositForm state - const [form, setForm] = useState({ - amount: undefined, - governedTokenAccount: undefined, - castleVaultId: '', - programId: programId?.toString(), - mintInfo: undefined, - }) - - const [castleVaults, setCastleVaults] = useState< - VaultConfig[] | null - >(null) - - const [governedAccount, setGovernedAccount] = useState< - ProgramAccount | undefined - >(undefined) - - const [formErrors, setFormErrors] = useState({}) - - const mintMinAmount = form.mintInfo - ? getMintMinAmountAsDecimal(form.mintInfo) - : 1 - - const currentPrecision = precision(mintMinAmount) - const { handleSetInstructions } = useContext(NewProposalContext) - - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - - const setMintInfo = (value) => { - setForm({ ...form, mintInfo: value }) - } - - const setAmount = (event) => { - const value = event.target.value - handleSetForm({ - value: value, - propertyName: 'amount', - }) - } - - const validateAmountOnBlur = () => { - const value = form.amount - - handleSetForm({ - value: parseFloat( - Math.max( - Number(mintMinAmount), - Math.min(Number(Number.MAX_SAFE_INTEGER), Number(value)) - ).toFixed(currentPrecision) - ), - propertyName: 'amount', - }) - } - - async function getInstruction(): Promise { - return await getCastleDepositInstruction({ - schema, - form, - amount: form.amount ?? 0, - programId, - connection, - wallet, - setFormErrors, - }) - } - - // Grab Castle vault information from config server - useEffect(() => { - const getCastleConfig = async () => { - const vaults = (await getCastleVaults()).filter((v) => - connection.cluster == 'mainnet' - ? v.cluster == Clusters.mainnetBeta - : v.cluster == Clusters.devnet - ) - console.log(vaults) - setCastleVaults(vaults) - } - getCastleConfig() - }, [connection.cluster]) - - useEffect(() => { - handleSetForm({ - propertyName: 'programId', - value: programId?.toString(), - }) - }, [realmInfo?.programId]) - - useEffect(() => { - handleSetInstructions( - { governedAccount: governedAccount, getInstruction }, - index - ) - }, [form]) - - useEffect(() => { - setGovernedAccount(form.governedTokenAccount?.governance) - setMintInfo(form.governedTokenAccount?.extensions.mint?.account) - }, [form.governedTokenAccount]) - - const schema = getCastleDepositSchema({ form }) - - return ( - - { - handleSetForm({ value, propertyName: 'governedTokenAccount' }) - }} - value={form.governedTokenAccount} - error={formErrors['governedTokenAccount']} - shouldBeGoverned={shouldBeGoverned} - governance={governance} - /> - - - - - ) -} - -export default CastleDeposit diff --git a/pages/dao/[symbol]/proposal/components/instructions/Castle/CastleWithdraw.tsx b/pages/dao/[symbol]/proposal/components/instructions/Castle/CastleWithdraw.tsx deleted file mode 100644 index d0bcba7961..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Castle/CastleWithdraw.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import React, { useContext, useEffect, useState } from 'react' -import Input from '@components/inputs/Input' -import useRealm from '@hooks/useRealm' -import { getMintMinAmountAsDecimal } from '@tools/sdk/units' -import { PublicKey } from '@solana/web3.js' -import { precision } from '@utils/formatting' -import useWalletStore from 'stores/useWalletStore' -import { - CastleWithdrawForm, - UiInstruction, -} from '@utils/uiTypes/proposalCreationTypes' -import { NewProposalContext } from '../../../new' -import { getCastleWithdrawSchema } from '@utils/validations' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { Governance } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import GovernedAccountSelect from '../../GovernedAccountSelect' -import Select from '@components/inputs/Select' -import { - VaultConfig, - DeploymentEnvs, - Clusters, -} from '@castlefinance/vault-core' -import { - getCastleVaults, - getCastleWithdrawInstruction, -} from '@utils/instructions/Castle' - -const CastleWithdraw = ({ - index, - governance, -}: { - index: number - governance: ProgramAccount | null -}) => { - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const { realmInfo } = useRealm() - const { governedTokenAccountsWithoutNfts } = useGovernanceAssets() - const shouldBeGoverned = index !== 0 && governance - const programId: PublicKey | undefined = realmInfo?.programId - - // Store CastleWithdrawForm state - const [form, setForm] = useState({ - amount: undefined, - governedTokenAccount: undefined, - castleVaultId: '', - programId: programId?.toString(), - mintInfo: undefined, - }) - - const [castleVaults, setCastleVaults] = useState< - VaultConfig[] | null - >(null) - - const [governedAccount, setGovernedAccount] = useState< - ProgramAccount | undefined - >(undefined) - - const [formErrors, setFormErrors] = useState({}) - - const mintMinAmount = form.mintInfo - ? getMintMinAmountAsDecimal(form.mintInfo) - : 1 - - const currentPrecision = precision(mintMinAmount) - const { handleSetInstructions } = useContext(NewProposalContext) - - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - - const setMintInfo = (value) => { - setForm({ ...form, mintInfo: value }) - } - - const setAmount = (event) => { - const value = event.target.value - handleSetForm({ - value: value, - propertyName: 'amount', - }) - } - - const validateAmountOnBlur = () => { - const value = form.amount - - handleSetForm({ - value: parseFloat( - Math.max( - Number(mintMinAmount), - Math.min(Number(Number.MAX_SAFE_INTEGER), Number(value)) - ).toFixed(currentPrecision) - ), - propertyName: 'amount', - }) - } - - async function getInstruction(): Promise { - return await getCastleWithdrawInstruction({ - schema, - form, - amount: form.amount ?? 0, - programId, - connection, - wallet, - setFormErrors, - }) - } - - // Grab Castle vault information from config server - useEffect(() => { - const getCastleConfig = async () => { - const vaults = (await getCastleVaults()).filter((v) => - connection.cluster == 'mainnet' - ? v.cluster == Clusters.mainnetBeta - : v.cluster == Clusters.devnet - ) - setCastleVaults(vaults) - } - getCastleConfig() - }, []) - - useEffect(() => { - handleSetForm({ - propertyName: 'programId', - value: programId?.toString(), - }) - }, [realmInfo?.programId]) - - useEffect(() => { - if (wallet) { - handleSetInstructions( - { governedAccount: governedAccount, getInstruction }, - index - ) - } - }, [form]) - - useEffect(() => { - setGovernedAccount(form.governedTokenAccount?.governance) - setMintInfo(form.governedTokenAccount?.extensions.mint?.account) - }, [form.governedTokenAccount]) - - const schema = getCastleWithdrawSchema() - - return ( - - { - handleSetForm({ value, propertyName: 'governedTokenAccount' }) - }} - value={form.governedTokenAccount} - error={formErrors['governedTokenAccount']} - shouldBeGoverned={shouldBeGoverned} - governance={governance} - /> - - - - ) -} - -export default CastleWithdraw diff --git a/pages/dao/[symbol]/proposal/components/instructions/Change/ChangeDonation.tsx b/pages/dao/[symbol]/proposal/components/instructions/Change/ChangeDonation.tsx index 125382167c..2b60c4b376 100644 --- a/pages/dao/[symbol]/proposal/components/instructions/Change/ChangeDonation.tsx +++ b/pages/dao/[symbol]/proposal/components/instructions/Change/ChangeDonation.tsx @@ -6,7 +6,6 @@ import { getMintMinAmountAsDecimal } from '@tools/sdk/units' import { PublicKey } from '@solana/web3.js' import { precision } from '@utils/formatting' import { tryParseKey } from '@tools/validators/pubkey' -import useWalletStore from 'stores/useWalletStore' import { TokenProgramAccount, tryGetTokenAccount } from '@utils/tokens' import { SplTokenTransferForm, @@ -26,6 +25,8 @@ import { getTransferInstruction, } from '@utils/instructionTools' import NonprofitSelect from '@components/inputs/ChangeNonprofitSelect' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' const ChangeDonation = ({ index, @@ -34,11 +35,11 @@ const ChangeDonation = ({ index: number governance: ProgramAccount | null }) => { - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() const { realmInfo } = useRealm() const { governedTokenAccountsWithoutNfts } = useGovernanceAssets() - const shouldBeGoverned = index !== 0 && governance + const shouldBeGoverned = !!(index !== 0 && governance) const programId: PublicKey | undefined = realmInfo?.programId const [form, setForm] = useState({ destinationAccount: '', @@ -183,6 +184,7 @@ const ChangeDonation = ({ propertyName: 'programId', value: programId?.toString(), }) + // 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 }, [realmInfo?.programId]) useEffect(() => { if (form.destinationAccount) { @@ -198,16 +200,19 @@ const ChangeDonation = ({ } else { setDestinationAccount(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.destinationAccount]) useEffect(() => { handleSetInstructions( { governedAccount: governedAccount, getInstruction }, index ) + // 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]) useEffect(() => { setGovernedAccount(form.governedTokenAccount?.governance) setMintInfo(form.governedTokenAccount?.extensions.mint?.account) + // 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.governedTokenAccount]) const destinationAccountName = destinationAccount?.publicKey && diff --git a/pages/dao/[symbol]/proposal/components/instructions/CloseMultipleTokenAccounts.tsx b/pages/dao/[symbol]/proposal/components/instructions/CloseMultipleTokenAccounts.tsx new file mode 100644 index 0000000000..93e0bb253c --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/CloseMultipleTokenAccounts.tsx @@ -0,0 +1,268 @@ +import { useContext, useEffect, useState } from 'react' +import { + Governance, + ProgramAccount, + serializeInstructionToBase64, +} from '@solana/spl-governance' +import { validateInstruction } from '@utils/instructionTools' +import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes' + +import { NewProposalContext } from '../../new' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import { AssetAccount } from '@utils/uiTypes/assets' +import InstructionForm, { InstructionInput } from './FormCreator' +import { InstructionInputType } from './inputInstructionType' +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + Token, + TOKEN_PROGRAM_ID, +} from '@solana/spl-token' +import * as yup from 'yup' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { getATA } from '@utils/ataTools' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import Checkbox from '@components/inputs/Checkbox' +import tokenPriceService from '@utils/services/tokenPrice' +import { fmtMintAmount } from '@tools/sdk/units' + +interface CloseMultiTokenAccountForm { + wallet: AssetAccount | undefined | null + tokenAccounts: AssetAccount[] + fundsDestinationAccount: string + solRentDestination: string +} + +const CloseMultipleTokenAccounts = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const realm = useRealmQuery().data?.result + const wallet = useWalletOnePointOh() + const connection = useLegacyConnectionContext() + const shouldBeGoverned = !!(index !== 0 && governance) + const { governedTokenAccountsWithoutNfts } = useGovernanceAssets() + const [form, setForm] = useState({ + wallet: null, + tokenAccounts: [], + fundsDestinationAccount: '', + solRentDestination: '', + }) + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const schema = yup.object().shape({ + wallet: yup + .object() + .nullable() + .required('Program governed account is required'), + }) + async function getInstruction(): Promise { + const isValid = await validateInstruction({ schema, form, setFormErrors }) + + const additionalSerializedInstructions: string[] = [] + const prerequisiteInstructions: TransactionInstruction[] = [] + const mintsOfCurrentlyPushedAtaInstructions: string[] = [] + if ( + isValid && + form!.wallet?.governance?.account && + wallet?.publicKey && + realm + ) { + for (const tokenAccount of form.tokenAccounts) { + const sourceAccount = tokenAccount.pubkey + //this is the original owner + const destinationAccount = new PublicKey(form!.fundsDestinationAccount) + const mintPK = tokenAccount.extensions.mint!.publicKey + const amount = tokenAccount.extensions.token!.account.amount + + //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 && + !mintsOfCurrentlyPushedAtaInstructions.find( + (x) => x === mintPK.toBase58() + ) + ) { + const createAtaInstruction = 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 + ) + mintsOfCurrentlyPushedAtaInstructions.push(mintPK.toBase58()) + prerequisiteInstructions.push(createAtaInstruction) + } + + if (!amount.isZero()) { + const transferIx = Token.createTransferInstruction( + TOKEN_PROGRAM_ID, + sourceAccount!, + receiverAddress, + tokenAccount.extensions.token!.account.owner, + [], + amount + ) + additionalSerializedInstructions.push( + serializeInstructionToBase64(transferIx) + ) + } + + const closeInstruction = Token.createCloseAccountInstruction( + TOKEN_PROGRAM_ID, + tokenAccount.pubkey, + new PublicKey(form!.solRentDestination), + tokenAccount.extensions.token!.account.owner, + [] + ) + additionalSerializedInstructions.push( + serializeInstructionToBase64(closeInstruction) + ) + } + } + const obj: UiInstruction = { + prerequisiteInstructions: prerequisiteInstructions, + serializedInstruction: '', + additionalSerializedInstructions: additionalSerializedInstructions, + chunkBy: 3, + isValid, + governance: form!.wallet?.governance, + } + + return obj + } + useEffect(() => { + handleSetInstructions( + { governedAccount: form?.wallet?.governance, getInstruction }, + index + ) + // 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]) + + const inputs: InstructionInput[] = [ + { + label: 'Wallet', + initialValue: null, + name: 'wallet', + type: InstructionInputType.GOVERNED_ACCOUNT, + shouldBeGoverned: shouldBeGoverned as any, + governance: governance, + options: governedTokenAccountsWithoutNfts.filter((x) => x.isSol), + assetType: 'wallet', + additionalComponent: ( +
+ {governedTokenAccountsWithoutNfts + .filter( + (x) => + x.isToken && + (x.extensions.token?.account.owner.toBase58() === + form.wallet?.extensions.transferAddress?.toBase58() || + x.extensions.token?.account.owner.toBase58() === + form.wallet?.governance.pubkey.toBase58()) + ) + .sort((a, b) => { + const AAmount = fmtMintAmount( + a.extensions.mint!.account, + a!.extensions.token!.account.amount + ) + + const BAmount = fmtMintAmount( + b.extensions.mint!.account, + b!.extensions.token!.account.amount + ) + + return BAmount.length - AAmount.length + }) + .map((x) => { + const info = tokenPriceService.getTokenInfo( + x.extensions.mint!.publicKey.toBase58() + ) + const pubkey = x.pubkey.toBase58() + const tokenName = info?.name ? info.name : '' + const amount = fmtMintAmount( + x.extensions.mint!.account, + x!.extensions.token!.account.amount + ) + return ( +
+ + toAcc.pubkey.toBase58() === x.pubkey.toBase58() + ) + } + onChange={(e) => { + let newTokenAccounts = form.tokenAccounts + ? [...form.tokenAccounts] + : [] + if (e.target.checked) { + newTokenAccounts = [...newTokenAccounts, x] + } else { + newTokenAccounts = newTokenAccounts.filter( + (toAcc) => + toAcc.pubkey.toBase58() !== x.pubkey.toBase58() + ) + } + setForm({ + ...form, + tokenAccounts: newTokenAccounts, + }) + }} + > +
+ ) + })} +
+ ), + }, + { + label: 'Token recipient', + initialValue: '', + name: 'fundsDestinationAccount', + type: InstructionInputType.INPUT, + inputType: 'text', + hide: form?.wallet?.extensions.amount?.isZero(), + }, + { + label: 'Sol recipient', + initialValue: + governedTokenAccountsWithoutNfts + .find((x) => x.isSol) + ?.extensions.transferAddress?.toBase58() || + wallet?.publicKey?.toBase58(), + name: 'solRentDestination', + type: InstructionInputType.INPUT, + inputType: 'text', + }, + ] + return ( + <> + + + ) +} + +export default CloseMultipleTokenAccounts diff --git a/pages/dao/[symbol]/proposal/components/instructions/CloseTokenAccount.tsx b/pages/dao/[symbol]/proposal/components/instructions/CloseTokenAccount.tsx index 07989f555c..968a6b73ec 100644 --- a/pages/dao/[symbol]/proposal/components/instructions/CloseTokenAccount.tsx +++ b/pages/dao/[symbol]/proposal/components/instructions/CloseTokenAccount.tsx @@ -1,31 +1,33 @@ -import React, { useContext, useEffect, useState } from 'react' +import { useContext, useEffect, useState } from 'react' import { Governance, ProgramAccount, serializeInstructionToBase64, } from '@solana/spl-governance' -import { - getTransferInstructionObj, - validateInstruction, -} from '@utils/instructionTools' +import { validateInstruction } from '@utils/instructionTools' import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes' -import useWalletStore from 'stores/useWalletStore' import { NewProposalContext } from '../../new' -import useRealm from '@hooks/useRealm' import useGovernanceAssets from '@hooks/useGovernanceAssets' import { AssetAccount } from '@utils/uiTypes/assets' -import InstructionForm, { - InstructionInput, - InstructionInputType, -} from './FormCreator' -import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token' +import InstructionForm, { InstructionInput } from './FormCreator' +import { InstructionInputType } from './inputInstructionType' +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + Token, + TOKEN_PROGRAM_ID, +} from '@solana/spl-token' import * as yup from 'yup' import { getValidatedPublickKey } from '@utils/validations' import { PublicKey } from '@solana/web3.js' +import { getATA } from '@utils/ataTools' +import { sendTransactionsV3, SequenceType } from '@utils/sendTransactions' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useRealmQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' -export interface CloseTokenAccountForm { - governedAccount: AssetAccount | undefined +interface CloseTokenAccountForm { + governedAccount: AssetAccount | undefined | null fundsDestinationAccount: string solRentDestination: string } @@ -37,12 +39,16 @@ const CloseTokenAccount = ({ index: number governance: ProgramAccount | null }) => { - const { realm } = useRealm() - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - const shouldBeGoverned = index !== 0 && governance + const realm = useRealmQuery().data?.result + const wallet = useWalletOnePointOh() + const connection = useLegacyConnectionContext() + const shouldBeGoverned = !!(index !== 0 && governance) const { governedTokenAccountsWithoutNfts } = useGovernanceAssets() - const [form, setForm] = useState() + const [form, setForm] = useState({ + governedAccount: null, + fundsDestinationAccount: '', + solRentDestination: '', + }) const [formErrors, setFormErrors] = useState({}) const { handleSetInstructions } = useContext(NewProposalContext) const schema = yup.object().shape({ @@ -101,23 +107,72 @@ const CloseTokenAccount = ({ async function getInstruction(): Promise { const isValid = await validateInstruction({ schema, form, setFormErrors }) let serializedInstructionClose = '' - let serializedTransfer = '' - let instructions: any = null + const additionalSerializedInstructions: string[] = [] if ( isValid && form!.governedAccount?.governance?.account && wallet?.publicKey && realm ) { - instructions = !form!.governedAccount.extensions.token!.account.amount?.isZero() - ? await getTransferInstructionObj({ - connection: connection, - governedTokenAccount: form!.governedAccount!, - amount: form!.governedAccount.extensions.token!.account.amount!, - destinationAccount: form!.fundsDestinationAccount!, + if (!form!.governedAccount.extensions.token!.account.amount?.isZero()) { + const sourceAccount = form!.governedAccount.extensions.token?.publicKey + //this is the original owner + const destinationAccount = new PublicKey(form!.fundsDestinationAccount) + const mintPK = form!.governedAccount.extensions.mint!.publicKey + const amount = form!.governedAccount.extensions.token!.account.amount + + //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) { + const createAtaInstruction = 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 + ) + //ata needs to be created before otherwise simulations will throw errors. + //createCloseAccountInstruction has check if ata is existing its not like in transfer where we can run + //simulation without created ata and we create it on the fly before proposal + await sendTransactionsV3({ + connection: connection.current, wallet: wallet, + transactionInstructions: [ + { + instructionsSet: [ + { + transactionInstruction: createAtaInstruction, + }, + ], + sequenceType: SequenceType.Parallel, + }, + ], }) - : null + } + const transferIx = Token.createTransferInstruction( + TOKEN_PROGRAM_ID, + sourceAccount!, + receiverAddress, + form!.governedAccount!.extensions!.token!.account.owner, + [], + amount + ) + additionalSerializedInstructions.push( + serializeInstructionToBase64(transferIx) + ) + } + const closeInstruction = Token.createCloseAccountInstruction( TOKEN_PROGRAM_ID, form!.governedAccount.extensions.token!.publicKey!, @@ -125,26 +180,19 @@ const CloseTokenAccount = ({ form!.governedAccount.extensions.token!.account.owner!, [] ) - serializedTransfer = instructions?.transferInstruction - ? serializeInstructionToBase64(instructions?.transferInstruction) - : '' serializedInstructionClose = serializeInstructionToBase64( closeInstruction ) + additionalSerializedInstructions.push(serializedInstructionClose) } const obj: UiInstruction = { prerequisiteInstructions: [], - serializedInstruction: serializedInstructionClose, - additionalSerializedInstructions: [], + serializedInstruction: '', + additionalSerializedInstructions: additionalSerializedInstructions, isValid, governance: form!.governedAccount?.governance, } - if (instructions?.ataInstruction) { - obj.prerequisiteInstructions?.push(instructions?.ataInstruction) - } - if (serializedTransfer) { - obj.additionalSerializedInstructions!.push(serializedTransfer) - } + return obj } useEffect(() => { @@ -152,6 +200,7 @@ const CloseTokenAccount = ({ { governedAccount: form?.governedAccount?.governance, getInstruction }, index ) + // 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]) const inputs: InstructionInput[] = [ { @@ -162,6 +211,7 @@ const CloseTokenAccount = ({ shouldBeGoverned: shouldBeGoverned as any, governance: governance, options: governedTokenAccountsWithoutNfts.filter((x) => !x.isSol), + assetType: 'token', }, { label: 'Token recipient', diff --git a/pages/dao/[symbol]/proposal/components/instructions/CreateAssociatedTokenAccount.tsx b/pages/dao/[symbol]/proposal/components/instructions/CreateAssociatedTokenAccount.tsx index e1647af26b..1b5b020d83 100644 --- a/pages/dao/[symbol]/proposal/components/instructions/CreateAssociatedTokenAccount.tsx +++ b/pages/dao/[symbol]/proposal/components/instructions/CreateAssociatedTokenAccount.tsx @@ -16,12 +16,13 @@ import { } from '@utils/uiTypes/proposalCreationTypes' /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import useWalletStore from 'stores/useWalletStore' import { NewProposalContext } from '../../new' import GovernedAccountSelect from '../GovernedAccountSelect' import useGovernanceAssets from '@hooks/useGovernanceAssets' import TokenMintInput from '@components/inputs/TokenMintInput' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' const CreateAssociatedTokenAccount = ({ index, @@ -30,13 +31,13 @@ const CreateAssociatedTokenAccount = ({ index: number governance: ProgramAccount | null }) => { - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() const { realmInfo } = useRealm() const { assetAccounts } = useGovernanceAssets() - const shouldBeGoverned = index !== 0 && governance + const shouldBeGoverned = !!(index !== 0 && governance) const programId: PublicKey | undefined = realmInfo?.programId const [form, setForm] = useState({}) const [formErrors, setFormErrors] = useState({}) @@ -94,6 +95,7 @@ const CreateAssociatedTokenAccount = ({ propertyName: 'programId', value: programId?.toString(), }) + // 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 }, [programId]) useEffect(() => { @@ -104,6 +106,7 @@ const CreateAssociatedTokenAccount = ({ }, index ) + // 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]) const schema = yup.object().shape({ diff --git a/pages/dao/[symbol]/proposal/components/instructions/CreateTokenMetadata.tsx b/pages/dao/[symbol]/proposal/components/instructions/CreateTokenMetadata.tsx index 12e7d84255..f1633ef158 100644 --- a/pages/dao/[symbol]/proposal/components/instructions/CreateTokenMetadata.tsx +++ b/pages/dao/[symbol]/proposal/components/instructions/CreateTokenMetadata.tsx @@ -14,7 +14,8 @@ import { getCreateTokenMetadataSchema } from 'utils/validations' import GovernedAccountSelect from '../GovernedAccountSelect' import { getCreateTokenMetadataInstruction } from 'utils/instructionTools' import { AccountType } from '@utils/uiTypes/assets' -import useWalletStore from 'stores/useWalletStore' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' const CreateTokenMetadata = ({ index, @@ -23,13 +24,13 @@ const CreateTokenMetadata = ({ index: number governance: ProgramAccount | null }) => { - const connection = useWalletStore((s) => s.connection) + const connection = useLegacyConnectionContext() const { realmInfo } = useRealm() const { assetAccounts } = useGovernanceAssets() const mintGovernancesWithMintInfo = assetAccounts.filter( (x) => x.type === AccountType.MINT ) - const shouldBeGoverned = index !== 0 && governance + const shouldBeGoverned = !!(index !== 0 && governance) const programId: PublicKey | undefined = realmInfo?.programId const [form, setForm] = useState({ name: '', @@ -38,7 +39,7 @@ const CreateTokenMetadata = ({ mintAccount: undefined, programId: programId?.toString(), }) - const wallet = useWalletStore((s) => s.current) + const wallet = useWalletOnePointOh() const [governedAccount, setGovernedAccount] = useState< ProgramAccount | undefined >(undefined) @@ -77,6 +78,7 @@ const CreateTokenMetadata = ({ propertyName: 'programId', value: programId?.toString(), }) + // 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 }, [realmInfo?.programId]) useEffect(() => { @@ -84,6 +86,7 @@ const CreateTokenMetadata = ({ { governedAccount: governedAccount, getInstruction }, index ) + // 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, governedAccount]) useEffect(() => { setGovernedAccount(form?.mintAccount?.governance) @@ -124,6 +127,7 @@ const CreateTokenMetadata = ({ error={formErrors['mintAccount']} shouldBeGoverned={shouldBeGoverned} governance={governance} + type="mint" /> {shouldMakeSolTreasury && ( diff --git a/pages/dao/[symbol]/proposal/components/instructions/CustomBase64.tsx b/pages/dao/[symbol]/proposal/components/instructions/CustomBase64.tsx index 801b685258..4e30215f0b 100644 --- a/pages/dao/[symbol]/proposal/components/instructions/CustomBase64.tsx +++ b/pages/dao/[symbol]/proposal/components/instructions/CustomBase64.tsx @@ -1,9 +1,10 @@ -import React, { useContext, useEffect, useState } from 'react' +import { useContext, useEffect, useState } from 'react' import * as yup from 'yup' import { getInstructionDataFromBase64, Governance, ProgramAccount, + serializeInstructionToBase64, } from '@solana/spl-governance' import Input from '@components/inputs/Input' import Textarea from '@components/inputs/Textarea' @@ -13,12 +14,15 @@ import { UiInstruction, } from '@utils/uiTypes/proposalCreationTypes' -import useWalletStore from 'stores/useWalletStore' - import { NewProposalContext } from '../../new' import GovernedAccountSelect from '../GovernedAccountSelect' -import useRealm from '@hooks/useRealm' import useGovernanceAssets from '@hooks/useGovernanceAssets' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { useLegacyVoterWeight } from '@hooks/queries/governancePower' +import ForwarderProgram, { + useForwarderProgramHelpers, +} from '@components/ForwarderProgram/ForwarderProgram' +import { TransactionInstruction } from '@solana/web3.js' const CustomBase64 = ({ index, @@ -27,10 +31,11 @@ const CustomBase64 = ({ index: number governance: ProgramAccount | null }) => { - const { ownVoterWeight } = useRealm() - const wallet = useWalletStore((s) => s.current) + const { result: ownVoterWeight } = useLegacyVoterWeight() + const wallet = useWalletOnePointOh() const { assetAccounts } = useGovernanceAssets() - const shouldBeGoverned = index !== 0 && governance + const forwarderProgramHelpers = useForwarderProgramHelpers() + const shouldBeGoverned = !!(index !== 0 && governance) const [form, setForm] = useState({ governedAccount: undefined, base64: '', @@ -50,7 +55,19 @@ const CustomBase64 = ({ form.governedAccount?.governance?.account && wallet?.publicKey ) { - serializedInstruction = form.base64 + if (forwarderProgramHelpers.form.useExecutableBy) { + const ix = getInstructionDataFromBase64(form.base64) + const tx = new TransactionInstruction({ + keys: ix.accounts, + data: Buffer.from(ix.data), + programId: ix.programId, + }) + serializedInstruction = serializeInstructionToBase64( + forwarderProgramHelpers.withForwarderWrapper(tx) + ) + } else { + serializedInstruction = form.base64 + } } const obj: UiInstruction = { serializedInstruction: serializedInstruction, @@ -65,7 +82,12 @@ const CustomBase64 = ({ { governedAccount: form.governedAccount?.governance, getInstruction }, index ) - }, [form]) + // 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, + forwarderProgramHelpers.form, + forwarderProgramHelpers.withForwarderWrapper, + ]) const schema = yup.object().shape({ governedAccount: yup .object() @@ -111,7 +133,7 @@ const CustomBase64 = ({ - ownVoterWeight.canCreateProposal(x.governance.account.config) + ownVoterWeight?.canCreateProposal(x.governance.account.config) )} onChange={(value) => { handleSetForm({ value, propertyName: 'governedAccount' }) @@ -149,6 +171,7 @@ const CustomBase64 = ({ } error={formErrors['base64']} > + ) } diff --git a/pages/dao/[symbol]/proposal/components/instructions/DistrubtionProgram/CloseVaults.tsx b/pages/dao/[symbol]/proposal/components/instructions/DistrubtionProgram/CloseVaults.tsx new file mode 100644 index 0000000000..e05bce5b65 --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/DistrubtionProgram/CloseVaults.tsx @@ -0,0 +1,285 @@ +import { useCallback, useContext, useEffect, useMemo, useState } from 'react' +import * as yup from 'yup' +import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import { + Governance, + SYSTEM_PROGRAM_ID, + serializeInstructionToBase64, +} from '@solana/spl-governance' +import { ProgramAccount } from '@solana/spl-governance' +import { AccountType, AssetAccount } from '@utils/uiTypes/assets' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { NewProposalContext } from '../../../new' +import InstructionForm, { InstructionInput } from '../FormCreator' +import { InstructionInputType } from '../inputInstructionType' +import { + Distribution, + MangoMintsRedemptionClient, +} from '@blockworks-foundation/mango-mints-redemption' +import { AnchorProvider } from '@coral-xyz/anchor' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import EmptyWallet from '@utils/Mango/listingTools' +import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js' +import { tryGetTokenAccount } from '@utils/tokens' +import Button from '@components/Button' +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + Token, +} from '@solana/spl-token' +import { validateInstruction } from '@utils/instructionTools' +import { SEASON_PREFIX } from './FillVaults' + +interface CloseVaultsForm { + governedAccount: AssetAccount | null + season: number +} + +type Vault = { + publicKey: PublicKey + amount: bigint + mintIndex: number + mint: PublicKey + type: string +} + +const CloseVaults = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const wallet = useWalletOnePointOh() + const { assetAccounts } = useGovernanceAssets() + const solAccounts = assetAccounts.filter((x) => x.type === AccountType.SOL) + const connection = useLegacyConnectionContext() + const shouldBeGoverned = !!(index !== 0 && governance) + const [form, setForm] = useState({ + governedAccount: null, + season: 0, + }) + const [client, setClient] = useState() + const [distribution, setDistribution] = useState() + const [vaults, setVaults] = useState<{ [pubkey: string]: Vault }>() + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const schema = useMemo( + () => + yup.object().shape({ + governedAccount: yup + .object() + .nullable() + .required('Program governed account is required'), + }), + [] + ) + const getInstruction = useCallback(async () => { + const isValid = await validateInstruction({ schema, form, setFormErrors }) + let serializedInstruction = '' + const mintsOfCurrentlyPushedAtaInstructions: string[] = [] + const additionalSerializedInstructions: string[] = [] + const prerequisiteInstructions: TransactionInstruction[] = [] + if ( + isValid && + form.governedAccount?.governance?.account && + wallet?.publicKey && + vaults + ) { + for (const v of Object.values(vaults)) { + const ataAddress = await Token.getAssociatedTokenAddress( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + v.mint, + form.governedAccount.extensions.transferAddress!, + true + ) + + const depositAccountInfo = await connection.current.getAccountInfo( + ataAddress + ) + if ( + !depositAccountInfo && + !mintsOfCurrentlyPushedAtaInstructions.find( + (x) => x === v.mint.toBase58() + ) + ) { + // generate the instruction for creating the ATA + prerequisiteInstructions.push( + Token.createAssociatedTokenAccountInstruction( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + v.mint, + ataAddress, + form.governedAccount.extensions.transferAddress!, + wallet.publicKey + ) + ) + mintsOfCurrentlyPushedAtaInstructions.push(v.mint.toBase58()) + } + + const ix = await client?.program.methods + .vaultClose() + .accounts({ + distribution: distribution?.publicKey, + vault: v.publicKey, + mint: v.mint, + destination: ataAddress, + authority: form.governedAccount.extensions.transferAddress, + systemProgram: SYSTEM_PROGRAM_ID, + tokenProgram: TOKEN_PROGRAM_ID, + }) + .instruction() + additionalSerializedInstructions.push(serializeInstructionToBase64(ix!)) + } + serializedInstruction = '' + } + const obj: UiInstruction = { + additionalSerializedInstructions, + prerequisiteInstructions, + serializedInstruction: serializedInstruction, + isValid, + governance: form.governedAccount?.governance, + } + return obj + }, [ + client?.program.methods, + connection, + distribution?.publicKey, + form, + schema, + vaults, + wallet?.publicKey, + ]) + const handleSelectDistribution = async (number: number) => { + const distribution = await client?.loadDistribution( + Number(`${SEASON_PREFIX}${number}`) + ) + setDistribution(distribution) + } + const fetchVaults = async () => { + if (!client || !distribution) return + const v: any = {} + for (let i = 0; i < distribution.metadata!.mints.length; i++) { + const mint = distribution.metadata!.mints[i] + const type = mint.properties.type + const vaultAddress = distribution.findVaultAddress( + new PublicKey(mint.address) + ) + try { + const tokenAccount = await tryGetTokenAccount( + connection.current, + vaultAddress + ) + + v[vaultAddress.toString()] = { + publicKey: vaultAddress, + amount: tokenAccount?.account.amount, + mint: tokenAccount?.account.mint, + mintIndex: i, + type: type, + } + } catch { + v[vaultAddress.toString()] = { amount: -1, mintIndex: i } + } + } + setVaults(v) + } + useEffect(() => { + if (distribution) { + fetchVaults() + } + }, [distribution]) + useEffect(() => { + const client = new MangoMintsRedemptionClient( + new AnchorProvider( + connection.current, + new EmptyWallet(Keypair.generate()), + { skipPreflight: true } + ) + ) + setClient(client) + }, []) + useEffect(() => { + handleSetInstructions( + { governedAccount: form.governedAccount?.governance, getInstruction }, + index + ) + }, [form, getInstruction, handleSetInstructions, index, vaults]) + + const inputs: InstructionInput[] = [ + { + label: 'Governance', + initialValue: form.governedAccount, + name: 'governedAccount', + type: InstructionInputType.GOVERNED_ACCOUNT, + shouldBeGoverned: shouldBeGoverned as any, + governance: governance, + options: solAccounts, + }, + { + label: 'Distribution Number', + initialValue: form.season, + type: InstructionInputType.INPUT, + additionalComponent: ( +
+ +
+ ), + inputType: 'number', + name: 'season', + }, + ] + + return ( + <> + {form && ( + <> + + {distribution && vaults && ( +
+ + Vaults to close + + +
+ {vaults + ? Object.entries(vaults).map(([address, vault]) => { + return ( +
+

{address}

{' '} +

+ { + distribution.metadata!.mints[vault.mintIndex] + .properties?.name + } +

{' '} + + {vault.amount > -1 + ? vault.amount.toString() + : 'Deleted'} + +
+ ) + }) + : 'Loading...'} +
+
+
+ )} + + )} + + ) +} + +export default CloseVaults diff --git a/pages/dao/[symbol]/proposal/components/instructions/DistrubtionProgram/FillVaults.tsx b/pages/dao/[symbol]/proposal/components/instructions/DistrubtionProgram/FillVaults.tsx new file mode 100644 index 0000000000..b548b3f82d --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/DistrubtionProgram/FillVaults.tsx @@ -0,0 +1,329 @@ +import { useCallback, useContext, useEffect, useMemo, useState } from 'react' +import * as yup from 'yup' +import { UiInstruction } from '@utils/uiTypes/proposalCreationTypes' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import { + Governance, + serializeInstructionToBase64, +} from '@solana/spl-governance' +import { ProgramAccount } from '@solana/spl-governance' +import { AccountType, AssetAccount } from '@utils/uiTypes/assets' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { NewProposalContext } from '../../../new' +import InstructionForm, { InstructionInput } from '../FormCreator' +import { InstructionInputType } from '../inputInstructionType' +import { + Distribution, + MangoMintsRedemptionClient, +} from '@blockworks-foundation/mango-mints-redemption' +import { AnchorProvider } from '@coral-xyz/anchor' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import EmptyWallet from '@utils/Mango/listingTools' +import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js' +import { tryGetTokenAccount } from '@utils/tokens' +import Button from '@components/Button' +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + Token, + u64, +} from '@solana/spl-token' +import Input from '@components/inputs/Input' +import { parseMintNaturalAmountFromDecimal } from '@tools/sdk/units' +import { validateInstruction } from '@utils/instructionTools' +import useGovernanceNfts from '@components/treasuryV2/WalletList/WalletListItem/AssetList/useGovernanceNfts' + +export const SEASON_PREFIX = 134 + +interface FillVaultsForm { + governedAccount: AssetAccount | null + season: number +} + +type Vault = { + publicKey: PublicKey + amount: bigint + mintIndex: number + mint: PublicKey + type: string +} + +type Transfer = { + from: PublicKey + to: PublicKey + amount: string + decimals: number + mintIndex: number +} + +const FillVaults = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const wallet = useWalletOnePointOh() + const { assetAccounts } = useGovernanceAssets() + const solAccounts = assetAccounts.filter((x) => x.type === AccountType.SOL) + const connection = useLegacyConnectionContext() + const shouldBeGoverned = !!(index !== 0 && governance) + const [form, setForm] = useState({ + governedAccount: null, + season: 1, + }) + const [transfers, setTransfers] = useState([]) + const [client, setClient] = useState() + const [distribution, setDistribution] = useState() + const [vaults, setVaults] = useState<{ [pubkey: string]: Vault }>() + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const nfts = useGovernanceNfts(form.governedAccount?.governance.pubkey) + + const schema = useMemo( + () => + yup.object().shape({ + governedAccount: yup + .object() + .nullable() + .required('Program governed account is required'), + }), + [] + ) + + const getInstruction = useCallback(async () => { + const isValid = await validateInstruction({ schema, form, setFormErrors }) + let serializedInstruction = '' + const additionalSerializedInstructions: string[] = [] + const prerequisiteInstructions: TransactionInstruction[] = [] + + if ( + isValid && + form.governedAccount?.governance?.account && + wallet?.publicKey && + vaults + ) { + for (const t of transfers.filter((x) => x.amount)) { + const mintAmount = parseMintNaturalAmountFromDecimal( + t.amount, + t.decimals + ) + const transferIx = Token.createTransferInstruction( + TOKEN_PROGRAM_ID, + t.from, + t.to, + form.governedAccount.extensions.transferAddress!, + [], + new u64(mintAmount.toString()) + ) + additionalSerializedInstructions.push( + serializeInstructionToBase64(transferIx!) + ) + } + serializedInstruction = '' + } + const obj: UiInstruction = { + additionalSerializedInstructions, + prerequisiteInstructions, + serializedInstruction: serializedInstruction, + isValid, + governance: form.governedAccount?.governance, + } + + return obj + }, [form, schema, transfers, vaults, wallet?.publicKey]) + const handleSelectDistribution = async (number: number) => { + const distribution = await client?.loadDistribution( + Number(`${SEASON_PREFIX}${number}`) + ) + setDistribution(distribution) + } + const fetchVaults = async () => { + if (!client || !distribution) return + const v: any = {} + for (let i = 0; i < distribution.metadata!.mints.length; i++) { + const mint = distribution.metadata!.mints[i] + const type = mint.properties.type + const vaultAddress = distribution.findVaultAddress( + new PublicKey(mint.address) + ) + try { + const tokenAccount = await tryGetTokenAccount( + connection.current, + vaultAddress + ) + + v[vaultAddress.toString()] = { + publicKey: vaultAddress, + amount: tokenAccount?.account.amount, + mint: tokenAccount?.account.mint, + mintIndex: i, + type: type, + } + } catch { + v[vaultAddress.toString()] = { amount: -1, mintIndex: i } + } + } + setVaults(v) + } + + useEffect(() => { + if (distribution) { + fetchVaults() + } + }, [distribution]) + useEffect(() => { + const client = new MangoMintsRedemptionClient( + new AnchorProvider( + connection.current, + new EmptyWallet(Keypair.generate()), + { skipPreflight: true } + ) + ) + setClient(client) + }, []) + useEffect(() => { + if (vaults && form.governedAccount) { + const trans = Object.values(vaults) + .filter((x) => x.mint) + .map((v) => { + const isToken = v.type.toLowerCase() === 'token' + const fromToken = assetAccounts.find( + (assetAccount) => + assetAccount.isToken && + assetAccount.extensions.mint?.publicKey.equals(v.mint) && + assetAccount.extensions.token?.account.owner.equals( + form.governedAccount!.extensions.transferAddress! + ) + ) + const fromNft = nfts?.find((x) => x.id === v.mint.toBase58()) + + if (!fromToken && !fromNft) { + return undefined + } + + return { + from: isToken + ? fromToken!.pubkey + : PublicKey.findProgramAddressSync( + [ + new PublicKey(fromNft!.ownership.owner).toBuffer(), + TOKEN_PROGRAM_ID.toBuffer(), + new PublicKey(fromNft!.id).toBuffer(), + ], + ASSOCIATED_TOKEN_PROGRAM_ID + )[0], + to: v.publicKey, + amount: '', + decimals: isToken + ? fromToken!.extensions.mint!.account.decimals + : 0, + mintIndex: v.mintIndex, + } + }) + setTransfers(trans.filter((x) => x) as Transfer[]) + } else { + setTransfers([]) + } + }, [vaults]) + + useEffect(() => { + handleSetInstructions( + { governedAccount: form.governedAccount?.governance, getInstruction }, + index + ) + }, [form, getInstruction, handleSetInstructions, index, vaults]) + + const inputs: InstructionInput[] = [ + { + label: 'Governance', + initialValue: form.governedAccount, + name: 'governedAccount', + type: InstructionInputType.GOVERNED_ACCOUNT, + shouldBeGoverned: shouldBeGoverned as any, + governance: governance, + options: solAccounts, + }, + { + label: 'Season', + initialValue: form.season, + type: InstructionInputType.INPUT, + additionalComponent: ( +
+ +
+ ), + inputType: 'number', + name: 'season', + }, + ] + + return ( + <> + {form && ( + <> + + {distribution && vaults && ( +
+ + Vaults to fill + + +
+ {transfers + ? transfers.map((t, idx) => { + return ( +
+

{t.to.toBase58()}

{' '} +

+ { + distribution.metadata!.mints[t.mintIndex] + .properties?.name + } +

{' '} + + { + const newTrans = transfers.map( + (x, innerIdex) => { + if (innerIdex === idx) { + return { + ...x, + amount: e.target.value, + } + } + return x + } + ) + setTransfers(newTrans) + }} + type="text" + > + +
+ ) + }) + : 'Loading...'} +
+
+
+ )} + + )} + + ) +} + +export default FillVaults diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/DualAirdrop.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualAirdrop.tsx new file mode 100644 index 0000000000..2ebd29dd1d --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualAirdrop.tsx @@ -0,0 +1,188 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import React, { useContext, useEffect, useState } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceAirdropForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import GovernedAccountSelect from '../../GovernedAccountSelect' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import Input from '@components/inputs/Input' +import { + getGovernanceAirdropInstruction, + getMerkleAirdropInstruction, +} from '@utils/instructions/Dual/airdrop' +import { + getDualFinanceGovernanceAirdropSchema, + getDualFinanceMerkleAirdropSchema, +} from '@utils/validations' +import Tooltip from '@components/Tooltip' +import Select from '@components/inputs/Select' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' + +const DualAirdrop = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + root: '', + amountPerVoter: 0, + eligibilityStart: 0, + eligibilityEnd: 0, + amount: 0, + treasury: undefined, + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + const [governedAccount, setGovernedAccount] = useState< + ProgramAccount | undefined + >(undefined) + const [airdropType, setAirdropType] = useState('Merkle Proof') + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + } + function getInstruction(): Promise { + if (airdropType == 'Merkle Proof') { + return getMerkleAirdropInstruction({ + connection, + form, + schema: merkleSchema, + setFormErrors, + wallet, + }) + } else { + return getGovernanceAirdropInstruction({ + connection, + form, + schema: governanceSchema, + setFormErrors, + wallet, + }) + } + } + useEffect(() => { + handleSetInstructions( + { governedAccount: governedAccount, getInstruction }, + index + ) + }, [form]) + useEffect(() => { + setGovernedAccount(form.treasury?.governance) + }, [form.treasury]) + + const merkleSchema = getDualFinanceMerkleAirdropSchema({form}); + const governanceSchema = getDualFinanceGovernanceAirdropSchema({form}); + + return ( + <> + + {airdropType == 'Merkle Proof' && ( + + + handleSetForm({ + value: evt.target.value, + propertyName: 'root', + }) + } + error={formErrors['root']} + /> + + )} + {airdropType == 'Governance' && ( + <> + + handleSetForm({ + value: evt.target.value, + propertyName: 'eligibilityStart', + }) + } + error={formErrors['eligibilityStart']} + /> + + handleSetForm({ + value: evt.target.value, + propertyName: 'eligibilityEnd', + }) + } + error={formErrors['eligibilityEnd']} + /> + + handleSetForm({ + value: evt.target.value, + propertyName: 'amountPerVoter', + }) + } + error={formErrors['amountPerVoter']} + /> + + )} + {/* TODO: Note that this is full tokens, not atoms since expectation is that this composes with staking options */} + + handleSetForm({ + value: evt.target.value, + propertyName: 'amount', + }) + } + error={formErrors['amount']} + /> + { + handleSetForm({ value, propertyName: 'treasury' }) + }} + value={form.treasury} + error={formErrors['treasury']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + type="token" + > + + ) +} + +export default DualAirdrop diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/DualDelegate.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualDelegate.tsx new file mode 100644 index 0000000000..e0ec30bc28 --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualDelegate.tsx @@ -0,0 +1,119 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import React, { useContext, useEffect, useMemo, useState } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceDelegateForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import GovernedAccountSelect from '../../GovernedAccountSelect' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import Input from '@components/inputs/Input' +import { getDelegateInstruction } from '@utils/instructions/Dual/delegate' +import { getDualFinanceDelegateSchema } from '@utils/validations' +import Tooltip from '@components/Tooltip' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' + +const DualDelegate = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + delegateAccount: undefined, + realm: undefined, + delegateToken: undefined, + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + const [governedAccount, setGovernedAccount] = useState< + ProgramAccount | undefined + >(undefined) + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + } + const schema = useMemo(getDualFinanceDelegateSchema, []) + useEffect(() => { + function getInstruction(): Promise { + return getDelegateInstruction({ + connection, + form, + schema, + setFormErrors, + wallet, + }) + } + handleSetInstructions( + { governedAccount: governedAccount, getInstruction }, + index + ) + }, [ + form, + governedAccount, + handleSetInstructions, + index, + connection, + schema, + wallet, + ]) + useEffect(() => { + setGovernedAccount(form.delegateToken?.governance) + }, [form.delegateToken?.governance]) + + // TODO: Include this in the config instruction which can optionally be done + // if the project doesnt need to change where the tokens get returned to. + return ( + <> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'delegateAccount', + }) + } + error={formErrors['delegateAccount']} + /> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'realm', + }) + } + error={formErrors['realm']} + /> + + { + handleSetForm({ value, propertyName: 'delegateToken' }) + }} + value={form.delegateToken} + error={formErrors['delegateToken']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + type="token" + > + + + ) +} + +export default DualDelegate diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/DualExercise.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualExercise.tsx new file mode 100644 index 0000000000..7cd76971dc --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualExercise.tsx @@ -0,0 +1,148 @@ +import React, { useContext, useEffect, useMemo, useState } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceExerciseForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import GovernedAccountSelect from '../../GovernedAccountSelect' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import Input from '@components/inputs/Input' +import { getExerciseInstruction } from '@utils/instructions/Dual' +import { getDualFinanceExerciseSchema } from '@utils/validations' +import Tooltip from '@components/Tooltip' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' + +const DualExercise = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + numTokens: 0, + soName: undefined, + baseTreasury: undefined, + quoteTreasury: undefined, + optionAccount: undefined, + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + const [governedAccount, setGovernedAccount] = useState< + ProgramAccount | undefined + >(undefined) + + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + } + const schema = useMemo(getDualFinanceExerciseSchema, []) + useEffect(() => { + function getInstruction(): Promise { + return getExerciseInstruction({ + connection, + form, + schema, + setFormErrors, + wallet, + }) + } + handleSetInstructions( + { governedAccount: governedAccount, getInstruction }, + index + ) + }, [ + form, + governedAccount, + handleSetInstructions, + index, + connection, + schema, + wallet, + ]) + useEffect(() => { + setGovernedAccount(form.baseTreasury?.governance) + }, [form.baseTreasury]) + + // TODO: Find the name from a lookup of all staking option states + return ( + <> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'soName', + }) + } + error={formErrors['soName']} + /> + + + { + handleSetForm({ value, propertyName: 'optionAccount' }) + }} + value={form.optionAccount} + error={formErrors['optionAccount']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + type="token" + > + + + { + handleSetForm({ value, propertyName: 'quoteTreasury' }) + }} + value={form.quoteTreasury} + error={formErrors['quoteTreasury']} + governance={governance} + type="token" + > + + + { + handleSetForm({ value, propertyName: 'baseTreasury' }) + }} + value={form.baseTreasury} + error={formErrors['baseTreasury']} + governance={governance} + type="token" + > + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'numTokens', + }) + } + error={formErrors['numTokens']} + /> + + + ) +} + +export default DualExercise diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/DualGso.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualGso.tsx new file mode 100644 index 0000000000..8d7aa580b0 --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualGso.tsx @@ -0,0 +1,239 @@ +import React, { useContext, useEffect, useState } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceGsoForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import GovernedAccountSelect from '../../GovernedAccountSelect' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import Input from '@components/inputs/Input' +import { getConfigGsoInstruction } from '@utils/instructions/Dual' +import { getDualFinanceGsoSchema } from '@utils/validations' +import Tooltip from '@components/Tooltip' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' + +const DualGso = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + soName: undefined, + optionExpirationUnixSeconds: 0, + numTokens: 0, + lotSize: 0, + lockupMint: '', + baseTreasury: undefined, + quoteTreasury: undefined, + payer: undefined, + strike: 0, + subscriptionPeriodEnd: 0, + lockupRatio: 0 + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + const [governedAccount, setGovernedAccount] = useState< + ProgramAccount | undefined + >(undefined) + + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + } + const schema = getDualFinanceGsoSchema({form}) + useEffect(() => { + function getInstruction(): Promise { + return getConfigGsoInstruction({ + connection, + form, + schema, + setFormErrors, + wallet, + }) + } + handleSetInstructions( + { governedAccount: governedAccount, getInstruction }, + index + ) + }, [ + form, + governedAccount, + handleSetInstructions, + index, + connection, + schema, + wallet, + ]) + useEffect(() => { + setGovernedAccount(form.baseTreasury?.governance) + }, [form.baseTreasury]) + + return ( + <> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'soName', + }) + } + error={formErrors['soName']} + /> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'lockupMint', + }) + } + error={formErrors['lockupMint']} + /> + + { + handleSetForm({ value, propertyName: 'baseTreasury' }) + }} + value={form.baseTreasury} + error={formErrors['baseTreasury']} + governance={governance} + type="token" + > + + + { + handleSetForm({ value, propertyName: 'quoteTreasury' }) + }} + value={form.quoteTreasury} + error={formErrors['quoteTreasury']} + governance={governance} + type="token" + > + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'numTokens', + }) + } + error={formErrors['numTokens']} + /> + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'optionExpirationUnixSeconds', + }) + } + error={formErrors['optionExpirationUnixSeconds']} + /> + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'subscriptionPeriodEnd', + }) + } + error={formErrors['subscriptionPeriodEnd']} + /> + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'strike', + }) + } + error={formErrors['strike']} + /> + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'lockupRatio', + }) + } + error={formErrors['lockupRatio']} + /> + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'lotSize', + }) + } + error={formErrors['lotSize']} + /> + + + + x.isSol && + form.baseTreasury?.governance && + x.governance.pubkey.equals(form.baseTreasury.governance.pubkey) + )} + onChange={(value) => { + handleSetForm({ value, propertyName: 'payer' }) + }} + value={form.payer} + error={formErrors['payer']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + > + + + ) +} + +export default DualGso diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/DualGsoWithdraw.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualGsoWithdraw.tsx new file mode 100644 index 0000000000..72abd3ab05 --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualGsoWithdraw.tsx @@ -0,0 +1,98 @@ +import React, { useCallback, useContext, useEffect, useState } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceGsoWithdrawForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import { getGsoWithdrawInstruction } from '@utils/instructions/Dual' +import { getDualFinanceGsoWithdrawSchema } from '@utils/validations' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import Input from '@components/inputs/Input' +import GovernedAccountSelect from '../../GovernedAccountSelect' +import Tooltip from '@components/Tooltip' + +const DualGsoWithdraw = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + soName: undefined, + baseTreasury: undefined, + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + const [governedAccount, setGovernedAccount] = useState< + ProgramAccount | undefined + >(undefined) + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = useCallback(({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + }, [form]) + const schema = getDualFinanceGsoWithdrawSchema() + useEffect(() => { + function getInstruction(): Promise { + return getGsoWithdrawInstruction({ + connection, + form, + schema, + setFormErrors, + wallet, + }) + } + handleSetInstructions( + { governedAccount: governedAccount, getInstruction }, + index + ) + }, [form, governedAccount, handleSetInstructions, index, connection, wallet]) + useEffect(() => { + handleSetForm({ value: undefined, propertyName: 'mintPk' }) + }, [form.baseTreasury]) + useEffect(() => { + setGovernedAccount(form.baseTreasury?.governance) + }, [form.baseTreasury]) + + return ( + <> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'soName', + }) + } + error={formErrors['soName']} + /> + + + { + handleSetForm({ value, propertyName: 'baseTreasury' }) + }} + value={form.baseTreasury} + error={formErrors['baseTreasury']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + type="token" + > + + + ) +} + +export default DualGsoWithdraw diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/DualVoteDeposit.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualVoteDeposit.tsx new file mode 100644 index 0000000000..10a4646d18 --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualVoteDeposit.tsx @@ -0,0 +1,111 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { useContext, useEffect, useState } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceVoteDepositForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import GovernedAccountSelect from '../../GovernedAccountSelect' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import Input from '@components/inputs/Input' +import { getVoteDepositInstruction } from '@utils/instructions/Dual/delegate' +import { getDualFinanceVoteDepositSchema } from '@utils/validations' +import Tooltip from '@components/Tooltip' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { useRealmPubkeyByPkOrSymbol } from '@hooks/selectedRealm/useSelectedRealmPubkey' + +const DualVoteDeposit = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + numTokens: 0, + realm: '', + delegateToken: undefined, + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + } + + const realmInputParsed = useRealmPubkeyByPkOrSymbol(form.realm) + + useEffect(() => { + const schema = getDualFinanceVoteDepositSchema() + function getInstruction(): Promise { + return getVoteDepositInstruction({ + connection, + form, + schema, + setFormErrors, + wallet, + realmPk: realmInputParsed, + }) + } + handleSetInstructions( + { governedAccount: form.delegateToken?.governance, getInstruction }, + index + ) + }, [form, handleSetInstructions, index, connection, wallet, realmInputParsed]) + + // TODO: Include this in the config instruction which can optionally be done + // if the project doesnt need to change where the tokens get returned to. + return ( + <> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'numTokens', + }) + } + error={formErrors['numTokens']} + /> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'realm', + }) + } + error={formErrors['realm']} + /> + + { + handleSetForm({ value, propertyName: 'delegateToken' }) + }} + value={form.delegateToken} + error={formErrors['delegateToken']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + type="token" + > + + + ) +} + +export default DualVoteDeposit diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/DualVoteDepositWithdraw.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualVoteDepositWithdraw.tsx new file mode 100644 index 0000000000..0f8ec6d2ba --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualVoteDepositWithdraw.tsx @@ -0,0 +1,103 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import React, { useContext, useEffect, useMemo, useState } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceDelegateWithdrawForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import { getDelegateWithdrawInstruction } from '@utils/instructions/Dual/delegate' +import { getDualFinanceDelegateWithdrawSchema } from '@utils/validations' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' + +const DualVoteDepositWithdraw = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + realm: undefined, + delegateToken: undefined, + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + const [governedAccount, setGovernedAccount] = useState< + ProgramAccount | undefined + >(undefined) + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + } + console.log(shouldBeGoverned, assetAccounts, formErrors, handleSetForm) + const schema = useMemo(getDualFinanceDelegateWithdrawSchema, []) + useEffect(() => { + function getInstruction(): Promise { + return getDelegateWithdrawInstruction({ + connection, + form, + schema, + setFormErrors, + wallet, + }) + } + handleSetInstructions( + { governedAccount: governedAccount, getInstruction }, + index + ) + }, [ + form, + governedAccount, + handleSetInstructions, + index, + connection, + schema, + wallet, + ]) + useEffect(() => { + setGovernedAccount(form.delegateToken?.governance) + }, [form.delegateToken?.governance]) + + // TODO: Include this in the config instruction which can optionally be done + // if the project doesnt need to change where the tokens get returned to. + return ( + <> + {/* + handleSetForm({ + value: evt.target.value, + propertyName: 'realm', + }) + } + error={formErrors['realm']} + /> + + { + handleSetForm({ value, propertyName: 'delegateToken' }) + }} + value={form.delegateToken} + error={formErrors['delegateToken']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + type="token" + > + */} +
Not implemented
+ + ) +} + +export default DualVoteDepositWithdraw diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/DualWithdraw.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualWithdraw.tsx new file mode 100644 index 0000000000..d1a062dec7 --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/DualWithdraw.tsx @@ -0,0 +1,115 @@ +import React, { useContext, useEffect, useState, useMemo } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceWithdrawForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import { getWithdrawInstruction } from '@utils/instructions/Dual' +import { getDualFinanceWithdrawSchema } from '@utils/validations' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import Input from '@components/inputs/Input' +import GovernedAccountSelect from '../../GovernedAccountSelect' +import Tooltip from '@components/Tooltip' + +const DualWithdraw = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + soName: undefined, + baseTreasury: undefined, + mintPk: undefined, + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + const [governedAccount, setGovernedAccount] = useState< + ProgramAccount | undefined + >(undefined) + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + } + const schema = useMemo(getDualFinanceWithdrawSchema, []) + useEffect(() => { + function getInstruction(): Promise { + return getWithdrawInstruction({ + connection, + form, + schema, + setFormErrors, + wallet, + }) + } + handleSetInstructions( + { governedAccount: governedAccount, getInstruction }, + index + ) + }, [form, governedAccount, handleSetInstructions, index, connection, wallet]) + useEffect(() => { + handleSetForm({ value: undefined, propertyName: 'mintPk' }) + }, [form.baseTreasury]) + useEffect(() => { + setGovernedAccount(form.baseTreasury?.governance) + }, [form.baseTreasury]) + + // TODO: Include this in the config instruction which can optionally be done + // if the project doesnt need to change where the tokens get returned to. + return ( + <> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'soName', + }) + } + error={formErrors['soName']} + /> + + + { + handleSetForm({ value, propertyName: 'baseTreasury' }) + }} + value={form.baseTreasury} + error={formErrors['baseTreasury']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + type="token" + > + + {form.baseTreasury?.isSol && ( + + handleSetForm({ + value: evt.target.value, + propertyName: 'mintPk', + }) + } + error={formErrors['mintPk']} + /> + )} + + ) +} + +export default DualWithdraw diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/InitStrike.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/InitStrike.tsx new file mode 100644 index 0000000000..a381d80fd7 --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/InitStrike.tsx @@ -0,0 +1,128 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import React, { useContext, useEffect, useState, useMemo } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceInitStrikeForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import GovernedAccountSelect from '../../GovernedAccountSelect' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import Input from '@components/inputs/Input' +import { getInitStrikeInstruction } from '@utils/instructions/Dual' +import { getDualFinanceInitStrikeSchema } from '@utils/validations' +import Tooltip from '@components/Tooltip' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' + +const InitStrike = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + payer: undefined, + baseTreasury: undefined, + soName: '', + strikes: '', + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + const [governedAccount, setGovernedAccount] = useState< + ProgramAccount | undefined + >(undefined) + + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + } + function getInstruction(): Promise { + return getInitStrikeInstruction({ + connection, + form, + schema, + setFormErrors, + wallet, + }) + } + useEffect(() => { + handleSetInstructions( + { governedAccount: governedAccount, getInstruction }, + index + ) + }, [form]) + useEffect(() => { + setGovernedAccount(form.baseTreasury?.governance) + }, [form.baseTreasury]) + const schema = useMemo(getDualFinanceInitStrikeSchema, []) + + return ( + <> + + handleSetForm({ + value: evt.target.value, + propertyName: 'soName', + }) + } + error={formErrors['soName']} + /> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'strikes', + }) + } + error={formErrors['strikes']} + /> + + + { + handleSetForm({ value, propertyName: 'baseTreasury' }) + }} + value={form.baseTreasury} + error={formErrors['baseTreasury']} + governance={governance} + type="token" + > + + + + x.isSol && + form.baseTreasury?.governance && + x.governance.pubkey.equals(form.baseTreasury.governance.pubkey) + )} + onChange={(value) => { + handleSetForm({ value, propertyName: 'payer' }) + }} + value={form.payer} + error={formErrors['payer']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + > + + + ) +} + +export default InitStrike diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/LiquidityStakingOption.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/LiquidityStakingOption.tsx new file mode 100644 index 0000000000..9ae48026d9 --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/LiquidityStakingOption.tsx @@ -0,0 +1,159 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import React, { useContext, useEffect, useState } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceLiquidityStakingOptionForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import GovernedAccountSelect from '../../GovernedAccountSelect' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import Input from '@components/inputs/Input' +import { getConfigLsoInstruction } from '@utils/instructions/Dual' +import { getDualFinanceLiquidityStakingOptionSchema } from '@utils/validations' +import Tooltip from '@components/Tooltip' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' + +const LiquidityStakingOption = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + optionExpirationUnixSeconds: 0, + numTokens: 0, + lotSize: 0, + baseTreasury: undefined, + quoteTreasury: undefined, + payer: undefined, + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + const [governedAccount, setGovernedAccount] = useState< + ProgramAccount | undefined + >(undefined) + + const [formErrors, setFormErrors] = useState({}) + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + } + function getInstruction(): Promise { + return getConfigLsoInstruction({ + connection, + form, + schema, + setFormErrors, + wallet, + }) + } + useEffect(() => { + handleSetInstructions( + { governedAccount: governedAccount, getInstruction }, + index + ) + }, [form]) + useEffect(() => { + setGovernedAccount(form.baseTreasury?.governance) + }, [form.baseTreasury]) + const schema = getDualFinanceLiquidityStakingOptionSchema({form}) + + return ( + <> + + { + handleSetForm({ value, propertyName: 'baseTreasury' }) + }} + value={form.baseTreasury} + error={formErrors['baseTreasury']} + governance={governance} + type="token" + > + + + { + handleSetForm({ value, propertyName: 'quoteTreasury' }) + }} + value={form.quoteTreasury} + error={formErrors['quoteTreasury']} + governance={governance} + type="token" + > + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'numTokens', + }) + } + error={formErrors['numTokens']} + /> + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'optionExpirationUnixSeconds', + }) + } + error={formErrors['optionExpirationUnixSeconds']} + /> + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'lotSize', + }) + } + error={formErrors['lotSize']} + /> + + + + x.isSol && + form.baseTreasury?.governance && + x.governance.pubkey.equals(form.baseTreasury.governance.pubkey) + )} + onChange={(value) => { + handleSetForm({ value, propertyName: 'payer' }) + }} + value={form.payer} + error={formErrors['payer']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + > + + + ) +} + +export default LiquidityStakingOption diff --git a/pages/dao/[symbol]/proposal/components/instructions/Dual/StakingOption.tsx b/pages/dao/[symbol]/proposal/components/instructions/Dual/StakingOption.tsx new file mode 100644 index 0000000000..5bb64c82e1 --- /dev/null +++ b/pages/dao/[symbol]/proposal/components/instructions/Dual/StakingOption.tsx @@ -0,0 +1,284 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import React, { useContext, useEffect, useState } from 'react' +import { ProgramAccount, Governance } from '@solana/spl-governance' +import { + UiInstruction, + DualFinanceStakingOptionForm, +} from '@utils/uiTypes/proposalCreationTypes' +import { NewProposalContext } from '../../../new' +import GovernedAccountSelect from '../../GovernedAccountSelect' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import Input from '@components/inputs/Input' +import { getConfigInstruction } from '@utils/instructions/Dual' +import { getDualFinanceStakingOptionSchema } from '@utils/validations' +import Tooltip from '@components/Tooltip' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools' + +interface MintMetadata { + logo: string, + name: string, + symbol: string, + displayPrice: string, + decimals: number, +} + +const StakingOption = ({ + index, + governance, +}: { + index: number + governance: ProgramAccount | null +}) => { + const [form, setForm] = useState({ + soName: undefined, + optionExpirationUnixSeconds: 0, + numTokens: '0', + lotSize: 1, + baseTreasury: undefined, + quoteTreasury: undefined, + payer: undefined, + userPk: undefined, + strike: 0, + }) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const shouldBeGoverned = !!(index !== 0 && governance) + const { assetAccounts } = useGovernanceAssets() + const [governedAccount, setGovernedAccount] = useState< + ProgramAccount | undefined + >(undefined) + + const [formErrors, setFormErrors] = useState({}) + + const [baseMetadata, setBaseMetadata] = useState() + const [quoteMetadata, setQuoteMetadata] = useState() + + const { handleSetInstructions } = useContext(NewProposalContext) + const handleSetForm = ({ propertyName, value }) => { + setFormErrors({}) + setForm({ ...form, [propertyName]: value }) + } + const schema = getDualFinanceStakingOptionSchema({form, connection}); + useEffect(() => { + function getInstruction(): Promise { + return getConfigInstruction({ + connection, + form, + schema, + setFormErrors, + wallet, + }) + } + handleSetInstructions( + { governedAccount: governedAccount, getInstruction }, + index + ) + if (form.baseTreasury && form.baseTreasury.extensions.mint && form.baseTreasury.extensions.mint.account.decimals) { + const { + logo, + name, + symbol, + displayPrice, + } = getTreasuryAccountItemInfoV2(form.baseTreasury) + setBaseMetadata({ + logo, + name, + symbol, + displayPrice, + decimals: form.baseTreasury.extensions.mint.account.decimals + }) + } else { + setBaseMetadata(undefined) + } + if (form.quoteTreasury && form.quoteTreasury.extensions.mint && form.quoteTreasury.extensions.mint.account.decimals) { + const { + logo, + name, + symbol, + displayPrice, + } = getTreasuryAccountItemInfoV2(form.quoteTreasury) + setQuoteMetadata({ + logo, + name, + symbol, + displayPrice, + decimals: form.quoteTreasury.extensions.mint.account.decimals + }) + } else { + setQuoteMetadata(undefined) + } + }, [ + form, + governedAccount, + handleSetInstructions, + index, + connection, + schema, + wallet, + ]) + useEffect(() => { + setGovernedAccount(form.baseTreasury?.governance) + }, [form.baseTreasury]) + + return ( + <> + + + handleSetForm({ + value: evt.target.value, + propertyName: 'soName', + }) + } + error={formErrors['soName']} + /> + + + { + handleSetForm({ value, propertyName: 'baseTreasury' }) + }} + value={form.baseTreasury} + error={formErrors['baseTreasury']} + governance={governance} + type="token" + > + + + { + handleSetForm({ value, propertyName: 'quoteTreasury' }) + }} + value={form.quoteTreasury} + error={formErrors['quoteTreasury']} + governance={governance} + type="token" + > + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'numTokens', + }) + } + error={formErrors['numTokens']} + /> + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'optionExpirationUnixSeconds', + }) + } + error={formErrors['optionExpirationUnixSeconds']} + /> + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'strike', + }) + } + error={formErrors['strike']} + /> + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'lotSize', + }) + } + error={formErrors['lotSize']} + /> + + + + x.isSol && + form.baseTreasury?.governance && + x.governance.pubkey.equals(form.baseTreasury.governance.pubkey) + )} + onChange={(value) => { + handleSetForm({ value, propertyName: 'payer' }) + }} + value={form.payer} + error={formErrors['payer']} + shouldBeGoverned={shouldBeGoverned} + governance={governance} + > + + + + handleSetForm({ + value: evt.target.value, + propertyName: 'userPk', + }) + } + error={formErrors['userPk']} + /> + + {baseMetadata && quoteMetadata && ( + <> +
+ {form.strike / form.lotSize * 10 ** (-quoteMetadata.decimals + baseMetadata.decimals) * (Number(form.numTokens) / 10 ** baseMetadata.decimals)} + { + currentTarget.onerror = null // prevents looping + currentTarget.hidden = true + }} + /> + = + {Number(form.numTokens) / 10 ** baseMetadata.decimals} + { + currentTarget.onerror = null // prevents looping + currentTarget.hidden = true + }} + /> + + + )} + + ) +} + +export default StakingOption diff --git a/pages/dao/[symbol]/proposal/components/instructions/Empty.tsx b/pages/dao/[symbol]/proposal/components/instructions/Empty.tsx index 8f2d384ee3..f93190a006 100644 --- a/pages/dao/[symbol]/proposal/components/instructions/Empty.tsx +++ b/pages/dao/[symbol]/proposal/components/instructions/Empty.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect, useState } from 'react' +import { useContext, useEffect, useState } from 'react' import * as yup from 'yup' import { Governance, ProgramAccount } from '@solana/spl-governance' import { validateInstruction } from '@utils/instructionTools' @@ -8,8 +8,8 @@ import { } from '@utils/uiTypes/proposalCreationTypes' import { NewProposalContext } from '../../new' import GovernedAccountSelect from '../GovernedAccountSelect' -import useRealm from '@hooks/useRealm' import useGovernanceAssets from '@hooks/useGovernanceAssets' +import { useLegacyVoterWeight } from '@hooks/queries/governancePower' const Empty = ({ index, governance, @@ -20,9 +20,9 @@ const Empty = ({ const [form, setForm] = useState({ governedAccount: undefined, }) - const { ownVoterWeight } = useRealm() + const { result: ownVoterWeight } = useLegacyVoterWeight() const { assetAccounts } = useGovernanceAssets() - const shouldBeGoverned = index !== 0 && governance + const shouldBeGoverned = !!(index !== 0 && governance) const [formErrors, setFormErrors] = useState({}) const { handleSetInstructions } = useContext(NewProposalContext) const handleSetForm = ({ propertyName, value }) => { @@ -44,6 +44,7 @@ const Empty = ({ { governedAccount: form.governedAccount?.governance, getInstruction }, index ) + // 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]) const schema = yup.object().shape({ governedAccount: yup @@ -53,9 +54,9 @@ const Empty = ({ }) return ( - ownVoterWeight.canCreateProposal(x.governance.account.config) + ownVoterWeight?.canCreateProposal(x.governance.account.config) )} onChange={(value) => { handleSetForm({ value, propertyName: 'governedAccount' }) diff --git a/pages/dao/[symbol]/proposal/components/instructions/Everlend/DepositForm.tsx b/pages/dao/[symbol]/proposal/components/instructions/Everlend/DepositForm.tsx deleted file mode 100644 index 91a143d426..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Everlend/DepositForm.tsx +++ /dev/null @@ -1,232 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import React, { useContext, useEffect, useState } from 'react' -import * as yup from 'yup' - -import { - Governance, - ProgramAccount, - serializeInstructionToBase64, -} from '@solana/spl-governance' -import { PublicKey } from '@solana/web3.js' -import Input from '@components/inputs/Input' -import useRealm from '@hooks/useRealm' -import { isFormValid } from '@utils/formValidation' -import { - DepositReserveLiquidityAndObligationCollateralForm, - UiInstruction, -} from '@utils/uiTypes/proposalCreationTypes' -import useWalletStore from 'stores/useWalletStore' -import { NewProposalContext } from '../../../new' -import GovernedAccountSelect from '../../GovernedAccountSelect' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { handleEverlendDeposit } from 'Strategies/protocols/everlend/depositTools' -import { getEverlendStrategies } from 'Strategies/protocols/everlend/tools' -import { - CONFIG_MAINNET, - REGISTRY_MAIN, - REWARD_PROGRAM_ID, -} from 'Strategies/protocols/everlend/constants' -import { getMintNaturalAmountFromDecimalAsBN } from '@tools/sdk/units' -import { - ASSOCIATED_TOKEN_PROGRAM_ID, - Token, - TOKEN_PROGRAM_ID, -} from '@solana/spl-token' - -const DepositForm = ({ - index, - governance, -}: { - index: number - governance: ProgramAccount | null -}) => { - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const { realmInfo } = useRealm() - const [stratagies, setStratagies] = useState([]) - - const { assetAccounts } = useGovernanceAssets() - // Hardcoded gate used to be clear about what cluster is supported for now - if (connection.cluster !== 'mainnet') { - return <>This instruction does not support {connection.cluster} - } - - useEffect(() => { - const fetchStratagies = async () => { - const fetchedStratagies = await getEverlendStrategies(connection) - setStratagies(fetchedStratagies) - } - - fetchStratagies() - }, []) - - const shouldBeGoverned = index !== 0 && governance - const programId: PublicKey | undefined = realmInfo?.programId - const [ - form, - setForm, - ] = useState({ - uiAmount: '0', - }) - const [formErrors, setFormErrors] = useState({}) - const { handleSetInstructions } = useContext(NewProposalContext) - - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - - const validateInstruction = async (): Promise => { - const { isValid, validationErrors } = await isFormValid(schema, form) - setFormErrors(validationErrors) - return isValid - } - console.log(form.governedAccount) - - async function getInstruction(): Promise { - const isValid = await validateInstruction() - - if ( - !connection || - !isValid || - !programId || - !form.governedAccount?.governance?.account || - !wallet?.publicKey - ) { - return { - serializedInstruction: '', - isValid: false, - governance: form.governedAccount?.governance, - } - } - - const owner = form.governedAccount.governance.owner - const isSol = form.governedAccount.isSol - - const REGISTRY = new PublicKey(REGISTRY_MAIN) - const CONFIG = new PublicKey(CONFIG_MAINNET) - - console.log(stratagies) - - const matchedStratagie = stratagies.find( - (el) => - el.handledMint === - form.governedAccount?.extensions.mint?.publicKey.toString() - ) - - console.log(matchedStratagie) - - const [rewardPool] = PublicKey.findProgramAddressSync( - [ - Buffer.from('reward_pool'), - CONFIG.toBuffer(), - new PublicKey(matchedStratagie.handledMint).toBuffer(), - ], - REWARD_PROGRAM_ID - ) - const [rewardAccount] = PublicKey.findProgramAddressSync( - [Buffer.from('mining'), owner.toBuffer(), rewardPool.toBuffer()], - REWARD_PROGRAM_ID - ) - - const ctokenATA = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - new PublicKey(matchedStratagie.handledMint), - owner, - true - ) - - const liquidityATA = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - new PublicKey(matchedStratagie.poolMint), - owner, - true - ) - - const { actionTx: tx } = await handleEverlendDeposit( - wallet, - Boolean(isSol), - connection, - owner, - REGISTRY, - CONFIG, - rewardPool, - rewardAccount, - matchedStratagie.poolPubKey, - getMintNaturalAmountFromDecimalAsBN( - +form.uiAmount as number, - form.governedAccount.extensions.mint!.account.decimals - ), - ctokenATA, - liquidityATA - ) - - return { - serializedInstruction: serializeInstructionToBase64(tx.instructions[0]), - isValid: true, - governance: form.governedAccount.governance, - } - } - - useEffect(() => { - handleSetForm({ - propertyName: 'programId', - value: programId?.toString(), - }) - }, [programId]) - - useEffect(() => { - handleSetInstructions( - { - governedAccount: form.governedAccount?.governance, - getInstruction, - }, - index - ) - }, [form]) - - const schema = yup.object().shape({ - governedAccount: yup - .object() - .nullable() - .required('Governed account is required'), - uiAmount: yup - .number() - .moreThan(0, 'Amount should be more than 0') - .required('Amount is required'), - }) - - return ( - <> - { - handleSetForm({ value, propertyName: 'governedAccount' }) - }} - value={form.governedAccount} - error={formErrors['governedAccount']} - shouldBeGoverned={shouldBeGoverned} - governance={governance} - /> - - - handleSetForm({ - value: evt.target.value, - propertyName: 'uiAmount', - }) - } - error={formErrors['uiAmount']} - /> - - ) -} - -export default DepositForm diff --git a/pages/dao/[symbol]/proposal/components/instructions/Everlend/WithdrawForm.tsx b/pages/dao/[symbol]/proposal/components/instructions/Everlend/WithdrawForm.tsx deleted file mode 100644 index 1c025d25d4..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Everlend/WithdrawForm.tsx +++ /dev/null @@ -1,231 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import React, { useContext, useEffect, useState } from 'react' -import * as yup from 'yup' - -import { - Governance, - ProgramAccount, - serializeInstructionToBase64, -} from '@solana/spl-governance' -import { PublicKey } from '@solana/web3.js' -import Input from '@components/inputs/Input' -import useRealm from '@hooks/useRealm' -import { isFormValid } from '@utils/formValidation' -import { - DepositReserveLiquidityAndObligationCollateralForm, - UiInstruction, -} from '@utils/uiTypes/proposalCreationTypes' -import useWalletStore from 'stores/useWalletStore' -import { NewProposalContext } from '../../../new' -import GovernedAccountSelect from '../../GovernedAccountSelect' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { handleEverlendWithdraw } from 'Strategies/protocols/everlend/depositTools' -import { getEverlendStrategies } from 'Strategies/protocols/everlend/tools' -import { - CONFIG_MAINNET, - REGISTRY_MAIN, - REWARD_PROGRAM_ID, -} from 'Strategies/protocols/everlend/constants' -import { getMintNaturalAmountFromDecimalAsBN } from '@tools/sdk/units' -import { - ASSOCIATED_TOKEN_PROGRAM_ID, - Token, - TOKEN_PROGRAM_ID, -} from '@solana/spl-token' - -const WithdrawForm = ({ - index, - governance, -}: { - index: number - governance: ProgramAccount | null -}) => { - const connection = useWalletStore((s) => s.connection) - const wallet = useWalletStore((s) => s.current) - const { realmInfo } = useRealm() - const [stratagies, setStratagies] = useState([]) - - const { assetAccounts } = useGovernanceAssets() - // Hardcoded gate used to be clear about what cluster is supported for now - if (connection.cluster !== 'mainnet') { - return <>This instruction does not support {connection.cluster} - } - - useEffect(() => { - const fetchStratagies = async () => { - const fetchedStratagies = await getEverlendStrategies(connection) - setStratagies(fetchedStratagies) - } - - fetchStratagies() - }, []) - - const shouldBeGoverned = index !== 0 && governance - const programId: PublicKey | undefined = realmInfo?.programId - const [ - form, - setForm, - ] = useState({ - uiAmount: '0', - }) - const [formErrors, setFormErrors] = useState({}) - const { handleSetInstructions } = useContext(NewProposalContext) - - const handleSetForm = ({ propertyName, value }) => { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - - const validateInstruction = async (): Promise => { - const { isValid, validationErrors } = await isFormValid(schema, form) - setFormErrors(validationErrors) - return isValid - } - console.log(form.governedAccount) - - async function getInstruction(): Promise { - const isValid = await validateInstruction() - - if ( - !connection || - !isValid || - !programId || - !form.governedAccount?.governance?.account || - !wallet?.publicKey - ) { - return { - serializedInstruction: '', - isValid: false, - governance: form.governedAccount?.governance, - } - } - - const owner = form.governedAccount.governance.owner - const isSol = form.governedAccount.isSol - - const REGISTRY = new PublicKey(REGISTRY_MAIN) - const CONFIG = new PublicKey(CONFIG_MAINNET) - - console.log(stratagies) - - const matchedStratagie = stratagies.find( - (el) => - el.handledMint === - form.governedAccount?.extensions.mint?.publicKey.toString() - ) - - console.log(matchedStratagie) - - const [rewardPool] = PublicKey.findProgramAddressSync( - [ - Buffer.from('reward_pool'), - CONFIG.toBuffer(), - new PublicKey(matchedStratagie.handledMint).toBuffer(), - ], - REWARD_PROGRAM_ID - ) - const [rewardAccount] = PublicKey.findProgramAddressSync( - [Buffer.from('mining'), owner.toBuffer(), rewardPool.toBuffer()], - REWARD_PROGRAM_ID - ) - - const ctokenATA = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - new PublicKey(matchedStratagie.handledMint), - owner, - true - ) - - const liquidityATA = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - new PublicKey(matchedStratagie.poolMint), - owner, - true - ) - - const { withdrawTx: tx } = await handleEverlendWithdraw( - Boolean(isSol), - connection, - owner, - REGISTRY, - CONFIG, - rewardPool, - rewardAccount, - matchedStratagie.poolPubKey, - getMintNaturalAmountFromDecimalAsBN( - +form.uiAmount as number, - form.governedAccount.extensions.mint!.account.decimals - ), - ctokenATA, - liquidityATA - ) - - return { - serializedInstruction: serializeInstructionToBase64(tx.instructions[0]), - isValid: true, - governance: form.governedAccount.governance, - } - } - - useEffect(() => { - handleSetForm({ - propertyName: 'programId', - value: programId?.toString(), - }) - }, [programId]) - - useEffect(() => { - handleSetInstructions( - { - governedAccount: form.governedAccount?.governance, - getInstruction, - }, - index - ) - }, [form]) - - const schema = yup.object().shape({ - governedAccount: yup - .object() - .nullable() - .required('Governed account is required'), - uiAmount: yup - .number() - .moreThan(0, 'Amount should be more than 0') - .required('Amount is required'), - }) - - return ( - <> - { - handleSetForm({ value, propertyName: 'governedAccount' }) - }} - value={form.governedAccount} - error={formErrors['governedAccount']} - shouldBeGoverned={shouldBeGoverned} - governance={governance} - /> - - - handleSetForm({ - value: evt.target.value, - propertyName: 'uiAmount', - }) - } - error={formErrors['uiAmount']} - /> - - ) -} - -export default WithdrawForm diff --git a/pages/dao/[symbol]/proposal/components/instructions/Execute.tsx b/pages/dao/[symbol]/proposal/components/instructions/Execute.tsx deleted file mode 100644 index dfac47e671..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Execute.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react' -import { RpcContext } from '@solana/spl-governance' -import useWalletStore from 'stores/useWalletStore' -import useRealm from 'hooks/useRealm' -import Button, { SecondaryButton } from '@components/Button' -import { notify } from 'utils/notifications' -import Modal from '@components/Modal' -import { executeTransaction } from 'actions/executeTransaction' -import { ProposalTransaction } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import { getProgramVersionForRealm } from '@models/registry/api' - -type ExecuteInstructionProps = { - onClose: () => void - isOpen: boolean - instruction: ProgramAccount | any -} - -const ExecuteInstruction = ({ - onClose, - isOpen, - instruction, -}: ExecuteInstructionProps) => { - const wallet = useWalletStore((s) => s.current) - const connection = useWalletStore((s) => s.connection) - const { proposal } = useWalletStore((s) => s.selectedProposal) - const { realmInfo } = useRealm() - - const handleExecuteInstruction = async () => { - try { - if (proposal && realmInfo) { - const rpcContext = new RpcContext( - proposal.owner, - getProgramVersionForRealm(realmInfo), - wallet!, - connection.current, - connection.endpoint - ) - - await executeTransaction(rpcContext, proposal, instruction) - - onClose() - } - } catch (error) { - notify({ - type: 'error', - message: `Error: Could not execute instruction.`, - }) - - console.log('error executing instruction', error) - - onClose() - } - } - - return ( - -

Execute instruction

- -

Do you want to execute instruction?

- -
- - No - - - -
-
- ) -} - -export default ExecuteInstruction diff --git a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeAddMarketListToCategoryParams.tsx b/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeAddMarketListToCategoryParams.tsx deleted file mode 100644 index 488c3fbe6e..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeAddMarketListToCategoryParams.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import React from 'react' -import { ForesightMakeAddMarketListToCategoryParams } from '@utils/uiTypes/proposalCreationTypes' -import { Governance } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import { governance as foresightGov } from '@foresight-tmp/foresight-sdk' -import { - commonAssets, - ForesightCategoryIdInput, - ForesightMarketListIdInput, -} from '@utils/Foresight' - -function MakeAddMarketListToCategoryParams({ - index, - governance, -}: { - index: number - governance: ProgramAccount | null -}) { - const { - inputProps, - effector, - governedAccountSelect, - wallet, - } = commonAssets( - { categoryId: '', marketListId: '' }, - index, - governance - ) - async function ixCreator(form: ForesightMakeAddMarketListToCategoryParams) { - const { ix } = await foresightGov.genAddMarketListToCategoryIx( - Buffer.from(form.categoryId.padEnd(20)), - Buffer.from(form.marketListId.padEnd(20)), - wallet!.publicKey! - ) - return ix - } - effector(ixCreator) - - return ( - <> - {governedAccountSelect} - - - - ) -} - -export default MakeAddMarketListToCategoryParams diff --git a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeInitCategoryParams.tsx b/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeInitCategoryParams.tsx deleted file mode 100644 index 04003cf3da..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeInitCategoryParams.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import React from 'react' -import { ForesightHasCategoryId } from '@utils/uiTypes/proposalCreationTypes' -import { Governance } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import { governance as foresightGov } from '@foresight-tmp/foresight-sdk' -import { commonAssets, ForesightCategoryIdInput } from '@utils/Foresight' - -const MakeInitCategoryParams = ({ - index, - governance, -}: { - index: number - governance: ProgramAccount | null -}) => { - const { - inputProps, - effector, - governedAccountSelect, - wallet, - } = commonAssets( - { categoryId: '' }, - index, - governance - ) - async function ixCreator(form: ForesightHasCategoryId) { - const { ix } = await foresightGov.genInitCategoryIx( - Buffer.from(form.categoryId.padEnd(20)), - wallet!.publicKey! - ) - return ix - } - effector(ixCreator) - return ( - <> - {governedAccountSelect} - - - ) -} - -export default MakeInitCategoryParams diff --git a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeInitMarketListParams.tsx b/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeInitMarketListParams.tsx deleted file mode 100644 index 158a268b51..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeInitMarketListParams.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import React from 'react' -import { ForesightHasMarketListId } from '@utils/uiTypes/proposalCreationTypes' -import { Governance } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import { governance as foresightGov } from '@foresight-tmp/foresight-sdk' -import { commonAssets, ForesightMarketListIdInput } from '@utils/Foresight' - -const MakeInitMarketListParams = ({ - index, - governance, -}: { - index: number - governance: ProgramAccount | null -}) => { - const { - inputProps, - effector, - governedAccountSelect, - wallet, - } = commonAssets( - { marketListId: '' }, - index, - governance - ) - async function ixCreator(form: ForesightHasMarketListId) { - const { ix } = await foresightGov.genInitMarketListIx( - Buffer.from(form.marketListId.padEnd(20)), - wallet!.publicKey!, - form.governedAccount.extensions.transferAddress! - ) - return ix - } - effector(ixCreator) - - return ( - <> - {governedAccountSelect} - - - ) -} - -export default MakeInitMarketListParams diff --git a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeInitMarketParams.tsx b/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeInitMarketParams.tsx deleted file mode 100644 index c7a5386b3e..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeInitMarketParams.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import React from 'react' -import { ForesightHasMarketId } from '@utils/uiTypes/proposalCreationTypes' -import { Governance } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import { governance as foresightGov, utils } from '@foresight-tmp/foresight-sdk' -import { - commonAssets, - ForesightMarketIdInput, - ForesightMarketListIdInput, -} from '@utils/Foresight' - -const MakeInitMarketParams = ({ - index, - governance, -}: { - index: number - governance: ProgramAccount | null -}) => { - const { - inputProps, - effector, - governedAccountSelect, - wallet, - } = commonAssets( - { marketListId: '', marketId: 0 }, - index, - governance - ) - async function ixCreator(form: ForesightHasMarketId) { - const { ix } = await foresightGov.genInitMarketIx( - Buffer.from(form.marketListId.padEnd(20)), - utils.intToArray(form.marketId, 1), - wallet!.publicKey! - ) - return ix - } - effector(ixCreator) - - return ( - <> - {governedAccountSelect} - - - - ) -} - -export default MakeInitMarketParams diff --git a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeResolveMarketParams.tsx b/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeResolveMarketParams.tsx deleted file mode 100644 index 928e5850b1..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeResolveMarketParams.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import React from 'react' -import { ForesightMakeResolveMarketParams } from '@utils/uiTypes/proposalCreationTypes' -import { Governance } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import { governance as foresightGov, utils } from '@foresight-tmp/foresight-sdk' -import { - commonAssets, - ForesightMarketIdInput, - ForesightMarketListIdInput, - ForesightWinnerInput, -} from '@utils/Foresight' - -const MakeResolveMarketParams = ({ - index, - governance, -}: { - index: number - governance: ProgramAccount | null -}) => { - const { - inputProps, - effector, - governedAccountSelect, - } = commonAssets( - { marketListId: '', marketId: 0, winner: 0 }, - index, - governance - ) - async function ixCreator(form: ForesightMakeResolveMarketParams) { - const ix = await foresightGov.genResolveMarketIx( - form.winner, - utils.intToArray(form.marketId, 1), - Buffer.from(form.marketListId.padEnd(20)), - form.governedAccount.extensions.transferAddress! - ) - return ix - } - effector(ixCreator) - - return ( - <> - {governedAccountSelect} - - - - - ) -} - -export default MakeResolveMarketParams diff --git a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeSetMarketMetadataParams.tsx b/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeSetMarketMetadataParams.tsx deleted file mode 100644 index 4c5bfb82d4..0000000000 --- a/pages/dao/[symbol]/proposal/components/instructions/Foresight/MakeSetMarketMetadataParams.tsx +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import React from 'react' -import { ForesightMakeSetMarketMetadataParams } from '@utils/uiTypes/proposalCreationTypes' -import { Governance } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import { - governance as foresightGov, - consts as foresightConsts, - utils, -} from '@foresight-tmp/foresight-sdk' -import { - commonAssets, - ForesightContentInput, - ForesightMarketIdInput, - ForesightMarketListIdInput, - ForesightMarketMetadataFieldSelect, -} from '@utils/Foresight' - -export default function MakeSetMarketMetadataParams({ - index, - governance, -}: { - index: number - governance: ProgramAccount | null -}) { - const { - inputProps, - effector, - governedAccountSelect, - wallet, - } = commonAssets( - { - marketListId: '', - marketId: 0, - content: '', - field: Object.keys( - foresightConsts.MARKET_METADATA_FIELDS - )[0] as foresightConsts.MarketMetadataFieldName, - }, - index, - governance - ) - async function ixCreator(form: ForesightMakeSetMarketMetadataParams) { - const field = foresightConsts.MARKET_METADATA_FIELDS[form.field] - const { ix } = await foresightGov.genWriteToFieldMarketMetadataIx( - utils.intToArray(form.marketId, 1), - Buffer.from(form.marketListId.padEnd(20)), - form.content, - new field(), - wallet!.publicKey! - ) - return ix - } - effector(ixCreator) - return ( - <> - {governedAccountSelect} - - - - - - ) -} diff --git a/pages/dao/[symbol]/proposal/components/instructions/FormCreator.tsx b/pages/dao/[symbol]/proposal/components/instructions/FormCreator.tsx index db38c55ca8..17fd957967 100644 --- a/pages/dao/[symbol]/proposal/components/instructions/FormCreator.tsx +++ b/pages/dao/[symbol]/proposal/components/instructions/FormCreator.tsx @@ -7,27 +7,23 @@ import { precision } from '@utils/formatting' import Switch from '@components/Switch' import Select from '@components/inputs/Select' import { usePrevious } from '@hooks/usePrevious' - -export enum InstructionInputType { - GOVERNED_ACCOUNT, - INPUT, - TEXTAREA, - SWITCH, - SELECT, -} +import { DISABLED_VALUE } from '@tools/constants' +import { InstructionInputType } from './inputInstructionType' export interface InstructionInput { label: string + subtitle?: string initialValue: any name: string type: InstructionInputType + assetType?: 'mint' | 'token' | 'wallet' inputType?: string placeholder?: string min?: number max?: number step?: number onBlur?: () => void - shouldBeGoverned?: false | ProgramAccount | null + shouldBeGoverned?: boolean governance?: ProgramAccount | null options?: any[] hide?: boolean | (() => boolean) @@ -47,9 +43,9 @@ const InstructionForm = ({ setFormErrors: React.Dispatch> formErrors setForm: React.Dispatch> - outerForm: any + outerForm: { [key: string]: any } | undefined }) => { - const [form, setInnerForm] = useState({}) + const [form, setInnerForm] = useState(outerForm ? { ...outerForm } : {}) const handleSetForm = ({ propertyName, value }) => { setFormErrors({}) setInnerForm({ ...outerForm, [propertyName]: value }) @@ -57,14 +53,19 @@ const InstructionForm = ({ const previousInitialValue = usePrevious( JSON.stringify(inputs.map((x) => x.initialValue)) ) + useEffect(() => { setForm(form) + // 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 }, [JSON.stringify(form)]) + useEffect(() => { setInnerForm({ ...inputs.reduce((a, v) => ({ ...a, [v.name]: v.initialValue }), {}), }) + // 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 }, [ + // 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 previousInitialValue !== JSON.stringify(inputs.map((x) => x.initialValue)), ]) return ( @@ -106,7 +107,7 @@ const InstructionInput = ({ case InstructionInputType.GOVERNED_ACCOUNT: return ( { @@ -116,12 +117,15 @@ const InstructionInput = ({ error={formErrors[input.name]} shouldBeGoverned={input.shouldBeGoverned} governance={input.governance} + type={input.assetType} /> ) case InstructionInputType.SELECT: return ( { - handleSetForm({ - value: event.target.value, - propertyName: input.name, - }) + if (input.inputType === 'number') { + const isNumber = + event.target.value !== '' && + !isNaN(Number(event.target.value)) + + handleSetForm({ + value: isNumber + ? Number(event.target.value) + : event.target.value, + propertyName: input.name, + }) + } else { + handleSetForm({ + value: event.target.value, + propertyName: input.name, + }) + } }} step={input.step} error={formErrors[input.name]} @@ -184,7 +202,7 @@ const InstructionInput = ({ ? input.onBlur : input.validateMinMax ? validateAmountOnBlur - : null + : undefined } /> ) @@ -192,6 +210,7 @@ const InstructionInput = ({ case InstructionInputType.TEXTAREA: return ( - {canChooseWhoVote && ( + {shouldShowVoteByCouncilToggle && ( { @@ -805,79 +737,112 @@ const New = () => { }} > )} - -

Transactions

- {instructionsData.map((instruction, idx) => { - const availableInstructionsForIdx = getAvailableInstructionsForIndex( - idx - ) - return ( -
- Transaction {idx + 1} - ({ - data: availableInstruction, - key: availableInstruction.id.toString(), - text: availableInstruction.name, - }) - )} - placeholder="Add a transaction" - selected={ - instruction.type - ? { - key: instruction.type.id.toString(), - } - : undefined - } - onSelect={(option) => { - setInstructionType({ value: option?.data, idx }) - }} - /> -
- - {getCurrentInstruction({ - typeId: instruction.type?.id, - idx, - })} - - {idx !== 0 && ( - removeInstruction(idx)} - > - - Remove - - )} -
-
- ) - })} -
-
- - - Add transaction - +
+
+ setIsMulti(false)} + selected={!isMulti} + disabled={false} + className="grow" + > + Executable + +
+
+
+ +
New: Multiple Choice Polls
+
+ setIsMulti(true)} + selected={isMulti} + disabled={false} + className="w-full" + > + Non-Executable
(Multiple-Choice) +
+
+ {isMulti ? ( + + ) : ( +
+ +

Transactions

+ {instructionsData.map((instruction, index) => { + // copy index to keep its value for onChange function + const idx = index + + return ( +
+ Instruction {idx + 1} + + + setInstructionType({ + value: instructionType, + idx, + }) + } + selectedInstruction={instruction.type} + /> + +
+ + {getCurrentInstruction({ + typeId: instruction.type?.id, + index: idx, + })} + + {idx !== 0 && ( + removeInstruction(idx)} + > + + Remove + + )} +
+
+ ) + })} +
+
+ + + Add instruction + +
+
+ )}
import('VoteStakeRegistry/components/LockTokenStats/VestingVsTime'), { @@ -54,18 +57,87 @@ const VestingVsTime = dynamic( const isBetween = require('dayjs/plugin/isBetween') dayjs.extend(isBetween) +const mainMangoVaultPk = 'Guiwem4qBivtkSFrxZAEfuthBz6YuWyCwS4G3fjBYu5Z' + +const useGivenGrantsTokenAmounts = () => { + const realm = useRealmQuery().data?.result + const { data: proposals } = useRealmProposalsQuery() + const { realmInfo } = useRealm() + const connection = useLegacyConnectionContext() + + const possibleGrantProposals = useMemo( + () => + proposals?.filter( + (x) => + x.account.governance.toBase58() === MANGO_DAO_TREASURY && + x.account.accountType === GovernanceAccountType.ProposalV2 + ), + [proposals] + ) + + const enabled = + realmInfo?.programId !== undefined && possibleGrantProposals !== undefined + const { data: proposalTxs } = useQuery({ + enabled, + queryKey: [ + connection.current.rpcEndpoint, + realmInfo?.programId, + 'fetch proposals transactions', + possibleGrantProposals, + ], + queryFn: () => { + if (!enabled) throw new Error('query ran while disabled :o') + return getProposalsTransactions( + possibleGrantProposals.map((x) => x.pubkey) ?? [], + connection, + realmInfo.programId + ) + }, + }) + + const givenGrantsTokenAmounts = useMemo( + () => + proposalTxs + ?.filter( + (x) => + x.account.executionStatus === InstructionExecutionStatus.Success + ) + .flatMap((x) => + x.account.instructions + .filter( + (x) => + x.data[0] === 145 && + x.accounts[9].pubkey.toBase58() === + realm?.account.communityMint.toBase58() + ) + .map((instruction) => { + const data = new BorshInstructionCoder(IDL).decode( + Buffer.from(instruction.data) + )?.data as GrantInstruction | null + return { + voterPk: instruction.accounts[1].pubkey, + amount: data?.amount, + startTs: data?.startTs, + } + }) + ), + [proposalTxs, realm?.account.communityMint] + ) + + return givenGrantsTokenAmounts +} + const LockTokenStats = () => { const walletsPerPage = 10 const pagination = useRef<{ setPage: (val) => void }>(null) - const { realmInfo, realm, symbol, mint, proposals } = useRealm() - const vsrClient = useVotePluginsClientStore((s) => s.state.vsrClient) - const voteStakeRegistryRegistrarPk = useVotePluginsClientStore( - (s) => s.state.voteStakeRegistryRegistrarPk - ) - const voteStakeRegistryRegistrar = useVotePluginsClientStore( - (s) => s.state.voteStakeRegistryRegistrar - ) - const connection = useWalletStore((s) => s.connection) + const realm = useRealmQuery().data?.result + const mint = useRealmCommunityMintInfoQuery().data?.result + const { symbol } = useRouter().query + const { realmInfo } = useRealm() + const { vsrClient, plugin } = useVsrClient(); + const voteStakeRegistryRegistrar = plugin?.params as Registrar | undefined; + const voteStakeRegistryRegistrarPk = plugin?.registrarPublicKey; + const governedTokenAccounts = useGovernanceAssetsStore( (s) => s.governedTokenAccounts ) @@ -76,36 +148,174 @@ const LockTokenStats = () => { account: any }[] >([]) - const [depositsWithWallets, setDepositsWithWallets] = useState< - DepositWithWallet[] - >([]) - const [givenGrantsTokenAmounts, setGivenGrantsTokenAmounts] = useState< - DepoistWithVoter[] - >([]) + const [unlockedFromGrants, setUnlockedFromGrants] = useState(new BN(0)) - const [ - liquidityMiningEmissionPerMonth, - setLiqudiityMiningEmissionPerMonth, - ] = useState(new BN(0)) - const [vestPerMonthStats, setVestPerMonthStats] = useState<{ - [key: string]: { vestingDate: dayjs.Dayjs; vestingAmount: BN }[] - }>({}) + const [liquidityMiningEmissionPerMonth] = useState(new BN(0)) + const [statsMonths, setStatsMonths] = useState([]) const [paginatedWallets, setPaginatedWallets] = useState( [] ) + + const givenGrantsTokenAmounts = useGivenGrantsTokenAmounts() + + const depositsWithWallets = useMemo(() => { + const depositsWithWalletsInner: DepositWithWallet[] = [] + for (const voter of voters) { + const deposits = voter.account.deposits.filter( + (x) => + x.isUsed && + typeof x.lockup?.kind.none === 'undefined' && + x.votingMintConfigIdx === + voteStakeRegistryRegistrar?.votingMints.findIndex( + (votingMint) => + votingMint.mint.toBase58() === + realm?.account.communityMint.toBase58() + ) + ) + for (const deposit of deposits) { + const depositWithWallet = { + voter: voter.publicKey, + wallet: voter.account.voterAuthority, + deposit: deposit, + } + depositsWithWalletsInner.push(depositWithWallet) + } + } + return depositsWithWalletsInner.sort((a, b) => + a.deposit.amountDepositedNative.eq(b.deposit.amountDepositedNative) + ? 0 + : a.deposit.amountDepositedNative.lt(b.deposit.amountDepositedNative) + ? 1 + : -1 + ) + }, [ + realm?.account.communityMint, + voteStakeRegistryRegistrar?.votingMints, + voters, + ]) + const filteredDepositWithWallets = depositsWithWallets.filter((x) => search ? x.wallet.toBase58().includes(search) : x ) - const givenGrantsTokenAmount = givenGrantsTokenAmounts.reduce( + + const givenGrantsTokenAmount = givenGrantsTokenAmounts?.reduce( (acc, curr) => acc.add(curr.amount!), new BN(0) ) - const possibleGrantProposals = Object.values(proposals).filter( - (x) => - x.account.governance.toBase58() === MANGO_DAO_TREASURY && - x.account.accountType === GovernanceAccountType.ProposalV2 + const calcVestingAmountsPerLastXMonths = useCallback( + (monthsNumber: number) => { + const depositsWithWalletsSortedByDate = [...depositsWithWallets].sort( + (x, y) => + x.deposit.lockup.startTs.toNumber() * 1000 - + y.deposit.lockup.startTs.toNumber() * 1000 + ) + + const months: dayjs.Dayjs[] = [] + const vestingPerMonth: { + [key: string]: { vestingDate: dayjs.Dayjs; vestingAmount: BN }[] + } = {} + const currentDate = dayjs() + // Make sure we capture the full monthly vesting amount for the last month + const oldestDate = dayjs().add(monthsNumber, 'month').endOf('month') + + for (let i = 0; i < monthsNumber; i++) { + // add months so we get the current month onward + const date = dayjs().add(i, 'month') + months.push(date) + vestingPerMonth[date.format('MMM')] = [] + } + + for (const depositWithWallet of depositsWithWalletsSortedByDate) { + const unixLockupStart = + depositWithWallet.deposit.lockup.startTs.toNumber() * 1000 + const unixLockupEnd = + depositWithWallet.deposit.lockup.endTs.toNumber() * 1000 + const depositType = getDepositType(depositWithWallet.deposit) + + const finalUnlockDate = dayjs(unixLockupEnd) + const vestingStart = dayjs(unixLockupStart) + + const monthlyPossibleVest = + depositType == 'monthly' && + finalUnlockDate.isAfter(currentDate) && + vestingStart.isBefore(oldestDate) + + const cliffPossibleVest = + depositType == 'cliff' && + finalUnlockDate.isAfter(currentDate) && + finalUnlockDate.isBefore(oldestDate) + const isPossibleToVest = monthlyPossibleVest || cliffPossibleVest + + if (isPossibleToVest) { + let vestingAmount = new BN(0) + if (depositType === 'monthly') { + const vestingCount = Math.ceil( + dayjs(unixLockupEnd).diff(unixLockupStart, 'month', true) + ) + vestingAmount = depositWithWallet.deposit.amountInitiallyLockedNative.divn( + vestingCount + ) + // Monthly vesting needs to be calculated over time + for (let i = 1; i <= vestingCount; i++) { + const nextVestinDays = i * DAYS_PER_MONTH + const vestingDate = dayjs(unixLockupStart).add( + nextVestinDays, + 'day' + ) + for (const date of months) { + if ( + //@ts-ignore + vestingDate.isBetween( + date.startOf('month'), + date.endOf('month') + ) + ) { + vestingPerMonth[date.format('MMM')] = [ + ...vestingPerMonth[date.format('MMM')], + { + vestingDate, + vestingAmount, + }, + ] + } + } + } + } else if (depositType === 'cliff') { + vestingAmount = + depositWithWallet.deposit.amountInitiallyLockedNative + // Find the month the cliff period ends in and bucket it + for (const date of months) { + if ( + // @ts-ignore + finalUnlockDate.isBetween( + date.startOf('month'), + date.endOf('month') + ) + ) { + vestingPerMonth[date.format('MMM')] = [ + ...vestingPerMonth[date.format('MMM')], + { + // @ts-expect-error who knows + finalUnlockDate, + vestingAmount, + }, + ] + } + } + } + } + } + return { vestingPerMonth, months } + }, + [depositsWithWallets] ) + + const vestPerMonthStats = useMemo( + () => calcVestingAmountsPerLastXMonths(6).vestingPerMonth, + [calcVestingAmountsPerLastXMonths] + ) + const currentMonthName = statsMonths.length ? statsMonths[0] : '' const vestingThisMonth = currentMonthName && vestPerMonthStats[currentMonthName] @@ -113,19 +323,22 @@ const LockTokenStats = () => { (acc, val) => acc.add(val.vestingAmount), new BN(0) ) - : new BN(0) + : undefined + const walletsCount = [ ...new Set(depositsWithWallets.map((x) => x.wallet.toBase58())), ].length const mngoValut = governedTokenAccounts.find( (x) => x.extensions.mint?.publicKey.toBase58() === - realm?.account.communityMint.toBase58() + realm?.account.communityMint.toBase58() && + x.extensions.transferAddress?.toBase58() === mainMangoVaultPk ) const mngoLocked = depositsWithWallets.reduce( (acc, curr) => acc.add(curr.deposit.amountDepositedNative), new BN(0) ) + const circulatingSupply = mngoValut && mint ? mint.supply.sub(mngoValut.extensions.amount!).sub(mngoLocked) @@ -136,60 +349,7 @@ const LockTokenStats = () => { (acc, curr) => acc.add(curr.deposit.amountDepositedNative), new BN(0) ) - const calcVestingAmountsPerLastXMonths = (monthsNumber: number) => { - const depositsWithWalletsSortedByDate = [...depositsWithWallets].sort( - (x, y) => - x.deposit.lockup.startTs.toNumber() * 1000 - - y.deposit.lockup.startTs.toNumber() * 1000 - ) - const months: dayjs.Dayjs[] = [] - const vestingPerMonth = {} - const currentDate = dayjs() - const oldestDate = dayjs().subtract(monthsNumber, 'month') - for (let i = 0; i < monthsNumber; i++) { - const date = dayjs().subtract(i, 'month') - months.push(date) - vestingPerMonth[date.format('MMM')] = [] - } - for (const depositWithWallet of depositsWithWalletsSortedByDate) { - const unixLockupStart = - depositWithWallet.deposit.lockup.startTs.toNumber() * 1000 - const unixLockupEnd = - depositWithWallet.deposit.lockup.endTs.toNumber() * 1000 - const isPossibleToVest = - typeof depositWithWallet.deposit.lockup.kind.monthly !== 'undefined' && - currentDate.isAfter(unixLockupStart) && - oldestDate.isBefore(unixLockupEnd) - - if (isPossibleToVest) { - const vestingCount = Math.ceil( - dayjs(unixLockupEnd).diff(unixLockupStart, 'month', true) - ) - const vestingAmount = depositWithWallet.deposit.amountInitiallyLockedNative.divn( - vestingCount - ) - for (let i = 1; i <= vestingCount; i++) { - const nextVestinDays = i * DAYS_PER_MONTH - const vestingDate = dayjs(unixLockupStart).add(nextVestinDays, 'day') - for (const date of months) { - if ( - //@ts-ignore - vestingDate.isBetween(date.startOf('month'), date.endOf('month')) - ) { - vestingPerMonth[date.format('MMM')] = [ - ...vestingPerMonth[date.format('MMM')], - { - vestingDate, - vestingAmount, - }, - ] - } - } - } - } - } - return { vestingPerMonth, months } - } + const fmtAmount = (val) => { const formatter = Intl.NumberFormat('en', { notation: 'compact', @@ -199,76 +359,6 @@ const LockTokenStats = () => { : '0' } - useEffect(() => { - const getProposalsInstructions = async () => { - const accounts = await getProposalsTransactions( - possibleGrantProposals.map((x) => x.pubkey), - connection, - realmInfo!.programId - ) - - const givenGrantsTokenAmounts = accounts - .filter( - (x) => - x.account.executionStatus === InstructionExecutionStatus.Success - ) - .flatMap((x) => - x.account.instructions - .filter( - (x) => - x.data[0] === 145 && - x.accounts[9].pubkey.toBase58() === - realm?.account.communityMint.toBase58() - ) - .map((instruction) => { - const data = new BorshInstructionCoder( - vsrClient!.program.idl - ).decode(Buffer.from(instruction.data)) - ?.data as GrantInstruction | null - return { - voterPk: instruction.accounts[1].pubkey, - amount: data?.amount, - startTs: data?.startTs, - } - }) - ) - setGivenGrantsTokenAmounts(givenGrantsTokenAmounts) - } - if (realmInfo?.programId && vsrClient) { - getProposalsInstructions() - } - }, [possibleGrantProposals.length, realmInfo?.programId]) - useEffect(() => { - const depositsWithWalletsInner: DepositWithWallet[] = [] - for (const voter of voters) { - const deposits = voter.account.deposits.filter( - (x) => - x.isUsed && - typeof x.lockup?.kind.none === 'undefined' && - x.votingMintConfigIdx === - voteStakeRegistryRegistrar?.votingMints.findIndex( - (votingMint) => - votingMint.mint.toBase58() === - realm?.account.communityMint.toBase58() - ) - ) - for (const deposit of deposits) { - const depositWithWallet = { - voter: voter.publicKey, - wallet: voter.account.voterAuthority, - deposit: deposit, - } - depositsWithWalletsInner.push(depositWithWallet) - } - } - const depositWithWalletSorted = depositsWithWalletsInner.sort( - (a, b) => - b.deposit.amountDepositedNative.toNumber() - - a.deposit.amountDepositedNative.toNumber() - ) - setDepositsWithWallets(depositWithWalletSorted) - }, [voters.length]) - useEffect(() => { const getLockedDeposits = async () => { const allVoters = await vsrClient?.program.account.voter.all([ @@ -285,18 +375,17 @@ const LockTokenStats = () => { if (vsrClient && voteStakeRegistryRegistrarPk) { getLockedDeposits() } - }, [ - vsrClient?.program.programId.toBase58(), - voteStakeRegistryRegistrarPk?.toBase58(), - ]) + }, [voteStakeRegistryRegistrarPk, vsrClient]) + useEffect(() => { - const { vestingPerMonth, months } = calcVestingAmountsPerLastXMonths(6) + const { months } = calcVestingAmountsPerLastXMonths(6) const monthsFormat = months.map((x) => x.format('MMM')) - setVestPerMonthStats(vestingPerMonth) setStatsMonths(monthsFormat) + // 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 }, [depositsWithWallets.length]) + useEffect(() => { - if (depositsWithWallets.length && givenGrantsTokenAmounts.length) { + if (depositsWithWallets.length && givenGrantsTokenAmounts?.length) { const currentlyUnlocked = new BN(0) for (const depostiWithVoter of givenGrantsTokenAmounts) { const grantDeposit = depositsWithWallets.find((x) => { @@ -320,44 +409,15 @@ const LockTokenStats = () => { } setUnlockedFromGrants(currentlyUnlocked) } - }, [depositsWithWallets.length, givenGrantsTokenAmounts.length]) - useEffect(() => { - const mngoPerpMarket = async () => { - const GROUP = connection.cluster === 'devnet' ? 'devnet.2' : 'mainnet.1' - const groupConfig = Config.ids().getGroupWithName(GROUP)! - const client = new MangoClient( - connection.current, - groupConfig.mangoProgramId - ) - const group = await client.getMangoGroup(groupConfig.publicKey) - const perpMarkets = await Promise.all([ - ...groupConfig!.perpMarkets.map((x) => - group.loadPerpMarket( - connection.current, - x.marketIndex, - x.baseDecimals, - x.quoteDecimals - ) - ), - ]) + // 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 + }, [depositsWithWallets.length, givenGrantsTokenAmounts?.length]) - const emissionPerMonth = perpMarkets - .reduce( - (acc, next) => acc.iadd(next.liquidityMiningInfo.mngoPerPeriod), - new BN(0) - ) - .muln(SECS_PER_MONTH) - .div(perpMarkets[0].liquidityMiningInfo.targetPeriodLength) - setLiqudiityMiningEmissionPerMonth(emissionPerMonth) - } - if (symbol === 'MNGO') { - mngoPerpMarket() - } - }, [connection.cluster]) useEffect(() => { setPaginatedWallets(paginateWallets(0)) pagination?.current?.setPage(0) + // 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 }, [JSON.stringify(filteredDepositWithWallets)]) + const onPageChange = (page) => { setPaginatedWallets(paginateWallets(page)) } @@ -373,9 +433,8 @@ const LockTokenStats = () => { : symbol const renderAddressName = (wallet) => { return ( - { ) } const renderAddressImage = (wallet) => ( - } + ) @@ -484,10 +540,10 @@ const LockTokenStats = () => { .reduce((acc, curr) => { return acc.add(curr.vestingAmount) }, new BN(0)) - .toNumber(), + .toString(), } }), - ].reverse()} + ]} fmtAmount={fmtAmount} >
@@ -555,8 +611,11 @@ const LockTokenStats = () => { {isConstant - ? getMinDurationFmt(x.deposit as any) - : getTimeLeftFromNowFmt(x.deposit as any)} + ? getMinDurationFmt( + x.deposit.lockup.startTs, + x.deposit.lockup.endTs + ) + : getTimeLeftFromNowFmt(x.deposit.lockup.endTs)} {lockedTokens} @@ -608,8 +667,11 @@ const LockTokenStats = () => {
{isConstant - ? getMinDurationFmt(x.deposit as any) - : getTimeLeftFromNowFmt(x.deposit as any)} + ? getMinDurationFmt( + x.deposit.lockup.startTs, + x.deposit.lockup.endTs + ) + : getTimeLeftFromNowFmt(x.deposit.lockup.endTs)}
diff --git a/pages/dao/[symbol]/treasury/governance/[governanceId]/edit.tsx b/pages/dao/[symbol]/treasury/governance/[governanceId]/edit.tsx new file mode 100644 index 0000000000..9127a7ea0b --- /dev/null +++ b/pages/dao/[symbol]/treasury/governance/[governanceId]/edit.tsx @@ -0,0 +1,44 @@ +import Head from 'next/head' +import { useRouter } from 'next/router' +import { PublicKey } from '@solana/web3.js' + +import { EditWalletRules } from '@hub/components/EditWalletRules' +import { GraphQLProvider } from '@hub/providers/GraphQL' +import { JWTProvider } from '@hub/providers/JWT' +import useSelectedRealmPubkey from '@hooks/selectedRealm/useSelectedRealmPubkey' + +export default function EditWallet() { + const router = useRouter() + const { governanceId } = router.query + + // router queries are undefined on first load, apparently + const governanceAddress = + typeof governanceId === 'string' ? new PublicKey(governanceId) : undefined + + const realmPk = useSelectedRealmPubkey() + + return ( + governanceAddress && + realmPk && ( + <> + + + {/* We should obviously eventually refactor the queries used by EditWalletRules so that these providers aren't needed */} + + Edit Wallet Rules + + +
+
+ +
+
+
+
+ + ) + ) +} diff --git a/pages/dao/[symbol]/treasury/index.tsx b/pages/dao/[symbol]/treasury/index.tsx deleted file mode 100644 index 3d7af72e74..0000000000 --- a/pages/dao/[symbol]/treasury/index.tsx +++ /dev/null @@ -1,219 +0,0 @@ -import PreviousRouteBtn from '@components/PreviousRouteBtn' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { useTotalTreasuryPrice } from '@hooks/useTotalTreasuryPrice' -import { useEffect, useState } from 'react' -import useTreasuryAccountStore from 'stores/useTreasuryAccountStore' -import AccountsTabs from '@components/TreasuryAccount/AccountsTabs' -import AccountOverview from '@components/TreasuryAccount/AccountOverview' -import useWalletStore from 'stores/useWalletStore' -import useRealm from 'hooks/useRealm' -import { CurrencyDollarIcon, PlusCircleIcon } from '@heroicons/react/outline' -import { LinkButton } from '@components/Button' -import { useRouter } from 'next/router' -import useQueryContext from '@hooks/useQueryContext' -import tokenService from '@utils/services/token' -import useStrategiesStore from 'Strategies/store/useStrategiesStore' -import Select from '@components/inputs/Select' -import { getTreasuryAccountItemInfoV2 } from '@utils/treasuryTools' -import { AssetAccount } from '@utils/uiTypes/assets' -import Tooltip from '@components/Tooltip' - -export const NEW_TREASURY_ROUTE = `/treasury/new` - -const Treasury = () => { - const { getStrategies } = useStrategiesStore() - const { - governedTokenAccountsWithoutNfts, - auxiliaryTokenAccounts, - } = useGovernanceAssets() - const { setCurrentAccount } = useTreasuryAccountStore() - const connection = useWalletStore((s) => s.connection) - const { - ownVoterWeight, - symbol, - realm, - toManyCommunityOutstandingProposalsForUser, - toManyCouncilOutstandingProposalsForUse, - } = useRealm() - const router = useRouter() - const { fmtUrlWithCluster } = useQueryContext() - const connected = useWalletStore((s) => s.connected) - const [treasuryAccounts, setTreasuryAccounts] = useState([]) - const [activeAccount, setActiveAccount] = useState(null) - const [accountInfo, setAccountInfo] = useState(null) - const { realmInfo } = useRealm() - useEffect(() => { - if ( - tokenService._tokenList.length && - governedTokenAccountsWithoutNfts.filter((x) => x.extensions.mint).length - ) { - getStrategies(connection) - } - }, [ - tokenService._tokenList.length, - governedTokenAccountsWithoutNfts.filter((x) => x.extensions.mint).length, - ]) - useEffect(() => { - async function prepTreasuryAccounts() { - if ( - governedTokenAccountsWithoutNfts.every( - (x) => x.extensions.transferAddress - ) - ) { - const accounts = [ - ...governedTokenAccountsWithoutNfts, - ...auxiliaryTokenAccounts, - ] - const accountsSorted = accounts.sort((a, b) => { - const infoA = getTreasuryAccountItemInfoV2(a) - const infoB = getTreasuryAccountItemInfoV2(b) - return infoB.totalPrice - infoA.totalPrice - }) - setTreasuryAccounts(accountsSorted) - } - } - prepTreasuryAccounts() - }, [JSON.stringify(governedTokenAccountsWithoutNfts)]) - - useEffect(() => { - if (treasuryAccounts.length > 0 && treasuryAccounts[0].extensions.mint) { - setActiveAccount(treasuryAccounts[0]) - setCurrentAccount(treasuryAccounts[0], connection) - } - }, [JSON.stringify(treasuryAccounts)]) - - const { totalPriceFormatted } = useTotalTreasuryPrice() - - const handleChangeAccountTab = (acc) => { - if (acc) { - setActiveAccount(acc) - setCurrentAccount(acc, connection) - } - } - - const goToNewAccountForm = () => { - router.push(fmtUrlWithCluster(`/dao/${symbol}${NEW_TREASURY_ROUTE}`)) - } - - const canCreateGovernance = realm - ? ownVoterWeight.canCreateGovernance(realm) - : null - const isConnectedWithGovernanceCreationPermission = - connected && - canCreateGovernance && - !toManyCommunityOutstandingProposalsForUser && - !toManyCouncilOutstandingProposalsForUse - - const addNewAssetTooltip = !connected - ? 'Connect your wallet to create new asset' - : !canCreateGovernance - ? "You don't have enough governance power to create a new asset" - : toManyCommunityOutstandingProposalsForUser - ? 'You have too many community outstanding proposals. You need to finalize them before creating a new asset.' - : toManyCouncilOutstandingProposalsForUse - ? 'You have too many council outstanding proposals. You need to finalize them before creating a new asset.' - : '' - useEffect(() => { - if (activeAccount) { - const info = getTreasuryAccountItemInfoV2(activeAccount) - setAccountInfo(info) - } - }, [activeAccount]) - - return ( - <> -
-
-
-
- -
-
-
- {realmInfo?.ogImage ? ( - - ) : null} -
-

{realmInfo?.displayName}

-

Treasury

-
-
- {totalPriceFormatted && ( -
-
- -
-

Treasury Value

-
- ${totalPriceFormatted} -
-
-
-
- )} -
-
- <> -
-
-

Treasury Accounts

- - - - New DAO wallet - - -
-
- -
-
- handleChangeAccountTab(t)} - tabs={treasuryAccounts} - /> -
-
-
- -
- -
-
- - ) -} - -export default Treasury diff --git a/pages/dao/[symbol]/treasury/new.tsx b/pages/dao/[symbol]/treasury/new.tsx index e2a20f4a16..2d74f01613 100644 --- a/pages/dao/[symbol]/treasury/new.tsx +++ b/pages/dao/[symbol]/treasury/new.tsx @@ -1,11 +1,11 @@ -import NewAccountForm from '@components/TreasuryAccount/NewTreasuryAccountForm' +import { NewWallet } from '@hub/components/NewWallet/NewWallet' import React from 'react' const New = () => { return ( -
-
- +
+
+
) diff --git a/pages/dao/[symbol]/treasury/v2/index.tsx b/pages/dao/[symbol]/treasury/v2/index.tsx index f02056769f..f5346ec6ac 100644 --- a/pages/dao/[symbol]/treasury/v2/index.tsx +++ b/pages/dao/[symbol]/treasury/v2/index.tsx @@ -1,4 +1,5 @@ import { useEffect, useRef, useState } from 'react' +import { pipe } from 'fp-ts/function' import PreviousRouteBtn from '@components/PreviousRouteBtn' import TotalValueTitle from '@components/treasuryV2/TotalValueTitle' @@ -8,6 +9,7 @@ import { map, Status } from '@utils/uiTypes/Result' import useTreasuryInfo from '@hooks/useTreasuryInfo' import { AuxiliaryWallet, Wallet } from '@models/treasury/Wallet' import { Asset } from '@models/treasury/Asset' +import { useTreasurySelectState } from '@components/treasuryV2/Details/treasurySelectStore' export default function Treasury() { const data = useTreasuryInfo() @@ -20,10 +22,11 @@ export default function Treasury() { const observer = useRef(null) useEffect(() => { - if (data.status === Status.Ok && !selectedWallet) { + if (data._tag === Status.Ok && !selectedWallet) { setSelectedWallet(data.data.wallets[0]) } - }, [data.status]) + // 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 + }, [data._tag]) useEffect(() => { if (stickyTracker.current) { @@ -41,36 +44,59 @@ export default function Treasury() { return () => observer.current?.disconnect() }, [stickyTracker, observer, setIsStickied]) + const [treasurySelect, setTreasurySelect] = useTreasurySelectState() + + // @asktree: We are migrating away from prop-drilling data as state towards, a hook that manages state (and no data) + // But for now views can use either + + // If the new system is used, then the legacy prop-drilled data and state should just be a special value. + const legacySelectedWallet = + treasurySelect?._kind === 'Legacy' + ? selectedWallet + : ('USE NON-LEGACY STATE' as const) + const legacySelectedAsset = + treasurySelect?._kind === 'Legacy' + ? selectedAsset + : ('USE NON-LEGACY STATE' as const) + return (
({ - realm: { - icon: data.icon, - name: data.name, - }, - value: data.totalValue, - }))} + data={pipe( + data, + map((data) => ({ + realm: { + icon: data.icon, + name: data.name, + }, + value: data.totalValue, + })) + )} />
({ - auxiliaryWallets: data.auxiliaryWallets, - wallets: data.wallets, - }))} - selectedAsset={selectedAsset} - selectedWallet={selectedWallet} + data={pipe( + data, + map((data) => ({ + auxiliaryWallets: data.auxiliaryWallets, + wallets: data.wallets, + })) + )} + selectedAsset={legacySelectedAsset} + selectedWallet={legacySelectedWallet} onSelectAsset={(asset, wallet) => { setSelectedWallet(wallet) setSelectedAsset(() => asset) + setTreasurySelect({ _kind: 'Legacy' }) }} onSelectWallet={(wallet) => { setSelectedWallet(() => wallet) setSelectedAsset(null) + setTreasurySelect({ _kind: 'Legacy' }) }} />
@@ -82,10 +108,10 @@ export default function Treasury() { />
({ - asset: selectedAsset, - wallet: selectedWallet, - }))} + data={map(() => ({ + asset: legacySelectedAsset, + wallet: legacySelectedWallet, + }))(data)} isStickied={isStickied} />
diff --git a/pages/discover/edit/index.tsx b/pages/discover/edit/index.tsx new file mode 100644 index 0000000000..46b98b4866 --- /dev/null +++ b/pages/discover/edit/index.tsx @@ -0,0 +1,14 @@ +import Head from 'next/head' +import { EditDiscoverPage } from '@hub/components/EditDiscoverPage' + +export default function Stats() { + return ( + <> + + Edit Discover + + + + + ) +} diff --git a/pages/discover/index.tsx b/pages/discover/index.tsx new file mode 100644 index 0000000000..8d26eba172 --- /dev/null +++ b/pages/discover/index.tsx @@ -0,0 +1,15 @@ +import Head from 'next/head' + +import { DiscoverPage } from '@hub/components/DiscoverPage' + +export default function Discover() { + return ( +
+ + Discover + + + +
+ ) +} diff --git a/pages/ecosystem/[feedItemId]/[commentId]/index.tsx b/pages/ecosystem/[feedItemId]/[commentId]/index.tsx new file mode 100644 index 0000000000..e182b3535e --- /dev/null +++ b/pages/ecosystem/[feedItemId]/[commentId]/index.tsx @@ -0,0 +1,23 @@ +import Head from 'next/head' +import { useRouter } from 'next/router' + +import { FeedItemComment } from '@hub/components/FeedItemComment' + +export default function EcosystemFeedItemComment() { + const router = useRouter() + const { feedItemId, commentId } = router.query + + return ( +
+ + Realm + + + +
+ ) +} diff --git a/pages/ecosystem/[feedItemId]/index.tsx b/pages/ecosystem/[feedItemId]/index.tsx new file mode 100644 index 0000000000..6154f7cc06 --- /dev/null +++ b/pages/ecosystem/[feedItemId]/index.tsx @@ -0,0 +1,19 @@ +import Head from 'next/head' +import { useRouter } from 'next/router' + +import { FeedItem } from '@hub/components/FeedItem' + +export default function EcosystemFeedItem() { + const router = useRouter() + const { feedItemId } = router.query + + return ( +
+ + Realm + + + +
+ ) +} diff --git a/pages/ecosystem/index.tsx b/pages/ecosystem/index.tsx new file mode 100644 index 0000000000..1cc2e689d8 --- /dev/null +++ b/pages/ecosystem/index.tsx @@ -0,0 +1,15 @@ +import Head from 'next/head' + +import { EcosystemFeed } from '@hub/components/EcosystemFeed' + +export default function Ecosystem() { + return ( +
+ + Ecosystem + + + +
+ ) +} diff --git a/pages/feed/index.tsx b/pages/feed/index.tsx new file mode 100644 index 0000000000..be87d19eea --- /dev/null +++ b/pages/feed/index.tsx @@ -0,0 +1,15 @@ +import Head from 'next/head' + +import { MyFeed } from '@hub/components/MyFeed' + +export default function Feed() { + return ( +
+ + Ecosystem + + + +
+ ) +} diff --git a/pages/index.tsx b/pages/index.tsx index 1c42b787b1..de92639f17 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,13 +1,16 @@ import { useEffect } from 'react' import { useRouter } from 'next/router' + const Index = () => { const router = useRouter() + const REALM = process?.env?.REALM useEffect(() => { - const { REALM } = process.env const mainUrl = REALM ? `/dao/${REALM}` : '/realms' - router.replace(mainUrl) - }, []) + if (!router.asPath.includes(mainUrl)) { + router.replace(mainUrl) + } + }, [REALM]) return null } diff --git a/pages/matchday/verify-wallet.tsx b/pages/matchday/verify-wallet.tsx new file mode 100644 index 0000000000..524d63960b --- /dev/null +++ b/pages/matchday/verify-wallet.tsx @@ -0,0 +1,17 @@ +import { Application } from '@verify-wallet/constants' +import VerifyPage from '@verify-wallet/components' + +const MatchdayVerifyPage = () => { + const parsedLocationHash = new URLSearchParams( + window.location.search.substring(1) + ) + + return ( + + ) +} + +export default MatchdayVerifyPage diff --git a/pages/realm/[id]/[feedItemId]/[commentId]/index.tsx b/pages/realm/[id]/[feedItemId]/[commentId]/index.tsx new file mode 100644 index 0000000000..877ba65c85 --- /dev/null +++ b/pages/realm/[id]/[feedItemId]/[commentId]/index.tsx @@ -0,0 +1,48 @@ +import Head from 'next/head' +import { useRouter } from 'next/router' +import { useEffect } from 'react' + +import { FeedItemComment } from '@hub/components/FeedItemComment' +import { ECOSYSTEM_PAGE } from '@hub/lib/constants' + +export default function RealmFeedItemComment() { + const router = useRouter() + const { id, feedItemId, commentId } = router.query + + if (typeof commentId !== 'string') { + throw new Error('Not a valid comment') + } + + if (typeof feedItemId !== 'string') { + throw new Error('Not a valid feed') + } + + if (typeof feedItemId !== 'string') { + throw new Error('Not a valid feed') + } + + useEffect(() => { + if (id === ECOSYSTEM_PAGE.toBase58()) { + router.replace('/ecosystem') + } + // 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 + }, [id]) + + if (id === ECOSYSTEM_PAGE.toBase58()) { + return
+ } + + return ( +
+ + Realm + + + +
+ ) +} diff --git a/pages/realm/[id]/[feedItemId]/index.tsx b/pages/realm/[id]/[feedItemId]/index.tsx new file mode 100644 index 0000000000..42d4cc8362 --- /dev/null +++ b/pages/realm/[id]/[feedItemId]/index.tsx @@ -0,0 +1,36 @@ +import Head from 'next/head' +import { useRouter } from 'next/router' +import { useEffect } from 'react' + +import { FeedItem } from '@hub/components/FeedItem' +import { ECOSYSTEM_PAGE } from '@hub/lib/constants' + +export default function RealmFeedItem() { + const router = useRouter() + const { id, feedItemId } = router.query + + if (typeof feedItemId !== 'string') { + throw new Error('Not a valid feed') + } + + useEffect(() => { + if (id === ECOSYSTEM_PAGE.toBase58()) { + router.replace('/ecosystem') + } + // 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 + }, [id]) + + if (id === ECOSYSTEM_PAGE.toBase58()) { + return
+ } + + return ( +
+ + Realm + + + +
+ ) +} diff --git a/pages/realm/[id]/hub/edit/index.tsx b/pages/realm/[id]/hub/edit/index.tsx new file mode 100644 index 0000000000..90f4c0c5dc --- /dev/null +++ b/pages/realm/[id]/hub/edit/index.tsx @@ -0,0 +1,25 @@ +import Head from 'next/head' +import { useRouter } from 'next/router' + +import { EditMetadata } from '@hub/components/EditMetadata' + +export default function Edit() { + const router = useRouter() + const { id } = router.query + const queryStr = typeof window !== 'undefined' ? location.search : '' + const newRealmMode = queryStr.includes('initial=true') + + return ( +
+ + Edit + + + +
+ ) +} diff --git a/pages/realm/[id]/hub/index.tsx b/pages/realm/[id]/hub/index.tsx new file mode 100644 index 0000000000..81a0803060 --- /dev/null +++ b/pages/realm/[id]/hub/index.tsx @@ -0,0 +1,32 @@ +import Head from 'next/head' +import { useRouter } from 'next/router' +import { useEffect } from 'react' + +import { Hub } from '@hub/components/Hub' +import { ECOSYSTEM_PAGE } from '@hub/lib/constants' + +export default function RealmAbout() { + const router = useRouter() + const { id } = router.query + + useEffect(() => { + if (id === ECOSYSTEM_PAGE.toBase58()) { + router.replace('/ecosystem') + } + // 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 + }, [id]) + + if (id === ECOSYSTEM_PAGE.toBase58()) { + return
+ } + + return ( +
+ + About + + + +
+ ) +} diff --git a/pages/realm/[id]/index.tsx b/pages/realm/[id]/index.tsx new file mode 100644 index 0000000000..b2f141ee0d --- /dev/null +++ b/pages/realm/[id]/index.tsx @@ -0,0 +1,32 @@ +import Head from 'next/head' +import { useRouter } from 'next/router' +import { useEffect } from 'react' + +import { Home } from '@hub/components/Home' +import { ECOSYSTEM_PAGE } from '@hub/lib/constants' + +export default function Realm() { + const router = useRouter() + const { id } = router.query + + useEffect(() => { + if (id === ECOSYSTEM_PAGE.toBase58()) { + router.replace('/ecosystem') + } + // 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 + }, [id]) + + if (id === ECOSYSTEM_PAGE.toBase58()) { + return
+ } + + return ( +
+ + Realm + + + +
+ ) +} diff --git a/pages/realms/components/RealmsGrid.tsx b/pages/realms/components/RealmsGrid.tsx index ae0773ff14..8333573ed0 100644 --- a/pages/realms/components/RealmsGrid.tsx +++ b/pages/realms/components/RealmsGrid.tsx @@ -53,7 +53,7 @@ const RealmBox = React.forwardRef(

{realm.displayName ?? realm.symbol}

{editing && ( - + )} {editing && inGrid && (
{ - console.log(arrayMove(gridRealms, oldIndex, newIndex)) setGridRealms((array) => arrayMove(array, oldIndex, newIndex)) localStorage.setItem( STORAGE_REALMS, @@ -141,6 +140,7 @@ function RealmsGrid({ useEffect(() => { setGridRealms(getGridRealms()) + // 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 }, []) const goToRealm = (realmInfo: RealmInfo) => { @@ -238,6 +238,7 @@ function RealmsGrid({ ) && (
import('./components/RealmsDashboard')) +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { PublicKey } from '@solana/web3.js' +import { DEFAULT_GOVERNANCE_PROGRAM_ID } from '@components/instructions/tools' +import { useRealmsByProgramQuery } from '@hooks/queries/realm' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import RealmsDashboard from './components/RealmsDashboard' const Realms = () => { const [realms, setRealms] = useState>([]) @@ -26,33 +28,47 @@ const Realms = () => { >([]) const [isLoadingRealms, setIsLoadingRealms] = useState(true) const [editingGrid, setEditingGrid] = useState(false) - const { actions, selectedRealm, connection } = useWalletStore((s) => s) - const { connected, current: wallet } = useWalletStore((s) => s) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected const router = useRouter() const { fmtUrlWithCluster } = useQueryContext() const [searchString, setSearchString] = useState('') const { cluster } = router.query //Small hack to prevent race conditions with cluster change until we remove connection from store and move it to global dep. const routeHasClusterInPath = router.asPath.includes('cluster') + const programs = useMemo( + () => new PublicKey(DEFAULT_GOVERNANCE_PROGRAM_ID), + [] + ) + const { data: queryRealms } = useRealmsByProgramQuery(programs) useMemo(async () => { if ( connection && ((routeHasClusterInPath && cluster) || !routeHasClusterInPath) ) { - const [certifiedRealms, uncharteredRealms] = await Promise.all([ + const [certifiedRealms] = await Promise.all([ getCertifiedRealmInfos(connection), - getUnchartedRealmInfos(connection), ]) - const allRealms = [...certifiedRealms, ...uncharteredRealms] + const unchartedRealms = + queryRealms + ?.filter( + (x) => !certifiedRealms.find((y) => y.realmId.equals(x.pubkey)) + ) + .map((x) => + createUnchartedRealmInfo({ + name: x.account.name, + programId: x.owner.toBase58(), + address: x.pubkey.toBase58(), + }) + ) ?? [] + const allRealms = [...certifiedRealms, ...unchartedRealms] setRealms(sortDaos(allRealms)) setFilteredRealms(sortDaos(allRealms)) setIsLoadingRealms(false) } - if (selectedRealm.realm) { - actions.deselectRealm() - } - }, [connection]) + }, [connection, routeHasClusterInPath, cluster, queryRealms]) const handleCreateRealmButtonClick = async () => { if (!connected) { diff --git a/pages/realms/new.tsx b/pages/realms/new.tsx index aacbe83912..dbb7e03cc7 100644 --- a/pages/realms/new.tsx +++ b/pages/realms/new.tsx @@ -54,7 +54,7 @@ const New: React.FC = () => {
diff --git a/pages/realms/new/community-token/index.tsx b/pages/realms/new/community-token/index.tsx index 4151a8dec4..b9a067bc6c 100644 --- a/pages/realms/new/community-token/index.tsx +++ b/pages/realms/new/community-token/index.tsx @@ -1,36 +1,43 @@ -import { useState } from 'react' import { useRouter } from 'next/router' +import { useState } from 'react' +import useQueryContext from '@hooks/useQueryContext' import { PublicKey } from '@solana/web3.js' -import useWalletStore from 'stores/useWalletStore' import createTokenizedRealm from 'actions/createTokenizedRealm' -import useQueryContext from '@hooks/useQueryContext' import { DEFAULT_GOVERNANCE_PROGRAM_ID } from '@components/instructions/tools' import { notify } from '@utils/notifications' import FormPage from '@components/NewRealmWizard/PageTemplate' +import AddCouncilForm, { + AddCouncil, + AddCouncilSchema, +} from '@components/NewRealmWizard/components/steps/AddCouncilForm' import BasicDetailsForm, { - BasicDetailsSchema, BasicDetails, + BasicDetailsSchema, } from '@components/NewRealmWizard/components/steps/BasicDetailsForm' import CommunityTokenDetailsForm, { - CommunityTokenSchema, CommunityToken, + CommunityTokenSchema, } from '@components/NewRealmWizard/components/steps/CommunityTokenDetailsForm' -import YesVotePercentageForm, { - CommunityYesVotePercentageSchema, - CommunityYesVotePercentage, -} from '@components/NewRealmWizard/components/steps/YesVotePercentageThresholdForm' -import AddCouncilForm, { - AddCouncilSchema, - AddCouncil, -} from '@components/NewRealmWizard/components/steps/AddCouncilForm' import InviteMembersForm, { - InviteMembersSchema, InviteMembers, + InviteMembersSchema, } from '@components/NewRealmWizard/components/steps/InviteMembersForm' +import YesVotePercentageForm, { + CommunityYesVotePercentage, + CommunityYesVotePercentageSchema, + CouncilYesVotePercentageSchema, +} from '@components/NewRealmWizard/components/steps/YesVotePercentageThresholdForm' +import { PluginName } from '@constants/plugins' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { + GoverningTokenConfigAccountArgs, + GoverningTokenType, +} from '@solana/spl-governance' export const FORM_NAME = 'tokenized' @@ -40,36 +47,118 @@ type CommunityTokenForm = BasicDetails & AddCouncil & InviteMembers +// All transformation of form data to business logical program inputs should occur here +const transformFormData2RealmCreation = (formData: CommunityTokenForm) => { + const createCouncil = formData.addCouncil ?? false + const existingCouncilMintPk = formData.councilTokenMintAddress + ? new PublicKey(formData.councilTokenMintAddress) + : undefined + + const programIdAddress = formData?.programId || DEFAULT_GOVERNANCE_PROGRAM_ID + + // If plugins are being added to the realm, we want to delay setting the realm authority + // until after they are added, so that the plugins can be added by the current wallet, without going through + // a proposal. + // If more plugins are included in the Community token flow, then we should generalise this + const shouldSkipSettingRealmAuthority = formData.isQuadratic ?? false + + const params = { + ...{ + programIdAddress, + realmName: formData.name, + // COMMUNITY INFO + tokensToGovernThreshold: formData.minimumNumberOfCommunityTokensToGovern, + useSupplyFactor: formData.useSupplyFactor, + communityAbsoluteMaxVoteWeight: formData.communityAbsoluteMaxVoteWeight, + communityMintSupplyFactor: formData.communityMintSupplyFactor, + communityYesVotePercentage: formData.communityYesVotePercentage, + existingCommunityMintPk: formData.communityTokenMintAddress + ? new PublicKey(formData.communityTokenMintAddress) + : undefined, + transferCommunityMintAuthority: + formData.transferCommunityMintAuthority ?? true, + // COUNCIL INFO + createCouncil: formData.addCouncil ?? false, + communityTokenConfig: new GoverningTokenConfigAccountArgs({ + tokenType: GoverningTokenType.Liquid, + voterWeightAddin: undefined, + maxVoterWeightAddin: undefined, + }), + existingCouncilMintPk: formData.councilTokenMintAddress + ? new PublicKey(formData.councilTokenMintAddress) + : undefined, + transferCouncilMintAuthority: + formData.transferCouncilMintAuthority ?? true, + councilWalletPks: + formData?.memberAddresses?.map((w) => new PublicKey(w)) || [], + skipRealmAuthority: shouldSkipSettingRealmAuthority, + coefficientA: formData.coefficientA, + coefficientB: formData.coefficientB, + coefficientC: formData.coefficientC, + civicPass: formData.civicPass, + }, + ...(formData._programVersion === 3 + ? ({ + _programVersion: 3, + councilYesVotePercentage: formData.councilYesVotePercentage, + councilTokenConfig: + createCouncil || existingCouncilMintPk + ? new GoverningTokenConfigAccountArgs({ + tokenType: GoverningTokenType.Membership, + voterWeightAddin: undefined, + maxVoterWeightAddin: undefined, + }) + : new GoverningTokenConfigAccountArgs({ + tokenType: GoverningTokenType.Dormant, + voterWeightAddin: undefined, + maxVoterWeightAddin: undefined, + }), + } as const) + : ({ _programVersion: 2 } as const)), + } as const + + return params +} + export default function CommunityTokenWizard() { - const { connected, connection, current: wallet } = useWalletStore((s) => s) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected const { push } = useRouter() const { fmtUrlWithCluster } = useQueryContext() const [requestPending, setRequestPending] = useState(false) const steps = [ - { Form: BasicDetailsForm, schema: BasicDetailsSchema, required: 'true' }, + { + Form: BasicDetailsForm, + schema: BasicDetailsSchema, + required: () => true, + }, { Form: CommunityTokenDetailsForm, schema: CommunityTokenSchema, - required: 'true', + required: () => true, }, { Form: YesVotePercentageForm, schema: CommunityYesVotePercentageSchema, - required: 'true', + required: () => true, forCommunity: true, + title: "Next, set your DAO's community approval threshold.", }, - { Form: AddCouncilForm, schema: AddCouncilSchema, required: 'true' }, + { Form: AddCouncilForm, schema: AddCouncilSchema, required: () => true }, { Form: InviteMembersForm, schema: InviteMembersSchema, - required: 'form.addCouncil', + required: (form: CommunityTokenForm) => form.addCouncil, + }, + { + Form: YesVotePercentageForm, + schema: CouncilYesVotePercentageSchema, + required: (form: CommunityTokenForm) => + form.addCouncil && form._programVersion >= 3, + forCouncil: true, + title: "Next, set your DAO's council approval threshold.", }, - // { - // Form: YesVotePercentageForm, - // schema: CouncilYesVotePercentageSchema, - // required: 'true', - // forCouncil: true, - // }, ] async function handleSubmit(formData: CommunityTokenForm) { @@ -84,32 +173,18 @@ export default function CommunityTokenWizard() { throw new Error('No valid wallet connected') } - const programIdAddress = - formData?.programId || DEFAULT_GOVERNANCE_PROGRAM_ID + // A Quadratic Voting DAO includes two plugins: + // - Gateway Plugin: sybil resistance protection (by default provided by civic.com) + // - QV Plugin: adapt the vote weight according to the quadratic formula: ax^1/2 + bx + c + const pluginList: PluginName[] = formData.isQuadratic + ? ['gateway', 'QV'] + : [] const results = await createTokenizedRealm({ wallet, connection: connection.current, - programIdAddress, - realmName: formData.name, - // COMMUNITY INFO - tokensToGovernThreshold: - formData.minimumNumberOfCommunityTokensToGovern, - communityMintSupplyFactor: formData.communityMintSupplyFactor, - communityYesVotePercentage: formData.communityYesVotePercentage, - existingCommunityMintPk: formData.communityTokenMintAddress - ? new PublicKey(formData.communityTokenMintAddress) - : undefined, - transferCommunityMintAuthority: formData.transferCommunityMintAuthority, - // COUNCIL INFO - createCouncil: formData.addCouncil, - // councilVotePercentage: formData.communityYesVotePercentage, - existingCouncilMintPk: formData.councilTokenMintAddress - ? new PublicKey(formData.councilTokenMintAddress) - : undefined, - transferCouncilMintAuthority: formData.transferCouncilMintAuthority, - councilWalletPks: - formData?.memberAddresses?.map((w) => new PublicKey(w)) || [], + ...transformFormData2RealmCreation(formData), + pluginList, }) if (results) { diff --git a/pages/realms/new/multisig/index.tsx b/pages/realms/new/multisig/index.tsx index 416778e237..d8713acefd 100644 --- a/pages/realms/new/multisig/index.tsx +++ b/pages/realms/new/multisig/index.tsx @@ -2,7 +2,6 @@ import { useState } from 'react' import { useRouter } from 'next/router' import { PublicKey } from '@solana/web3.js' -import useWalletStore from 'stores/useWalletStore' import createMultisigWallet from 'actions/createMultisigWallet' import useQueryContext from '@hooks/useQueryContext' @@ -24,31 +23,110 @@ import YesVotePercentageForm, { CouncilYesVotePercentage, } from '@components/NewRealmWizard/components/steps/YesVotePercentageThresholdForm' import FormPage from '@components/NewRealmWizard/PageTemplate' +import { + GoverningTokenConfigAccountArgs, + GoverningTokenType, +} from '@solana/spl-governance' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' export const FORM_NAME = 'multisig' -type MultisigForm = BasicDetails & InviteMembers & CouncilYesVotePercentage +type MultisigForm = BasicDetails & + InviteMembers & + CouncilYesVotePercentage & { _programVersion: 2 | 3 } + +const transformMultisigForm2RealmCreation = ({ ...formData }: MultisigForm) => { + const programIdAddress = formData?.programId || DEFAULT_GOVERNANCE_PROGRAM_ID + + const sharedParams = { + programIdAddress, + + realmName: formData.name, + tokensToGovernThreshold: undefined, + + existingCommunityMintPk: undefined, + transferCommunityMintAuthority: true, + communityYesVotePercentage: 'disabled', + + // (useSupplyFactor = true && communityMintSupplyFactor = undefined) => FULL_SUPPLY_FRACTION + useSupplyFactor: true, + communityMintSupplyFactor: undefined, + communityAbsoluteMaxVoteWeight: undefined, + + createCouncil: true, + existingCouncilMintPk: undefined, + transferCouncilMintAuthority: true, + councilWalletPks: formData.memberAddresses.map((w) => new PublicKey(w)), + } + const discriminatedParams = + formData._programVersion === 3 + ? ({ + _programVersion: 3, + communityYesVotePercentage: 'disabled', + councilYesVotePercentage: formData.councilYesVotePercentage, + councilTokenConfig: new GoverningTokenConfigAccountArgs({ + tokenType: GoverningTokenType.Membership, + voterWeightAddin: undefined, + maxVoterWeightAddin: undefined, + }), + communityTokenConfig: new GoverningTokenConfigAccountArgs({ + tokenType: GoverningTokenType.Dormant, + voterWeightAddin: undefined, + maxVoterWeightAddin: undefined, + }), + } as const) + : ({ + _programVersion: 2, + communityYesVotePercentage: formData.councilYesVotePercentage, + communityTokenConfig: new GoverningTokenConfigAccountArgs({ + tokenType: GoverningTokenType.Liquid, + voterWeightAddin: undefined, + maxVoterWeightAddin: undefined, + }), + } as const) + + return { + ...sharedParams, + ...discriminatedParams, + } +} export default function MultiSigWizard() { - const { connected, connection, current: wallet } = useWalletStore((s) => s) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected const { push } = useRouter() const { fmtUrlWithCluster } = useQueryContext() const [requestPending, setRequestPending] = useState(false) const steps = [ - { Form: BasicDetailsForm, schema: BasicDetailsSchema, required: 'true' }, - { Form: InviteMembersForm, schema: InviteMembersSchema, required: 'true' }, + { + Form: BasicDetailsForm, + schema: BasicDetailsSchema, + required: () => true, + }, + { + Form: InviteMembersForm, + schema: InviteMembersSchema, + required: () => true, + }, { Form: YesVotePercentageForm, schema: CouncilYesVotePercentageSchema, - required: 'true', + required: () => true, forCouncil: true, + title: `Next, set your wallet's approval threshold.`, }, ] async function handleSubmit(formData: MultisigForm) { console.log('submit clicked') setRequestPending(true) + + if (formData._programVersion !== 3 && formData._programVersion !== 2) + throw new Error('Could not verify version of supplied programId') + try { console.log('connection', connected, wallet) if (!connected) { @@ -58,17 +136,10 @@ export default function MultiSigWizard() { throw new Error('No valid wallet connected') } - const programIdAddress = - formData?.programId || DEFAULT_GOVERNANCE_PROGRAM_ID - const results = await createMultisigWallet({ wallet, connection: connection.current, - programIdAddress, - - realmName: formData.name, - councilYesVotePercentage: formData.councilYesVotePercentage, - councilWalletPks: formData.memberAddresses.map((w) => new PublicKey(w)), + ...transformMultisigForm2RealmCreation(formData), }) if (results) { diff --git a/pages/realms/new/nft/index.tsx b/pages/realms/new/nft/index.tsx index 7b4949d3f8..8c974a0c96 100644 --- a/pages/realms/new/nft/index.tsx +++ b/pages/realms/new/nft/index.tsx @@ -4,7 +4,6 @@ import { PublicKey } from '@solana/web3.js' import createNFTRealm from 'actions/createNFTRealm' import { DEFAULT_GOVERNANCE_PROGRAM_ID } from '@components/instructions/tools' -import useWalletStore from 'stores/useWalletStore' import useQueryContext from '@hooks/useQueryContext' @@ -28,29 +27,53 @@ import InviteMembersForm, { } from '@components/NewRealmWizard/components/steps/InviteMembersForm' import FormPage from '@components/NewRealmWizard/PageTemplate' +import { + GoverningTokenConfigAccountArgs, + GoverningTokenType, +} from '@solana/spl-governance' + +import YesVotePercentageForm, { + CouncilYesVotePercentageSchema, +} from '@components/NewRealmWizard/components/steps/YesVotePercentageThresholdForm' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { DEFAULT_NFT_VOTER_PLUGIN } from '@tools/constants' +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' export const FORM_NAME = 'nft' type NFTForm = BasicDetails & AddNFTCollection & AddCouncil & InviteMembers export default function NFTWizard() { - const { connected, connection, current: wallet } = useWalletStore((s) => s) + const connection = useLegacyConnectionContext() + const wallet = useWalletOnePointOh() + const connected = !!wallet?.connected const { push } = useRouter() const { fmtUrlWithCluster } = useQueryContext() const [requestPending, setRequestPending] = useState(false) const steps = [ - { Form: BasicDetailsForm, schema: BasicDetailsSchema, required: 'true' }, + { + Form: BasicDetailsForm, + schema: BasicDetailsSchema, + required: () => true, + }, { Form: AddNFTCollectionForm, schema: AddNFTCollectionSchema, - required: 'true', + required: () => true, }, - { Form: AddCouncilForm, schema: AddCouncilSchema, required: 'true' }, + { Form: AddCouncilForm, schema: AddCouncilSchema, required: () => true }, { Form: InviteMembersForm, schema: InviteMembersSchema, - required: 'form.addCouncil', + required: (form: NFTForm) => form.addCouncil, + }, + { + Form: YesVotePercentageForm, + schema: CouncilYesVotePercentageSchema, + required: (form: NFTForm) => form.addCouncil && form._programVersion >= 3, + forCouncil: true, + title: "Next, set your DAO's council approval threshold.", }, ] @@ -70,29 +93,71 @@ export default function NFTWizard() { const programIdAddress = formData?.programId || DEFAULT_GOVERNANCE_PROGRAM_ID - const results = await createNFTRealm({ - wallet, - connection: connection.current, - programIdAddress, - - realmName: formData.name, - collectionAddress: formData.collectionKey, - collectionCount: formData.numberOfNFTs, - tokensToGovernThreshold: 1, // 1 NFT 1 vote - - existingCommunityMintPk: undefined, - communityYesVotePercentage: formData.communityYesVotePercentage, - - // COUNCIL INFO - createCouncil: formData.addCouncil, - // councilVotePercentage: formData.communityYesVotePercentage, - existingCouncilMintPk: formData.councilTokenMintAddress - ? new PublicKey(formData.councilTokenMintAddress) - : undefined, - transferCouncilMintAuthority: formData.transferCouncilMintAuthority, - councilWalletPks: - formData?.memberAddresses?.map((w) => new PublicKey(w)) || [], - }) + // All transformation of form data to business logical program inputs should occur here + const params = { + ...{ + programIdAddress, + realmName: formData.name, + collectionAddress: formData.collectionKey, + nftCollectionCount: formData.numberOfNFTs, + tokensToGovernThreshold: 1, // 1 NFT 1 vote + + existingCommunityMintPk: undefined, + communityYesVotePercentage: formData.communityYesVotePercentage, + + // COUNCIL INFO + createCouncil: formData.addCouncil ?? false, + + existingCouncilMintPk: formData.councilTokenMintAddress + ? new PublicKey(formData.councilTokenMintAddress) + : undefined, + transferCouncilMintAuthority: + formData.transferCouncilMintAuthority ?? true, + councilWalletPks: + formData?.memberAddresses?.map((w) => new PublicKey(w)) || [], + transferCommunityMintAuthority: true, + + // (useSupplyFactor = true && communityMintSupplyFactor = undefined) => FULL_SUPPLY_FRACTION + useSupplyFactor: true, + communityMintSupplyFactor: undefined, + communityAbsoluteMaxVoteWeight: undefined, + communityTokenConfig: new GoverningTokenConfigAccountArgs({ + voterWeightAddin: new PublicKey(DEFAULT_NFT_VOTER_PLUGIN), + maxVoterWeightAddin: new PublicKey(DEFAULT_NFT_VOTER_PLUGIN), + tokenType: GoverningTokenType.Liquid, + }), + + skipRealmAuthority: true, + }, + } + + const results = + formData._programVersion === 3 + ? await createNFTRealm({ + _programVersion: 3, + wallet, + connection: connection.current, + ...params, + councilYesVotePercentage: formData.councilYesVotePercentage, + councilTokenConfig: + params.createCouncil || params.existingCouncilMintPk + ? new GoverningTokenConfigAccountArgs({ + tokenType: GoverningTokenType.Membership, + voterWeightAddin: undefined, + maxVoterWeightAddin: undefined, + }) + : new GoverningTokenConfigAccountArgs({ + tokenType: GoverningTokenType.Dormant, + voterWeightAddin: undefined, + maxVoterWeightAddin: undefined, + }), + }) + : await createNFTRealm({ + _programVersion: 2, + wallet, + connection: connection.current, + ...params, + }) if (results) { push( diff --git a/pages/stats/index.tsx b/pages/stats/index.tsx new file mode 100644 index 0000000000..956244ab2b --- /dev/null +++ b/pages/stats/index.tsx @@ -0,0 +1,14 @@ +import Head from 'next/head' +import { GlobalStats } from '@hub/components/GlobalStats' + +export default function Stats() { + return ( + <> + + Realm + + + + + ) +} diff --git a/pages/tools/all-realms.tsx b/pages/tools/all-realms.tsx new file mode 100644 index 0000000000..4f1bf6a873 --- /dev/null +++ b/pages/tools/all-realms.tsx @@ -0,0 +1,23 @@ +import { DEFAULT_GOVERNANCE_PROGRAM_ID } from '@components/instructions/tools' +import { useRealmsByProgramQuery } from '@hooks/queries/realm' +import { PublicKey } from '@solana/web3.js' + +const AllRealmsPage = () => { + const realms = useRealmsByProgramQuery( + new PublicKey(DEFAULT_GOVERNANCE_PROGRAM_ID) + ) + + return realms.isLoading ? ( + <>loading... + ) : ( + <> + {realms.data?.map((x) => ( +
+ {x.pubkey.toString()} {x.account.name} +
+ ))} + + ) +} + +export default AllRealmsPage diff --git a/pages/tools/mint-pnft.tsx b/pages/tools/mint-pnft.tsx new file mode 100644 index 0000000000..f1947c2118 --- /dev/null +++ b/pages/tools/mint-pnft.tsx @@ -0,0 +1,37 @@ +import useLegacyConnectionContext from '@hooks/useLegacyConnectionContext' +import useWalletOnePointOh from '@hooks/useWalletOnePointOh' +import { Metaplex, walletAdapterIdentity } from '@metaplex-foundation/js' +import { TokenStandard } from '@metaplex-foundation/mpl-token-metadata' +import { Keypair } from '@solana/web3.js' + +const MintPnft = () => { + const wallet = useWalletOnePointOh() + const connection = useLegacyConnectionContext() + + const mint = async () => { + if (!wallet?.publicKey) throw new Error() + + const metaplex = new Metaplex(connection.current, { + cluster: 'devnet', + }).use(walletAdapterIdentity(wallet)) + const signerman = new Keypair() + await metaplex.nfts().create({ + updateAuthority: signerman, + mintAuthority: signerman, + useNewMint: signerman, + mintTokens: true, + tokenOwner: wallet?.publicKey, + tokenStandard: TokenStandard.ProgrammableNonFungible, + uri: 'https://arweave.net/Al7yuB-ew-3LoD0hvhXzGElLgZnX2S4qZMC5w0STc7s', + name: 'test pNFT', + sellerFeeBasisPoints: 0, + }) + } + return ( + <> + + + ) +} + +export default MintPnft diff --git a/pages/verify-wallet/index.tsx b/pages/verify-wallet/index.tsx new file mode 100644 index 0000000000..f98bcaebf4 --- /dev/null +++ b/pages/verify-wallet/index.tsx @@ -0,0 +1,15 @@ +import VerifyWallet from '@verify-wallet/components' +import { Application } from '@verify-wallet/constants' + +export default () => { + const parsedLocationHash = new URLSearchParams( + window.location.search.substring(1) + ) + + return ( + + ) +} diff --git a/public/actions.json b/public/actions.json new file mode 100644 index 0000000000..72f60ddb4e --- /dev/null +++ b/public/actions.json @@ -0,0 +1,8 @@ +{ + "rules": [ + { + "pathPattern": "/dao/**", + "apiPath": "https://realms.dial.to/vote/dao/**" + } + ] +} diff --git a/public/banners/1.jpg b/public/banners/1.jpg new file mode 100755 index 0000000000..b4589b14d8 Binary files /dev/null and b/public/banners/1.jpg differ diff --git a/public/banners/10.jpg b/public/banners/10.jpg new file mode 100755 index 0000000000..83fd921ad8 Binary files /dev/null and b/public/banners/10.jpg differ diff --git a/public/banners/11.jpg b/public/banners/11.jpg new file mode 100755 index 0000000000..a0177a0d5f Binary files /dev/null and b/public/banners/11.jpg differ diff --git a/public/banners/12.jpg b/public/banners/12.jpg new file mode 100755 index 0000000000..e26b7d9f4b Binary files /dev/null and b/public/banners/12.jpg differ diff --git a/public/banners/13.jpg b/public/banners/13.jpg new file mode 100755 index 0000000000..1fac983d86 Binary files /dev/null and b/public/banners/13.jpg differ diff --git a/public/banners/14.jpg b/public/banners/14.jpg new file mode 100755 index 0000000000..b4589b14d8 Binary files /dev/null and b/public/banners/14.jpg differ diff --git a/public/banners/15.jpg b/public/banners/15.jpg new file mode 100755 index 0000000000..3e4f513621 Binary files /dev/null and b/public/banners/15.jpg differ diff --git a/public/banners/16.jpg b/public/banners/16.jpg new file mode 100755 index 0000000000..a4248bb519 Binary files /dev/null and b/public/banners/16.jpg differ diff --git a/public/banners/17.jpg b/public/banners/17.jpg new file mode 100755 index 0000000000..4340c9698c Binary files /dev/null and b/public/banners/17.jpg differ diff --git a/public/banners/18.jpg b/public/banners/18.jpg new file mode 100755 index 0000000000..1e5895105e Binary files /dev/null and b/public/banners/18.jpg differ diff --git a/public/banners/19.jpg b/public/banners/19.jpg new file mode 100755 index 0000000000..d32944bb65 Binary files /dev/null and b/public/banners/19.jpg differ diff --git a/public/banners/2.jpg b/public/banners/2.jpg new file mode 100755 index 0000000000..471797518c Binary files /dev/null and b/public/banners/2.jpg differ diff --git a/public/banners/20.jpg b/public/banners/20.jpg new file mode 100755 index 0000000000..8e4d742899 Binary files /dev/null and b/public/banners/20.jpg differ diff --git a/public/banners/3.jpg b/public/banners/3.jpg new file mode 100755 index 0000000000..9f73237a8b Binary files /dev/null and b/public/banners/3.jpg differ diff --git a/public/banners/4.jpg b/public/banners/4.jpg new file mode 100755 index 0000000000..30411e166c Binary files /dev/null and b/public/banners/4.jpg differ diff --git a/public/banners/5.jpg b/public/banners/5.jpg new file mode 100755 index 0000000000..9add983dac Binary files /dev/null and b/public/banners/5.jpg differ diff --git a/public/banners/6.jpg b/public/banners/6.jpg new file mode 100755 index 0000000000..61cbf201ff Binary files /dev/null and b/public/banners/6.jpg differ diff --git a/public/banners/7.jpg b/public/banners/7.jpg new file mode 100755 index 0000000000..8d98f485bd Binary files /dev/null and b/public/banners/7.jpg differ diff --git a/public/banners/8.jpg b/public/banners/8.jpg new file mode 100755 index 0000000000..e154185a42 Binary files /dev/null and b/public/banners/8.jpg differ diff --git a/public/banners/9.jpg b/public/banners/9.jpg new file mode 100755 index 0000000000..3b91923abf Binary files /dev/null and b/public/banners/9.jpg differ diff --git a/public/img/bg-desktop.png b/public/img/bg-desktop.png index e64936748b..f509fb09be 100644 Binary files a/public/img/bg-desktop.png and b/public/img/bg-desktop.png differ diff --git a/public/img/bg-mobile.png b/public/img/bg-mobile.png index 9d3e17fead..de0749a58c 100644 Binary files a/public/img/bg-mobile.png and b/public/img/bg-mobile.png differ diff --git a/public/img/bg-quorum-all-sizes.png b/public/img/bg-quorum-all-sizes.png index 6499a55532..946e189eeb 100644 Binary files a/public/img/bg-quorum-all-sizes.png and b/public/img/bg-quorum-all-sizes.png differ diff --git a/public/img/civic.svg b/public/img/civic.svg new file mode 100644 index 0000000000..90e7fa691d --- /dev/null +++ b/public/img/civic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/collectablesIcon.svg b/public/img/collectablesIcon.svg index 20667e6cc9..ec0905fc18 100644 --- a/public/img/collectablesIcon.svg +++ b/public/img/collectablesIcon.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/img/creation-bg-desktop.png b/public/img/creation-bg-desktop.png index aca5befe78..78469c7ecb 100644 Binary files a/public/img/creation-bg-desktop.png and b/public/img/creation-bg-desktop.png differ diff --git a/public/img/dual-logo.png b/public/img/dual-logo.png new file mode 100644 index 0000000000..877ad30354 Binary files /dev/null and b/public/img/dual-logo.png differ diff --git a/public/img/foresight.png b/public/img/foresight.png new file mode 100644 index 0000000000..44bb2f02f1 Binary files /dev/null and b/public/img/foresight.png differ diff --git a/public/img/identity.png b/public/img/identity.png new file mode 100644 index 0000000000..fadf6715bf Binary files /dev/null and b/public/img/identity.png differ diff --git a/public/img/logo-realms.png b/public/img/logo-realms.png index 77dd6c4ba3..08feb1bdf7 100644 Binary files a/public/img/logo-realms.png and b/public/img/logo-realms.png differ diff --git a/public/img/logo-realms.svg b/public/img/logo-realms.svg index a895b373e9..7a42adb528 100644 --- a/public/img/logo-realms.svg +++ b/public/img/logo-realms.svg @@ -1,10 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/public/img/logotype-realms-blue-white.svg b/public/img/logotype-realms-blue-white.svg index 2515cf43fa..97f5ce197b 100644 --- a/public/img/logotype-realms-blue-white.svg +++ b/public/img/logotype-realms-blue-white.svg @@ -1,16 +1 @@ - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/public/img/mango.png b/public/img/mango.png new file mode 100644 index 0000000000..8d36d9e79d Binary files /dev/null and b/public/img/mango.png differ diff --git a/public/img/meanfinance.png b/public/img/meanfinance.png new file mode 100644 index 0000000000..d74044ddc5 Binary files /dev/null and b/public/img/meanfinance.png differ diff --git a/public/img/nft-logo.jpeg b/public/img/nft-logo.jpeg index 3e20ca58e1..61cbdfec04 100644 Binary files a/public/img/nft-logo.jpeg and b/public/img/nft-logo.jpeg differ diff --git a/public/img/psyfinance.png b/public/img/psyfinance.png new file mode 100644 index 0000000000..b1047fedf0 Binary files /dev/null and b/public/img/psyfinance.png differ diff --git a/public/img/pyth.svg b/public/img/pyth.svg new file mode 100644 index 0000000000..e8a3bbffcb --- /dev/null +++ b/public/img/pyth.svg @@ -0,0 +1,6 @@ + + + + diff --git a/public/img/serum.png b/public/img/serum.png new file mode 100644 index 0000000000..975595b9c5 Binary files /dev/null and b/public/img/serum.png differ diff --git a/public/img/solana-logo.svg b/public/img/solana-logo.svg index f7f376886b..2a906c6a7a 100644 --- a/public/img/solana-logo.svg +++ b/public/img/solana-logo.svg @@ -1,12 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/public/img/solend.png b/public/img/solend.png new file mode 100644 index 0000000000..f147ae2a42 Binary files /dev/null and b/public/img/solend.png differ diff --git a/public/img/squads.png b/public/img/squads.png new file mode 100644 index 0000000000..25ffdf2c7a Binary files /dev/null and b/public/img/squads.png differ diff --git a/public/img/streamflow.png b/public/img/streamflow.png new file mode 100644 index 0000000000..77b110ee3b Binary files /dev/null and b/public/img/streamflow.png differ diff --git a/public/img/switchboard.png b/public/img/switchboard.png new file mode 100644 index 0000000000..6f3ecd4c67 Binary files /dev/null and b/public/img/switchboard.png differ diff --git a/public/img/symmetry.png b/public/img/symmetry.png new file mode 100644 index 0000000000..27ac77afe4 Binary files /dev/null and b/public/img/symmetry.png differ diff --git a/public/realms/ALL/favicon.ico b/public/realms/ALL/favicon.ico new file mode 100644 index 0000000000..6449d50862 Binary files /dev/null and b/public/realms/ALL/favicon.ico differ diff --git a/public/realms/ALL/img/logo.png b/public/realms/ALL/img/logo.png new file mode 100644 index 0000000000..95e1e791c0 Binary files /dev/null and b/public/realms/ALL/img/logo.png differ diff --git a/public/realms/Advocat/AdvocatBusiness.png b/public/realms/Advocat/AdvocatBusiness.png new file mode 100644 index 0000000000..403d36a0ef Binary files /dev/null and b/public/realms/Advocat/AdvocatBusiness.png differ diff --git a/public/realms/Advocat/AdvocatDev.png b/public/realms/Advocat/AdvocatDev.png new file mode 100644 index 0000000000..9a224ddb90 Binary files /dev/null and b/public/realms/Advocat/AdvocatDev.png differ diff --git a/public/realms/Advocat/banner.jpg b/public/realms/Advocat/banner.jpg new file mode 100644 index 0000000000..34df5759e1 Binary files /dev/null and b/public/realms/Advocat/banner.jpg differ diff --git a/public/realms/Advocat/logo.png b/public/realms/Advocat/logo.png new file mode 100644 index 0000000000..2e770d43db Binary files /dev/null and b/public/realms/Advocat/logo.png differ diff --git a/public/realms/AgrichainxTribeDao/AgrichainxTribeDao.jpeg b/public/realms/AgrichainxTribeDao/AgrichainxTribeDao.jpeg new file mode 100644 index 0000000000..5e27902963 Binary files /dev/null and b/public/realms/AgrichainxTribeDao/AgrichainxTribeDao.jpeg differ diff --git a/public/realms/Allie-Coin-DAO/Allie-Coin-Logo.png b/public/realms/Allie-Coin-DAO/Allie-Coin-Logo.png new file mode 100644 index 0000000000..41954359c7 Binary files /dev/null and b/public/realms/Allie-Coin-DAO/Allie-Coin-Logo.png differ diff --git a/public/realms/Allie-Coin-DAO/Allie-Coin-Particle-Logo-Compressed.png b/public/realms/Allie-Coin-DAO/Allie-Coin-Particle-Logo-Compressed.png new file mode 100644 index 0000000000..acca67fe84 Binary files /dev/null and b/public/realms/Allie-Coin-DAO/Allie-Coin-Particle-Logo-Compressed.png differ diff --git a/public/realms/AntlerDAO/Logo.jpg b/public/realms/AntlerDAO/Logo.jpg new file mode 100644 index 0000000000..0cc259d20f Binary files /dev/null and b/public/realms/AntlerDAO/Logo.jpg differ diff --git a/public/realms/BOHlogo.png b/public/realms/BOHlogo.png new file mode 100644 index 0000000000..f8feb8f741 Binary files /dev/null and b/public/realms/BOHlogo.png differ diff --git a/public/realms/Blockgame/Blockgame.png b/public/realms/Blockgame/Blockgame.png new file mode 100644 index 0000000000..378ecac025 Binary files /dev/null and b/public/realms/Blockgame/Blockgame.png differ diff --git a/public/realms/Blockride/banner.png b/public/realms/Blockride/banner.png new file mode 100644 index 0000000000..ec8b2ba0f0 Binary files /dev/null and b/public/realms/Blockride/banner.png differ diff --git a/public/realms/Blockride/logo.png b/public/realms/Blockride/logo.png new file mode 100644 index 0000000000..01e6e1e45c Binary files /dev/null and b/public/realms/Blockride/logo.png differ diff --git a/public/realms/BlueChickNFTsDAO/BlueChickNFTsDAO-banner.png b/public/realms/BlueChickNFTsDAO/BlueChickNFTsDAO-banner.png new file mode 100644 index 0000000000..72f1a0d56b Binary files /dev/null and b/public/realms/BlueChickNFTsDAO/BlueChickNFTsDAO-banner.png differ diff --git a/public/realms/BlueChickNFTsDAO/BlueChickNFTsDAO.png b/public/realms/BlueChickNFTsDAO/BlueChickNFTsDAO.png new file mode 100644 index 0000000000..442bd4ca01 Binary files /dev/null and b/public/realms/BlueChickNFTsDAO/BlueChickNFTsDAO.png differ diff --git a/public/realms/BoH b/public/realms/BoH new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/public/realms/BoH @@ -0,0 +1 @@ + diff --git a/public/realms/BootstrapDAO/BootRealms.png b/public/realms/BootstrapDAO/BootRealms.png index 599e81c6d9..259a41fe86 100644 Binary files a/public/realms/BootstrapDAO/BootRealms.png and b/public/realms/BootstrapDAO/BootRealms.png differ diff --git a/public/realms/ClackDAO/Logo.png b/public/realms/ClackDAO/Logo.png new file mode 100644 index 0000000000..483bd9d2e0 Binary files /dev/null and b/public/realms/ClackDAO/Logo.png differ diff --git a/public/realms/CoalitionDAO/banner.png b/public/realms/CoalitionDAO/banner.png new file mode 100644 index 0000000000..ed08c93880 Binary files /dev/null and b/public/realms/CoalitionDAO/banner.png differ diff --git a/public/realms/CoalitionDAO/logo.png b/public/realms/CoalitionDAO/logo.png new file mode 100644 index 0000000000..36a1e7797f Binary files /dev/null and b/public/realms/CoalitionDAO/logo.png differ diff --git a/public/realms/ComradeDAO/img/comradedaologo.png b/public/realms/ComradeDAO/img/comradedaologo.png new file mode 100644 index 0000000000..23726361dd Binary files /dev/null and b/public/realms/ComradeDAO/img/comradedaologo.png differ diff --git a/public/realms/ConkDao/conk.png b/public/realms/ConkDao/conk.png new file mode 100644 index 0000000000..4c1826f43d Binary files /dev/null and b/public/realms/ConkDao/conk.png differ diff --git a/public/realms/ConkDao/conk_banner.png b/public/realms/ConkDao/conk_banner.png new file mode 100644 index 0000000000..d619846d4d Binary files /dev/null and b/public/realms/ConkDao/conk_banner.png differ diff --git a/public/realms/CryptoHelp/cryptohelp.png b/public/realms/CryptoHelp/cryptohelp.png new file mode 100644 index 0000000000..18d0713458 Binary files /dev/null and b/public/realms/CryptoHelp/cryptohelp.png differ diff --git a/public/realms/DeanListGrape/deans-list-logo.png b/public/realms/DeanListGrape/deans-list-logo.png new file mode 100644 index 0000000000..09bd80e25d Binary files /dev/null and b/public/realms/DeanListGrape/deans-list-logo.png differ diff --git a/public/realms/Dean's List Grape/deans list logo.png b/public/realms/Deans-List-Grape/deans-list-logo.png similarity index 100% rename from public/realms/Dean's List Grape/deans list logo.png rename to public/realms/Deans-List-Grape/deans-list-logo.png diff --git a/public/realms/Deans-List-Solarplex-State/img/banner-deanslist-solarplex.png b/public/realms/Deans-List-Solarplex-State/img/banner-deanslist-solarplex.png new file mode 100644 index 0000000000..e5ed9605e6 Binary files /dev/null and b/public/realms/Deans-List-Solarplex-State/img/banner-deanslist-solarplex.png differ diff --git a/public/realms/Deans-List-Solarplex-State/img/deans_list_solarplex_state.png b/public/realms/Deans-List-Solarplex-State/img/deans_list_solarplex_state.png new file mode 100644 index 0000000000..077ad4c1a3 Binary files /dev/null and b/public/realms/Deans-List-Solarplex-State/img/deans_list_solarplex_state.png differ diff --git a/public/realms/Deans_List_Network_State/avatar-deanslist.png b/public/realms/Deans_List_Network_State/avatar-deanslist.png new file mode 100644 index 0000000000..5dd74a4937 Binary files /dev/null and b/public/realms/Deans_List_Network_State/avatar-deanslist.png differ diff --git a/public/realms/Deans_List_Network_State/banner-deanslist.png b/public/realms/Deans_List_Network_State/banner-deanslist.png new file mode 100644 index 0000000000..6eb091ca6c Binary files /dev/null and b/public/realms/Deans_List_Network_State/banner-deanslist.png differ diff --git a/public/realms/Dialect/img/avatar-dialect.png b/public/realms/Dialect/img/avatar-dialect.png new file mode 100644 index 0000000000..c52d2f85f0 Binary files /dev/null and b/public/realms/Dialect/img/avatar-dialect.png differ diff --git a/public/realms/Dialect/img/banner-dialect.png b/public/realms/Dialect/img/banner-dialect.png new file mode 100644 index 0000000000..a7a4b5f87d Binary files /dev/null and b/public/realms/Dialect/img/banner-dialect.png differ diff --git a/public/realms/EpicentralLabsDAO/Epicentral-Labs-Logo.png b/public/realms/EpicentralLabsDAO/Epicentral-Labs-Logo.png new file mode 100644 index 0000000000..a54df83969 Binary files /dev/null and b/public/realms/EpicentralLabsDAO/Epicentral-Labs-Logo.png differ diff --git a/public/realms/EpicentralLabsDAO/EpicentralDAOBanner.png b/public/realms/EpicentralLabsDAO/EpicentralDAOBanner.png new file mode 100644 index 0000000000..bb9bca54d9 Binary files /dev/null and b/public/realms/EpicentralLabsDAO/EpicentralDAOBanner.png differ diff --git a/public/realms/Epics/Epics-logo-background.png b/public/realms/Epics/Epics-logo-background.png new file mode 100644 index 0000000000..519bb1ab88 Binary files /dev/null and b/public/realms/Epics/Epics-logo-background.png differ diff --git a/public/realms/Epics/EpicsLogoSquare.svg b/public/realms/Epics/EpicsLogoSquare.svg new file mode 100644 index 0000000000..c6236dcb90 --- /dev/null +++ b/public/realms/Epics/EpicsLogoSquare.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/realms/Epics/EpicsLogoSquareInvert.svg b/public/realms/Epics/EpicsLogoSquareInvert.svg new file mode 100644 index 0000000000..fa443e562d --- /dev/null +++ b/public/realms/Epics/EpicsLogoSquareInvert.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/realms/FABS/img/fabio.png b/public/realms/FABS/img/fabio.png new file mode 100644 index 0000000000..e429e1415a Binary files /dev/null and b/public/realms/FABS/img/fabio.png differ diff --git a/public/realms/FABS/img/fabs-banner.jpeg b/public/realms/FABS/img/fabs-banner.jpeg new file mode 100644 index 0000000000..a91cb864f0 Binary files /dev/null and b/public/realms/FABS/img/fabs-banner.jpeg differ diff --git a/public/realms/FOXTAG/FOXTAG.png b/public/realms/FOXTAG/FOXTAG.png new file mode 100644 index 0000000000..bde9ca9c68 Binary files /dev/null and b/public/realms/FOXTAG/FOXTAG.png differ diff --git a/public/realms/FinanceIsMagic/Banner.png b/public/realms/FinanceIsMagic/Banner.png new file mode 100644 index 0000000000..6604018935 Binary files /dev/null and b/public/realms/FinanceIsMagic/Banner.png differ diff --git a/public/realms/FinanceIsMagic/Logo.png b/public/realms/FinanceIsMagic/Logo.png new file mode 100644 index 0000000000..0e37c39d7a Binary files /dev/null and b/public/realms/FinanceIsMagic/Logo.png differ diff --git a/public/realms/GARI Network DAO/Gari discord (1).png b/public/realms/GARI Network DAO/Gari discord (1).png new file mode 100644 index 0000000000..4815d5da54 Binary files /dev/null and b/public/realms/GARI Network DAO/Gari discord (1).png differ diff --git a/public/realms/GARI Network DAO/gari.png b/public/realms/GARI Network DAO/gari.png new file mode 100644 index 0000000000..b6d30aa4e7 Binary files /dev/null and b/public/realms/GARI Network DAO/gari.png differ diff --git a/public/realms/GCDC/img/gaycoinz-banner.png b/public/realms/GCDC/img/gaycoinz-banner.png new file mode 100644 index 0000000000..b85f506404 Binary files /dev/null and b/public/realms/GCDC/img/gaycoinz-banner.png differ diff --git a/public/realms/GCDC/img/gaycoinz-logo.png b/public/realms/GCDC/img/gaycoinz-logo.png new file mode 100644 index 0000000000..97ebe6b197 Binary files /dev/null and b/public/realms/GCDC/img/gaycoinz-logo.png differ diff --git a/public/realms/Guacamole/Guacamole_Banner.png b/public/realms/Guacamole/Guacamole_Banner.png new file mode 100644 index 0000000000..06a3b4f5c1 Binary files /dev/null and b/public/realms/Guacamole/Guacamole_Banner.png differ diff --git a/public/realms/Guacamole/Guacamole_Token_Logo_Green.png b/public/realms/Guacamole/Guacamole_Token_Logo_Green.png new file mode 100644 index 0000000000..20fa58838d Binary files /dev/null and b/public/realms/Guacamole/Guacamole_Token_Logo_Green.png differ diff --git a/public/realms/HackerzDAO/img/HackerzDAO_PFP.png b/public/realms/HackerzDAO/img/HackerzDAO_PFP.png new file mode 100644 index 0000000000..a8d044fa28 Binary files /dev/null and b/public/realms/HackerzDAO/img/HackerzDAO_PFP.png differ diff --git a/public/realms/HadeswapGovernance/hadeswap_logo.jpg b/public/realms/HadeswapGovernance/hadeswap_logo.jpg new file mode 100644 index 0000000000..9eea545afb Binary files /dev/null and b/public/realms/HadeswapGovernance/hadeswap_logo.jpg differ diff --git a/public/realms/Helium/img/iotlogo.png b/public/realms/Helium/img/iotlogo.png new file mode 100644 index 0000000000..09da0cead2 Binary files /dev/null and b/public/realms/Helium/img/iotlogo.png differ diff --git a/public/realms/Helium/img/logo.svg b/public/realms/Helium/img/logo.svg new file mode 100644 index 0000000000..eb3e833c3c --- /dev/null +++ b/public/realms/Helium/img/logo.svg @@ -0,0 +1,9 @@ + + + Combined Shape + + + + + + \ No newline at end of file diff --git a/public/realms/Helium/img/mobilelogo.png b/public/realms/Helium/img/mobilelogo.png new file mode 100644 index 0000000000..ab2dbd2f6a Binary files /dev/null and b/public/realms/Helium/img/mobilelogo.png differ diff --git a/public/realms/IKB/ikb_dao_banner.jpg b/public/realms/IKB/ikb_dao_banner.jpg new file mode 100644 index 0000000000..bf5a4c2b4b Binary files /dev/null and b/public/realms/IKB/ikb_dao_banner.jpg differ diff --git a/public/realms/IKB/ikb_dao_logo.jpg b/public/realms/IKB/ikb_dao_logo.jpg new file mode 100644 index 0000000000..f780ccc9c8 Binary files /dev/null and b/public/realms/IKB/ikb_dao_logo.jpg differ diff --git a/public/realms/JetSkiDAO/banner.png b/public/realms/JetSkiDAO/banner.png new file mode 100644 index 0000000000..7ad7afea5a Binary files /dev/null and b/public/realms/JetSkiDAO/banner.png differ diff --git a/public/realms/JetSkiDAO/logo.jpeg b/public/realms/JetSkiDAO/logo.jpeg new file mode 100644 index 0000000000..a2f9dbec4f Binary files /dev/null and b/public/realms/JetSkiDAO/logo.jpeg differ diff --git a/public/realms/Jito/jito.png b/public/realms/Jito/jito.png new file mode 100644 index 0000000000..efd5f85459 Binary files /dev/null and b/public/realms/Jito/jito.png differ diff --git a/public/realms/LavaDAO/img/lavalogo.png b/public/realms/LavaDAO/img/lavalogo.png new file mode 100644 index 0000000000..c8a9eee5c6 Binary files /dev/null and b/public/realms/LavaDAO/img/lavalogo.png differ diff --git a/public/realms/MDLH/img/MDLH.png b/public/realms/MDLH/img/MDLH.png new file mode 100644 index 0000000000..d85aff6b0e Binary files /dev/null and b/public/realms/MDLH/img/MDLH.png differ diff --git a/public/realms/MDLH/img/banner.jpeg b/public/realms/MDLH/img/banner.jpeg new file mode 100644 index 0000000000..5f68d2821a Binary files /dev/null and b/public/realms/MDLH/img/banner.jpeg differ diff --git a/public/realms/MEAN/favicon.ico b/public/realms/MEAN/favicon.ico new file mode 100644 index 0000000000..17345334f1 Binary files /dev/null and b/public/realms/MEAN/favicon.ico differ diff --git a/public/realms/MEAN/logo.svg b/public/realms/MEAN/logo.svg new file mode 100644 index 0000000000..252ac61c7b --- /dev/null +++ b/public/realms/MEAN/logo.svg @@ -0,0 +1,16 @@ + + + mean-logo + + + + + + + + + + \ No newline at end of file diff --git a/public/realms/MNDE/img/mnde_header.png b/public/realms/MNDE/img/mnde_header.png new file mode 100644 index 0000000000..2a2d700045 Binary files /dev/null and b/public/realms/MNDE/img/mnde_header.png differ diff --git a/public/realms/MOUTAI/MF.png b/public/realms/MOUTAI/MF.png new file mode 100644 index 0000000000..ecf72c620c Binary files /dev/null and b/public/realms/MOUTAI/MF.png differ diff --git a/public/realms/MOUTAI/mdao.jpg b/public/realms/MOUTAI/mdao.jpg new file mode 100644 index 0000000000..adc3c21104 Binary files /dev/null and b/public/realms/MOUTAI/mdao.jpg differ diff --git a/public/realms/MOUTAI/t b/public/realms/MOUTAI/t new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/public/realms/MOUTAI/t @@ -0,0 +1 @@ + diff --git a/public/realms/MemeCoinDAOai/MemeCoinDAOBanner1_15.png b/public/realms/MemeCoinDAOai/MemeCoinDAOBanner1_15.png new file mode 100644 index 0000000000..c269797d18 Binary files /dev/null and b/public/realms/MemeCoinDAOai/MemeCoinDAOBanner1_15.png differ diff --git a/public/realms/MemeCoinDAOai/MemeCoinDAOFinalLogo.png b/public/realms/MemeCoinDAOai/MemeCoinDAOFinalLogo.png new file mode 100644 index 0000000000..8e1ff1b54d Binary files /dev/null and b/public/realms/MemeCoinDAOai/MemeCoinDAOFinalLogo.png differ diff --git a/public/realms/MewfasaDAO/banner-dao.jpg b/public/realms/MewfasaDAO/banner-dao.jpg new file mode 100644 index 0000000000..841d64044a Binary files /dev/null and b/public/realms/MewfasaDAO/banner-dao.jpg differ diff --git a/public/realms/MewfasaDAO/mewfasadao.jpg b/public/realms/MewfasaDAO/mewfasadao.jpg new file mode 100644 index 0000000000..e84cf13d22 Binary files /dev/null and b/public/realms/MewfasaDAO/mewfasadao.jpg differ diff --git a/public/realms/ODCO/OCDC.png b/public/realms/ODCO/OCDC.png new file mode 100644 index 0000000000..73ae8343fb Binary files /dev/null and b/public/realms/ODCO/OCDC.png differ diff --git a/public/realms/ODCO/OCDLO.png b/public/realms/ODCO/OCDLO.png new file mode 100644 index 0000000000..b306510e11 Binary files /dev/null and b/public/realms/ODCO/OCDLO.png differ diff --git a/public/realms/OPANZ/OPANZ_Logo.png b/public/realms/OPANZ/OPANZ_Logo.png index b306510e11..98876063f4 100644 Binary files a/public/realms/OPANZ/OPANZ_Logo.png and b/public/realms/OPANZ/OPANZ_Logo.png differ diff --git a/public/realms/OpenBook/OpenBook-Horizontal Lockup.svg b/public/realms/OpenBook/OpenBook-Horizontal Lockup.svg new file mode 100644 index 0000000000..4f813db98d --- /dev/null +++ b/public/realms/OpenBook/OpenBook-Horizontal Lockup.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + OpenBook + + + diff --git a/public/realms/OpenBook/OpenBook-Logomark.svg b/public/realms/OpenBook/OpenBook-Logomark.svg new file mode 100644 index 0000000000..45b299b922 --- /dev/null +++ b/public/realms/OpenBook/OpenBook-Logomark.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/public/realms/PAWN/img/pawn.png b/public/realms/PAWN/img/pawn.png new file mode 100644 index 0000000000..3c1c6f8008 Binary files /dev/null and b/public/realms/PAWN/img/pawn.png differ diff --git a/public/realms/PAWN/img/pawns-banner.png b/public/realms/PAWN/img/pawns-banner.png new file mode 100644 index 0000000000..9a19f8ba8b Binary files /dev/null and b/public/realms/PAWN/img/pawns-banner.png differ diff --git a/public/realms/PAWNGO/img/pawngo.png b/public/realms/PAWNGO/img/pawngo.png new file mode 100644 index 0000000000..2bcde3a6b7 Binary files /dev/null and b/public/realms/PAWNGO/img/pawngo.png differ diff --git a/public/realms/PAWNGO/img/pawngodao.png b/public/realms/PAWNGO/img/pawngodao.png new file mode 100644 index 0000000000..17d85663f0 Binary files /dev/null and b/public/realms/PAWNGO/img/pawngodao.png differ diff --git a/public/realms/PHNXDAO/phnxLogo.png b/public/realms/PHNXDAO/phnxLogo.png new file mode 100644 index 0000000000..288b3e8723 Binary files /dev/null and b/public/realms/PHNXDAO/phnxLogo.png differ diff --git a/public/realms/PHY/favicon.ico b/public/realms/PHY/favicon.ico new file mode 100644 index 0000000000..aafd9f7764 Binary files /dev/null and b/public/realms/PHY/favicon.ico differ diff --git a/public/realms/PHY/img/physis-holo-blk-sml.png b/public/realms/PHY/img/physis-holo-blk-sml.png new file mode 100644 index 0000000000..a293450fa2 Binary files /dev/null and b/public/realms/PHY/img/physis-holo-blk-sml.png differ diff --git a/public/realms/PYTH/favicon.ico b/public/realms/PYTH/favicon.ico index ac4f1c2869..56072a4860 100644 Binary files a/public/realms/PYTH/favicon.ico and b/public/realms/PYTH/favicon.ico differ diff --git a/public/realms/PYTH/img/pyth.svg b/public/realms/PYTH/img/pyth.svg index 37f7276db5..caa105d3b9 100644 --- a/public/realms/PYTH/img/pyth.svg +++ b/public/realms/PYTH/img/pyth.svg @@ -1,7 +1,4 @@ - - - - - - + + + diff --git a/public/realms/PibbleDAO/Banner.png b/public/realms/PibbleDAO/Banner.png new file mode 100644 index 0000000000..de51395995 Binary files /dev/null and b/public/realms/PibbleDAO/Banner.png differ diff --git a/public/realms/PibbleDAO/logo.png b/public/realms/PibbleDAO/logo.png new file mode 100644 index 0000000000..14cea48313 Binary files /dev/null and b/public/realms/PibbleDAO/logo.png differ diff --git a/public/realms/PolarDao.png b/public/realms/PolarDao.png new file mode 100644 index 0000000000..2b6703f7ec Binary files /dev/null and b/public/realms/PolarDao.png differ diff --git a/public/realms/Poll DAO/Vote Vote Vote.png b/public/realms/Poll DAO/Vote Vote Vote.png new file mode 100644 index 0000000000..c2f6941c3d Binary files /dev/null and b/public/realms/Poll DAO/Vote Vote Vote.png differ diff --git a/public/realms/Poll DAO/poll.jpg b/public/realms/Poll DAO/poll.jpg new file mode 100644 index 0000000000..8dc81347b8 Binary files /dev/null and b/public/realms/Poll DAO/poll.jpg differ diff --git a/public/realms/PoodlePawsDAO/PoodlePawsDAO.png b/public/realms/PoodlePawsDAO/PoodlePawsDAO.png new file mode 100644 index 0000000000..296b0f39e3 Binary files /dev/null and b/public/realms/PoodlePawsDAO/PoodlePawsDAO.png differ diff --git a/public/realms/RCH/banner.png b/public/realms/RCH/banner.png new file mode 100644 index 0000000000..1aa1d33880 Binary files /dev/null and b/public/realms/RCH/banner.png differ diff --git a/public/realms/RCH/icon.png b/public/realms/RCH/icon.png new file mode 100644 index 0000000000..60cc783a9e Binary files /dev/null and b/public/realms/RCH/icon.png differ diff --git a/public/realms/ResonanceDAO/hldr b/public/realms/ResonanceDAO/hldr new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/public/realms/ResonanceDAO/hldr @@ -0,0 +1 @@ + diff --git a/public/realms/ResonanceDAO/resonancedaologo.png b/public/realms/ResonanceDAO/resonancedaologo.png new file mode 100644 index 0000000000..330c070f06 Binary files /dev/null and b/public/realms/ResonanceDAO/resonancedaologo.png differ diff --git a/public/realms/SOLDCDAO/img/NEWSOLDCDAO.png b/public/realms/SOLDCDAO/img/NEWSOLDCDAO.png new file mode 100644 index 0000000000..86981f5f7f Binary files /dev/null and b/public/realms/SOLDCDAO/img/NEWSOLDCDAO.png differ diff --git a/public/realms/SatorDAO/SatorLogo.png b/public/realms/SatorDAO/SatorLogo.png new file mode 100644 index 0000000000..99d571e438 Binary files /dev/null and b/public/realms/SatorDAO/SatorLogo.png differ diff --git a/public/realms/Solsaur/solsaur-realms-banner.png b/public/realms/Solsaur/solsaur-realms-banner.png new file mode 100644 index 0000000000..a6f7b7f3e8 Binary files /dev/null and b/public/realms/Solsaur/solsaur-realms-banner.png differ diff --git a/public/realms/Solsaur/solsaur.png b/public/realms/Solsaur/solsaur.png new file mode 100644 index 0000000000..128c25fbca Binary files /dev/null and b/public/realms/Solsaur/solsaur.png differ diff --git a/public/realms/SolshureDAO/img/solshure_dao.png b/public/realms/SolshureDAO/img/solshure_dao.png new file mode 100644 index 0000000000..0d63d9cf93 Binary files /dev/null and b/public/realms/SolshureDAO/img/solshure_dao.png differ diff --git a/public/realms/Squads/banner.png b/public/realms/Squads/banner.png new file mode 100644 index 0000000000..63f9d90070 Binary files /dev/null and b/public/realms/Squads/banner.png differ diff --git a/public/realms/THIRD/favicon.ico b/public/realms/THIRD/favicon.ico new file mode 100644 index 0000000000..ee206e060d Binary files /dev/null and b/public/realms/THIRD/favicon.ico differ diff --git a/public/realms/THIRD/img/logo.png b/public/realms/THIRD/img/logo.png new file mode 100644 index 0000000000..44eccffccd Binary files /dev/null and b/public/realms/THIRD/img/logo.png differ diff --git a/public/realms/TensorDAO/TensorDAO_banner.png b/public/realms/TensorDAO/TensorDAO_banner.png new file mode 100644 index 0000000000..8dc41f1999 Binary files /dev/null and b/public/realms/TensorDAO/TensorDAO_banner.png differ diff --git a/public/realms/TensorDAO/TensorDAO_logo.png b/public/realms/TensorDAO/TensorDAO_logo.png new file mode 100644 index 0000000000..038b745f32 Binary files /dev/null and b/public/realms/TensorDAO/TensorDAO_logo.png differ diff --git a/public/realms/The $GREED Experiment/The $GREED Experiment logo.png b/public/realms/The $GREED Experiment/The $GREED Experiment logo.png new file mode 100644 index 0000000000..ed17caa4a6 Binary files /dev/null and b/public/realms/The $GREED Experiment/The $GREED Experiment logo.png differ diff --git a/public/realms/The $GREED Experiment/The_$GREED_Experiment_logo.png b/public/realms/The $GREED Experiment/The_$GREED_Experiment_logo.png new file mode 100644 index 0000000000..ed17caa4a6 Binary files /dev/null and b/public/realms/The $GREED Experiment/The_$GREED_Experiment_logo.png differ diff --git a/public/realms/TokenSolutionsDAO/favicon.ico b/public/realms/TokenSolutionsDAO/favicon.ico new file mode 100644 index 0000000000..f369b6500a Binary files /dev/null and b/public/realms/TokenSolutionsDAO/favicon.ico differ diff --git a/public/realms/TokenSolutionsDAO/img/image1.png b/public/realms/TokenSolutionsDAO/img/image1.png new file mode 100644 index 0000000000..087452fc75 Binary files /dev/null and b/public/realms/TokenSolutionsDAO/img/image1.png differ diff --git a/public/realms/TokenSolutionsDAO/img/image2.png b/public/realms/TokenSolutionsDAO/img/image2.png new file mode 100644 index 0000000000..7601b15af8 Binary files /dev/null and b/public/realms/TokenSolutionsDAO/img/image2.png differ diff --git a/public/realms/TrustBet/Bannerontransparent.png b/public/realms/TrustBet/Bannerontransparent.png new file mode 100644 index 0000000000..5a19e3344e Binary files /dev/null and b/public/realms/TrustBet/Bannerontransparent.png differ diff --git a/public/realms/TrustBet/LRlogo.png b/public/realms/TrustBet/LRlogo.png new file mode 100644 index 0000000000..281d116bbd Binary files /dev/null and b/public/realms/TrustBet/LRlogo.png differ diff --git a/public/realms/TrustBet/logo.png b/public/realms/TrustBet/logo.png new file mode 100644 index 0000000000..bbfaef76b5 Binary files /dev/null and b/public/realms/TrustBet/logo.png differ diff --git a/public/realms/VIEWSDAO/img/views_banner.jpg b/public/realms/VIEWSDAO/img/views_banner.jpg new file mode 100644 index 0000000000..8408d64f82 Binary files /dev/null and b/public/realms/VIEWSDAO/img/views_banner.jpg differ diff --git a/public/realms/VIEWSDAO/img/views_logo.png b/public/realms/VIEWSDAO/img/views_logo.png new file mode 100644 index 0000000000..880c6bd6a3 Binary files /dev/null and b/public/realms/VIEWSDAO/img/views_logo.png differ diff --git a/public/realms/VillagesDAO/hldr b/public/realms/VillagesDAO/hldr new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/public/realms/VillagesDAO/hldr @@ -0,0 +1 @@ + diff --git a/public/realms/VillagesDAO/villagesdaologo.png b/public/realms/VillagesDAO/villagesdaologo.png new file mode 100644 index 0000000000..e238b52bec Binary files /dev/null and b/public/realms/VillagesDAO/villagesdaologo.png differ diff --git a/public/realms/Wen DAO/Wen DAO.png b/public/realms/Wen DAO/Wen DAO.png new file mode 100644 index 0000000000..89e07f0182 Binary files /dev/null and b/public/realms/Wen DAO/Wen DAO.png differ diff --git a/public/realms/WezeshaDAO/img/WezeshaBanner.png b/public/realms/WezeshaDAO/img/WezeshaBanner.png new file mode 100644 index 0000000000..96339e9e3f Binary files /dev/null and b/public/realms/WezeshaDAO/img/WezeshaBanner.png differ diff --git a/public/realms/WisdomDAO/banner.jpg b/public/realms/WisdomDAO/banner.jpg new file mode 100644 index 0000000000..0392e4e4ef Binary files /dev/null and b/public/realms/WisdomDAO/banner.jpg differ diff --git a/public/realms/WisdomDAO/og.jpg b/public/realms/WisdomDAO/og.jpg new file mode 100644 index 0000000000..01473e89e1 Binary files /dev/null and b/public/realms/WisdomDAO/og.jpg differ diff --git a/public/realms/about.json b/public/realms/about.json new file mode 100644 index 0000000000..87e08e86f7 --- /dev/null +++ b/public/realms/about.json @@ -0,0 +1,5277 @@ +{ + "DA5G7QQbFioZ6K33wQcH8fVdgFcnaDjLD7DLQkapZg5X": { + "symbol": "Metaplex", + "token": "METAewgxyPbgwsseH8T16a39CQ5VyVxZi9zXiDPY18m", + "heading": "Metaplex makes it easy to build your project in minutes and grow your community in the world’s largest NFT ecosystem.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Metaplex is a permissionless on-chain protocol for creators to launch their own non-fungible token (NFT) storefront to connect directly with their audiences, natively on the Solana blockchain. The protocol offers an open-source framework to manage independent NFT storefronts, which can be fully customized and self-hosted without passing through a centralized authority — all with significantly lower minting and transaction fees. Metaplex is a collection of tools, smart contracts, and more designed to make the process of creating and launching NFTs easier." + ] + }, + { + "heading": "The World’s Fastest Growing Web3 Creator Platform", + "content": [ + "Metaplex Studios, ecosystem, and community have been moving quickly to support the thousands of developer teams and creators looking to launch their NFT projects on Solana. In response to feedback, we've created tools like our Candy Machine v2™, to help mint and sell thousands of NFTs for NFT collections and/or common profile picture projects you all know and love." + ] + }, + { + "heading": "Built on Solana", + "content": [ + "Metaplex is built on Solana not only because of scalability, but also because Solana has many other great features, including \"Proof of History\". Solana has a great reputation around launching NFTs in part because of the work of the Metaplex team. Initially a Solana initiative, we were spun out in order to achieve our goal of creating a best-in-class NFT creator experience." + ] + }, + { + "content": [ + "We believe anyone can be a creator with our Creator Studio, which offers artists web-based user interfaces atop robust no-code tools, making it easy to create, sell and manage NFTs on Solana without writing a single line of code. Not a dev? No problem. Simply provide the art and some basic information about your project, and you’ll be launching NFTs powered by the fastest growing web3 creator platform in the world." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.metaplex.com/" + }, + "gallery": [ + { + "url": "https://www.youtube.com/watch?v=AygobJL_yAU", + "height": 448, + "width": 800 + }, + { + "caption": "Our Head of Partnerships: this is culture driving technology.", + "url": "https://pbs.twimg.com/media/FV-i2JYXwAI0MgM?format=jpg&name=large", + "height": 650, + "width": 487 + }, + { + "caption": "The first official Metaplex wallpaper, designed by the Metaplex Studios team", + "url": "https://pbs.twimg.com/media/FdSnSbjXkAEcm7d?format=jpg&name=4096x4096", + "height": 448, + "width": 800 + }, + { + "url": "https://pbs.twimg.com/media/FN0qydiXIAAhoR7?format=jpg&name=large", + "height": 600, + "width": 800 + }, + { + "caption": "Metaplex Office Hours in Paris", + "url": "https://pbs.twimg.com/media/FX1t3u8XEAA6-AC?format=jpg&name=medium", + "height": 532, + "width": 800 + } + ], + "resources": [ + { + "title": "Metaplex Foundation Closes $46M Funding Round", + "content": [ + "The raise was co-led by Multicoin Capital and Jump Crypto, with participation from Alameda Research, Solana Ventures and Animoca Brands…" + ], + "url": "https://blockworks.co/metaplex-foundation-closes-46m-funding-round/" + }, + { + "title": "Metaplex Set to Airdrop MPLX Tokens to Solana NFT Creators", + "content": [ + "Metaplex will launch a DAO to enable community governance, with non-U.S. creators set to reap the reward of MPLX tokens." + ], + "url": "https://decrypt.co/110099/metaplex-airdrop-mplx-token-solana-nft-creators" + }, + { + "title": "NFT collection y00ts pushes Solana trading volume to highest since May", + "content": [ + "Adoption “really happens” when a person “figures out how to generate a key and store it securely, and then sign transactions. That’s a really slow process,”…" + ], + "url": "https://fortune.com/2022/09/12/solana-nft-trading-volume-highest-since-may-crypto-web3/" + } + ], + "team": [ + { + "name": "Stephen Hess", + "avatar": "https://s.yimg.com/ny/api/res/1.2/_LZuGyNQkzaHgTqFIRLeRA--/YXBwaWQ9aGlnaGxhbmRlcjt3PTk2MDtoPTY0MTtjZj13ZWJw/https://s.yimg.com/uu/api/res/1.2/XZ.BQoe4WGFgYHj2SiEekw--~B/aD00NzU7dz03MTE7YXBwaWQ9eXRhY2h5b24-/https://media.zenfs.com/en/coin_rivet_596/0ca8a7254a0c6cab2cca6796efe519fa", + "description": [ + "Stephen became Metaplex's Chief Executive Officer in February 2022 after serving as Head of Product at Solana Labs and Director at the Metaplex Foundation. Prior to joining Solana Labs, Stephen held product leadership roles at a variety of technology startups, most recently as a Product Director at Omada Health. Since the Metaplex protocol launched last July, creators have used it to mint 5.7 million NFTs with over 600,000 unique wallets holding one. Metaplex’s Candy Machine is responsible for virtually every generative collection in the ecosystem, and its commerce program Auction House is quickly gaining adoption from projects like Fractal that value open protocols, global price discovery, and decentralization." + ], + "role": "Chief Executive Officer", + "twitter": "@meta_hess" + } + ], + "faq": [ + { + "question": "What is Metaplex?", + "answer": [ + "Metaplex is a collection of tools, smart contracts, and more designed to make the process of creating and launching NFTs easier. While initially focused on supporting the needs of the arts and entertainment industry our plans extend far beyond that to all use cases where an NFT may add value.", + "", + "Currently, our three major projects are:", + "", + "Token Metadata - the NFT standard for Solana", + "The Candy Machine v2™ - a Profile Picture (PFP) focused tool that works like the gumball-style candy machines of old", + "Auction House - a decentralized sales protocol for NFT marketplaces" + ] + }, + { + "question": "What is Auction House?", + "answer": [ + "Auction House is a protocol for marketplaces to implement a decentralized sales contract. It is simple, fast and very cheap. Auction House is a Solana program available on Mainnet Beta and Devnet. Anyone can create an Auction House." + ] + }, + { + "question": "How do I mint NFTs on Solana?", + "answer": [ + "While the Candy Machine is ready to mint after being deployed, in most cases you will want to provide a front end experience to allow your community the chance to mint, too." + ] + }, + { + "question": "How do I implement a decentralized sales contract?", + "answer": [ + "For the NFT Seller the NFT doesn't leave their wallet until the sale completes. This is due to the use of Solana Token Delegates, and it allows them to list their NFT on other Marketplaces that implement the Auction House protocol." + ] + }, + { + "question": "Do you have an SDK?", + "answer": ["Yes we have three."] + } + ] + }, + "BzGL6wbCvBisQ7s1cNQvDGZwDRWwKK6bhrV93RYdetzJ": { + "symbol": "Squads", + "heading": "The multisig standard you were looking for on Solana", + "about": [ + { + "heading": "Introduction", + "content": [ + "Squads Protocol is the multi-signature wallet standard of Solana, providing critical infrastructure for teams, DAOs and institutions looking to securely manage their treasuries, programs, tokens and workflows." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.squads.so/squads-v3-docs/" + } + }, + "5NNv1oJ4PFhE2416kTNDzrR9axoHjBTw2CNABqcYpXXL": { + "symbol": "Superteam", + "heading": "Superteam is a community dedicated to helping Solana projects launch and grow. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "We help the most promising Solana projects in the ascending world (India, South East Asia, Eastern Europe, and Africa) launch and grow. We are organized as a co-operative of creatives, developers, and operators who are experienced in launching and growing technology businesses.", + "We value the sovereignty that comes with founding a company, the skin in the game that comes with investing, and the joy that comes with getting sh*t done. In a pre-crypto world, we had to fit into broiler categories — founder, investor, or employee. Crypto allows us to be free-range and be all 3 at the same time." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "" + }, + "resources": [ + { + "title": "The Superteam Newsletter", + "content": [ + "We help the most promising projects in the Solana ecosystem in the ascending world launch and grow" + ], + "url": "https://superteam.substack.com/" + }, + { + "title": "The Superteam Podcast", + "content": [ + "Superteam is the podcast that explores the web3 ecosystem in India. " + ], + "url": "https://www.youtube.com/channel/UCi-pkXLbm7sqXFhV1NBLUfQ" + } + ] + }, + "G4CR3KUvqPZWmHbuvWhBPqL4vBBBujviyeTVynN2rhKB": { + "symbol": "Hello Moon", + "heading": "Hello Moon provides innovative datasets on Solana to empower NFT & DeFi investors & traders.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Hello Moon provides innovative datasets on Solana to empower NFT & DeFi investors & traders. Explore & track top NFT projects, monitor wash trading & social (influencers and whales) activity, and swap DeFi tokens for free on HelloMoon.io." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "" + } + }, + "2Z5BXuRCJPqYUCBGyQTwAXHeJoFAnbtvoXja19aZFLKY": { + "symbol": "Jupiter Aggregator", + "heading": "The best swap aggregator & infrastructure for Solana - powering best price, token selection and UX for all users and devs.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Jupiter combines all the liquidity sources across Solana into a single endpoint, providing best-in-class swap aggregation, pricing data, and payment features for all users and developers alike.", + "Jupiter aggregates more than 20 DEXes and AMMs and is integrated with more than 60 top protocols in the Solana platform." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.jup.ag/" + }, + "resources": [ + { + "title": "Writings From Planet Jupiter", + "content": [""], + "url": "https://blog.jup.ag/" + }, + { + "title": "Exploring Solana with Jupiter", + "content": [ + "Ben Chow, the co-founder of Jupiter, talks with key crypto folks in the Solana ecosystem, from founder to investor, builder to community, or marketer." + ], + "url": "https://podcast.jup.ag/" + } + ] + }, + "HP1Y12FPbWMAqqVTpKMXKVk6yK3zJaNSxwUEqLzzzuqc": { + "symbol": "SolanaFM", + "heading": "Bridging the gaps of data accessibility via our indexer, APIs and explorer tools on Solana.", + "about": [ + { + "heading": "Introduction", + "content": [ + "SolanaFM is a leading blockchain explorer on Solana. As the first on-chain data indexer, the team provides human-readable data for users, developers and protocols." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "docs.solana.fm" + }, + "resources": [ + { + "title": "SolanaFM Insights", + "content": [ + "Navigate through the SOL ecosystem with SolanaFM Insights - a weekly series that uncovers intricate, data-driven concepts in Solana." + ], + "url": "https://solanafm.substack.com/" + } + ] + }, + "5Dj3fuNLYxd1tzpPnXiPo88V8JNVHhrDScTLMJpupoXf": { + "symbol": "Unique Venture Clubs", + "heading": "Explore a web3 native way to raise, invest and govern assets. Your partner for every stage of your venture.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Unique Venture Clubs (Unique.vc) is a platform that allows web3 investors, communities, and founders to raise funds, manage assets, and execute their investments on-chain.", + "We believe that blockchain technology can make the governance of your entity and funds more efficient and transparent.", + "Unique VC is the ultimate platform for:" + ] + }, + { + "content": [ + "Investors:\n- Invest early in world-changing start-ups and digital assets!\n- Power your group investments with advanced governance capabilities\n- Invest in projects directly\n- Create or join an investment club (Syndicate or VC)\n- Secondary trading of NFTs and crypto" + ] + }, + { + "content": [ + "Communities:\n- Elevate from Discord, turn Unique!\n- Enable your community to participate in financial decisions\n- Investment Clubs - Create an on-chain investment vehicle for your community\n- Community Clubs - involve your community in treasury spending decisions" + ] + }, + { + "content": [ + "Founders:\n- Create a fundraising-ready start-up!\n- Raise funds for your idea and bridge the early credibility gap with a secure and automated setup\n- Fundraising vehicle\n- Legal entity\n- Access to investors\n- Cap table management" + ] + }, + { + "heading": "What makes us unique?", + "content": [ + "On-chain governance: Participate in the decision-making process and have a clear overview of everything going on in your on-chain entity. Make use of the deposit- or role-based governance models and custom features to manage your activities and assets.\nAnti-rug protection: Control how money is being spent during every phase of the investment and project’s development. Vote on fund allocation proposals and have the ability to pull back the remaining funds if the project does not advance.\nNon-custodial platform: You’re the one who owns the keys and makes the decisions. Your assets are safe and secure on the Solana blockchain. Smart contracts ensure the funds are used for the right purposes.\nAutomated financial execution: The execution of your governance decisions is automated. Propose, vote on, and execute in a matter of seconds - all within one platform.\nIntegrated compliance tools: Get support with various legal wrappers in multiple jurisdictions and KYC or AML procedures. Keep your on-chain entity secure and compliant so that you can focus fully on your entity’s activities." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://uniquevc.gitbook.io/unique-venture-clubs-docs/" + }, + "resources": [ + { + "title": "Announcing winners of the Solana Season Hackathon", + "content": [ + "To accelerate the already rapid growth of the ecosystem, the Solana Foundation teamed up with leading crypto projects to host one of the largest online hackathons ever." + ], + "url": "https://solana.com/news/announcing-winners-of-the-solana-season-hackathon" + }, + { + "title": "Unique Venture Clubs Passes Zokyo’s Comprehensive Security Audit", + "content": [ + "Zokyo is pleased to announce that the collective investment and asset management platform Unique Venture Clubs passed our comprehensive security audit. " + ], + "url": "https://medium.com/@zokyo.io/unique-venture-clubs-passes-zokyos-comprehensive-security-audit-291504fa92e9" + }, + { + "title": "Platforme za DAO još su retkost, na jednoj rade i naši stručnjaci", + "content": [ + "Iako tradicionalni biznisi i dalje stidljivo prilaze blokčejn tehnologiji, čini se da ona polako ali sigurno krči svoj put do njih." + ], + "url": "https://rs.bloombergadria.com/tehnologija/blockchain/5582/platforme-za-dao-jos-su-retkost-na-jednoj-rade-i-nasi-strucnjaci/news" + } + ] + }, + "uWg5gaTsBnXc5qiVMB8XxBUPYqLAb5bzzgkkpxi6UAY": { + "symbol": "GARI Network", + "heading": "GARI Network enables everyone to monetize their social media time and activities by leveraging web3 technologies.", + "about": [ + { + "heading": "Introduction", + "content": [ + "GARI Network enables everyone to monetize their social media time and activities by leveraging web3 technologies.", + "Chingari and GARI Network is the leading short video app and web3 social network. Content creators and Content consumers are incentivized with smart money for their contributions. Smart money incentives that creators and consumers receive are in the form of a cryptocurrency, namely the GARI Token.", + "Similar to other social networks, Chingari app users contribute by publishing or engaging in content such as likes, sharing comment, following, being followed, tipping favourite creators, and 20 other in-app activities.", + "With over 40 million monthly active users, 170 million app downloads, and 1.47 million token holders, it's the largest web3 social network and community.", + "Create your Chingari profile now! Publish, engage and earn smart money from an inclusive creator economy. The Chingari app is available globally on all app stores. Join us today in our mission to onboard 1 billion web3 users in the next 5 years!", + "Linktree, join our community: https://linktr.ee/garinetwork" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "" + }, + "resources": [ + { + "title": "Top #1 Web3 Mobile App Globally Chingari", + "content": [ + "Chingari is the largest on-chain social graph on Web3–powered by crypto." + ], + "url": "https://youtu.be/zH1dMYqgzCg" + }, + { + "title": "Highlights From GARI Network x Bitrue “Ask Me Anything” Sessions", + "content": [ + "GARI, World’s biggest Social Utility Token announced its listing on one of world’s leading cryptocurrency exchanges, Bitrue on 12th Aug 2022." + ], + "url": "https://bitrue.medium.com/highlights-from-gari-network-x-bitrue-ask-me-anything-sessions-b324b392860" + }, + { + "title": "EBC22 | NFT: The Next Generation Tool for Content Creators", + "content": [ + "Listen to our panelists during the 7th European Blockchain Convention debating how NFTs can be a useful tool for the next generation content creators." + ], + "url": "https://youtu.be/3XfSTR9ywp4" + } + ] + }, + "9nUyxzVL2FUMuWUiVZG66gwK15CJiM3PoLkfrnGfkvt6": { + "symbol": "Drift Protocol", + "heading": "A lightning-fast and scalable perpetual futures DEX.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Drift is a full service DEX that offers a product offering of perpetual futures, spot trading, borrow and lend, passive liquidity provision (LP) and Insurance Fund staking.", + "Our mission is to build the best decentralised exchange. In the six months since initial main net, Drift powered over $10b in cumulative volume and hosted over 15,000 unique traders." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.drift.trade/" + } + }, + "HoSfB5xCk8oXRgmspugAx3yRgii8MezimDMfMVK4krBS": { + "symbol": "Zeta Markets", + "heading": "Zeta is the number one decentralized universal access derivatives layer for web3.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Zeta's flagship product is a capital efficient decentralised exchange offering perpetual contracts, European cash settled options and dated futures. The entire program has been built on Solana, including its risk engine and order book, making it the most composable full stack decentralised exchange in the world. The Zeta DEX has been live on Solana since January 2022, bootstrapped by some of the most experienced experts in cryptocurrency trading and decentralized finance, including Jump Crypto, Alameda Research, Wintermute, Pattern Research, and LedgerPrime." + ] + }, + { + "heading": "Generalised Options Infrastructure for Solana", + "content": [ + "In addition to the Zeta DEX, our expertise in options and financial technology have enabled us to build a range of exotic tokenised option structures on chain, used by some of the biggest brands in DeFi including Ribbon Finance for on chain structured products. Our tools and infrastructure make it easy for developers to build on chain agreements between counter-parties, allowing them to create defi products that are enforced entirely on chain." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://zetamarkets.gitbook.io/zeta/" + }, + "resources": [ + { + "title": "Zeta Markets: The Premier Under-Collateralized DeFi Options and Futures Trading Platform Built on Solana", + "content": [ + "We dive into Zeta’s under-collateralization mechanism, CeFi options versus DeFi options, the future of DeFi, and much more." + ], + "url": "https://members.delphidigital.io/media/zeta-markets-the-premier-under-collateralized-defi-options-and-futures-trading-platform-built-on-solana" + }, + { + "title": "Zeta Markets — From Uni Friends to Hackathon Winners — Serum Stories #1", + "content": [ + "Innovative projects and ambitious, talented people continue to emerge and push the boundaries of what was originally thought possible through their integrations with Serum DEX." + ], + "url": "https://medium.com/serum-stories/serum-stories-1-zeta-markets-from-uni-friends-to-hackathon-winners-634bfbf95ec0" + }, + { + "title": "Solana Derivatives Platform Zeta Markets to Go Live on Solana Mainnet", + "content": [ + "Zeta Markets, a cutting-edge decentralized finance (DeFi) derivatives exchange offering features found in traditional finance, today announced that it will go live on the Solana Mainnet on Monday, January 17, 2022." + ], + "url": "https://au.news.yahoo.com/solana-derivatives-platform-zeta-markets-130000885.html?guccounter=1&guce_referrer=aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS8&guce_referrer_sig=AQAAAGc3mnCrnKCJkrikiW_qpsQR6CTibb7pFWZWfMXV_uv1AiUVCSXxMFFqs94-VZfOxQf9cAEZa3W-yc_Eb40hptcvJJwgJAApwNuOhh7N6RkKjPDAzYYogUL6w0Ixv46cds4HtUIbeQJ9l55zXRImOJkJUFN83Bg0KR2iiIMxo_C3" + } + ] + }, + "22nDweMdSCCDoCMFUoS8Zgv7jnZxpLuqGrkL3cmSwuU3": { + "symbol": "IntoTheVerse ", + "heading": "Building #Games4Good powered by Blockchain Technology on Solana and Celo", + "about": [ + { + "heading": "Introduction", + "content": [ + "IntoTheVerse is an NFT utility-driven game-fi metaverse that is based in two worlds, the real world, and the unreal world. The real world is a pixel replication of the cities we live in, reimagining the possibilities where people owning avatars can own virtual lands, visit museums, schools, and banks, travel, and engage in recreational activities. Think of a virtual experience where most of our partner Defi, ReFi, and NFT projects would come out alive inside the city. Think about playing a world builder like SimCity Social, but inside a crypto-native city with a purpose.", + "The unreal world lies in the dark dungeons infested with demons and otherworldly creatures and filled with ancient secrets and treasure, where avatars transform into warriors and encounter the enemies to fight for treasure, forge, level-up and upgrade in a compelling MMORPG adventure!", + "We’re building for mobile and desktop to facilitate user onboarding, education, and fun game/social experience for the masses through web3 and also exploring how we might enable a global redistribution of value and strengthen social and regenerative economics by introducing Play, Own, Earn, Preserve and Learn mechanics." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://solana.com/summercamp/voting/solana-rpg-dungeon-quest-metaplex-multicharacter-integration" + }, + "resources": [ + { + "title": "Solana RPG Dungeon Quest—Metaplex Multi-character Integration", + "content": [ + "A lightweight pixel multicharacter, Play To Earn dungeon game built on the Solana Devnet Blockchain, built with Phaser, powered by Metaplex NFT Marketplace Protocol." + ], + "url": "https://solana.com/summercamp/voting/solana-rpg-dungeon-quest-metaplex-multicharacter-integration" + } + ] + }, + "Bwjrnh5dGZ2tHZKjLtMNwwhtk8sCGfR1ZM8ZxcVCe87m": { + "symbol": "Streamflow", + "heading": "Streamflow is the #1 token vesting and streaming platform on Solana. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Token vesting with Streamflow offers powerful features like: cliff dates, optionally transfer and cancel active streams, automatic withdrawals to recipient wallet and much more.", + "Streaming payments using Streamflow offer a great opportunity for payroll. The recipient can withdraw their salary as they earn it, or wait and have it automatically sent to their wallet at the end of the payment period.", + "Streamflow offers a powerful and secure multisig wallet for teams to manage their payments and vesting with confidence including a clear summary of their open streams, signers and more." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.streamflow.finance/" + } + }, + "2dZAfmpEVMa18ESGiMHQxTWpQvdzEdhNdT7Ai6wdNkZ1": { + "symbol": "Irreverent Labs", + "heading": "Irreverent Labs is creating hilarious automated entertainment from the future. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Irreverent Labs is building the future of automated entertainment. We are the creators of MechaFightClub.", + "We combine machine learning with 3D graphics automation to breathe life into characters that players own, train, breed, and share experiences with.", + "We're building a world where players build emotional connections with the characters and entities they own in the game.", + "We’re combining beautiful art, rich story-telling, and deep technology to build the future of entertainment.", + "Our team is diverse, and incredibly talented. We’re hiring top talent from machine learning, computer vision, computational biology, art and design, and gaming and entertainment.", + "Our founders worked together at Microsoft, they started Microsoft Ventures together.", + "The team was able to come together quickly because many of us have worked together in the past in various capacities." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://www.mechafightclub.com/boktoshi" + }, + "resources": [ + { + "title": "Rahul Sood’s Irreverent Labs unveils MechaFight Club NFT game", + "content": [ + "Born from the mind of Voodoo PC founder Rahul Sood, the Seattle-based blockchain game company has unveiled its first game: MechaFightClub." + ], + "url": "https://venturebeat.com/games/rahul-soods-irreverent-labs-unveils-mechafight-club-nft-game/" + }, + { + "title": "Microsoft vets reveal first game from new blockchain startup backed by Andreessen Horowitz", + "content": [ + " Irreverent Labs, a new Seattle startup led by Microsoft veterans that recently raised a $5 million seed round, just revealed its first game." + ], + "url": "https://www.geekwire.com/2022/microsoft-vets-reveal-first-game-from-new-blockchain-startup-backed-by-andreessen-horowitz/" + }, + { + "title": "MechaFightClub: Irreverent Labs is Using Humor & Advanced AI to Evolve NFT Fighting Games", + "content": [ + "Irreverant Labs’ first game, MechaFightClub, is Mortal Kombat meets Gundam Wing with a dash of South Park humor, all on the Solana blockchain." + ], + "url": "https://esports.gg/news/fgc/mechafightclub-irreverent-labs-solana-blockchain/" + } + ] + }, + "7fhfRApHt9N15v6Xccfd8iGnWZ3xvpUgHA8kieT2egBA": { + "symbol": "Shakudo", + "heading": "All data tools integrated into a fully-managed platform allowing data teams to remove DevOps and accelerate development cycles.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Shakudo is one of the fastest-growing companies that crosses over Web2 and Web3 data at scale. Our fully-managed end-to-end platform specializes in solving these 3 simple problems:\n1. Easily extract data from a range of blockchains such as Ethereum, Bitcoin and Solana\n2. Deposit the extracted data into a standard database such as Postgres or MongoDB (many others are supported)\n3. And last but not least, develop and run end-to-end analytics at scale while removing DevOps support and accelerating development cycles", + "We help great companies like Kin, MonkeDAO and Degenerate Ape Academy to achieve extreme cost reduction and substantial increases in speed and efficiency.", + "Spin up the RPC node, run your own validator, monitor wallets and smart contracts, read unlimited on-chain data and run analysis at scale - all in one Shakudo platform!" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.shakudo.io/home/" + }, + "resources": [ + { + "title": "Vector Institute welcomes three new partners to its AI ecosystem", + "content": [ + "Toronto-based non-profit Vector Institute has welcomed three new partners to its Artificial Intelligence (AI) ecosystem to further research and innovation and bolster the economy." + ], + "url": "https://www.itworldcanada.com/article/vector-institute-welcomes-three-new-partners-to-its-ai-ecosystem/495151" + }, + { + "title": "Rebranded Shakudo Secures $4.2 Million CAD to Help Data Science Teams Get AI Solutions to Market", + "content": [ + "Toronto-based software startup Shakudo has rebranded from DevSentient and raised $4.2 million CAD ($3.4 million USD) in seed funding to expand the reach of its artificial intelligence (AI) platform for data science and machine learning (ML) teams." + ], + "url": "https://betakit.com/rebranded-shakudo-secures-4-2-million-cad-to-help-data-science-teams-get-products-to-market/" + }, + { + "title": "Certified MLOps Software for NVIDIA DGX Systems", + "content": [ + "Explore enterprise-grade solutions for workflow, cluster management, and scheduling and orchestration." + ], + "url": "https://www.nvidia.com/en-us/data-center/dgx-ready-software/#shakudo" + } + ] + }, + "aoBhePkPBCvrSZrK1ioEz6duUY211jfeBPzMzeGAqT8": { + "symbol": "Panzerdogs", + "heading": "Panzerdogs is a Solana NFT gaming project where players can own all of their in-game assets and use them for P2E and P2P battles.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Panzerdogs is a Solana NFT gaming project where players can own all of their in-game assets and use them for P2E and P2P battles. The game is built to play directly on mobile and desktop browsers.", + "Pixel-art NFT collection on the Solana Blockchain. Holders got free airdrops to build their first tanks. Play to earn in the PVP arena.", + "Made by Lucky Kat Studios. A game studio from the Netherlands with a track record of having over 200 million downloads on the App Store and Google Play. We truly believe in the transition of games to web3 and that users should own each in-game asset." + ] + } + ] + }, + "AxPJNe69VrdqWV1VkgDoRcM6Utizje6HdUqE5paJopap": { + "symbol": "DeFi Land", + "heading": "DeFi Land is a unique agriculture-simulation game created to gamify all aspects of decentralized finance and web3.", + "about": [ + { + "heading": "Introduction", + "content": [ + "DeFi Land is a unique, multi-chain agriculture-simulation game created to gamify all aspects of decentralized finance. The main goal of the game is to make it easier and simpler for individuals to take part in the exciting world of DeFi and crypto, while also having the opportunity to have fun.", + "DeFi Land offers all the features that traditional platforms have, but everything is gathered in one place. The game offers players the opportunity to start playing for free, grind their way up to the Play and Earn tier (or simply purchase a Gen-0 NFT), compete with other players, craft, trade, and dive into DeFi in a fun and exciting way.", + "The native utility token is called DFL, and it can be used for:\n- Trading in-game assets and NFTs\n- Staking and LP incentives\n- Game mechanics\n - Governance votes, giving players the opportunity to determine how the network resources are allocated", + "The Play and Earn model introduced by DeFi Land allows users to earn income for completing tasks or reaching certain milestones. The game has something for everyone - whether you are looking for something laid-back and fun or something active and exciting, you can find it on DeFi Land." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "" + }, + "resources": [ + { + "title": "DeFi Land Youtube Channel", + "content": [ + "Providing videos giving our community insights in our game" + ], + "url": "https://www.youtube.com/channel/UCNMyY22SCeknZWo2Lza9a4A" + } + ] + }, + "8sMzPkk6TBM943XRXzScqrcZFfmK1pw62gUPdwtVckCJ": { + "symbol": "BetDEX Labs", + "heading": "BetDEX Labs will launch the BetDEX Exchange in Nov 2022 for Web3 sports betting and is a key contributor to the Monaco Protocol.", + "about": [ + { + "heading": "Introduction", + "content": [ + "BetDEX Labs is a web3 company building open source technology for global prediction markets. The BetDEX Exchange is a sports betting exchange built on the Monaco Protocol allowing for peer-to-peer wagering.", + "BetDEX is a key contributor to the Monaco Protocol, a permissionless, decentralized and open-sourced protocol built on the Solana blockchain, supporting prediction and betting markets. It serves as crucial infrastructure upon which third-party front-end applications for wagering on binary outcome events can be built while accessing a shared liquidity pool." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "" + }, + "resources": [ + { + "title": "Solana-Based Sports Betting Protocol BetDEX Closes $21M Seed Funding Round", + "content": [ + "In the announcement Wednesday, the Edinburgh-based BetDEX called the raise the “largest-ever seed investment round by a U.K. startup.”" + ], + "url": "https://www.yahoo.com/video/solana-based-sports-betting-protocol-223712339.html" + }, + { + "title": "Ex-FanDuel Execs Bet Crypto Can Disrupt Sports Gambling", + "content": [ + "BetDEX CEO hopes the Solana blockchain can help improve the sports wagering industry’s counterparty risk and high fees" + ], + "url": "https://blockworks.co/fanduel-execs-bitdex-bet-crypto-can-disrupt-sports-gambing/" + } + ] + }, + "2PBLG1LGAQYUd38KjJhyACksZH9S361XunVbD3EGxfJf": { + "symbol": "Aleph.im", + "heading": "Decentralized, open source, web3 cloud infrastructure (Storage, computing) and indexing solution. Decentralize your entire stack!", + "about": [ + { + "heading": "Introduction", + "content": [ + "Aleph.im is a distributed web3 cloud platform that provides serverless trusted computing services, file storage, and indexing solutions to replace traditional centralized cloud computing. It provides dApps of any chain instant access to database solutions thanks to its scalable peer-to-peer network and programming language-agnostic interface. Explore our decentralized indexing solution.", + "Follow us on Twitter: @aleph_im or check out our https://linktr.ee/alephim" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://aleph-im.gitbook.io/aleph-docs/introduction/welcome-to-your-dev-hub" + }, + "resources": [ + { + "title": "What does Aleph.im do and what does it stand for?", + "content": [ + "Well, we do a lot! See for yourself! #decentralized #storage #databases #computing #dID #Solana #indexing" + ], + "url": "https://youtu.be/TH-d3ZgJYpk" + } + ] + }, + "9efHuf3HAKiMDWNhgJyZW1Zyo8P7rRhAMXoJa9vpRo1e": { + "symbol": "Realms", + "heading": "The standard for enabling modern communities to share ideas, make decisions, and collectively manage treasuries.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Realms is the hub for community activity in web3. It's a space where users can engage with the projects and teams they care about, perform meaningful web3 actions, track their assets, and participate in the workstreams they’re interested in." + ] + }, + { + "content": [ + "The fundamental building block for this vision is the project. Web3 is made up of the projects that are being built within it, and by extension, a hub for web3 needs to comprise these projects. Realms is built to help the casual crypto follower learn and contribute to projects, consume the conversations on the biggest topics of the day, and make more informed decisions related to participating in organizations." + ] + }, + { + "content": [ + "For on-chain organizations, Realms enables DAO creation, voting, and treasury management, all in one fully on-chain product. Whether managing a multisig or a billion dollar protocol, Realms has the tools to enable your community to reach its full potential." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.realms.today/" + }, + "gallery": [ + { + "caption": "Discussing the Realms Roadmap", + "url": "https://www.youtube.com/watch?v=YGYSrmYhFQ0", + "height": 338, + "width": 600 + }, + { + "caption": "The Realms team at the inaugural AthensDAO Conference", + "url": "https://pbs.twimg.com/media/FT_4VAqXsAQCFBp?format=jpg&name=large", + "height": 600, + "width": 450 + }, + { + "caption": "Realms making a cameo in the Solana Summer Camp Hackathon trailer", + "url": "https://pbs.twimg.com/media/FXbJmCzWQAA41TF?format=jpg&name=large", + "height": 288, + "width": 600 + }, + { + "caption": "Sebastian talking about the future of DAOs on Solana", + "url": "https://pbs.twimg.com/media/Fbo8AAWX0AIpZvJ?format=jpg&name=4096x4096", + "height": 328, + "width": 600 + }, + { + "caption": "The Realms team gathering in Paris, July 2022", + "url": "https://lh3.googleusercontent.com/drive-viewer/AJc5JmS0E2aMJRNlmo1wHDqvhVyvYbbRg94B-ljQKX4RaSOMiJubLbeEaTbquDiytRXgTQBFoWgbEfY=w3456-h588", + "height": 450, + "width": 600 + } + ], + "resources": [ + { + "title": "The Realms Roadmap, with Product Manager Emon Motamedi", + "content": [ + "Emon Motamedi from Solana Labs presents the roadmap of Realms & SPL Governance. The goal is to use DAOs to drive activity to Solana & that can be done through awareness and enhancement of adoption within Web3 as well as from Web2." + ], + "url": "https://youtu.be/YGYSrmYhFQ0" + }, + { + "title": "Realms.Today - Seamless DAO Tools for Solana communities!", + "content": [ + "Realms.Today is the top tier Community Token DAO, Multi-Signature Wallet Management and NFT Community DAO creation Tool. It will help you along the way and is entirely customizable to suit all your DAO needs." + ], + "url": "https://www.solananews.xyz/realms-today/" + }, + { + "title": "Where DAOs Excel — And Where They Must Improve", + "content": [ + "DAOs, DAOs, DAOs. Civic Identity is excited about where DAOs are headed, and particularly excited about our integration with Realms." + ], + "url": "https://twitter.com/civickey/status/1570164818191208448?s=20&t=dKgTwPIdQN8zKfK9x2bikQ" + } + ], + "team": [ + { + "name": "Sebastian Bor", + "avatar": "https://pbs.twimg.com/profile_images/1427584976221089792/wzCRED_r_400x400.jpg", + "description": [ + "Sebastian is responsible for developing SPL Governance as well as the backend infrastructure for Realms. Prior to Solana Labs, he spent his career in the finance and gaming industries." + ], + "role": "Contract Development", + "twitter": "@Sebastian_Bor" + }, + { + "name": "Emon Motamedi", + "avatar": "https://pbs.twimg.com/profile_images/1146682718849159168/v7O-oZAf_400x400.jpg", + "description": [ + "Emon leads the product development for the Realms team, overseeing its vision as well as its day to day needs. Before joining Solana Labs, Emon ran product teams for Reddit and founded a fintech startup called Florian." + ], + "role": "Product", + "twitter": "@EmonMotamedi" + }, + { + "name": "Niranjan Ramadas", + "avatar": "https://drive.google.com/uc?id=12ASbqu9gHLRnlIN7itZnorJZDBFYBqFv", + "description": [ + "Niranjan serves as the frontend and api engineer on the Realms team. Prior to Solana Labs, he worked at Reddit and co-founded a startup building software for remote teams." + ], + "role": "Frontend Development", + "twitter": "@RamadasNiranjan" + }, + { + "name": "Dan Madden", + "avatar": "https://drive.google.com/uc?id=1bt92ZpMPzq5sRYCMLMxJOuyKFJjrkU8b", + "description": [ + "Dan is responsible for the design direction and implementation of Realms. Prior to Solana Labs, he led the design discipline at several product development agencies." + ], + "role": "Design", + "twitter": "@maddendan" + } + ], + "roadmap": { + "items": [ + { + "title": "Launch Realms", + "date": "2021-11-01T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "SPL Governance launches with Realms.today", + "url": "https://twitter.com/Sebastian_Bor/status/1459241354958098449?s=20&t=rmk-mpoG0WnVAoEoo_Cc6g" + } + }, + { + "title": "Launch Wallets & Assets View", + "date": "2022-08-12T15:45:01.159Z", + "status": "completed", + "resource": { + "title": "DAO wallets make it simple for DAOs to own any digital asset", + "url": "https://twitter.com/Realms_DAOs/status/1558148559513452546" + } + }, + { + "title": "Launch SPL Gov V3 Contract", + "date": "2022-09-08T15:46:07.387Z", + "status": "completed", + "resource": null + }, + { + "title": "Launch Organization Hub & Feed", + "date": "2022-11-04T16:47:34.797Z", + "status": "inprogress", + "resource": null + }, + { + "title": "Launch Discovery Experience", + "date": "2022-11-04T16:47:34.797Z", + "status": "inprogress", + "resource": null + }, + { + "title": "Launch Personal Feed & Org Following", + "date": "2022-12-31T16:47:34.797Z", + "status": "upcoming", + "resource": null + } + ] + }, + "faq": [ + { + "question": "How do I create a hub for my organization?", + "answer": [ + "You may fill out our form which outlines the critical information displayed within Realms hubs. You can start here: https://forms.gle/g4kfwtgz5RK9NsLh7" + ] + }, + { + "question": "What types of content should I post on my organization’s feed?", + "answer": [ + "Your organization’s feed belongs to you and the Realms community. Once connected via Solana, anyone may post relevant team updates, interesting insights, explainers, and other pertinent content. You may also add to the conversation by threading your comments and upvoting posts and comments." + ] + }, + { + "question": "Who do I reach out to with questions?", + "answer": [ + "You can post a question to the Realms Community Hub and start a conversation there. You may also email the team at realms@solana.com." + ] + }, + { + "question": "What types of projects should be made into hubs?", + "answer": [ + "The Solana ecosystem is brimming with activity and groundbreaking innovation, and we encourage all projects building on Solana to create hubs to contribute to and grow their communities." + ] + } + ] + }, + "96VSxgcsxhh8qcFXdT7nMzxA1CMrUBxrxcetqYFqdV5V": { + "symbol": "GenesysGo", + "heading": "The Shadow Platform is the first Web3 cloud services platform built for speed, scale, and stability. Web3 without compromises!", + "about": [ + { + "heading": "Introduction", + "content": [ + "The Shadow Platform, built by GenesysGo and powered by Shadow Operators, is a stable high-performance cloud platform powered by a decentralized network of operators. Unlike traditional cloud platforms, all network-generated revenues are sent to Shadow Operators. Shadow is the only commodity cloud network designed to democratize the hundreds of billions earned each year by traditional cloud platforms without sacrificing performance." + ] + }, + { + "content": [ + "The Shadow RPC Network provides high-performance RPC access for Solana builders for minimal cost. Powered by a network of independent operators, Shadow’s Solana RPCs truly decentralize your back-end API with payments going directly to ecosystem operators. Upgrade your back-end API to fit a Web3 ethos while still benefiting from resiliency, performance, and affordability." + ] + }, + { + "content": [ + "Shadow Drive is the first Solana native decentralized, performant, and scalable storage solution built for Web3 developers. Integrate blockchain tech into your business or project with a storage solution that's resilient, secure, and built to scale." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://genesysgo.com" + }, + "team": [ + { + "name": "Frank", + "avatar": "https://media-exp1.licdn.com/dms/image/C5603AQHhsAAH5TC2hg/profile-displayphoto-shrink_800_800/0/1624316377490?e=1672272000&v=beta&t=C7ULngIGY6DSbQWh3Qr6eKdlNTgz6yAaTD7Uk-FMhSc", + "role": "Co-Founder, CEO", + "linkedin": "https://www.linkedin.com/in/frankgenesysgo/" + }, + { + "name": "Knox", + "avatar": "https://pbs.twimg.com/profile_images/1584366672751763456/aqejCPfC_400x400.jpg", + "role": "Developer Relations - Dev Tamer", + "twitter": "@knox_trades" + }, + { + "name": "Tracy", + "avatar": "https://pbs.twimg.com/profile_images/1447400220162101249/tUmZFtrH_400x400.jpg", + "role": "Dev God", + "twitter": "@tracy_codes" + }, + { + "name": "Cavey", + "avatar": "https://pbs.twimg.com/profile_images/1532361682449641477/RG3yU4dt_400x400.jpg", + "role": "Giga-brain monster dev", + "twitter": "@CavemanLoverBoy" + } + ], + "roadmap": { + "items": [ + { + "title": "Launch a Solana validator and achieve profitability", + "date": "2021-04-15T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Shadowy Super Coder DAO on Stakewiz.com", + "url": "https://stakewiz.com/validator/AKoVXpZmi8wSz3sGvCYEygbpdHvSRysWsh36b97iPvKh" + } + }, + { + "title": "Deploy Centralized Solana RPC Network as a first step towards full decentralization", + "date": "2021-05-17T15:45:01.159Z", + "status": "completed", + "resource": null + }, + { + "title": "Create and Deploy Shadow Drive, the Solana ecosystem's first and only native decentralize storage data platform.", + "date": "2022-06-01T15:46:07.387Z", + "status": "completed", + "resource": { + "title": "Shadow Drive: Introducing Decentralized Storage on Solana", + "url": "https://docs.genesysgo.com/shadow/shadow-drive" + } + }, + { + "title": "Deploy the Shadow RPC Network - Solana's most performant and most decentralized RPC network powered by independent operators", + "date": "2022-10-04T16:47:34.797Z", + "status": "completed", + "resource": { + "title": "The $SHDW Premium RPC Network has been deployed for all of Solana!", + "url": "https://twitter.com/GenesysGo/status/1581074282960261120?s=20&t=cDgUHfI3DBvSa_a5M2secQ" + } + }, + { + "title": "Launch the Shadow.Cloud testnet environment at Solana Breakpoint 2022 and debut/showcase the D.A.G.G.E.R. network!", + "date": "2022-11-04T16:47:34.797Z", + "status": "inprogress", + "resource": { + "title": "shadow.cloud is live on Solana fam!", + "url": "https://twitter.com/GenesysGo/status/1584754443853398016?s=20&t=cDgUHfI3DBvSa_a5M2secQ" + } + } + ] + } + }, + "By2sVGZXwfQq6rAiAM3rNPJ9iQfb5e2QhnF4YjJ4Bip": { + "symbol": "GRAPE", + "token": "8upjSpvjcdpuzhfR1zriwg5NXkwDruejqNE9WNbPRtyA", + "heading": "GRAPE DAO is a power user community for digital governance primitives & tooling", + "about": [ + { + "heading": "Introduction", + "content": [ + "Connecting members social accounts to unique cryptographic keys is at the core of our Dynamic Balance-Based Membership solution.", + "Users gain permission and access rights based on their wallets balances, providing direct proof of \"Skin in the Game\" for every community member." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.grapes.network/what-is-grape/overview" + }, + "resources": [ + { + "title": "Grape's Youtube Channel", + "content": [ + "Providing educational videos related to building, using, investing and supporting the Solana ecosystem" + ], + "url": "https://www.youtube.com/c/GrapeProtocol" + }, + { + "title": "The Grape DAO Times", + "content": [ + "Our Weekly Newsletter is a great way to learn about the Grape community and its partners" + ], + "url": "https://medium.com/great-ape" + } + ] + }, + "B1CxhV1khhj7n5mi5hebbivesqH9mvXr5Hfh2nD2UCh6": { + "symbol": "MonkeDAO", + "heading": "", + "about": [ + { + "heading": "Introduction", + "content": [ + "We’re working to become the premier decentralized community of Web3, by providing unparalleled value to our members and the Solana ecosystem through community-led projects, connections and innovations." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://monkedao.gitbook.io/welcome-to-monkedao/" + }, + "resources": [ + { + "title": "MonkeBrains.com", + "content": [ + "A knowledge base for the Solana Blockchain Ecosystem hosted by MonkeDAO" + ], + "url": "https://monkebrains.com/" + }, + { + "title": "Monke Country Club 🎉", + "content": [ + "An exclusive, 24/7 club that will only allow witty bantering, jokes that are too clever, and expressions of love for one another." + ], + "url": "https://monkedao.notion.site/monkedao/Calling-all-Monkes-19eb9ff4a6434eef8e709dfd40ff9cd0" + } + ] + }, + "7s5QZmpit4uu1y2bkByXerE2mv3XBHtiNQ4JkDdmKRiQ": { + "symbol": "Dialect", + "heading": "Dialect is building an open source protocol for Smart Messaging — dynamic, composable dapp notifications and wallet-to-wallet chat", + "about": [ + { + "heading": "Introduction", + "content": [ + "Dialect makes web3 messaging magical. We are building an open-source protocol, a suite of developer tools, and a mobile messaging app to bring interactive, composable wallet-to-wallet messaging and notifications to users and projects across the ecosystem. Today, Dialect is powering messaging and notifications for 30 of the biggest and best known projects." + ] + }, + { + "heading": "Smart Messaging", + "content": [ + "This new interaction mode for messaging uses a primitive we call Smart Messaging. With Smart Messages, users can take action within their messages and notifications. Send and receive tokens, bid on auctions, like or follow content, stake or re-stake assets, execute trades, all right from your inbox.", + "The Smart Messaging Standard will be available soon for builders and projects to create their own interactive messaging experiences." + ] + }, + { + "heading": "The Dialect App (coming soon)", + "content": [ + "Dialect has also created a mobile messaging app for users and projects to send and receive wallet-to-wallet messages and notifications. The Dialect App allows you to connect with other web3 users directly and is the best place to receive, send, and interact with Smart Messages. Dialect App users can also enable and manage notifications from the over 30+ projects that have integrated Dialect. Lastly, there will be some crypto native delight embedded into your messaging experience. You'll want to be early...waitlist coming soon." + ] + }, + { + "heading": "Building with Dialect", + "content": [ + "We'd love to build with you and we're here to help! Please visit our documentation (docs.dialect.to), open source repositories on GitHub (github.com/dialectlabs), Discord (discord.gg/dialect), or reach out to us directly on Twitter (twitter.com/saydialect) to learn more." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "docs.dialect.to" + }, + "resources": [ + { + "title": "Dialect Raises $4.1M to Bring ‘Smart Messaging’ to Solana", + "content": [ + "The project wants Solana-based DeFi apps to have actionable alerts and wallet-to-wallet chat." + ], + "url": "https://www.coindesk.com/business/2022/03/02/dialect-raises-41m-to-bring-smart-messaging-to-solana/" + } + ] + }, + "6jydyMWSqV2bFHjCHydEQxa9XfXQWDwjVqAdjBEA1BXx": { + "symbol": "Gilder", + "heading": "Gilder makes interacting and staying connected to your decentralized internet community easy on mobile. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "On Gilder you can view and keep up to date with any SPL-governance dao. You'll be able to get notifications directly as they are created, vote and create proposals all from your Android or IOS device. Gilder recently merged with the Bastion team, the winners of the DAO category in the Solana Summer Camp Hackathon 2022 and built on top of Realms; Bastion provides a comprehensive DAO tool that helps DAOs on Solana to truly access DeFi and help it's voters become more involved. With the new team consisting of the Bastion and Gilder team, DAOs will become first class citizens on Solana." + ] + } + ] + }, + "9PmmctkHPN5Br8V4gmjNuUdccrD7TtzfJ7U8mcpoBGXd": { + "symbol": "Neo Fairies DAO", + "heading": "A fantasy-punk shared world that’s shaped and owned by community.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Neo Fairies is a fantasy-punk shared world designed from the ground up to be co-created, owned, and governed by a creator-led DAO. The Neo Fairies DAO is a new kind of entertainment DAO which could also be considered an IP (Intellectual Property) DAO. " + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.neofairies.com" + }, + "resources": [ + { + "title": "PlayStation, Google Vets to Co-Create New Franchises Via Solana DAOs", + "content": [ + "Web3 startup Luda is focused on “create-to-own” experiences through new IP shaped by DAO communities, starting with Neo Fairies." + ], + "url": "https://decrypt.co/103302/playstation-google-vets-to-co-create-new-franchises-via-solana-daos" + }, + { + "title": "Reimagining NFT's - The Metacast by Naavik", + "content": [ + "On this week’s Crypto Corner, Luda CEO and Cofounder Vijay Sundaram joins your host Nico Vereecke for a conversation" + ], + "url": "https://youtu.be/RpjY3nkPymA" + }, + { + "title": "The Neo Fairies Project", + "content": [ + "We are Luda, the creators of Neo Fairies. In this post, we introduce our first create-to-own project: Neo Fairies." + ], + "url": "https://mirror.xyz/luda.eth/k5tIEGvz6RXkr18WPzVuLCJFpYWHScgq2bGuvBWu3RE" + } + ] + }, + "GXw7esYZ42nRZBFZTnAXa5fkdDgkvdZh7xeVuCEXoJZP": { + "symbol": "Lighthouse", + "heading": "Lighthouse enables communities to design reputation, rewards and membership systems by attesting to member contributions on-chain.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Lighthouse is a proof-of-contribution protocol that enables communities to capture on-chain and off-chain contributions and attest to them on as on-chain transactions.", + "As a building block for intra-community trust, Lighthouse promises to bring a non-financial component to Solana that enables communities to build sustainable, long-term models of cooperation based on affinity with a community instead of upside.", + "Today, communities use Lighthouse to build to define credentials or criteria for accessing a wide range of benefits including rewards, reputation, membership, governance power and even undercollateralized loans." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://lighthouse-docs.gitbook.io/lighthouse/" + } + }, + "DCdCsuUjg6MnULfEmBUmvg1heggnLrKSFdp5uTRSKuwR": { + "symbol": "Epics DAO", + "heading": "Buidl to Earn. Epics is a decentralized crowdsourcing platform for incentivizing open-source software development.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Epics is a decentralized crowdsourcing platform for incentivizing open source software development.", + "Clients can set up a GitHub issue as a Quest (Smart Contract).", + "Developers can receive token prizes by solving GitHub issues (Quests).", + "This ecosystem makes developers focus on problems in their expertise. Also, clients will be able to solve more advanced problems.", + "The more token prizes, the more attention to be solved issues. As a result, open source software grows faster in quality.", + "Epics solves resource imbalances in software development." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://epics.dev/" + }, + "resources": [ + { + "title": "Meet the winners of the Solana Summer Camp Hackathon", + "content": [ + "The Solana Foundation is pleased to announce the results of the Solana Summer Camp Hackathon, a global competition focused on bringing the next wave of high-impact projects into the Solana ecosystem." + ], + "url": "https://solana.com/news/solana-summer-camp-winners" + }, + { + "title": "Solana Foundation Becomes Epics DAO Partner", + "content": [ + "The Solana Foundation has partnered with the Epics DAO after placing fifth in the Solana Summer Camp Hackathon DAOs Track." + ], + "url": "https://news.infoseek.co.jp/article/prtimes_000000009_000105962" + }, + { + "title": "Zebec Protocol Becomes Epics DAO Partner", + "content": [ + "Epics DAO's Solana Summer Camp Hackathon DAOs track 5th place, Zebec Protocol has partnered with Epics DAO." + ], + "url": "https://prtimes.jp/main/html/rd/p/000000010.000105962.html" + } + ] + }, + "A1f6LNEymJSSJsEVCL1FSgtS1jA9dNTC4ni8SkmbwQjG": { + "symbol": "Pyth Network", + "heading": "The Pyth network aims to bring valuable financial market data to DeFi applications and the general public", + "about": [ + { + "heading": "Introduction", + "content": [ + "The Pyth network is a first-party financial oracle network designed to publish continuous real-world data on-chain in a tamper-resistant, decentralized, and self-sustainable environment.", + "The network incentivizes market participants — exchanges, market makers, and financial services providers — to share directly on-chain the price data collected as part of their existing operations. The network then aggregates this first-party price data (still on-chain) and makes it available for free to either on- or off-chain applications.", + "Pyth has been publishing live prices for US equities, FX, metals, and of course, crypto since our deployment on Solana mainnet in August last year.", + "With over [80 price feeds](https://pyth.network/price-feeds) supported by more than [70 best-in-class data providers](https://pyth.network/publishers) across traditional and decentralized finance, we’ve grown considerably since our humble devnet days. And with Pyth now securing over half a billion in TVL and garnering over [550K client downloads](https://github.com/pyth-network), it’s safe to say that developers have taken a liking to what Pyth offers.", + "You’ll recognize many **#PoweredByPyth** applications: [Solend](https://solend.fi/), [Mango Markets](https://mango.markets/), [Friktion](https://friktion.fi/), [Zeta Markets](https://zeta.markets/), [Drift](https://drift.trade/), [Backpack](https://www.backpack.app/), [Jet](https://jetprotocol.io/), and many more. Off-chain solutions, like [OpenBB](https://openbb.co/) and [SHIFT Search](https://shiftsearch.com/), and institutions like [QCP](https://qcp.capital/) and [Geneva Trading](https://geneva-trading.com/), are also tapping into Pyth’s data.", + "As of October 2022, Pyth data has been available on other blockchains such as BNB Chain, Aptos, Ethereum and Optimism with more to come thanks to Wormhole" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.pyth.network/" + } + }, + "AgR2tq1xcbqwmgDcNRaV1BEP5J3kfJfswP5vn6WWe6uC": { + "symbol": "Hubble Protocol", + "heading": "Hubble Protocol is the issuer of USDH, a Solana native crypto-backed stablecoin that anyone can mint by depositing their crypto.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Hubble is a stablecoin borrowing platform that enables users to unlock the liquidity of their assets by borrowing USDH. When borrowing USDH, users retain exposure to the price movements of their assets, while having the freedom to deploy USDH to earn yield across Solana. On Hubble, borrowers maintain full ownership of their loans and the assets within them, and have total control of managing their positions. Hubble is built to facilitate user liquidity, while establishing USDH as the primary stablecoin on Solana." + ] + }, + { + "heading": "An Inclusive Financial System", + "content": [ + "Hubble aligns itself with the vision of decentralized finance to establish a new, inclusive financial system. In accordance with this, both tokens in the Hubble ecosystem, USDH and Hubble's native token, HBB, can be staked on the protocol to receive rewards generated by borrowing activity." + ] + }, + { + "heading": "Stability and Security", + "content": [ + "Hubble assigns immense importance to the stability of USDH, and the safety of Hubble users. To this end, the protocol maintains flexible borrowing rates and safe loan ratios, ensuring that USDH is always overcollateralized by crypto assets. The USDH stablecoin itself has a robust pegging infrastructure, aimed at ensuring peg stability in any market conditions." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.hubbleprotocol.io/" + }, + "gallery": [ + { + "caption": "Hubble Borrowing Page", + "url": "https://i.imgur.com/i8HQIpJ.png", + "height": 400, + "width": 600 + }, + { + "caption": "Hubble Vaults Page", + "url": "https://i.imgur.com/RErx70N.png", + "height": 400, + "width": 600 + }, + { + "caption": "Hubble Loan Management Suite", + "url": "https://i.imgur.com/9vv51f4.png", + "height": 400, + "width": 600 + }, + { + "caption": "USDH and HBB Staking Page", + "url": "https://i.imgur.com/smL6ZcK.png", + "height": 400, + "width": 600 + }, + { + "caption": "Hubble On-platform Swap", + "url": "https://i.imgur.com/XKJeS1E.png", + "height": 400, + "width": 600 + } + ], + "resources": [ + { + "title": "Hubble Protocol Raises $5M to Expand Solana-Based DeFi Protocol", + "content": [ + "The protocol aims to create a Solana-based equivalent of MakerDao: a DeFi protocol with a U.S. dollar denominated stablecoin." + ], + "url": "https://www.coindesk.com/business/2022/09/08/hubble-protocol-raises-5m-to-expand-solana-based-defi-protocol/" + }, + { + "title": "Hubble Protocol Revamps dApp As USDH Gains Wider Adoption in Solana DeFi", + "content": [ + "The updates included changes made from user feedback since the protocol's launch earlier this year." + ], + "url": "https://www.nasdaq.com/press-release/hubble-protocol-revamps-dapp-as-usdh-gains-wider-adoption-in-solana-defi-2022-05-04" + }, + { + "title": "Hubble Protocol Launches Kamino Finance to Optimize Yields for Liquidity Providers on Solana", + "content": [ + "Hubble Protocol, home of the USDH stablecoin, has launched Kamino Finance: the first concentrated liquidity market maker optimizer of its kind on the Solana blockchain." + ], + "url": "https://news.bitcoin.com/hubble-protocol-launches-kamino-finance-to-optimize-yields-for-liquidity-providers-on-solana/" + } + ], + "roadmap": { + "items": [ + { + "title": "Mainnet Launch", + "date": "2022-01-28T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Hubble Protocol and USDH Launch on Solana Mainnet", + "url": "https://finance.yahoo.com/news/hubble-protocol-usdh-launch-solana-114500370.html" + } + }, + { + "title": "USDH as Quote Token on Primary Solana DEXes", + "date": "2022-04-01T15:42:21.109Z", + "status": "completed" + }, + { + "title": "Onboard Numerous Liquid Staked SOL Assets", + "date": "2022-05-01T15:42:21.109Z", + "status": "completed" + }, + { + "title": "Peg Stability Module Launch", + "date": "2022-08-01T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Introducing the Hubble Peg Stability Module", + "url": "https://blog.hubbleprotocol.io/introducing-peg-stability-mobule/" + } + }, + { + "title": "Introduction of Stability Fees & Isolated Vaults", + "date": "2022-08-01T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Hubble Introduces Stability Fees", + "url": "https://blog.hubbleprotocol.io/hubble-stability-fees/" + } + }, + { + "title": "Onboard Kamino kTokens as Collateral", + "date": "2022-09-01T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Hubble Protocol Accepts Kamino kTokens as USDH Collateral", + "url": "https://blog.hubbleprotocol.io/hubble-kamino-ktokens-usdh/" + } + } + ] + }, + "faq": [ + { + "question": "What can I do on Hubble?", + "answer": [ + "With Hubble’s borrowing platform, you can:\n- Borrow USDH for as long as you’d like\n- Deposit multiple cryptos to mint USDH: SOL, BTC, ETH, mSOL, stSOL, daoSOL, RAY, SRM, FTT, cTokens from Solend, and kTokens from Kamino\n- Yield positive interest on collateral deposits (earn while you borrow)\n- Earn protocol rewards by staking HBB\n- Earn from liquidations by depositing USDH in the Stability Vault (formerly Stability Pool)." + ] + }, + { + "question": "Why should I borrow through Hubble?", + "answer": [ + "Hubble combines several features into one borrowing platform that increases capital efficiency in multiple ways.", + "If you want to go long on SOL, Hubble lets you hold onto your SOL as it appreciates in value while borrowing USDH to deploy in DeFi.", + "Borrow USDH while you yield. You can earn interest from liquid staking tokens like mSOL, stSOL, and daoSOL or from lending with Solend cTokens while borrowing USDH at the same time.", + "With kTokens, you can earn yield from Kamino vaults while leveraging your position up to 20x with USDH." + ] + }, + { + "question": "What is USDH?", + "answer": [ + "USDH is a censorship-resistant, crypto-backed stablecoin, soft-pegged to the US Dollar. USDH is fully collateralized by a basket of crypto assets, deposited into a Hubble Smart Contract.\nUSDH is Solana-native, and can be held in any Solana wallet. For every 1 USDH on the market, more than $1 of crypto is deposited into Hubble.\nAll USDH in existence is minted from Hubble Protocol. Users can mint USDH by depositing their crypto assets into Hubble. By depositing collateral, a user enables the minting of USDH, thus bringing more USDH into circulation." + ] + }, + { + "question": "How does USDH maintain its peg?", + "answer": [ + "1. Peg Stability Module\nThe Peg Stability Module is Hubble's primary pegging mechanism, allowing zero-slippage swaps between USDH and USDC to allow frictionless arbitrage.", + "2. Stability Fees\nHubble has a Stability Fee, acting as an interest rate, that can be increased if USDH falls below peg. The Stability Fee incentivizes users to repay their loans, which can help reduce USDH supply on the market when necessary.", + "3. Hubble Native Yield\nUSDH Vault stakers earn a an adjustable % yield referred to as the Hubble Native Yield (HNY). The HNY can be manually adjusted to increase or decrease rewards, thus increasing or decreasing USDH demand.", + "4. Liquidity\nBy establishing USDH as a ubiquitous stablecoin across Solana, pairing USDH with numerous tokens across multiple DEXes and attracting liquidity, USDH becames more and more settled at a 1:1 ratio with the USD. The more USDH liquidity grows, the stronger the USDH peg becomes." + ] + }, + { + "question": "What is the HBB token?", + "answer": [ + "HBB is Hubble’s ecosystem token, and can be used to participate in the protocol.", + "Once Hubble completes its transition into a Decentralized Autonomous Organization (DAO), HBB will become a governance token. This means that Hubble users will be able to participate in the protocol’s decision-making process by holding and staking HBB.", + "For example, HBB stakers will actively vote on Stability Fee and Hubble Native Yield rates." + ] + }, + { + "question": "How does Hubble approach security?", + "answer": [ + "Hubble is obsessed with security. There are way more lines of code for testing than actual smart contract functionality. Code reviews are extremely strict and security audits are performed regularly, with five having been completed thus far. Hubble works with the \"Move slow and don't break things\" attitude, as the smart contracts involve users' funds.", + "Here are some of the protocol's coding and security practices:\n- Integration tests\n- Stress tests\n- Security tests\n- Sec3 audit tool\n- Property based tests, fuzzing\n- Asset-based Deposit caps\n- Withdrawal flow caps" + ] + } + ] + }, + "759qyfKDMMuo9v36tW7fbGanL63mZFPNbhU7zjPrkuGK": { + "symbol": "Socean", + "heading": "Socean Stake Pool gives you the best risk-free yields on Solana.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Socean Stake Pool is an algorithmic stake pool. A stake pool helps stake SOL on the user’s behalf. We issue depositors a token (scnSOL) that can be redeemed for SOL anytime. scnSOL can be used in DeFi to earn extra yield by lending, borrowing, providing liquidity and purchasing structured products.", + "Why should I stake with Socean Stake?: We are the top performing stake pool by APR over the past year. Over the past year, we outperformed every single stake pool, delivering the best APR for stakers. Our strong delegation strategy and low fees allow us to offer high returns for stakers.", + "Our delegation strategy not only maximises APY for stakers, but also promotes network health. Unlike other stake pools, we don't make backroom deals, or have a preferred set of validators: any validator can and will be selected by our delegation algorithm as long as it demonstrates good performance.", + "The Socean Team actively contribute to core development in the Solana runtime and participate in a variety of Solana ecosystem projects. We've worked with the Solana Foundation for many months, helping to develop the Foundation's stake pool program. We've also received multiple grants from the Foundation to develop the stake pool ecosystem.", + "Unlike some stake pools which run their own code, we use the Solana Foundation's open-source reference implementation. This ensures that our stake pool has been audited for safety, and receives timely fixes and updates. The program can be built from source and verified against the on-chain version.", + "Socean have partnered with most of the best DeFi Protocols on Solana like Orca, Raydium and Solend, so that you can maximise your yield with scnSOL." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://www.notion.so/soceanfi/Socean-Finance-c0dfcb8ae6224fd8b1b87a5355ce774f" + } + }, + "FiG6YoqWnVzUmxFNukcRVXZC51HvLr6mts8nxcm7ScR8": { + "symbol": "Psy DAO", + "heading": "An ecosystem of financial products governed by PSY token holders. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "The Psy DAO mission is to democratize the existing derivatives based crypto infrastructure, build awesome products, and develop exceptional user experiences. The DAO is fully governed by its $PSY token holders and has three core product lines:", + "PsyFinance, a structured products protocol that delivers best in class transparent returns tailored for each users risk tolerance.", + "PsyOptions, a permissionless open-source options protocol that serves as a public good for anyone to create crypto options products.", + "Fusion, an option airdrop and liquidity mining platform that allows teams to raise funds and align incentives between their communities and protocols." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.psyoptions.io/" + } + }, + "6Yj8shsZrjqYQuPkEzcvkmdFq5Nn7RSVQ4EsNqLx7DJQ": { + "symbol": "Duck Punkz", + "heading": "Crypto Duck Punkz: The Great Quekening ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Crypto Duck Punkz is the definition of a Solana NFT pixel project. It embodies everything we know and love about the Solana NFT community. We look forward to building a community of degenerates and memes that value beautifully curated pixel animals." + ] + } + ] + }, + "BZE9AiJrMxUXXjwy9iBPzj34Wh5Zf1wLEFAM4oSSMRLi" : { + "symbol": "Allie Coin", + "heading": "Allie Coin unlocks a new world of gaming.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Allie Coin is a Web3 gaming community founded by Twitch streamer Alliestrasza. Allie has been producing gaming content for more than six years, primarily on Twitch and YouTube, where she has amassed a following of over 200,000 fans. In 2017, she decided to create Allie Coin to combine her loves for gaming and content creation within the emerging Web3 universe. The Allie Coin gaming community is designed to unlock fun and competitive gaming experiences for a global community." + ] + }, + { + "heading": "$ALLIE", + "content": [ + "$ALLIE is a Rally-backed social token you can earn, buy, and trade to support the Allie Coin ecosystem, unlock valuable gaming assets, and vote in our Allie Coin DAO. $ALLIE is on the Solana blockchain, making all transactions energy efficient and secure." + ] + }, + { + "heading": "Play-to-earn Games", + "content": [ + "Our Allie Coin community was born from a love for competitive gaming. By collaborating with the newest and greatest play-to-earn games, we offer our $ALLIE holders the in-game resources, education, and exclusive tournament play opportunities they need to leap ahead of the competition." + ] + }, + { + "heading": "Allie Coin DAO", + "content": [ + "We believe the best way to provide ongoing value to our Allie Coin community is to offer true ownership of the Allieverse. Part of all $sRLY rewards earned with $ALLIE go to our community treasury. All $ALLIE holders have voting power to decide how we spend those treasury assets and what we build next for our ecosystem." + ] + }, + { + "heading": "NFTs", + "content": [ + "Use your $ALLIE to buy NFTs! Own Allie history with Allie Ross animations, unlock special access with tiered Badges, and establish your creative identity with Allie Cats." + ] + }, + { + "heading": "YT Channel", + "content": [ + "For gamers new to the web3 world, we produce public educational content on our Allie Coin YouTube channel about play-to-earn games, social tokens, NFTs, the creator economy, and more." + ] + }, + { + "heading": "Discord", + "content": [ + "Everyone, regardless of whether you hold $ALLIE or not, is welcome to join our Allie fam in the Allie Coin Discord server. Hang out in exclusive chats with Allie, develop new friendships with likeminded gamers, and compete for prizes." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://smooth-exception-37e.notion.site/Allie-Coin-DAO-Charter-2551dc1f4fe24068b783ff365c80f0f8" + }, + "gallery": [ + { + "caption": "Welcome to Allie Coin!", + "url": "https://www.youtube.com/watch?v=5sW5WIfiFD0", + "height": 338, + "width": 600 + }, + { + "url": "https://pbs.twimg.com/media/Ffi7BVIVsAE5R3M?format=jpg&name=large", + "height": 338, + "width": 600 + }, + { + "caption": "IRL Allie Coins given to holders at TwitchCon 2022", + "url": "https://pbs.twimg.com/media/FfDbRhnUoAEcoNs?format=jpg&name=4096x4096", + "height": 600, + "width": 552 + }, + { + "caption": "The Allie Coin team in Joshua Tree", + "url": "https://pbs.twimg.com/media/FbWGr3pUcAAqhLw?format=jpg&name=large", + "height": 400, + "width": 600 + }, + { + "caption": "The Allie Cats unveil a new Realm...", + "url": "https://pbs.twimg.com/media/Fa87rJvUsAAym2o?format=jpg&name=large", + "height": 338, + "width": 600 + } + ], + "resources": [ + { + "title": "Major YouTube Gaming Streamer Joins Forces with Leading Blockchain Game", + "content": [ + "Today the world's leading blockchain game, Splinterlands, announced a new tournament collaboration with major YouTube Streamer, Alliestrasza and CEO of Allie Coin." + ], + "url": "https://www.yahoo.com/now/major-youtube-gaming-streamer-joins-160000079.html?guccounter=1&guce_referrer=aHR0cHM6Ly90LmNvLw&guce_referrer_sig=AQAAACaiQoZ16LrGeP2PFK2untiV1k23PuNcBy_VovWYQLZERfHt-6yO2jR59VbbNRegpXG6hVpV1XebeEmegUxlD3nnrhRUQBWmuhI0tteYK167dcedsRCUJQR9cxhkSxz_R_SbOYvSGi5nxJQUgW6ErLdVyBPKzbtxKWCIl0lVsC7r" + } + ], + "team": [ + { + "name": "Allie Macpherson", + "avatar": "https://pbs.twimg.com/profile_images/1542942640332689410/hpoaZqUe_400x400.jpg", + "description": [ + "Allie is a content creator, gamer, and web3 enthusiast. She started streaming card games on Twitch six years ago under the gaming persona \"Alliestrasza\". She was also one of the first people to launch her social token on the Rally platform! Allie is passionate about innovating in the creator economy through new verticals in web3. She loves to chat about music and concerts, camera gear, strategy games, existentialism, and of course... cats!" + ], + "role": "Founder", + "twitter": "@Alliestrasza" + }, + { + "name": "Mason Geyser", + "avatar": "https://pbs.twimg.com/profile_images/1486148938906226689/y4_ysscW_400x400.png", + "description": [ + "Mason has been in crypto for six years doing everything including investing, trading, mining, DeFi, and social token management. For Allie Coin, he helps plan events, admin tournaments, develop games, research videos, and all sorts of other things that help make Allie Coin one of the best communities in web3. Outside of crypto, Mason loves to play video games, go to music festivals, travel the world, and eat delicious food. He also spends copious amounts of time cuddling with the IRL Allie Cats (and maybe some of the digital ones too)." + ], + "role": "Product Lead", + "twitter": "@Masongos_" + }, + { + "name": "Alex Finden", + "avatar": "https://pbs.twimg.com/profile_images/1560737021970198528/XQnN0fld_400x400.jpg", + "description": [ + "In addition to his career intersecting the creator economy with web3, Alex lives for role-playing games, electronic and metal music, and outdoor adventure sports. He has been advising and assisting creators for over five years and is now building communities for the innovators of web3." + ], + "role": "Community Lead", + "twitter": "@alexfinden" + } + ], + "roadmap": { + "items": [ + { + "title": "Migrate $ALLIE to Solana from Rally.io", + "date": "2022-07-25T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Allie Coin on Solscan", + "url": "https://solscan.io/token/EqTT2V7gcuGAz8croNJLVa63QqC8ZzGn6iwBiCfiFj8h#analysis" + } + }, + { + "title": "Splinterlands collaboration: tournaments + guild", + "date": "2022-09-27T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Major YouTube Gaming Streamer Joins Forces with Leading Blockchain Game", + "url": "https://www.yahoo.com/now/major-youtube-gaming-streamer-joins-160000079.html?guccounter=1&guce_referrer=aHR0cHM6Ly90LmNvLw&guce_referrer_sig=AQAAACaiQoZ16LrGeP2PFK2untiV1k23PuNcBy_VovWYQLZERfHt-6yO2jR59VbbNRegpXG6hVpV1XebeEmegUxlD3nnrhRUQBWmuhI0tteYK167dcedsRCUJQR9cxhkSxz_R_SbOYvSGi5nxJQUgW6ErLdVyBPKzbtxKWCIl0lVsC7r" + } + }, + { + "title": "Launch and Charter Allie Coin DAO", + "date": "2022-10-17T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Allie Coin DAO on Realms", + "url": "https://app.realms.today/dao/ALLIE" + } + }, + { + "title": "Migrate Allie Coin NFT collections to Solana", + "date": "2022-11-20T15:42:21.109Z", + "status": "upcoming", + "resource": { + "title": "Allie cats on Rally.io", + "url": "https://nft.rally.io/alliestrasza/collections/allie-cats" + } + }, + { + "title": "Develop $ALLIE Marketplace", + "date": "2022-01-30T15:42:21.109Z", + "status": "upcoming" + }, + { + "title": "Launch original play-to-earn game(s)", + "date": "2023-02-15T15:42:21.109Z", + "status": "inprogress" + } + ] + }, + "faq": [ + { + "question": "What can I do with Allie Coin ($ALLIE)?", + "answer": [ + "Allie Coin unlocks a new world of gaming. By holding $ALLIE, you can:", + "🏆 Get priority access to our sponsored tournaments\n🎉 Access giveaways of gaming assets, gift cards, and more\n🍻 Attend in-person and virtual events, such as our TwitchCon party or community game nights\n🕹 Unlock special access to our own play-to-earn games, under development now\n🔥 Purchase Allie Coin NFTs, giving you an even more elite status\n❤️ Support Alliestrasza and our community of likeminded gamers, all while retaining token ownership", + "Perhaps best of all, the future of Allie Coin is in the hands of our holders. By holding $ALLIE, you unlock voting power in our DAO, where you can propose new ideas for our community, vote on others, and help spend our treasury assets the way you think is most exciting." + ] + }, + { + "question": "How can I get some $ALLIE?", + "answer": [ + "$ALLIE is just like any other cryptocurrency on the Solana blockchain. To hold it and unlock its perks, you'll just need a Phantom wallet.", + "$ALLIE can be earned or purchased. By completing quests in Discord or participating in our gaming events and tournaments, you can earn $ALLIE without having to buy it!", + "Buying $ALLIE is also easy. You can either swap for $ALLIE from $sRLY on Solana using our website at https://alliecoin.io/swaps, or you can use PayPal to buy $ALLIE directly." + ] + }, + { + "question": "As a web3 game, how can I collaborate with Allie Coin?", + "answer": [ + "Allie Coin acts as both a growth solution and a gaming event producer for your web3 game. With her reach to over 300,000 followers on Twitch and YouTube, founder Allie (Alliestrasza) can help you reach new gamers in highly impactful ways. And with the Allie Coin treasury, we can co-produce tournaments and other gaming events to help introduce our community to yours. For our holders, Allie Coin unlocks a new world of gaming, and as a web3 game developer, you direct their adventures.", + "Take, for example, our collaboration with Splinterlands. Throughout September of 2022, we co-hosted two open tournaments with over $1,500 in prizes, launched a guild for Allie Coin holders, introduced over 200 new players to Splinterlands, and streamed hours of gameplay content from Allie to tens of thousands of live viewers.", + "For sponsorship inquiries: https://alliecoin.io/contact" + ] + }, + { + "question": "Why Solana?", + "answer": [ + "We chose to migrate $ALLIE and our NFTs from the Rally side chain of Ethereum to the Solana blockchain for three primary reasons:", + "1) To make $ALLIE and our NFTs easier to earn, buy, and trade\n2) To grow our treasury with $sRLY rewards and grants directly from the Rally Network Association\n3) To improve our ability to collaborate with likeminded communities" + ] + } + ] + }, + "G43QB1csngJDWBhrBCba5tbVcxcPHhGNtGkqfntfP6fg": { + "symbol": "BlockLive", + "heading": "BlockLive is fast, easy, transparent way to buy and sell live event tickets that you can hold onto for a lifetime.", + "about": [ + { + "heading": "Introduction", + "content": [ + "BlockLive ticketing infrastructure uses smart contracts to promote royalties on primary and secondary event ticket sales. The BlockLive event management and ticketing platform takes advantage of the blockchain to prove ownership, create price transparency, and increase the collectibility and community engagement features around our digital tickets and merchandise." + ] + } + ] + }, + "CXGN5H84vXjoQg7jkAKdAbMtEv3S2K4t8kptwzPzfQLQ": { + "symbol": "Friktion", + "heading": "Smarter returns on your crypto", + "about": [ + { + "heading": "Introduction", + "content": [ + "Friktion offers full-stack portfolio management built to perform across market cycles.", + "Risk-adjusted return strategies for DAOs, individuals, and Institutions." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.friktion.fi/" + }, + "resources": [ + { + "title": "Messari x Friktion", + "content": [ + "" + ], + "url": "https://messari.io/protocol/friktion" + }, + { + "title": "Delphi Digital Podcast", + "content": [ + "In this episode, we sit down with Friktion Labs’ Co-founders, Uddhav Marwaha (CEO) and Alex Wlezien (CTO)." + ], + "url": "https://youtu.be/NzBHEhcJksY" + }, + { + "title": "The Defiant - DeFi, Web3 & NFT Insights", + "content": [ + "Volatility's Best Friend: VOLT #05" + ], + "url": "https://www.youtube.com/watch?v=M6lmTW3Xdcw" + } + ] + }, + "8HZ4V94dtojrTpdUpWrfstr7bEhRnZZHn8jotfns9L9x": { + "symbol": "Ratio Finance", + "heading": "Our mission at Ratio Finance is to De-Risk DeFi for all.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Ratio Finance is a Quantitative Risk Assessment Protocol. Its first use case is allowing investors in the Solana ecosystem to extend the capabilities of their liquidity provisioning efforts by minting our stablecoin (USDr), using their LP tokens as collateral.", + "Our mission is to De-risk DeFi using quantitative and qualitative risk metrics, and credit risk modeling to build cutting edge financial products that allow retail and institutional investors alike to understand and mitigate the risks associated with this new, unique asset class.", + "Our long-term vision is to be the Risk Rating Agency for all of Decentralized Finance." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.ratio.finance/" + }, + "resources": [ + { + "title": "Ratio Finance Raises $2.25 Million to Unlock Liquidity on Solana with Collateralized Debt Positions", + "content": [ + "Ratio Finance is helping to unlock and provide additional liquidity to the Solana ecosystem by allowing Solana users to earn yield, take out collateralized loans, and realize the full potential of their capital, all from a user-friendly interface." + ], + "url": "https://www.bloomberg.com/press-releases/2021-07-16/ratio-finance-raises-2-25-million-to-unlock-liquidity-on-solana-with-collateralized-debt-positions" + } + ] + }, + "4Mgn32BDz48BNRTJLk7fKg3e5Rtgfvf4WvCisR58fsiw": { + "symbol": "Plantoids", + "heading": "Dynamically growing, genetically unique plants with customizable traits that remove CO2 from the atmosphere as they grow!", + "about": [ + { + "heading": "Introduction", + "content": [ + "Plantoids is the digital nursery of the Web3 world, aiming to fill as much of the internet with CO₂-capturing crypto-plants as we can. With the proper love and care from users, Plantoids will grow and change over time while removing 1000x as much carbon dioxide as average household plants through the purchase of carbon credits." + ] + }, + { + "content": [ + "Plantoids are highly customizable, through mutations of your plants genetics to attain different traits, splicing plants to combine multiple traits on one plant, or breeding Plantoids to mix traits you already have. The design of Plantoids allows for endless, unique combinations! Once you have a pool of perfect Plantoids, you can open your garden and sell them to others, spreading the love!" + ] + }, + { + "content": [ + "Together with the Solana community, we hope to grow together and leverage the potential of Web3 and NFT's to enact REAL change in the world." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.plantoids.io" + }, + "gallery": [ + { + "caption": "Introducing Plantoids", + "url": "https://i.imgur.com/ZTST3vh.mp4", + "height": 338, + "width": 600 + }, + { + "caption": "Full Grown Plantoid", + "url": "https://plantoidsblockchainbucket.s3.amazonaws.com/Beta/101.png", + "height": 600, + "width": 600 + }, + { + "caption": "Plantoid Mid Growth", + "url": "https://plantoidsblockchainbucket.s3.amazonaws.com/OG/Phase1/157.png", + "height": 600, + "width": 600 + }, + { + "url": "https://plantoidsblockchainbucket.s3.us-east-1.amazonaws.com/Beta/101.png", + "height": 600, + "width": 600 + } + ], + "team": [ + { + "name": "Mensheng Romano", + "avatar": "https://media-exp1.licdn.com/dms/image/C5603AQENGc-cCYDROQ/profile-displayphoto-shrink_800_800/0/1517858736860?e=1672876800&v=beta&t=GcYtXumMo_P5Y0Jq4nuu8OeZKJ1Y9wSZSdegzc94kwk", + "description": [ + "A Computer Science Engineer with a degree from Princeton University. Left his previous job at Capital One to pursue the chance to make a difference in the fight against climate change by leveraging the unbridled technical potential and community centric nature of NFTs. He hopes to break the mold of NFT projects with Plantoids, demonstrating to everybody, in and out of the crypto sphere, that NFTs can actually realize substantial global impact." + ], + "role": "Co-founder, CTO, Head Plant Smith" + }, + { + "name": "Jose Cruz", + "avatar": "https://pbs.twimg.com/profile_images/1489712247349911557/UuS5eLmC_400x400.jpg", + "description": [ + "A passionate Product Designer with 9+ years of experience designing B2C, B2B, and SaaS products. Now with the ambition of creating meaningful experiences for people through NFTs while having a positive impact on the world at the same time. " + ], + "role": "Co-founder and CPO", + "twitter": "@josecrusss" + } + ], + "roadmap": { + "items": [ + { + "title": "Non-deterministic growth", + "date": "2022-09-14T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Plantoids Whitepaper: Growth", + "url": "https://docs.plantoids.io/plantoids-nft/growth" + } + }, + { + "title": "Mint Phase 1", + "date": "2022-10-03T15:42:21.109Z", + "status": "completed" + }, + { + "title": "Mutation Feature Release", + "date": "2022-10-26T15:42:21.109Z", + "status": "inprogress", + "resource": { + "title": "Plantoids Whitepaper: Human Intervention", + "url": "https://docs.plantoids.io/plantoids-nft/human-intervention" + } + }, + { + "title": "Mint Phase 2", + "status": "upcoming" + } + ] + }, + "faq": [ + { + "question": "How do Plantoids capture CO2?", + "answer": [ + "A significant percentage of the mint price of each Plantoid immediately goes towards the purchase of carbon credits. This contribution is sustained over time by users watering, mutating, and breeding their Plantoids." + ] + }, + { + "question": "What is the carbon footprint of an NFT?", + "answer": [ + "Minting an NFT on the Solana Blockchain consumes as much energy as about 10 google searches. That's only 2 grams of carbon dioxide. A Plantoid consumes that much carbon dioxide in less than ten minutes!" + ] + }, + { + "question": "What are mutations?", + "answer": [ + "Mutations are ways to directly influence the design of your Plantoid. It allows you to change the size, shape, and frequency of your leaves and flowers or the branch structure and overall size of your Plantoid. Mutations even have the possibility of unlocking phenotypes that aren't available through minting!" + ] + } + ] + }, + "JDAa2nFhyaRsESqYqWoZp6aw8egtcSV2UvKRDgfvgNLY": { + "symbol": "Mini Royale Nations", + "heading": "Mini Royale: Nations is a community-owned skill-based shooter set on top of an ever-evolving social strategy game", + "about": [ + { + "heading": "Introduction", + "content": [ + "Mini Royale: Nations is a browser-based FPS + social strategy game. The core shooter game is set on top of a land control-oriented, social strategy game with a deep emphasis on clans, alliances and social mechanics. It is the first live multiplayer game to be powered by the Solana blockchain and boasts over 2 million registered players." + ] + }, + { + "content": [ + "Faraway is the studio behind Mini Royale: Nations and is proud to be supported by some of the best web3 investors including Lightspeed Venture Partners, a16z, Sequoia, FTX, Pantera Capital, among others. Faraway was founded by a team of game industry veterans passionate about open and player-driven economies. The team has served in leadership roles at Scopely, Glu Mobile, Wargaming, Mail.ru, Amazon, and other top game studios." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://whitepaper.miniroyale.io/" + }, + "gallery": [ + { + "caption": "Mini Royale: Nations - Season 3", + "url": "https://i.imgur.com/Hl9FMJL.jpg", + "height": 338, + "width": 600 + }, + { + "caption": "Mini Royale: Nations - Gameplay", + "url": "https://i.imgur.com/gZLI8Jt.png", + "height": 320, + "width": 600 + }, + { + "caption": "Mini Royale: Nations - Fusion Character", + "url": "https://i.imgur.com/Hu7jWLD.jpg", + "height": 338, + "width": 600 + } + ], + "resources": [ + { + "title": "Solana Game Mini Royale: Nations Hits 2M Players After NFT Launch", + "content": [ + "The web-based online shooter is Solana’s first live multiplayer game, and it has hit a new milestone after activating NFT avatars." + ], + "url": "https://decrypt.co/88757/solana-game-mini-royale-nations-hits-2m-players-nft-launch" + }, + { + "title": "Faraway raises $21M to make social games with player-driven economies", + "content": [ + "Faraway has raised $21 million to enable blockchain games with player-driven economies. Not bad for a company that started in June." + ], + "url": "https://venturebeat.com/games/faraway-raises-21m-to-make-social-games-with-player-driven-economies/" + } + ], + "team": [ + { + "name": "Alex Paley", + "avatar": "https://pbs.twimg.com/profile_images/1562890934265815040/rT-Ye3-s_400x400.jpg", + "description": [ + "Alex Paley is a co-founder of Faraway, a web3 gaming studio specializing in hyper-social games with player-driven economies. Prior to founding Faraway with his long-time co-founder, Dennis Zdonov, he was VP of Product at Scopely and Head of Studio at Glu Mobile." + ], + "role": "Co-Founder", + "twitter": "@apaley13" + }, + { + "name": "Dennis Zdonov", + "avatar": "https://media.licdn.com/dms/image/C4E03AQE4acqoOhvkGg/profile-displayphoto-shrink_800_800/0/1529192513215?e=1672876800&v=beta&t=OHx0X4thfZsRVzXcVm-zT28MoePVmaosevanjIWeBqk", + "description": [ + "Dennis Zdonov is a co-founder of Faraway, a web3 gaming studio specializing in hyper-social games with player-driven economies. Prior to founding Faraway with his long-time co-founder, Alex Paley, he was VP of Product at Scopely and Head of Studio at Glu Mobile." + ], + "role": "Co-Founder" + } + ], + "roadmap": { + "items": [ + { + "title": "Season 1 - Game Launch", + "date": "2021-12-09T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "The Mini Royale: Nations Whitepaper", + "url": "https://whitepaper.miniroyale.io/" + } + }, + { + "title": "Season 2 Launch", + "date": "2022-04-07T15:42:21.109Z", + "status": "completed" + }, + { + "title": "Season 3 Launch", + "date": "2022-09-01T15:42:21.109Z", + "status": "completed" + } + ] + }, + "faq": [ + { + "question": "Where can I see FAQs about the game?", + "answer": [ + "https://faq.miniroyale.io/" + ] + }, + { + "question": "Where can I play the game?", + "answer": [ + "https://miniroyale.io/" + ] + } + ] + }, + "6Ffasv4dQ8ZeRbZXZx2tiHcgJh5Y5VELmxnA7Qh1RWRg": { + "symbol": "EmpireDAO ", + "heading": "Web3’s Global Home ", + "about": [ + { + "heading": "Introduction", + "content": [ + "EmpireDAO is a value network of blockchain developers, entrepreneurs, creatives, and venture investors all focused on web3 adoption and community cultivation. " + ] + } + ] + }, + "4H282CCFjstxBd651gdhAydnXcjGk956Dk7p25MqxmfN": { + "symbol": "Holaplex", + "heading": "Holaplex provides a suite of web3 and NFT commerce solutions for businesses.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Holaplex provides a suite of blockchain and NFT products and services to power brands building new business opportunities in Web3. Holaplex makes the process of creating, selling and managing digital assets, both simple to execute and valuable for your business. Our robust suite of tools for enterprises building in Web3, are supported by a community of developers who contribute to critical open source projects we initiate." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.holaplex.com/" + } + }, + "AvpoeRXmbfrtkF9NQvWkcN4LbWmQHy3ntWnYudEUdU3N": { + "symbol": "Blockasset", + "heading": "Licensed athlete token, NFT & social platform.", + "about": [ + { + "heading": "Introduction", + "content": [ + "WHAT IS BLOCKASSET?\nBlockasset is an Athlete Social Token platform, built on Solana.", + "Blockasset athlete tokens are a shared asset controlled by fans and athletes alike. They allow fans direct access to the athlete’s experience with features that incentivize athletes to grow and reward their fanbase.", + "Blockasset has a number of world-famous athletes on board, including sporting Legends Wayne Rooney, Michael Bisping and Alex Ovechkin all of whom are partners & investors, and superstars like Khamzat Chimaev of the UFC and Heavyweight Boxing Champion Oleksandr Usyk, plus over 30 more athletes that are yet to be announced.", + "WHAT IS THE BLOCK TOKEN?\nBlockasset allows fans to invest directly into their favourite athletes through the BLOCK token, the main trading pair for all athlete tokens. Additionally, fans can use BLOCK token to access athlete IDOs via the Athlete Launchpad, think DAO Maker or Binance Launchpad, but for Athlete Social Tokens.", + "HOW DOES IT WORK?\nUsing an intuitive and interactive social platform, seasoned crypto investors and first-timers alike can easily buy, sell and trade athlete tokens, attaching their investments directly to athlete experiences, NFTs, media and governance. BLOCK acts as the gateway to all athlete tokens.", + "Fans can stake their tokens to access unique perks, including athlete governance voting, exclusive content and bonus rewards when their athlete celebrates a specific victory or milestone in their career. Meaning fans and athletes can mutually benefit from an athlete’s success.", + "Fans will be able to spend their athlete tokens on the athlete’s own ‘Experience Store’, where fans can purchase priceless experiences and items directly from the athlete, from Facetimes to sporting event watch parties with the athlete and other fans, training videos, signed memorabilia, real-life meetups and so much more. Via the governance system, fans can even vote on what they want to see in the experience store.", + "When a fan purchases an experience, a percentage goes directly to the athlete, and the remainder is burned, removed from the circulating supply. As a result, the more experiences the athletes offer, and the more fans engage, the more tokens are burned, and with this comes more demand, creating a healthy token economy for all involved.", + "Blockasset puts an athlete’s brand back in control of the two most interested parties—the athlete and their fans." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://blockasset.gitbook.io/whitepaper/blockasset-whitepaper" + } + }, + "FxccMsauuC2KSsWMvrTytm2eP18oRr1HC1VLCaWEysAR": { + "symbol": "Aten", + "heading": "A Solana native eCommerce platform!", + "about": [ + { + "heading": "Introduction", + "content": [ + "Aten is an eCommerce marketplace on Solana. We offer a seamless, no-code onboarding experience, with countless features for you to grow your business in the Web3 space.", + "Some of our key features are:\n- Crypto payments via Solana Pay\n- Fiat (credit card) payments via Stripe\n- SPL token support such as $USDC, $SAMO, $DUST, $STEP, $mSOL\n- Real-time pricing\n- NFT gating\n- Redeemable items via NFT\n- Web2 and Web3 platform integrations to offer the best of both worlds to our merchants" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://aten-solana.gitbook.io/aten/" + } + }, + "4pAWUQBEvSo5sAeKt2bT8htJXy55J4inJDQhzwDcHWv3": { + "symbol": "Virtual Basketball Association (VBA)", + "heading": "Own and manage a virtual basketball team. Build your roster of players and compete to win cash rewards in live basketball games.", + "about": [ + { + "heading": "Introduction", + "content": [ + "In the VBA you instantly take ownership of your very own virtual basketball franchise. VBA combines the best aspects of strategic manager games and fantasy sports into a new basketball experience. You get to build your roster, improve your team and compete to win cash rewards. In the VBA, it’s always game-day, 365 days a year - welcome to Instant Fantasy Basketball." + ] + } + ] + }, + "GL54h53j3KAJZ8AqihMo4H48DgRR8nmSwXxSz1ALTGXg": { + "symbol": "Ostium", + "heading": "A decentralized synthetic asset protocol bringing commodity markets on-chain.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Ostium is a decentralized synthetic asset protocol bringing commodities and other real-world assets on-chain. " + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://ostium-defi.notion.site/Ostium-Documentation-2a6dba08e90d4c41b4118a8af7632579" + } + }, + "EVsSaLkZbnekEnVeMsYEKtj2gYxcuaVYjGLUhVXzKTA9": { + "symbol": "01 Exchange", + "about": [ + { + "heading": "Introduction", + "content": [ + "Most powerful decentralized digital assets exchange, with perpetual futures, and power perpetuals." + ] + } + ] + }, + "EAyrTrS4fEkCCXtbn3qFEtv4LzocYMqeVGYKW7syPt6Y": { + "symbol": "Drippieverse", + "heading": "Bridging fashion and Web3 through a collection of vibey creatures", + "about": [ + { + "heading": "Introduction", + "content": [ + "Drippies™ is a vibey collection of NFTs on Solana that combine beautiful art with a passion for community, fashion, culture, utility & education. Aiming to educate people about the Web 3.0 space and fostering a community of likeminded people. Drippies™ aims to provide long term value combining digital & physical experiences.", + "Each Drippies™ NFT is a unique combination of beautiful handcrafted traits and comes with full commercial IP rights for the owner. Offering a wholesome and supportive community where people can learn and grow together. Exclusive workshops from industry professionals, regular giveaways & airdrops as well as physical items offer unparalleled utility & value." + ] + } + ] + }, + "8PaQWLgqMyF6oxhteahuhvKag2RcbedsRuy2jMFJoLzU": { + "symbol": "Degen Legends ", + "heading": "Degen Legends is esports & investment gaming organization, born in the heart of the web3 gaming revolution. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Degen Legends, previously known as 3D Gamers Guild, was formed by a collective of web2 pro gamers & content creators, crypto & NFT degens here to build a new era of Web 3 gaming culture.", + "Our mission at Degen Legends is our movement. We’re building a brand that proudly represents the crypto community & web2 gamers to the gaming world.", + "Our community is a group of gamers, poker players, traders & builders in the gaming ecosystem, which powers our content, esports & investment brand, linked to our project with our NFT & Token ecosystem.", + "Our front facing brand is a content & esports organization focused on building out web3 gaming.", + "Our backend is powered by our venture capital arm, which we invest into games at highly discounted prices (seed round), and build out games exposure through our community, content & esports. We then provide the assets to our community through our token, which can be earned by staking your NFT or completing missions for us through our gamified mission ecosystem." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://twitter.com/DegenLegends/status/1578460492560941056?s=20&t=_LU0jrtzc-4pZ9jhPRPE0A" + } + }, + "GMpWmXc3sKejmAcAFpcQ4NgCL9Fx3gFR2FeepNUtK5Mh": { + "symbol": "Francium", + "heading": "Francium is a DeFi yield strategy Platform on Solana. Granted by Solana & Serum.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Francium is a DeFi yield strategy platform built on Solana. Francium offers a variety of strategies for both users and strategy builders. We offer automated strategies including Leveraged Farming / Hedge Farming, DeFi Combination Strategies, and Smart Trading Strategies to the users. For strategy builders, Francium will offer DeFi automation toolset which comprises of DeFi Automation Framework, Strategy Dev Toolset, and Standard SDK." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.francium.io/" + }, + "team": [ + { + "name": "Icy", + "avatar": "https://pbs.twimg.com/profile_images/1506936505679319040/PgrlYQgT_400x400.jpg", + "description": [ + "Community Manager of Francium, Francium Supporter" + ], + "role": "Community Manager", + "twitter": "@Icy_Awake" + } + ], + "roadmap": { + "items": [ + { + "title": "Stop-Loss, Take-Profit, Hedge, Margin + Yield Farming", + "date": "2021-10-02T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Docs: Stop Loss", + "url": "https://docs.francium.io/product/stop-loss" + } + }, + { + "title": "Oracle cooperation and robot automation+ Well-known strategies", + "date": "2022-10-15T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Francium is now #PoweredByPyth", + "url": "https://twitter.com/Francium_Defi/status/1581086372211089410?s=20" + } + } + ] + }, + "faq": [ + { + "question": "What is Francium?", + "answer": [ + "Francium is a DeFi yield strategy platform built on Solana. Francium offers a variety of strategies for both users and strategy builders. We offer automated strategies including Leveraged Farming / Hedge Farming, DeFi Combination Strategies, and Smart Trading Strategies to the users. For strategy builders, Francium will offer DeFi automation toolset which comprises of DeFi Automation Framework, Strategy Dev Toolset, and Standard SDK." + ] + }, + { + "question": "Does Francium possess a native token?", + "answer": [ + "We haven't generated a native token, news will be announced through our official channels." + ] + }, + { + "question": "Has Francium been Audited?", + "answer": [ + "Yes, Francium's smart contract has been audited by two prominent firms, CertiK and SlowMist: https://docs.francium.io/resources/audits" + ] + }, + { + "question": "How to use Francium?", + "answer": [ + "Step-by-step instructions are available at https://docs.francium.io/product/how-to-participate." + ] + }, + { + "question": "How to do leveraged yield farming on Francium?", + "answer": [ + "Francium is very easy to use. For example, if you want to farm a pool, all you need to do is deposit a token, such as USDC. Francium's on-chain smart contract will automatically convert half of the deposited USDC into another token (e.g. SOL), then add these tokens to the relevant Dex to get the LP, and then stake the LP to the farming pools. In addition, Auto-compounding is an important way to generate high profits. Francium helps users automatically take out their earnings and reinvest them into relevant positions. This allows profits to be generated quickly, thus maximizing earnings." + ] + }, + { + "question": "Why is Francium built on Solana?", + "answer": [ + "Francium team explained 3 reasons why we have decided to build on Solana: https://francium-defi.medium.com/why-build-defi-on-solana-cc8bc90afdec" + ] + } + ] + }, + "9dvvWxLNRv2HWRkc1FJdgpXuF9fDRZMsCbw6vTdHbp5": { + "symbol": "Ora", + "heading": "The Search Engine for Blockchains", + "about": [ + { + "heading": "Introduction", + "content": [ + "Ora is the search engine for blockchain data. Users can easily traverse on-chain transactions with natural language and attribute filters. Our vision is to make querying a blockchain as easy as a Google search." + ] + } + ] + }, + "DdNEw88N8VTeYfvxdLBwQ9aR4trejTUapGZRGdaMqyNY": { + "symbol": "Contribute", + "heading": "Connect your Solana wallet to join a gated-access group chat with other, verified NFT collection holders.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Contribute is building an ecosystem that gives NFT collection owners full control of their community while eliminating manual processes to verify NFT ownership through Solana wallet gated-access.", + "Through hosting the NFT community chats on Contribute, the NFT collection owners require NFT holders to login using their SOL wallet in order to join NFT community chats. NFT collection owners are required to claim ownership, which Contribute shall verify through cross-checking their wallet addresses.", + "In doing so, NFT collection owners can avoid administrative hustles in verifying the authenticity of NFT holders.", + "In addition, hosting a NFT community on Contribute will avoid spamming accounts from accessing your community and all of its chatrooms within, while limiting security challenges." + ] + } + ] + }, + "2XsZGq4GJoaQ7dC91yWuneq4U9VK3wE6XJ185a4D7fwe": { + "symbol": "Artivive", + "heading": "Artivive is the AR art platform onboarding 200.000 artists to WEB3", + "about": [ + { + "heading": "Introduction", + "content": [ + "Artivive is defining the art form of the 21st century by building the community around creative augmented reality. With 200k creators from 190 countries, we have the 3rd biggest creator community after Facebook and Snapchat." + ] + } + ], + "team": [ + { + "name": "Sergiu", + "avatar": "https://media-exp1.licdn.com/dms/image/C4D03AQGizU9YfTo3QQ/profile-displayphoto-shrink_400_400/0/1658910213572?e=1675296000&v=beta&t=QmPugTj3m-8Fxqc18sU9jgEznwcuIxqphDmOaON1riM", + "description": [ + "Hi, I'm Sergiu.", + "SERIAL ENTREPRENEUR, CREATIVE DIRECTOR, SPEAKER, MENTOR", + "I see myself as a creative who builds tools. I love to travel, meet people, projects and try new things out.", + "Soon after getting my degree, I started with a friend at an agency in Vienna. The agency became a leading Augmented Reality agency serving clients from 42 countries such as Volkswagen and Audi.", + "Today I want to change how art is created and consumed. The project is called Artivive and became from an idea born at a beer to a platform serving more than 100k artists in 120 countries with offices in Europe, US and China." + ], + "role": "CEO" + }, + { + "name": "Codin", + "avatar": "https://media-exp1.licdn.com/dms/image/C4E03AQEqdL9rl4xbfw/profile-displayphoto-shrink_400_400/0/1522834753585?e=1675296000&v=beta&t=kDfdk-bHSAhAX0C9YE5Fn7sgGhSgM26z0dB3ufQ-Sxo", + "description": [ + "Codin is an Austrian-Romanian serial entrepreneur with more than 15 years of management experience in business and sales channel development. He highly values Impact projects and has held workshops and panel talks in several countries; one of his favorites being a digital art biz dev program in Zimbabwe. He believes AR is the new creative medium of our times and building Artivive to be the go-to worldwide platform for AR art is more than a commercial undertaking; it is his professional passion." + ], + "role": "CEO" + }, + { + "name": "Clemens", + "avatar": "https://media-exp1.licdn.com/dms/image/C5603AQHrYGhFmD3S2Q/profile-displayphoto-shrink_400_400/0/1657119850359?e=1675296000&v=beta&t=pGZZySoQJdmuFQntvqwM0YZWmVTPzM3gsI1O9-SAbps", + "description": [ + "Clemens is a self made entrepreneur since his early business years. Is a vespre native since 2016 and Leads the crapes and NFT project of Artivive." + ], + "role": "Head of Blockchain & NFT Management @ Artivive - Entrepreneur @ LoeX", + "twitter": "@WunderWandel" + } + ] + }, + "AH4qTqRFcoNqmYEi7p8heAGVSPHfJrNUPa8DvjDnBsf3": { + "symbol": "Carpool", + "heading": "Backend as a Service for Solana Developers", + "about": [ + { + "heading": "Introduction", + "content": [ + "Your team needs to focus on creating the best product for your users, not wiring up backend infrastructure for your basic needs. Carpool is Firebase for Solana developers. Our backend as a service will have you building better dapps faster and cheaper. We provide custom data APIs, automated alerting and PagerDuty integrations, metrics, and more. Onboard your contracts in 30 seconds, get the tools you need, and just build." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://carpool-dev.notion.site/carpool-dev/Carpool-Documentation-76d152f84e004371b18470f4382bd40d" + } + }, + "58axqgJSAEK3adKL5hx5dYoRqkYMEiEXQZqk9FFFpa7f": { + "symbol": "Solana Spaces", + "heading": "Experience the World of Solana. IRL.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Welcome to the first immersive Web3 learning space, where you can explore the ecosystem of Solana and learn about blockchains. All while earning rewards." + ] + } + ] + }, + "54owXqUwmzR18h4NY6VEp45SNp6qtJUfByDeQuHenhgK": { + "symbol": "Portals", + "heading": "Build your space in the Metaverse", + "about": [ + { + "heading": "Introduction", + "content": [ + "A browser-based metaverse, Portals is an immersive social space where you can explore, make your own, and gather with others." + ] + } + ] + }, + "uywFFJL6JFGwbSXgU95C6v8f4L4DqBXV2Z3KZaJSxy1": { + "symbol": "Orbis Protocol", + "heading": "Orbis Protocol makes it easy to build fast and decentralized social experiences", + "about": [ + { + "heading": "Introduction", + "content": [ + "Orbis Protocol is the web3 social protocol built for developers. Our solutions make it easy to build fast and decentralized social experiences; from messaging and feeds to full social platforms. Many developers use Orbis Protocol to add social features to existing applications, praising its frictionless user experience, speed and composability." + ] + }, + { + "content": [ + "Orbis Protocol works by combining social data standards with a powerful decentralized infrastructure, often known as a “decentralized social layer”. Developers can use the protocol’s advanced SDK and flexible modules to integrate web3 social features in just a few lines of code." + ] + }, + { + "content": [ + "Orbis Protocol is fully open-source and multi-chain, with current support for Ethereum, Polygon and Solana. Data storage is achieved with the Ceramic decentralized data network and encryption via Lit Protocol." + ] + }, + { + "content": [ + "Orbis Protocol is the foundation for a composable web3 ecosystem of applications and social features. This ecosystem is growing fast, with live integrations across categories including governance, creator economy and NFT communities." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://orbis.club/documentation/" + }, + "team": [ + { + "name": "Baptiste Grève", + "avatar": "https://media-exp1.licdn.com/dms/image/C4D03AQGLfQjyy-OkTA/profile-displayphoto-shrink_800_800/0/1632417740582?e=1672876800&v=beta&t=5MMoDXRM13oC2HV7F3aYFRbDXhOMyNuxpixJfYtN_RY", + "description": [ + "Orbis was founded by Baptiste who has been part of the crypto ecosystem for many years now. He founded MyDeFi, one of the first DeFi aggregators, in 2019, which ended up being acquired by Zerion. He also worked with Edge & Node, the team behind The Graph, as a Product Manager." + ], + "role": "Orbis' Founder", + "twitter": "@BaptisteGreve" + }, + { + "name": "Charles Levecque", + "avatar": "https://pbs.twimg.com/profile_images/1585656000048205827/onWxFjEX_400x400.jpg", + "description": [ + "Charles is bringing more than 8 years of experience at Meta & TikTok as business development leader and will support our growth within the web2 & web3 ecosystem." + ], + "role": "Head of Partnerships", + "twitter": "@chrlslev" + } + ], + "faq": [ + { + "question": "What is Orbis?", + "answer": [ + "Orbis Protocol is a set of social data models combined with a powerful decentralized infrastructure. Our advanced SDK and flexible modules make it easy to build fully composable social experiences." + ] + }, + { + "question": "Where is Orbis data stored?", + "answer": [ + "Orbis content is stored on a decentralized data network called Ceramic (off-chain). This ensures that the data shared by your users is open and publicly accessible." + ] + }, + { + "question": "Is Orbis available on Solana?", + "answer": [ + "Yes. A user’s decentralized identity can be created using wallets from Solana as well as other blockchains such any EVM chain (Ethereum Mainnet, Polygon, Optimism, Arbitrum) or Tezos (coming soon)." + ] + }, + { + "question": "Can I take my data from one application to another one?", + "answer": [ + "Yes if the experience is built on the Orbis Protocol. Applications share a common social graph and userbase. This enables a seamless social experience for users, who can take their exisiting data to new applications." + ] + }, + { + "question": "Do you enable any privacy capabilities?", + "answer": [ + "Yes. In the Orbis SDK you’ll find many options to build encrypted experiences like private conversations and token-gated content. Offer the benefits of decentralized social while ensuring the data privacy of your users." + ] + } + ] + }, + "2pJND9oPC1F4yWrBsxTDpmMcg6BbFSwvcu1kExBkbVDU": { + "symbol": "Bridgesplit", + "heading": "Bridgesplit is tokenization infrastructure for complex on & off-chain assets, powering indexes, tranching, lending and more.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Bridgesplit provides tokenization and financial infrastructure for complex assets, powering indexes, tranching, fractionalization, lending, and more. Bridgesplit facilitates $10M/month in digital asset volume and has expanded to support off-chain assets, working with institutions originating assets like commercial loans and climate credits." + ] + }, + { + "content": [ + "This infrastructure is a network of engines that enabling assets to be pooled, tranched, and fractionalized to create liquidity and composability for otherwise difficult to financialize assets. The network also includes plug-and-play financial products, like money-market lending and derivatives that leverage the global settlement layer of these tokenized assets." + ] + }, + { + "content": [ + "One of the larger applications on Bridgesplit is Elixir (https://app.elixirnft.io), a leading marketplace on Solana. Elixir allows users to trade NFTs as if it were a traditional marketplace, but all listings are powered by Bridgesplit pools. This liquidity enables new functionality like instant sales, partial ownership and dollar-cost-averaging, and margin purchases of NFTs." + ] + }, + { + "content": [ + "Beyond the native on-chain uses, the infrastructure supports off-chain assets compliantly, working with institutions and firms originating cash-flow or equity assets. Projects building on Bridgesplit include a commercial loan syndication protocol and an energy credit marketplace. To learn more about projects building on Bridgesplit in the off-chain asset space, visit https://turnpool.com." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.bridgesplit.com" + }, + "resources": [ + { + "title": "NFT Financialization Platform Bridgesplit Announces $4.25M Raise Led by CoinFund and Jump Capital", + "content": [ + "Bridgesplit, the first non-fungible token (NFT) financialization platform built on the Solana blockchain, today announced a $4.5 million seed round led by CoinFund and Jump Capital." + ], + "url": "https://finance.yahoo.com/news/nft-financialization-platform-bridgesplit-announces-140000134.html" + }, + { + "title": "Introducing Bridgesplit", + "content": [ + "Gm. Welcome to the era of financial, artistic, and functional derivatives for NFTs." + ], + "url": "https://medium.com/bridgesplit/introducing-bridgesplit-e505b08a6f47" + } + ], + "team": [ + { + "name": "Luke Truitt", + "avatar": "https://pbs.twimg.com/profile_images/1583244835263234051/mIv58r5f_400x400.jpg", + "description": [ + "Luke is a Duke University Computer Engineering and Economics graduate with a professional background in Quant Trading and Software Engineering. Before Bridgesplit, he co-founded and sold a defense contracting business and spent time at Cruise as an ML engineer and Optiver as a Quantitative Trader." + ], + "role": "Co-Founder", + "twitter": "@TruittLuke" + }, + { + "name": "Mary Gooneratne", + "avatar": "https://pbs.twimg.com/profile_images/1580344716440248322/kd0fXv5U_400x400.jpg", + "description": [ + "Mary is a Duke University Computer Engineering graduate with a professional background in Product and Machine Learning. Before Bridgesplit, she co-founded and sold a defense contracting business and spent time at Salesforce as a product manager and Google as an AI researcher." + ], + "role": "Co-Founder", + "twitter": "@marygooneratne" + } + ] + }, + "H3A8YM1ggR7GggD9qX4CEWkvPmkQUXuhGq2AGpbgqM6J": { + "symbol": "Garbles", + "heading": "The blockchain mobile game that cleans up the planet", + "about": [ + { + "heading": "Introduction", + "content": [ + "Garbles is a mobile game that cleans up the planet. Explore the physical world to collect trash items as NFT. Combine garbage to generate myriads of combinations of Garbles - every time you create a Garble with trash resources, you are removing real C02 from the environment! Use your favourite species to play minigames and missions around the world and embark on a journey to populate the planet... while saving it!" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.garbles.fun/" + }, + "resources": [ + { + "title": "Garbles joins the Crypto-Guilds Alliance", + "content": [ + "Garbles are cute, clumsy monsters that originate from garbage. Help them dove into our dumpsters and gobble up every plastic bottle they can find!" + ], + "url": "https://medium.com/@Crypto-Guilds/garbles-joins-the-crypto-guilds-alliance-4c5ae00cb8ac" + } + ] + }, + "52KrHUxbakN1rq9XoXQtSUmhdYyUZyp3YkWZQihZMTPu": { + "symbol": "Star Atlas", + "heading": "Next-gen gaming metaverse with triple-A UE5 graphics for creating, playing & learning with others worldwide. Power to the People!", + "about": [ + { + "heading": "Introduction", + "content": [ + "Star Atlas is a next-gen gaming metaverse emerging from the confluence of state-of-the-art blockchain, real-time graphics, multiplayer video games, and decentralized financial technologies.", + "Using Unreal Engine 5’s Nanite, real-time graphics technology allows for cinematic quality video game visuals. In addition, blockchain technology using the Solana protocol establishes a largely serverless and secured gameplay experience. Galactic items and resources obtained and traded within Star Atlas create an economy that replicates tangible world assets and ownership. To learn more, visit StarAtlas.com, download the UE5 Showroom on Store.EpicGames.com, join a faction at Play.StarAtlas.com and log in to view your spaceship fleet!" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://build.staratlas.com/" + }, + "resources": [ + { + "title": "Star Atlas on Epic Games", + "content": [ + "Test a high-fidelity, immersive space adventure and grand strategy MMO built in Unreal Engine 5 and sustained by a real galactic economy." + ], + "url": "https://store.epicgames.com/en-US/p/star-atlas-bead34" + }, + { + "title": "Star Atlas launches pre-alpha Unreal Engine 5 showroom", + "content": [ + "ATMTA is making a quarterly progress report on its blockchain-based sci-fi game, and today it said it has launched a pre-alpha playable Unreal Engine 5 experience in its Star Atlas universe." + ], + "url": "https://venturebeat.com/games/star-atlas-launches-pre-alpha-unreal-engine-5-showroom/" + }, + { + "title": "Balthazar Research Report: The Astronomical Weight of Star Atlas", + "content": [ + "Star Atlas takes GameFi to new heights through what we consider the boldest project in the entire space." + ], + "url": "https://bltzr.gg/balthazar-research-report-the-astronomical-weight-of-star-atlas/" + } + ] + }, + "7nLVPup5xx5dWWVcDfjyHXHSr4juFM9wn1XaGQYxcYN1": { + "symbol": "Notifi", + "heading": "Notifi allows Web3 teams to manage user communication under a unified platform.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Today communication tools in Web3 are highly fragmented, with each project often having to custom build their own solutions due to the limitations of alternatives available in the market.", + "This takes away time and resources from the core product and tech building and often yields low ROI for the team. Additionally, after Web3 teams build their own custom solutions, they need to dedicate ongoing resources to maintain and improve the communication tools.", + "This is akin to if every startup built their own CRM tool or social media management platform in-house.", + "At Notifi we believe in a better world where founders/project managers can focus on building what they build best and leave the communication to us." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.notifi.network/" + }, + "resources": [ + { + "title": "Notifi Is Latest Startup Trying to Crack Web 3’s Push Notification Problem", + "content": [ + "With $2.5 million in funding from Race Capital and others, CEO Paul Kim wants to give DeFi degens better tools for minding their bags." + ], + "url": "https://www.coindesk.com/business/2022/03/03/notifi-is-latest-startup-trying-to-crack-web-3s-push-notification-problem/" + }, + { + "title": "Solana DAOs can now bug you to vote with phone calls and texts", + "content": [ + "Notifi Network has integrated with the Solana Realms DAO platform to help increase governance participation rates by expanding notification services." + ], + "url": "https://cointelegraph.com/news/solana-daos-can-now-bug-you-to-vote-with-phone-calls-and-texts" + } + ] + }, + "VAf2xnozMTWeytjUU4GtoyqrGj63owBENr754Y3bzL5": { + "symbol": "Helius", + "heading": "Making Solana development easier, faster, and more accessible. Webhooks, enhanced APIs, and RPCs.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Helius helps you build Solana applications cheaper and faster. We parse on-chain data to extract important content (was this transaction a DAO vote? was it an NFT listing?) and make this data available via easy-to-use, low-latency webhooks, enhanced Solana APIs, and the most powerful (and affordable) RPCs in the ecosystem.", + "You can learn more at https://helius.xyz or read our docs at https://docs.helius.xyz" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.helius.xyz" + }, + "resources": [ + { + "title": "Helius Raises $3.1M to Make Solana App Building 'Faster and Cheaper'", + "content": [ + "Solana infrastructure startup Helius today announced that it raised a $3.1 million seed round co-led by Reciprocal Ventures and Chapter One" + ], + "url": "https://finance.yahoo.com/news/helius-raises-3-1m-solana-160002666.html?guccounter=1" + }, + { + "title": "The All-in-one Developer Tooling for Solana: A look at Helius", + "content": [ + "" + ], + "url": "https://mondaymunday.substack.com/p/the-all-in-one-developer-tooling" + } + ] + }, + "EhDvEUsxDSzU49jnyQ9iTheqQTPtG43gFvwbbrgye8t7": { + "symbol": "Zebec ", + "heading": "Zebec is a continuous settlement protocol on Solana. We are revolutionizing payroll by introducing streaming finance technology.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Zebec is a continuous settlement protocol that currently runs on Solana and supports over 300 projects. It allows for payments to be turned into continuous streams, allowing workers to leverage the time value of their wages, and its payroll application is tax-compliant. Zebec also provides Token Distribution and Vesting solutions for projects in the Solana Ecosystem.", + "Zebec is backed by some of the biggest VC’s in the industry including: Solana Ventures, Coinbase Ventures, Circle, Gemini, Alameda, Shima Capital raising over $40M in different Series rounds.", + "Zebec Protocol is currently the largest business-facing project in the Solana Ecosystem despite only being launched a little over six months ago. It has a TVL of over $200 million with over 300,000 community members." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.zebec.io/" + }, + "resources": [ + { + "title": "Explaining the Zebec Card", + "content": [ + "A payroll solution that gets you paid by the minute" + ], + "url": "https://www.tiktok.com/t/ZTR9nXXeV/" + }, + { + "title": "Zebec to Launch its Rollup Chain via Eclipse to Bring Frictionless Global Payment Standards", + "content": [ + "The Solana-Based Protocol Allows Employees to Be Paid in USDC or Other Stablecoins by the Second" + ], + "url": "https://www.yahoo.com/now/zebec-launch-rollup-chain-via-030000590.html" + }, + { + "title": "Zebec launches real-time, streaming USDC payments, with support from Circle Ventures+", + "content": [ + "New payments innovation pushes treasury management forward" + ], + "url": "https://www.circle.com/en/customer-stories/zebec" + } + ] + }, + "GZyALQBvdBswSpMLabKEBVgKykkZMgnYcJgFk5dGU4aV": { + "symbol": "Snowflake", + "heading": "The most trusted multisig platform on Solana with native automation & a rich app store built for every team's needs.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Snowflake is an institutional-grade multisig platform on Solana that incorporates native automation and a rich app store. We're multiple audited from the leading security firms and peer reviewed by a number of key teams in Solana. Snowflake is among protocols with the highest TVLs in the space.", + "Snowflake battle-tested multisig is one of the most secure ways to store crypto assets and avoid a single point of failure. We have secured the entire treasury for some of the largest teams in Solana.", + "Our native automation enables teams to schedule transactions securely and automate all aspects of asset management.", + "Snowflake app store has everything you need to run your team operations. You can schedule payrolls, manage token vestings, secure Solana program deployments, stake SOL, interact with other protocols, schedule DCA, purchase NFTs, automate custom transactions and many more." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.snowflake.so" + }, + "resources": [ + { + "title": "Partnership Announcement: Snowflake integrates Marinade Finance’s mSOL liquid staking", + "content": [ + "Today Marinade Finance and Snowflake are thrilled to announce a partnership that gives users and teams the ability to stake SOL directly from a secure multisig and receive mSOL" + ], + "url": "https://marinade.finance/blog/partnership-announcement-snowflake-integrates-marinade-msol-liquid-staking" + }, + { + "title": "Friktion enables secure multi-signature access with Snowflake", + "content": [ + "Friktion is proud to announce our partnership with Snowflake, a full-featured and institutional-grade multi-signature wallet." + ], + "url": "https://friktionlabs.medium.com/friktion-enables-secure-multi-signature-access-with-snowflake-93be63d6804c" + }, + { + "title": "Zeta Flex integration with Snowflake Safe Multisig", + "content": [ + "Working together to bring options trading to an institutional custody store." + ], + "url": "https://zetamarkets.medium.com/zeta-flex-integration-with-snowflake-safe-multisig-e5cd931e2cc1" + } + ] + }, + "H2wGwADHWze2yZRurayzutPnDeKxpvf6WhVJpzixM121": { + "symbol": "Hedge", + "heading": "Low-cost leverage of your crypto assets by minting USH, a decentralized overcollateralized stablecoin that is fully composable. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Hedge is a protocol that enables the minting of USH, a stablecoin soft-pegged to the US dollar. USH is backed by crypto collateral deposited by users, who can mint and borrow USH against their collateral at cost-effective rates, as low as 0% interest.", + "The borrowed USH can be used for multiple purposes, including exchanging it for other stablecoins or leveraging your crypto exposure by buying more crypto with USH and adding this to your collateral. You can also deposit the USH in the stability pool to earn HDG token rewards and rewards from liquidations." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.hedge.so" + }, + "resources": [ + { + "title": "Pantera Joins $3.7M Round for Solana Lending Protocol Hedge", + "content": [ + "Race Capital led the round for the interest-free lending protocol ahead of its public launch." + ], + "url": "https://www.coindesk.com/business/2022/04/19/pantera-joins-37m-round-for-solana-lending-protocol-hedge/" + } + ] + }, + "DVDoxbAiYv8oyScU1TUL7ZSsVMpU7zARaFTqwqdw5p5R": { + "symbol": "Solcial", + "heading": "web3 social network", + "about": [ + { + "heading": "Introduction", + "content": [ + "Solcial is a permissionless social network allowing users to be rewarded fairly for their work, and promoting freedom of speech by allowing users to interact without fearing ban or censorship.", + "Solcial is a mobile app (iOS and Android), a desktop app, and a website. On Solcial each user has their own token, allowing you to invest directly in them. You get minted 1 millions coins when you signup, that supply is fixed and the same for everyone. To begin with every user will have their token price set to $1 with 10,000 of their tokens put in a liquidity pool. This helps insure that tokens are tradeable and users can compare token prices knowing they began at the same price. Otherwise, these coins are yours, you can keep them or sell them (or send them to friends).", + "To follow people on Solcial we have 3 subscription levels: you can follow someone for free (Tier 1) to access their public content (similar to Twitter or Instagram), and to access their private content (what we call Tier 2 and 3 subscriptions) you need to own their token, to be an investor in them. That’s what we called the “invest-for-subscription” model.", + "You can also display your NFTs on your user profile, either just to show-off, or to buy & sell your NFTs with your friends.", + "All user content is stored on IPFS and accessed through a P2P layer that we developed. Therefore Solcial doesn't rely on censorable servers or gateways. And the token related operations (minting, trading etc) are all on the Solana blockchain." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://wiki.solcial.io/" + }, + "resources": [ + { + "title": "‘Solcial’ Raises $2.9M to Build Censorship-Free Social Media on Solana", + "content": [ + "The site will place a heavy focus on monetization opportunities for content creators." + ], + "url": "https://www.coindesk.com/business/2021/09/27/solcial-raises-29m-to-build-censorship-free-social-media-on-solana/" + } + ] + }, + "8V5BthCyL5LFDsWDKhfmAHqEgudSw1pXMC2PmWKAAr3D": { + "symbol": "Crossmint", + "heading": "Crossmint builds infrastructure to make NFTs accessible to everyone: minting APIs, fiat on-ramp, wallets, and more", + "about": [ + { + "heading": "Introduction", + "content": [ + "Crossmint is the leading provider of infrastructure to create and distribute NFTs at scale. Our product suite is comprised of:\n- Creation: mint NFTs and send them to any wallet or email address with one line of code. If the recipient doesn't have a wallet, we'll create one for them instantly\n- Payments: Crossmint is the leading fiat on-ramp for NFTs, powering 5,000+ enterprises and developers, like Magic Eden, David Guetta, and the Sacramento Kings. We also offer products like cross-chain payments, and accesslists with payment functionality\n- Wallets: custodial wallets-as-a-service" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.crossmint.io" + }, + "resources": [ + { + "title": "The Most Promising Crypto Startups of 2022, According to VCs", + "content": [ + "" + ], + "url": "https://www.businessinsider.com/most-promising-crypto-web3-startups-of-2022-2022-9" + }, + { + "title": "Announcing Crossmint’s NFT Minting API!", + "content": [ + "Announcing the Crossmint Minting API. " + ], + "url": "https://medium.com/crossmint-tech/announcing-crossmints-nft-minting-api-53020c866d7d" + }, + { + "title": "Web3 development is siloed. QuickNode wants to change that", + "content": [ + "Crossmint allows developers to mint NFTs and add them to a broader collection through a single request." + ], + "url": "https://fortune.com/crypto/2022/09/21/web3-development-is-siloed-quicknode/" + } + ] + }, + "FiKdbhsKRMTzSfyTDRqBY3cy5GjAqCSXYJYRe2wQQ8Ly": { + "symbol": "Unloc", + "heading": "Financial Products & Services for NFT Owners. Initially launching with a fully customizable NFT-collateralized loans platform.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Our goal is to become the preeminent Financial Products and Consumer Services platform on Solana; to provide NFT holders with better rights & more opportunities in Web3 than are afforded to owners of art, collectibles, & property in Web2 or “the real world”. We are working to empower NFT ownership. Our first product will be our fully customizable NFT-collateralized loans platform.", + "Unloc lets the Borrower set their own terms; select SOL or USDC as the loan currency, set your own loan-to-value (LTV) ratios (i.e. interest rate, loan amount, and duration), set multiple sub-offers allowing Lenders to find the perfect terms for their risk profiles, all while at the same time empowering Borrowers to unlock the full potential of their NFTs.", + "Both borrowers and lenders earn $UNLOC simply by engaging in a loan contract, “mining” tokens for the duration of the time the loan is active (not-repaid).", + "Staking Accounts on the Unloc platform have the ability to vote on specific collections’ $UNLOC token emission rates. This creates opportunities for NFT projects to add more utility to their NFT-holding communities.", + "We are also developing Unloc Score, based on locked staking amounts and total lock-up durations, which will determine voting power on the platform." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://unloc.xyz/" + }, + "resources": [ + { + "title": "The Unloc Blog", + "content": [ + "" + ], + "url": "https://blog.unloc.xyz/" + }, + { + "title": "Unloc on LinkedIn", + "content": [ + "" + ], + "url": "https://www.linkedin.com/company/unlocnft/" + } + ] + }, + "2m2HfiYwMdbwVQ2BsSdqzQihdK2c2JymVy7aREDa9Lzu": { + "symbol": "Credix", + "heading": "Credit investing made global ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Credix is rethinking and rebuilding how debt capital markets should work. It combines the most scalable web3 infrastructure including proprietary, highly scalable algorithms and innovative smart contract logic to provide institutional investors the experience and opportunities they’ve been looking for. Credix enables high quality loan originators around the world to access previously untapped capital in a matter of days, in a digital and regulatory compliant platform." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.credix.finance" + }, + "resources": [ + { + "title": "DeFi Platform Credix Raises $11.25M to Connect Institutional Lenders With Emerging Market Fintechs", + "content": [ + "The decentralized credit marketplace will use the capital to expand beyond Brazil." + ], + "url": "https://www.coindesk.com/business/2022/09/06/defi-platform-credix-raises-1125m-to-connect-institutional-lenders-with-emerging-market-fintechs/" + }, + { + "title": "What Is DeFi Credit? The Evolution of On-Chain Lending", + "content": [ + "Organizations such as Credix are working to bring real-world asset lending on-chain" + ], + "url": "https://blockworks.co/what-is-defi-credit-the-evolution-of-on-chain-lending/" + } + ] + }, + "6iMVHPfcBebctV5bvSY23d2nuDuKvzTLP9HNCwWV2gGe": { + "symbol": "Diaspora DAO", + "heading": "4,444 Ancestors to guide you on your Journey into Web3", + "about": [ + { + "heading": "Introduction", + "content": [ + "4,444 Ancestors to guide you on your Journey into Web3. Connecting the Diaspora on the Solana Blockchain with History, Lineage, Up-skilling & Digital Art. With a goal to inspire ‘Decentralized Powernomics’ across the culture, summon your Sol & Mint an Ancestor. Your key-to-access, collectible & guide.", + "Diaspora is a community centric DAO powered by the Solana blockchain. Leveraging blockchain technology, Diaspora’s members will empower economic opportunity, education, and equality. Projects under Diaspora will be funded initially by the launch of a unique NFT collection that showcases historic people, moments, and iconography of the diaspora. It will serve as a digital historical treasure, reimagined through a futuristic lens." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://www.ourdiaspora.xyz/DiasporaWhitePaper.pdf" + }, + "resources": [ + { + "title": "The Diaspora DAO Wordcel Page", + "content": [ + "" + ], + "url": "https://www.wordcelclub.com/diaspora.sol" + } + ] + }, + "DXezSkchMaYZTa3WM5xVU1SDQhMsFspMLuyyMuWk2YK9": { + "symbol": "Rage Effect", + "heading": "The First AAA-Quality Free-to-Play NFT MMO Shooter on Solana!", + "about": [ + { + "heading": "Introduction", + "content": [ + "Rage Effect is a community-driven PvP and PvE FPS based on the Solana blockchain that introduces a new gaming genre and a Play-and-Earn system. The genre is a cross between Shooter, Survival and Exploration, with a Counter Strike-like feel and dynamic gameplay by Guilds that encourages teamwork to help players survive and win rewards.", + "We have created a fast-paced combat battle game where players may choose among four maps, with none showing mercy. Players can discover their secrets, join forces with friends, devise plans, and emerge victorious. Create your own guild, invite their friends, and rise through the ranks together!" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.rageeffect.io" + }, + "resources": [ + { + "title": "The Rage Effect Medium Page", + "content": [ + "" + ], + "url": "https://rageeffect.medium.com/" + }, + { + "title": "The Rage Effect Youtube Channel", + "content": [ + "" + ], + "url": "https://www.youtube.com/channel/UCcNw733l1hEpO19Mln9Gf5A" + } + ] + }, + "3DLKv41oFs8DiHBkUEdm3MwiyJ9Sp4E6sb8QCAqynnbA": { + "symbol": "Satellite IM", + "heading": "A fully decentralized peer-to-peer communications platform", + "about": [ + { + "heading": "Introduction", + "content": [ + "Satellite IM is a Web3 fully decentralized peer-to-peer voice, video, and text communication platform. It is built as an EVM-compatible evolving protocol for simple sovereign storage and peer-to-peer communication, leveraging the interplanetary filesystem (IPFS). The platform allows users to sign, encrypt, broadcast, search, and store documents or messages with decentralized identifiers (DIDs), all while making the need for an existing wallet or on-chain data completely optional." + ] + } + ] + }, + "7KsnMMyrF8wsxsLZNBZ8hRkGe13MdjAT9ko1qDEvkEWQ": { + "symbol": "Rye", + "heading": "The easiest way to add checkout and shopping data to any app", + "about": [ + { + "heading": "Introduction", + "content": [ + "Rye is an open protocol for eCommerce that allows merchants, stores, and customers to transact openly and with minimal fees, controlled by the community.", + "The core of the protocol is the Rye eCommerce API which has three core products:\n1. Rye Checkout - Programmatic checkout that you can add anywhere.\n2. Rye Earn - Earn by setting your own custom margin or through affiliate commissions for any product.\n3. Rye Inventory - Get product data from any Amazon or Shopify store.", + "Affiliate links and ads do not work well. Rye Checkout and Affiliates lets developers add checkout to their native experience, eliminating conversion drop-off and streamlining the purchase experience. Rye inventory gives developers access to an inventory of 350 million products to power their checkout/affiliate experiences." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.rye.com/start-here/readme" + }, + "resources": [ + { + "title": "A16z Crypto Leads $14 Million Bet On Rye, New Web3 Commerce Startup From Justin Kan", + "content": [ + "Twitch cofounder Justin Kan is launching a new startup in the world of web3." + ], + "url": "https://www.forbes.com/sites/alexkonrad/2022/10/11/a16z-crypto-web3-commerce-rye-justin-kan/" + }, + { + "title": "A16z Leads $14M Funding Round for New E-Commerce Platform From Twitch Co-Founder", + "content": [ + "Rye plans to become fully decentralized on the Solana blockchain" + ], + "url": "https://www.coindesk.com/business/2022/10/11/a16z-leads-14m-funding-round-for-new-e-commerce-platform-from-twitch-co-founder/" + }, + { + "title": "Rye on Crunchbase", + "content": [ + "" + ], + "url": "https://www.crunchbase.com/funding_round/rye-series-a--e6df4b79" + } + ] + }, + "HJ4YUJFSa1xX5wfbrPQKMTcTTnyT2eMxBk2eyBFGVmR7": { + "symbol": "Ludex.gg", + "heading": "APIs & SDKs for video game developers to easily implement smart contracts into games with no blockchain knowledge required.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Ludex is building a dev-toolkit to help game developers build and implement all sort of blockchain transactions into their games (FTs, SFTs & NFTs) with no blockchain experience required.", + "With 2.7 billion gamers in the world, Ludex is an avid believer that the mass adoption of web3 will be heavily led by the videogaming industry. However, building a good/popular game is in itself a huge challenge and a very competitive space to be in. Hence, game developers should fully focus on making the best games possible, not on the technicalities of blockchain development and integrations.", + "Game devs take care of making awesome games, Ludex takes care of making it happen on chain." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.ludex.gg/" + }, + "resources": [ + { + "title": "Unity wallet integration & in-game signing Demo", + "content": [ + "We show how you can login with a wallet to a native unity mobile game via web2 socials." + ], + "url": "https://www.youtube.com/watch?v=Q8Vp1YAIShE" + }, + { + "title": "1V1 Wager Demo", + "content": [ + "All amounts and UI can be changed depending on the needs of the video game providers/devs." + ], + "url": "https://www.youtube.com/watch?v=ks2kurSSNgo" + }, + { + "title": "Dashboard Demo", + "content": [ + "Implement smart contracts easily into your game with the Ludex Dasboard." + ], + "url": "https://www.youtube.com/watch?v=hwvT3iyCZNc" + } + ] + }, + "DntR8BU5tYVhQUNfARFG5VxKrpdRaKY2qKC3v8cYJirm": { + "symbol": "Okay Bears", + "heading": "Okay Bears has the highest trade volume of any NFT collection on Solana and is an emerging global icon of clean, positive cool.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Okay Bears represent a seismic shift in online culture. Breaking NFT records at launch, the brand quickly transcended from a virtuous Web3 community to a unique place in mainstream popular culture." + ] + }, + { + "content": [ + "It is the first Web3 brand to be signed by IMG, the world’s leading brand licensing company representing global icons such as Angry Birds, Fortnite and Pepsi. Bruno Maglione, President of Licensing, IMG, said: “Okay Bears has shown that NFTs can be a powerful tool of mobilization and empowerment, creating a global community that exudes positivity and support. Their brand message and values have resonated with people across the world, and we plan to ensure these are celebrated and reflected in a range of creative collaborations and products as we work with Okay Bears towards elevating online and offline cultures together." + ] + }, + { + "content": [ + "The Okay Bears NFT collection features 10,000 diverse bears, reaching over $150 million in total trade volume since its launch in April 2022. The brand has also collaborated with NBA athletes and Wilson (via HEIR) and organically attracted a wide range of celebrities from Game of Thrones, FaZe Clan, Olympians, athletes, actors and models." + ] + }, + { + "content": [ + "Co-Founder Kais shares, “Together with our community, we inspire hope through our online activity every single day. We spread the message that you are enough just the way you are; that it is okay to just be okay." + ] + } + ], + "gallery": [ + { + "caption": "A celebration of over 15 Okay Bears holders.", + "url": "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/ff8338db-1c0b-490f-b8e3-4cdc40532786/dfffgfm-ba998197-d4fc-48f7-a1f4-c3b7b309f13f.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcL2ZmODMzOGRiLTFjMGItNDkwZi1iOGUzLTRjZGM0MDUzMjc4NlwvZGZmZmdmbS1iYTk5ODE5Ny1kNGZjLTQ4ZjctYTFmNC1jM2I3YjMwOWYxM2YuanBnIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.D-XpOtwpezcAkN0Kaw87z5A8v-GETiJjThOa591GrEw", + "height": 338, + "width": 600 + }, + { + "caption": "Okay Bears is a culture shift. A clean collection of 10,000 diverse bears building a virtuous community.", + "url": "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/ff8338db-1c0b-490f-b8e3-4cdc40532786/dfebic3-3383b36d-09e0-49c7-aabb-31abdde41757.png?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcL2ZmODMzOGRiLTFjMGItNDkwZi1iOGUzLTRjZGM0MDUzMjc4NlwvZGZlYmljMy0zMzgzYjM2ZC0wOWUwLTQ5YzctYWFiYi0zMWFiZGRlNDE3NTcucG5nIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.VC4P0KshwekGSxl62_NROWAIEonJ_lWvaGF2TfHJvIg", + "height": 388, + "width": 600 + }, + { + "caption": "Nothing says #WeAreOkay more than chill beats and good vibes. ", + "url": "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/ff8338db-1c0b-490f-b8e3-4cdc40532786/dfffdjb-39b49771-5f4d-4393-896e-ede247dbaf4f.png?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcL2ZmODMzOGRiLTFjMGItNDkwZi1iOGUzLTRjZGM0MDUzMjc4NlwvZGZmZmRqYi0zOWI0OTc3MS01ZjRkLTQzOTMtODk2ZS1lZGUyNDdkYmFmNGYucG5nIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.GojSqWwN15nfv4uvt29xEl8bLLj-abIZvafgw-AeWE4", + "height": 338, + "width": 600 + } + ], + "resources": [ + { + "title": "IMG & Okay Bears", + "content": [ + "" + ], + "url": "https://imglicensing.com/clients/okay-bears/" + } + ], + "team": [ + { + "name": "Chadwick", + "avatar": "https://assets-global.website-files.com/623ab58321ca25f489fca9e6/6307059865bd55479fe1f266_ChadBear-2.jpeg", + "description": [ + "Community engagement, growing brand reach, and strategy." + ], + "role": "Social Media and Engagement", + "twitter": "@chadwick" + } + ], + "roadmap": { + "items": [ + { + "title": "The Blueprint - We're Building This Together", + "date": "2023-11-01T15:42:21.109Z", + "status": "inprogress", + "resource": { + "url": "https://www.okaybears.com/blueprint" + } + } + ] + } + }, + "wij7YqAPCYtPk4isjY5TpoMpbYC7xupwuKVzpbnZHp7": { + "symbol": "HEIR Labs, Inc.", + "heading": "HEIR - the best sports culture community for athletes and fans with exclusive content, experience, merchandise, and digital assets", + "about": [ + { + "heading": "Introduction", + "content": [ + "We are building a community and a platform for athletes and other culture creators to expand, enhance, and deepen their relationships with their supporters around the world through membership-based access to:\n- a vibrant online community chatting about sports and culture all day\n- athletes' exclusive digital content such as introspective videos, inviting you to be part of their growth journey\n- unique digital assets that make you the envy of the crowd\n- intimate first-person experiences that make you part of an athlete's crew and part of the HEIR family\n- exclusive merchandise in partnerships with and from athletes and culture creators\nand more!", + "The platform is designed for culture leaders, creators, shapers, and consumers who love sports." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "" + }, + "resources": [ + { + "title": "Exclusive Q&A: Jeffrey Jordan on the inspiration for inaugural 'NFT JAM' Tournament", + "content": [ + "Michael Jordan’s son Jeffrey is following in his footsteps by redefining the fine art of the business of basketball." + ], + "url": "https://usatodayhss.com/2022/michael-jordan-son-jeffrey-jordan-on-nft-jam-tournament-web3" + }, + { + "title": "HEIR to launch Lonzo Ball NFT", + "content": [ + "HEIR, a Web3 platform co-founded by Michael Jordan's son, Jeffrey, is launching its first athlete membership NFT with Bulls star Lonzo Ball." + ], + "url": "https://www.axios.com/2022/06/02/michael-jordan-nft-with-lonzo-ball" + } + ] + }, + "GDBJ3qv4tJXiCbz5ASkSMYq6Xfb35MdXsMzgVaMnr9Q7": { + "symbol": "Raydium", + "heading": "Raydium is an Automated Market Maker (AMM) built on the Solana blockchain for the Serum Decentralized Exchange (DEX). ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Raydium is an automated market maker (AMM) and decentralized exchange (DEX) built on Solana. Raydium users can swap in liquidity pools, trade using an order book, participate in liquidity mining, or stake RAY to participate in IDOs through the Raydium AcceleRaytor launchpad.", + "Unlike other AMM DEXs where liquidity is siloed off from other platforms, Raydium leverages its pool liquidity to place orders on Serum's central limit order book, providing a free market making service to token pairs. Raydium features permissionless creation of constant product pools, yield farms and concentrated liquidity pools, allowing any project team or user to create a market, list a token, and automatically market make on Serum's central limit order book." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://raydium.gitbook.io/raydium/" + }, + "resources": [ + { + "title": "What Is Raydium (RAY)?", + "content": [ + "Raydium is an automated market maker (AMM) built on the Solana blockchain that shares liquidity with the Serum decentralized exchange." + ], + "url": "https://www.kraken.com/learn/what-is-raydium-ray" + }, + { + "title": "Raydium on Coinbase", + "content": [ + "" + ], + "url": "https://www.coinbase.com/price/raydium" + }, + { + "title": "Raydium on Coindesk", + "content": [ + "" + ], + "url": "https://www.coindesk.com/price/raydium/" + } + ] + }, + "DP2wpegQpLFYq9ntSZewi8XR6AoTdw31dbvinSekZKjr": { + "symbol": "Wordcel Club", + "heading": "Building the Layer0 of Social Connections and Information Sharing on Solana.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Wordcel is a Decentralised Publishing Stack on Solana to enable writers to publish and monetize their work on-chain and manage their distribution while truly owning every single piece of the puzzle.", + "It is our first step in bootstrapping a Decentralised Social Networking ecosystem built on top of Wordcel and Solana by enabling glass eaters in the ecosystem to build applications on top of our protocol.", + "We want to enable Social Sovereignty online for all forms of content via an ecosystem of tools under our protocol in the future, thereby forming the Layer0 of Social Connections and Online Information Sharing in the future." + ] + } + ], + "resources": [ + { + "title": "An invitation to build on Wordcel", + "content": [ + "A deep-dive on why you should build on Wordcel, along with 3 fundable RFPs" + ], + "url": "https://superteam.substack.com/p/an-invitation-to-build-on-wordcel" + } + ] + }, + "8mrcnaGgMVKsYzWRDzSe47n2hTQjkuhYeXHGgSR1xkHP": { + "symbol": "Primitives", + "heading": "primitives is the most joyful place to interact with blockchains :)", + "about": [ + { + "heading": "Introduction", + "content": [ + "Primitives exist to make crypto products fun, easy to use, and accessible to everybody. We believe we've created the easiest onboard into a crypto wallet, and an intuitive minting experience, tied together by ephemeral chatrooms all in one place.", + "Create a profile NFT and send it to close friends through Primitives to begin bringing your social graph on-chain." + ] + } + ], + "resources": [ + { + "title": "Primitives wants to turn your crypto wallet into a social network", + "content": [ + "DJ Gabeau, one of Snapchat Stories’ earliest engineers and founder of web3 social network Primitives, told TechCrunch that he thinks NFTs can be a genuinely enjoyable way for people to connect with one another digitally and make memories." + ], + "url": "https://techcrunch.com/2022/05/25/primitives-crypto-wallet-social-network-snapchat-startup/" + } + ] + }, + "HWYGhNLKUrrE8RmVkitDZrgsb68Ye8sp5P2pVLb2FyNf": { + "symbol": "Gangbusters Ltd", + "heading": "Community-driven Social Web3 Gaming - Building Everlasting IPs Togehter with Our Fans! ", + "about": [ + { + "heading": "Introduction", + "content": [ + "At Gangbusters, we are building community-driven, social cross-platform web3 games that are embedded into the way people spend time online. Our first game BattleTabs has had over 1.4m installs with an active community of over 15k fans on Discord. Inspired by our community activities, player-hosted tournaments, and fan content, we are leveraging composable, player-owned crypto assets to super-charge our community to create strong IPs with a rich ecosystem." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://www.gangbusters.io/blog" + }, + "resources": [ + { + "title": "An Interview with Justin Kan", + "content": [ + "" + ], + "url": "https://www.youtube.com/watch?v=nRbUc9N9hGY" + }, + { + "title": "BattleTabs Fleet Brawl x Fractal", + "content": [ + "Welcome to the BattleTabs x Fractal Tournament! Shoot down enemy battleships to win free mint tokens." + ], + "url": "https://fractal.medium.com/battletabs-fleet-brawl-x-fractal-d7e83852fc7e" + }, + { + "title": "Bandai Namco Investment Press", + "content": [ + "" + ], + "url": "https://www.bandainamcoent.co.jp/corporate/press/top/single.html?q=040SzIrxF6" + } + ] + }, + "8msNFq5VBectsGAv66zYx5QRve1p3m6ZEz49xaWX3tbd": { + "symbol": "Parcl", + "heading": "Parcl is an investment protocol that allows users to trade the price movements of real estate markets around the world. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "The Parcl Protocol is a DeFi investment platform that allows users to trade the price movements of real estate markets around the world. Users can discover global real estate markets, gain detailed insights, and have the opportunity to either buy or short real estate markets based on whether they think real world property values will increase or decrease. To provide users with the most accurate and reliable data to trade on, Parcl prices are powered by the Parcl Price Feed, which represents the median price per square foot/meter, aggregated at either the city or neighborhood level, and updated daily.", + "We're on a mission to deliver real estate to everyone." + ] + } + ], + "resources": [ + { + "title": "Blockchain Real Estate Startup Raises Round To Expand Digitized Property Investments", + "content": [ + "The capital will go toward staff expansion and marketing, co-founder and CEO Trevor Bacon told Blockworks" + ], + "url": "https://blockworks.co/blockchain-real-estate-startup-raises-round-to-expand-digitized-property-investments/" + }, + { + "title": "Housing Markets Are Tanking, But Can Blockchain Solve Real Estate Volatility? Interview With Parcl CEO Trevor Bacon", + "content": [ + "Benzinga sat down with Trevor Bacon, CEO and co-founder of Parcl, to gain insight on how to monetize current real estate market volatility through cutting-edge blockchain solutions." + ], + "url": "https://www.benzinga.com/markets/cryptocurrency/22/10/29279270/housing-markets-are-tanking-but-can-blockchain-solve-real-estate-volatility-interview-with" + }, + { + "title": "How Blockchain Is Enabling The Next-Generation Of Real Estate Investors", + "content": [ + "How Blockchain Is Enabling The Next-Generation Of Real Estate Investors" + ], + "url": "https://cryptonews.com/news/how-blockchain-is-enabling-the-next-generation-of-real-estate-investors.htm" + } + ] + }, + "5jHwG4CWkZhJD75M9kiZybGtzr4GC32NwvEq6dmSKefm": { + "symbol": "Enthusiast Gaming", + "heading": "Ev.io is a competitive first person shooter on Solana in which you can earn SOL for getting kills. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Ev.io is a play to earn blockchain FPS - equip an NFT character skin, weapon or sword to start earning e (which converts to SOL) for every kill. Equip all 3 to unlock maximum earning potential. Earn bonuses for bonuses e.g. sword kills, trip mine kills and killing sprees." + ] + } + ], + "resources": [ + { + "title": "A Glimpse into the Future of Gaming", + "content": [ + "EV.io is a Solana NFT-enabled game developed by a small team from Enthusiast Gaming, exemplifying a “game first, crypto second” approach to game development." + ], + "url": "https://www.vaneck.com/us/en/blogs/digital-assets/a-glimpse-into-the-future-of-gaming/" + } + ] + }, + "27tbVohNkTpWiKtz1oGJQPhb3gPSGJfc4e2MtqFcuSuW": { + "symbol": "Glass", + "heading": "Glass is the first video NFT marketplace for video creators, collectors, and traders built on the solana blockchain. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Glass is the first video NFT marketplace for video creators, collectors, and traders built on the solana blockchain. Glass helps creators by turning their videos into collectibles on the solana blockchain and allowing them to sell those video NFTs directly to their superfans. Our mission is to demonstrate the true value of video content with an ecosystem that accelerates investment, inspiration, creation & community. In the past year, the seven-person company has generated around $1 million in revenue for its creators, and the company itself has brought in about $100,000 in revenue from NFT revenue splits. It has worked with artists like Timbaland and Kygo." + ] + } + ], + "resources": [ + { + "title": "Exclusive: NFT video platform Glass raises $5M, led by TCG, 1kx", + "content": [ + "Glass, a video platform that allows creators to monetize their videos as NFTs, has raised a $5 million seed round." + ], + "url": "https://www.axios.com/2022/09/27/exclusive-nft-video-platform-glass-raises-5m-led-by-tcg" + } + ] + }, + "99vU7SHYJ4tSEqRNjY352Fx7gMSYfgcqxmjBMDyx3q8j": { + "symbol": "Vyper Protocol", + "heading": "A DeFi primitive to create, trade, and settle, on-chain derivatives", + "about": [ + { + "heading": "Introduction", + "content": [ + "Vyper is a primitive for permissionless derivatives. It allows anyone to participate in derivatives trading. Our unique architecture brings scalability and modularity to derivatives, bridging TradFi to DeFi" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.vyperprotocol.io/" + }, + "resources": [ + { + "title": "The Vyper Protocol Medium Page", + "content": [ + "" + ], + "url": "https://medium.com/@vyperprotocol" + } + ] + }, + "G2jq991DwNM1irZFwhPtCmzquXwBNQvAg5Sj8tBnqA2H": { + "symbol": "Hyperspace", + "heading": "Solana’s most powerful NFT trading platform. Explore and collect NFTs aggregated across all marketplaces.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Hyperspace.xyz is an all-in-one NFT platform built on Solana. Built by the original Solanalysis team.", + "Our Mission: To enable the best NFT trading and commerce experience for everyone - while protecting the openness and composability of web3.", + "Core Products:\nMarketplace - we've built the most powerful NFT trading experience on Solana. Not only can you trade on our native marketplace contract with low fees, but you can also trade across all other Solana marketplaces - all from a single UI\nLaunchpad - we work closely with project creators to launch new NFT projects\nAnalytics - quickly track and analyze trends across different NFT projects\nUpcoming Drops - monitor new NFT projects launching everyday on Solana" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.hyperspace.xyz/hype/" + }, + "resources": [ + { + "title": "Hyperspace raises $4.5m for aggregation of Solana NFTs", + "content": [ + "With this round of financing, Hyperspace said it plans to focus on product development and ramping up marketing efforts" + ], + "url": "https://coinrivet.com/hyperspace-raises-4-5m-for-aggregation-of-solana-nfts/" + } + ] + }, + "HivVP77n6hsrgsaJUoHkYRMzgjjfmgWdcRrdrYSm6LLg": { + "symbol": "CAMPUS", + "heading": "Helping brands, influencers, and their fans thrive in the new tokenized economy.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Backed by Solana Ventures and co-Founded by Tim Tebow, Christine Menedis, and Ricky Caplin, CAMPUS helps brands, influencers and their fans thrive in the new tokenized economy. Among those who trust CAMPUS with their on-chain brand are Nissan, dozens of top universities, the prestigious Heisman Trophy Trust, and hundreds of elite athletes and influencers.", + "CAMPUS has three verticals: media and marketing, college sports, and white-label solutions. The group takes standout, turnkey content creation, delivery, and analytics alongside web3 solutions that can all be skinned to different versions for any market and back it with custom, leading-edge tech built to facilitate ownership and transference of tokens. And, in the case of NFTs, the utility they unlock.", + "CAMPUS' officially-licensed college sports marketplace - https://campus.io - is the first and fastest growing within the sector. Join today to get in early." + ] + } + ], + "resources": [ + { + "title": "The Campus Medium Page", + "content": [ + "" + ], + "url": "https://medium.com/@campus.io" + }, + { + "title": "The Campus Youtube Channel", + "content": [ + "" + ], + "url": "https://link.campus.io/youtube" + }, + { + "title": "Tim Tebow and Nissan CMO Talk NFTs and NIL at Ad Age Event", + "content": [ + "The former college football star joins brand leaders from Macy's, Liberty Mutual, Abercrombie & Fitch and others" + ], + "url": "https://adage.com/article/ad-age-events/ad-age-next-cmo-dec-7-2022-tim-tebow-nissan-abercrombie-fitch-macys-liberty-mutual/2442136" + } + ] + }, + "FneznCHADXLsDjkvq51UmhZMropsXkSbkzJ5qXBMw1RF": { + "symbol": "Port Finance", + "heading": "", + "about": [ + { + "heading": "Introduction", + "content": [ + "Port Finance is a suite of interest rate products including variable rate lending, fixed rate lending and interest rate swap with peak TVL 300 Million. We have raised a total of 6.3 million of funding from investors such as Spartan Capital, Alameda Research, Brevan Howards, Jump Capital, Defi Alliance and many others.", + "We are one of the first protocols to bring variable rate lending to Solana mainnet and also the first protocol to introduce fixed rate lending. Both of the protocols, plus an open source SDKs to interact with them, a liquidator are all open-sourced to the wider Solana community." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.port.finance/" + }, + "resources": [ + { + "title": "Port Finance raises a $5.3M strategic round to offer fixed rate lending on Solana", + "content": [ + "Port Finance, the Solana based lending protocol with the vision of bringing a whole suite of interest rate products to DeFi users, has raised $5.3M in its latest strategic funding round." + ], + "url": "https://www.globenewswire.com/news-release/2021/12/23/2357516/0/en/Port-Finance-raises-a-5-3M-strategic-round-to-offer-fixed-rate-lending-on-Solana.html" + } + ] + }, + "J7deUothQNZ2momjrDwetv9RjL714h8U8cSz6oVd3s1m": { + "symbol": "Elusiv", + "heading": "Elusiv combines privacy with safety by offering compliance in mind next-generation privacy solutions for a better Web3.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Elusiv is a Zero-Knowledge privacy protocol for privately sending and receiving funds on-chain with a big focus on compliance. Elusiv both provides privacy to the users (even when interacting with normal non-private wallets on the blockchain) and safety by keeping malicious actors out of the privacy protocol. Furthermore, Elusiv VMs, an extension of Elusiv, enable rapid development of solutions leveraging more general ZK circuits." + ] + } + ] + }, + "C98yb8FSshG7oH5pCMf41ghg199YjsoUozxQ4VdCpwmM": { + "symbol": "Aurory", + "heading": "Aurory Project is a AAA studio building the web3 gaming platform of the future.", + "about": [ + { + "heading": "Introduction", + "content": [ + "In Aurory, players can complete quests, discover lost relics, defeat enemies, and compete against other players in a variety of immersive game modes using magical creatures called Nefties!", + "The single-player Aurory Adventure mode (PvE), features an epic storyline with parallels to the crypto-universe, told through aesthetically colorful art and delivered with high quality production value. Players are taught all about crypto, blockchain, NFTs, and more through an engaging story about the adventures of our heroes, Sam and Helios.", + "In the multiplayer Tactics Mode (PvP), players will learn how to best use their assets and rise to the top of the leaderboard, competing against other players.", + "Aurory bridges the gap between traditional pfp projects and AAA gaming. In October, 2021, Aurory launched it’s own 10K pfp NFT project called “Aurorians”. The team then had 10,000 unique 3D models created and in May 2022, they launched their first playable NFT experience. This allows Aurorian holders to play with their unique NFT avatar as the protagonist in the game’s Adventure Mode." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://aurory.substack.com/" + }, + "resources": [ + { + "title": "Aurory Launches New Patch with New Energy System and Reward Loop", + "content": [ + "Aurory Project outlined the new rewards system, new Nefty, big UI improvements, and other notable changes, such as the nerfing of specific functions." + ], + "url": "https://www.investing.com/news/cryptocurrency-news/aurory-launches-new-patch-with-new-energy-system-and-reward-loop-2924168" + }, + { + "title": "Esports Giant TSM FTX Teams Up With Solana 'Blue Chip' NFT Game Aurory", + "content": [ + "Aurory aims to be the “Axie Infinity” of Solana. It’s backed by some of the same investors, and now it’s mixing it up with one of biggest esports teams around." + ], + "url": "https://decrypt.co/82404/tsm-ftx-aurory-nfts-solana" + }, + { + "title": "Aurory set to release SyncSpace feature", + "content": [ + "The new feature for the Solana-based play-and-earn JRPG is a gamified inventory system that mixes on-chain and off-chain interaction in order to minimize the number of transactions, providing a more seamless experience." + ], + "url": "https://playtoearn.net/news/aurory-set-to-release-syncspace-feature" + } + ] + }, + "5KvezmjkfTshcWZ56jt6xj88Nu5Lbgy4gigHenhH8HPb": { + "symbol": "Chillchat", + "heading": "Chillchat is the collaborative platform to build virtual worlds.", + "about": [ + { + "heading": "Your home on the internet", + "content": [ + "Find an escape while exploring tons of unique worlds." + ] + }, + { + "heading": "Find your party", + "content": [ + "Find your party: A place where you belong, with people just as weird as you." + ] + }, + { + "heading": "Create your wildest dreams", + "content": [ + "Go at it alone or drag your frens along and build something epic. Don’t worry, it’s easy!" + ] + }, + { + "heading": "Virtual worlds make everything more fun", + "content": [ + "There's one for every occasion, whether for playing games, running events, working remotely, or just chilling out It's all up to how you use them." + ] + }, + { + "heading": "Powered by $CHILL", + "content": [ + "Use it to mint your creations as NFTs or buy, sell, and trade with other creators on our community marketplace. Got extra $CHILL? Stake it to earn more passively." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "" + }, + "resources": [ + { + "title": "Solana Ventures leads $1.9m round of NFT gaming platform", + "content": [ + "Southeast Asian blockchain company Chillchat has raised US$1.9 million in a seed round led by Solana Ventures, with participation from FTX Ventures, Animoca Brands, and Yield Guild Games Southeast Asia." + ], + "url": "https://www.techinasia.com/chillchat-seed-funding-solana-ventures" + }, + { + "title": "Chillchat Raises US$8.35M in Seed Rounds for a Social 'Create-to-Earn' Metaverse", + "content": [ + "Chillchat has raised US$6.5 million through a seed token round to build out its \"Create2Earn\" 2D pixel art social metaverse that fosters interpersonal connections and collaboration." + ], + "url": "https://www.globenewswire.com/en/news-release/2022/06/07/2457772/0/en/Chillchat-Raises-US-8-35M-in-Seed-Rounds-for-a-Social-Create-to-Earn-Metaverse.html" + } + ] + }, + "2hzSGHCfkAaGWedSc3Bh9CrmxGaQNCu8wjZPUfvbkYm7": { + "symbol": "Grim Syndicate", + "heading": "Global storytelling brand anchored in lore, gaming, and unique NFT experiences.", + "about": [ + { + "heading": "Introduction", + "content": [ + "The Grim Syndicate is collection of 10,000 unique, generative reaper agent NFTs minted on the Solana Blockchain. These Grims are both a pass into the community, as well as, a transportive ticket into a new infinitum of experiences.", + "The Lore: Whether you call us logistic supervisors or ferrymen for the non-corporeal, transporting Souls to the Ethereal Plane is quite literally our job at the Ethereal Transit Authority. We take pride in our work; shepherding Souls of each and every world, universe, and planar dimension to their next great adventure!", + "But while most newly untethered Souls easily make their way quickly and easily to our Phantom Phreights (patent pending), some Souls need a little extra ...encouragement!", + "That’s where the Agents of the Grim Syndicate come in – an elite collective responsible for ferrying some of those fickle Souls from across the dimensional spectrum (even those hard-to-reach pocket universes) to arrive at their final destination. At the Ethereal Transit Authority death doesn't have to mean a dead-end.", + "The Upcoming: Abysswalkers, our card and tile game, is the connective tissue that ties all of the Grim Syndicate experiences together in what will be a competitive gaming scene for Grim holders and others outside of the traditional NFT ecosystem." + ] + } + ], + "resources": [ + { + "title": "Grim Syndicate on Magic Eden", + "content": [ + "" + ], + "url": "https://magiceden.io/creators/grim_syndicate" + } + ] + }, + "7f47FkSAJqJLNY5p3jKxp7CLbEYbQDhhmKuYDJKrNJEq": { + "symbol": "Degenerate Ape Academy ", + "heading": "", + "about": [ + { + "heading": "Introduction", + "content": [ + "Our mission here at the academy is simple: Take 10,000 of the smoothest brained apes, put them all in one location and let the mayhem ensue. The academy was founded on the principles of friendship making, crayon eating and absolute, unregulated, deplorable, degenerate behaviour. Welcome fellow apes, to the Degenerate Ape Academy." + ] + } + ] + }, + "5Mt6EghNJHaPbNtHxH7tbbrMdwSP3sXcPRCqwPCbTVN4": { + "symbol": "Audius", + "heading": "Audius is a fully decentralized music platform. Own the masters & the platform.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Audius is a music community and discovery platform that puts the artist in control.", + "It does this by being fully decentralized: Audius is owned and run by a vibrant, open-source community of artists, fans, and developers all around the world. Audius gives artists the power to share never-before-heard music and monetize streams directly. Developers can build their own apps on top of Audius, giving them access to one of the most unique audio catalogs in existence.", + "Backed by an all-star team of investors, Audius was founded in 2018 and serves millions of users every month, making it one of the largest crypto applications ever built.", + "Learn more at https://audius.co" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.audius.org/" + }, + "resources": [ + { + "title": "And the First Streaming Service to Partner With TikTok Is…", + "content": [ + "It's the blockchain-powered Audius, rather than Spotify or Apple Music, that will let artists upload songs into TikTok's Sound Kit in one click" + ], + "url": "https://www.rollingstone.com/pro/news/tiktok-sounds-streaming-crypto-blockchain-nfts-audius-1211699/" + }, + { + "title": "Audius Acquires Virtual Music Experience Platform SoundStage.fm", + "content": [ + "Audius is already rolling out an \"ambitious product roadmap\" in the wake of the deal, which expands the company's efforts in the music metaverse." + ], + "url": "https://edm.com/industry/audius-acquires-soundstagefm" + }, + { + "title": "What is Audius? The Decentralized Music Sharing and Streaming Service", + "content": [ + "It’s like Spotify or SoundCloud, but on the blockchain: Audius is a crypto-powered music streaming app that’s giving power back to artists." + ], + "url": "https://decrypt.co/resources/what-is-audius-the-decentralized-music-sharing-and-streaming-service" + } + ] + }, + "23DjgMdE4vCCNckzy8F4NvRFMxH6X2LVU6DrC75btVR8": { + "symbol": "Cega", + "heading": "Cega is the #1 options protocol on Solana building exotic options structured products offering the best risk-adjusted yield.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Cega builds exotic options structured products for retail investors that generate superior yield and offer built-in protection against market downturns. Cega is developing new capabilities in tech, token contracts, and data modeling that will enable the next evolution of defi derivatives.", + "Cega's inaugural product is the fixed coupon note (FCN) which is a type of exotic option structured product that has both equity option and bond-like characteristics. Investors earn high, daily yield payments on their deposited capital until the FCN expires/matures", + "At expiry, the initial deposit is returned to investors in full if the price of the FCN's linked crypto assets have not fallen by a significant amount (e.g. 50% or more)." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://cega.gitbook.io/cega/" + }, + "resources": [ + { + "title": "Cega Mainnet Launch", + "content": [ + "" + ], + "url": "https://www.youtube.com/watch?v=3cI1z1sgpes" + } + ] + }, + "4vXAFpUSfRzxbtriRe7tH6u2Uwbm2SmBsD8EKnWow5qh": { + "symbol": "Cogni", + "heading": "Your crypto, paycheck, and debit card – all in one sleek app.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Cogni is a super wallet that lets you hold your crypto, paycheck, and debit card in the same app. Plus, powerful lifestyle features designed for the next generation of money and asset management. We’re a financial technology platform bringing banking and crypto services created for the 1% to the 99%. " + ] + } + ] + }, + "BqLWTZv8xfJiCtu9gm87T1EqtAnL2cCJ1PS9JoKn3oBy": { + "symbol": "Backpack", + "heading": "Backpack is a home for your xNFTs.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Today, wallets are the gatekeepers of blockchain ecosystems. They’re permissioned, closed, and closer to \"Web 2\" than they are to \"Web 3\". If you want to build a new protocol, you need to lobby for integration, but there are so many protocols on so many blockchains that no one can expect to be included. It’s a product management nightmare, and it’s holding back innovation. Wallets are more like blackberries than they are like iPhones—token specific asset management tools—but imagine a wallet that used all of your crypto assets. Imagine if you could manage your Mango margin accounts, stake your DeGods, or view your Magic Eden listings not in a web view, but natively in a single interface. Imagine if you wanted to create your own token protocol with your own twist without having to convince everyone to implement it. xNFTs are the standard breaking standard making all of this possible. And for the first chapter in this story, we’re building not a wallet, but something different, an xNFT operating system we call Backpack.", + "Like a wallet, Backpack manages your private keys and connects to apps. But unlike anything else, it’s asset and protocol agnostic. Everything in the wallet is an xNFT. This is a big deal. Most wallets only show your tokens. Some don’t even show your precious JPEGs. Backpack, however, is a home for everything. It’s an open, programmable system built for Web3. And like any other application operating system, has a set of developer frameworks and APIs associated with it, allowing anyone to build their own xNFT apps for any protocol on any blockchain—without permission.", + "Backpack and xNFTs give developers the ability to create more immersive and customized user experiences." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.xnft.gg" + }, + "resources": [ + { + "title": "An ‘iPhone launch moment for Web3’? Coral raises $20M from FTX Ventures and Jump Crypto to build Backpack", + "content": [ + "Coral wants to create the Web3 version of the Apple app store. To do so, it’s launching a different kind of wallet platform called Backpack." + ], + "url": "https://fortune.com/crypto/2022/09/28/coral-raises-20-million-ftx-ventures-jump-crypto-backpack-wallet/" + }, + { + "title": "Solana developer platform Coral raises $20M led by FTX, Jump Crypto to build web3’s iPhone", + "content": [ + "The company announced today that it has raised a $20 million strategic round led by FTX Ventures and Jump Crypto, with participation from Multicoin Capital, Anagram, K5 Global and others." + ], + "url": "https://techcrunch.com/2022/09/28/solana-coral-ftx-jump-crypto-iphone-web3-apps-xnfts/" + }, + { + "title": "FTX Ventures, Jump Crypto Lead $20M Fundraise for Executable NFT Wallet", + "content": [ + "The wallet, a forthcoming project from Solana developer Coral, will give users ownership of application code." + ], + "url": "https://www.coindesk.com/business/2022/09/28/ftx-ventures-jump-crypto-lead-20m-fundraise-for-executable-nft-wallet/" + } + ] + }, + "G1RWjNmizVM6vR8pEsHta4iRYcTa7jWM1mQErz4phpRy": { + "symbol": "Bastion", + "heading": "Bastion, leveling up the DAO experience both for the voter and for the DAO!", + "about": [ + { + "heading": "Introduction", + "content": [ + "Winners of the DAO category in the Solana Summer Camp Hackathon 2022 and built on top of Realms; Bastion provides a comprehensive DAO tool that helps DAOs on Solana to truly access DeFi and help it's voters become more involved. " + ] + } + ], + "resources": [ + { + "title": "Meet the winners of the Solana Summer Camp Hackathon", + "content": [ + "For the DAOs track, first place went to Bastion, which allows a DAO to become a wallet that transacts across Solana dApps and signs governance proposals, which secured a prize of $50,000 in USDC." + ], + "url": "https://solana.com/news/solana-summer-camp-winners" + }, + { + "title": "First place in the #SolanaSummerCamp DAOs Track goes to Bastion, which allows a DAO to become a wallet that transacts across Solana dApps and signs governance proposals", + "content": [ + "" + ], + "url": "https://twitter.com/solana/status/1570081447435997187" + } + ] + }, + "9MwbgfEkV8ZaeycfciBqytcxwfdYHqD2NYjsTZkH4GxA": { + "symbol": "Magic Eden", + "heading": "Magic Eden is the leading NFT platform for discovery, expression, and ownership across digital cultures. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Magic Eden is the leading community-centric NFT marketplace driving the next billion users to Web3. Led by product focused leaders, Magic Eden is building a user-friendly platform powered by market-leading minting and trading solutions.", + "Magic Eden brings dynamic cultural moments onto the blockchain, empowering users across thousands of digital communities to create, discover and collect unique NFTs.", + "MagicDAO is the platform and community in which people can engage with each other and product features supporting the future of our marketplace can be explored and tested together." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "" + }, + "resources": [ + { + "title": "Magic Eden raises $130M, hitting unicorn status at $1.6B valuation", + "content": [ + "NFT marketplace Magic Eden, launched just nine months ago, has raised $130 million in a Series B round co-led by Electric Capital and Greylock Partners, bringing its valuation to $1.6 billion." + ], + "url": "https://techcrunch.com/2022/06/21/magic-eden-raises-130m-hitting-unicorn-status-at-1-6b-valuation/" + }, + { + "title": "Magic Eden CEO: ‘Very Natural’ to Expand From Solana to Ethereum NFTs", + "content": [ + "Jack Lu tells Decrypt about the top Solana marketplace’s embrace of Ethereum—and why Magic Eden was “worried” about the reaction." + ], + "url": "https://decrypt.co/110185/magic-eden-ceo-very-natural-to-expand-from-solana-to-ethereum-nfts" + }, + { + "title": "Magic Eden launches Magic Ventures fund for Web3 games", + "content": [ + "Magic Eden has launched Magic Ventures, a new venture capital fund that will focus on investments in Web3 games." + ], + "url": "https://venturebeat.com/games/magic-eden-launches-magic-ventures-fund-for-web3-games/" + } + ] + }, + "wx9R4TZLgL4VaVK89uW9D9DpMKMUCSm16nABeahk9Ex": { + "symbol": "DeGods", + "heading": "Degods is on a mission to build the best communities on the internet. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Degods are a collection of degenerates, punks, and misfits. Gods of the metaverse & masters of our own universe. DeGods can be converted to DeadGods with DUST.", + "Known for their countless experiments and unique experiences, this community often leads the direction of the Solana NFT market." + ] + } + ] + }, + "ALzXvpmcmqmpNcFTbPzZ8ykSxHGqta85gTANfi8YPkPW": { + "symbol": "Solana Mobile", + "heading": "Solana Mobile is bringing web3 to mobile through the Solana Mobile Stack (SMS) and Saga, a flagship Android smartphone.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Solana Mobile’s mission is to provide the best web3 experience on mobile.", + "Solana Mobile’s first flagship device, Saga, is an Android mobile phone with unique functionality and features tightly integrated with the Solana blockchain. Saga makes it easy and secure to transact in web3 and manage digital assets, such as tokens and NFTs. Saga will be the first device to include Seed Vault, which protects user private keys via secure hardware and AES encryption.", + "We also launched the Solana Mobile Stack (SMS), which provides a new set of libraries for wallets and dApps, allowing developers to create rich mobile experiences on Solana, the world’s most performant blockchain. The SDK is built to run alongside Android and provides libraries and programming interfaces for Android apps and secure key custody, simplifying the developer experience to build and extend dApps functionality for Solana.", + "The Saga devices will be pre-installed with the Solana dApp Store, a new distribution channel for native mobile dApps built on Solana. With no fees on in-app purchases, dApp sales, or subscriptions, the dApp Store will be the home to the next wave of great web3 experiences." + ] + } + ] + }, + "DgWc4yWcqDnG62ZH6bHMeHfZUhBf5y7HZ9uqvgMs8JQW": { + "symbol": "Taki", + "heading": "Own your token-powered social network with TAKI.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Taki is a token powered global social network that enables creators and fans to own their influence. Anyone can create their own User Coin. Users and can earn social crypto tokens simply by participating within the community. Users can earn $TAKI, the basic social crypto token on the Taki App, by engaging and creating content - such as writing posts or commenting. $TAKI can then be used to buy User Coins which represent the value and influence creators bring to Taki. Use $TAKI and User Coins to reward others, grow your audience and share in the ownership of Taki." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://wiki.taki.app/key-concepts/taki-app" + }, + "resources": [ + { + "title": "Taki raises $3.45 mn in seed funding from CoinDXC, Coinbase Ventures, others", + "content": [ + "Taki brings a unique engagement platform for creators, users, and crypto enthusiasts, who can earn a daily income by posting content and chatting with others about things that interest them." + ], + "url": "https://www.livemint.com/companies/start-ups/taki-raises-3-45-mn-in-seed-funding-from-coindxc-coinbase-ventures-others-11649329623365.html" + }, + { + "title": "Taki is a social network that brings the old ‘engage to earn’ model in a new package, with crypto tokens as rewards", + "content": [ + "The Taki social network rewards its users to engage on the social network, giving them crypto tokens in exchange." + ], + "url": "https://www.businessinsider.in/cryptocurrency/news/taki-is-a-social-network-that-brings-the-old-engage-to-earn-model-in-a-new-package-with-crypto-tokens-as-rewards/articleshow/90561223.cms" + }, + { + "title": "Web3 Will Make Or Break Social Media", + "content": [ + "" + ], + "url": "https://www.forbes.com/sites/lawrencewintermeyer/2022/08/25/web3-will-make-or-break-social-media/?sh=13022ea55f38" + } + ] + }, + "7sf3tcWm58vhtkJMwuw2P3T6UBX7UE5VKxPMnXJUZ1Hn": { + "symbol": "Solend", + "heading": "Solend is the autonomous interest rate machine for lending on Solana", + "about": [ + { + "heading": "Introduction", + "content": [ + "Solend is a permissionless money market on Solana. Deposit over 70 assets to earn yields or use as collateral. Users can access deep liquidity pools of blue-chip assets in Main pool, or governance tokens in Isolated pools. Additionally, users may also create their own permissionless pools with any token of their choice. " + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.solend.fi" + } + }, + "899YG3yk4F66ZgbNWLHriZHTXSKk9e1kvsKEquW7L6Mo": { + "symbol": "Marinade", + "heading": "Secure Solana and earn rewards without your funds locked in.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Marinade is a DAO that helps Solana to become ever more censorship-resistant, performant, and capital efficient through liquid staking. It allows SOL holders to stake their SOL without locking their funds, so they can get both staking rewards and participate in DeFi using the staked SOL token called mSOL. With mSOL accepted in more than 40 projects on Solana, you can use it as collateral for borrows, provide liquidity, trade, pay for NFTs, or unstake immediately back to SOL without waiting days. Marinade stakes the delegated SOL through an open algorithmic delegation strategy, now supporting operations of over 400 validators on Solana." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.marinade.finance/" + }, + "resources": [ + { + "title": "Marinade DAO Executes Token Exchange Program to Align with Leading Solana Builders", + "content": [ + "Marinade is pleased to officially announce the next chapter of the DAO through the execution of the Token Exchange Program. " + ], + "url": "https://finance.yahoo.com/news/marinade-dao-executes-token-exchange-153500316.html" + } + ] + }, + "3MMDxjv1SzEFQDKryT7csAvaydYtrgMAc3L9xL9CVLCg": { + "symbol": "Project Serum", + "heading": "Faster, Cheaper and more Powerful DeFi", + "about": [ + { + "heading": "Introduction", + "content": [ + "Serum brings the speed and convenience of centralized exchanges to DeFi while remaining fully trustless and transparent." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.projectserum.com" + }, + "resources": [ + { + "title": "The Project Serum Youtube Channel", + "content": [ + "" + ], + "url": "https://www.youtube.com/channel/UCQ-jrhf6mt2PWa8cqF1-6Mw" + } + ] + }, + "9pLvqBe2CxC4HXQD5UQ7YLpQUqC5A9SqU4kNqw9inbNQ": { + "symbol": "Eternal Dragons", + "heading": "Eternal Dragons is a Web3 gaming series brought to you by Trailblazer Games, telling the story of the long-lost Eternal Dragons.", + "about": [ + { + "heading": "Introduction", + "content": [ + "The epic new gaming series Eternal Dragons is brought to you by Trailblazer Games. Trailblazer Games is a Web3-native gaming studio formed by a team consisting of three serial entrepreneurs and veteran gaming industry leaders from the likes of King, EA, and Microsoft, who have experience in building large-scale and sustainable free-to-play economies. A shared passion unites them for creating engaging and entertaining gaming experiences.", + "In parallel with the development of games, Trailblazer is developing a platform that will power a new global economy where guilds can efficiently access capital, trade assets, and hire talent to compete, grow and succeed. This platform is being integrated into the game experience to provide value directly to the players and the community by delivering a full vertical slice at each stage of development.", + "Our goal is that the Eternal Dragons IP will transcend the original game series, powered by the blockchain, to provide future value and experiences within other media and entertainment formats and in the decentralized finance space. To achieve that, we are laser-focused on, first and foremost, creating fun gameplay with mass market potential, packaged in an exciting fantasy universe of dragons and magic where anything is possible and where the players write the actual history." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://builder.eternaldragons.com/" + }, + "resources": [ + { + "title": "Trailblazer Games raises $8.2M for Eternal Dragons blockchain game", + "content": [ + "Trailblazer Games has raised $8.2 million to develop a fantasy blockchain game and universe dubbed Eternal Dragons." + ], + "url": "https://venturebeat.com/games/trailblazers-raises-8-2m-for-eternal-dragons-blockchain-game/" + }, + { + "title": "Episode 29 of the Right Click, Save NFT Podcast", + "content": [ + "In this week's episode we chat with Alex one of the founders of the Eternal Dragons project." + ], + "url": "https://www.youtube.com/watch?v=TlX4puABZyQ" + }, + { + "title": "Trailblazer Games on Crunchbase", + "content": [ + "" + ], + "url": "https://www.crunchbase.com/organization/trailblazergames" + } + ] + }, + "413KSeuFUBSWDzfjU9BBqBAWYKmoR8mncrhV84WcGNAk": { + "symbol": "Tulip", + "heading": "Solana's Yield Aggregation Homestead", + "about": [ + { + "heading": "Introduction", + "content": [ + "Tulip Protocol is the first yield aggregation platform built on Solana with auto-compounding vault strategies.", + "The dApp (decentralized application) is designed to take advantage of Solana's low cost, high efficiency blockchain; allowing the vault strategies to compound frequently. This benefits farmers with higher APYs, not requiring active management, and lower gas fees.", + "The protocol offers 4 main products: auto vaults, leveraged yield farming, lending, and strategy vaults." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://tulip-protocol.gitbook.io/tulip-protocol/" + }, + "resources": [ + { + "title": "The Tulip Protocol Medium Page", + "content": [ + "" + ], + "url": "https://medium.com/tulipprotocol" + } + ] + }, + "5o6gEoeJBpuXT1H1ijFTq3KcSGx7ayabdG2hji7cB3FG": { + "symbol": "Mean DAO ", + "heading": "Mean DAO is a protocol DAO offering Real-time payment infrastructure and Multisig to retail and businesses.", + "about": [ + { + "heading": "Introduction", + "content": [ + "As a protocol DAO, our philosophy is product quality and community first. Projects and people from across the DeFi space can come together to collaborate and vote to build the best products for the future of finance. Being a DAO means builders, investors, and users all have an aligned economic incentive to move us forward fast while benefiting all parties fairly." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.meandao.org/mean/products/mean-protocol" + } + }, + "3HC3mCQkpAAHQZa3aJjQJFpFNwoLp3ZWnkCYuWzoymo9": { + "symbol": "Amulet", + "heading": "Simple, Reliable Cover For Everyone in Web3.Maximum protection and yield, fully protected through Protocol Controlled Reserves", + "about": [ + { + "heading": "Introduction", + "content": [ + "Amulet Protocol (\"Amulet\") is a decentralized risk protection protocol (\"RPP\") built for Rust-based ecosystems, starting with the Solana blockchain. Amulet has designed an innovative and open risk protection model which not only effectively addresses the common challenges of existing decentralized RPPs, but also creates a new paradigm shift for the whole risk protection sector." + ] + }, + { + "content": [ + "Amulet's vision is to offer Simple, Reliable Cover for everyone in Web3. With the addition of Amulet, users in the entire Rust-based ecosystem will gain access to a new way to hedge various risks with cover product offerings." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.amulet.org/" + }, + "resources": [ + { + "title": "Staking capabilities with high APY percentages now available on Amulet", + "content": [ + "As Amulet has now been launched, the crypto community will be delighted to know that the platform has officially added staking capabilities with considerably high APY percentages." + ], + "url": "https://cointelegraph.com/press-releases/staking-capabilities-with-high-apy-percentages-now-available-on-amulet" + }, + { + "title": "TOKEN2049 Singapore 2022: \"I Love Hacks\"", + "content": [ + "Keynote Speaker: Rupert Barksfield, CEO" + ], + "url": "https://www.youtube.com/watch?v=phDloVO1RCQ" + }, + { + "title": "Preparations For Amulet Mainnet Launch Underway As Launch Date Gets Announced", + "url": "https://ripplecoinnews.com/preparations-for-amulet-mainnet-launch-underway-as-launch-date-gets-announced/" + } + ], + "team": [ + { + "name": "Martin", + "role": "Community Manager" + }, + { + "name": "Rob", + "avatar": "https://pbs.twimg.com/profile_images/1489011796576985094/KVBYfVRB_400x400.jpg", + "description": [ + "Marketer | 2022 is the year of DeFi cover " + ], + "role": "Marketing Manager", + "twitter": "@overcryptocal" + }, + { + "name": "Rupert", + "avatar": "https://pbs.twimg.com/profile_images/1480953683173158916/W4Ux0IRD_400x400.jpg", + "role": "Project Lead ", + "twitter": "@MET4BE4R" + }, + { + "name": "Hakon", + "avatar": "https://pbs.twimg.com/profile_images/1567440707412967427/xYWCNFS8_400x400.jpg", + "role": "BD & Marketing", + "twitter": "@DeFi_hawk" + } + ], + "roadmap": { + "items": [ + { + "title": "MainNet Launch", + "date": "2021-09-22T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Amulet’s 2022–2023 Roadmap", + "url": "https://amulet.org/blog/introducing-amulets-2022-2023-roadmap/" + } + } + ] + }, + "faq": [ + { + "question": "What is Amulet Protocol?", + "answer": [ + "Amulet is a decentralized risk protection protocol for the Rust-based ecosystem initially deployed on Solana." + ] + }, + { + "question": "What is decentralized risk protection protocol?", + "answer": [ + "Decentralized risk protection protocols provide a financial safety net for all users interacting with Web3 financial products. They generally encompasse smart contract risk, stablecoin de-peg risk, slashing risk, oracle failures, economic exploits, etc. Risk of smart contract exploits is particularly significant with over $3B lost to smart contract hacks in 2021. By offering protection against these more common DeFi risk types along with NFT and metaverse-related offerings, users and developers alike can enjoy a safer Web3 through Amulet." + ] + }, + { + "question": "What is unique about Amulet?", + "answer": [ + "Existing DeFi risk protection protocols rely on external underwriters to provide capital for claim payouts and cover capacity, which introduces unique and difficult challenges over business sustainability. Amulet is creating the risk protection industry's first Protocol-Controlled Underwriting (\"PCU\") approach. This is a significant change from the incumbent model of renting underwriting capital." + ] + }, + { + "question": "What kind of risk does Amulet cover?", + "answer": [ + "Smart contract exploits, stablecoin de-pegs, slashing, and more to come (NFT, Metaverse, and wallet protection currently in development)." + ] + }, + { + "question": "Why did we build Amulet on Solana?", + "answer": [ + "DeFi has experienced exponential growth since the summer of 2020 with the influx of hundreds of billions in capital and the emergence of multibillion-dollar protocols in just a little over two years. Riding along this wave of explosive growth is a rapidly increasing demand for risk hedging.", + "Rust-based public chains have been maturing rapidly with growth spearheaded in particular by Solana. According to Amulet's research, TVL on Solana has grown 5x faster than on Ethereum, and this growth is expected to continue given the distinctive strengths of Solana centered around its lower cost and higher throughput.", + "At the moment, risk management solutions are still relatively scarce or non-existent on Solana and the Rust-based ecosystems at large, presenting Amulet with an incredible and unique market opportunity. Amulet expects major demand for its cover products and other risk management solutions along with Solana's continued growth and adoption." + ] + }, + { + "question": "What is PCU?", + "answer": [ + "Amulet aims to build reserves that are controlled by the protocol with PCU, rather than renting capital from stakers as its primary underwriting source. Amulet believes this new model has the potential to scale sustainably." + ] + } + ] + }, + "HsU14rpiBDC33hBsDPFQdZWaeykmKr67x3D2hA5RJRJD": { + "symbol": "Angelic", + "about": [ + { + "heading": "Introduction", + "content": [ + "Angelic is a dark science fiction-themed narrative strategy role-playing game with turn-based combat, taking place in a collaborative universe, enhanced with blockchain elements. It has a huge story behind it and deep characters. As you play you get to know their backgrounds and love their personalities. The setting is dark sci-fi, meaning there are no good or bad people, they all have good and bad sides. Also, you don't control one character, you control a team, and each has a different part to play for you to succeed in the game. You need to learn to play with all characters to master the game." + ] + }, + { + "content": [ + "Through blockchain implementation, Angelic players will be able to securely trade hero skin nonfungible tokens, ships, and other items with other players. The decentralized autonomous organization mechanism will facilitate true ownership, autonomy, and voting rights to shape the outcome of Angelic's evolving story and even the game's development. They can contribute to the Angelic universe by creating content and even earn money along the way if they choose, all without affecting game balance." + ] + } + ], + "resources": [ + { + "title": "The Angelic Roadmap", + "url": "https://www.angelicthegame.com/roadmap/" + } + ], + "team": [ + { + "name": "Erkan Bayol", + "avatar": "https://pbs.twimg.com/profile_images/1571499039744561152/nTUEXchn_400x400.jpg", + "role": "Founder", + "twitter": "@erkanbayol_7" + }, + { + "name": "Anastasia Volgemut", + "avatar": "https://pbs.twimg.com/profile_images/1566360695809122308/oJy0g09O_400x400.jpg", + "role": "Director of Operations", + "twitter": "@Ana_Volgemut" + }, + { + "name": "Emek Ozben", + "role": "Art Director" + }, + { + "name": "Petar Kotevski", + "avatar": "https://media.licdn.com/dms/image/C4D03AQFzrEheVBHykA/profile-displayphoto-shrink_800_800/0/1516241932178?e=1672876800&v=beta&t=xvvCBeR2nmjo_jOJkFNezgEPGIVljFzJESsjdsKkl2U", + "role": "Tech Director" + } + ] + }, + "4X8PMiLabGjdAHdrKL9SLu1HAMMp9xNcn3DY2mAciT8N": { + "symbol": "Faraway", + "heading": "Faraway makes fun and social games with player-driven economies", + "about": [ + { + "heading": "Introduction", + "content": [ + "Faraway is the studio behind Mini Royale: Nations, a browser-based first person shooter built on Solana. Mini Royale is the first live multiplayer game on Solana and boasts over 2 million registered players. Faraway is proud to be supported by some of the best web3 investors including Lightspeed Venture Partners, a16z, Sequoia, FTX, Pantera Capital, among others. Prior to founding Faraway, the two co-founders, Alex Paley and Dennis Zdonov, were VPs of Product at Scopely and Heads of Studio at Glu Mobile." + ] + }, + { + "content": [ + "In addition to making games, Faraway is also the creator of the Faraway Platform, a web3 gaming platform used by multiple external studios to easily introduce a web3 economy to their games through production-tested smart contracts, a blockchain analytics suite, and tools to run a game economy." + ] + } + ], + "gallery": [ + { + "caption": "Mini Royale: Nations", + "url": "https://i.imgur.com/i9Blrl9.png", + "height": 338, + "width": 600 + } + ], + "team": [ + { + "name": "Alex Paley", + "avatar": "https://pbs.twimg.com/profile_images/1562890934265815040/rT-Ye3-s_400x400.jpg", + "description": [ + "Alex Paley is a co-founder of Faraway, a web3 gaming studio specializing in hyper-social games with player-driven economies. Prior to founding Faraway with his long-time co-founder, Dennis Zdonov, he was VP of Product at Scopely and Head of Studio at Glu Mobile." + ], + "role": "Co-Founder", + "twitter": "@apaley13" + }, + { + "name": "Dennis Zdonov", + "avatar": "https://media-exp1.licdn.com/dms/image/C4E03AQE4acqoOhvkGg/profile-displayphoto-shrink_800_800/0/1529192513215?e=1672876800&v=beta&t=OHx0X4thfZsRVzXcVm-zT28MoePVmaosevanjIWeBqk", + "description": [ + "Dennis Zdonov is a co-founder of Faraway, a web3 gaming studio specializing in hyper-social games with player-driven economies. Prior to founding Faraway with his long-time co-founder, Alex Paley, he was VP of Product at Scopely and Head of Studio at Glu Mobile." + ], + "role": "Co-Founder" + } + ] + }, + "EGYbpow8V9gt8JFmadFYai4sjfwc7Vc9gazU735hE6u7": { + "symbol": "Dual DAO", + "heading": "Sustainable Incentive Liquidity Infrastructure for Web3 Communities", + "about": [ + { + "heading": "Introduction", + "content": [ + "Dual Finance gives token communities sustainable ways to earn yield & generate value from their treasuries. Through liquid option based incentives, Dual Finance unlocks value & unleashes participation in decentralized communities. Goodbye inflationary token rewards. Hello sustainable Staking Options.", + "Dual Finance has designed itself upon this breakthrough token incentive mechanism to gain allegiance & prevent token dumping. DUAL token distribution is being conducted fully & fairly through the use of Staking Options.", + "Partner projects can use Staking Options themselves via Dual Finance to better incentivize their own communities. When designed through Dual Finance, Staking Options serve to bolster their token's option & spot liquidity by utilizing a DAO owned AMM (Risk Manager) and capitally efficient lending product (Rehypothecated Lending Pools).", + "Completing the offering are Dual Investment Pools (DIPs), an upgrade to conventional option vaults (DOVs) that offer streaming executable yield strategies. Customize strategies based on your risk appetite and earn yield immediately." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://medium.com/@dualfinance" + }, + "resources": [ + { + "title": "Dual Finance's Youtube Channel", + "content": [ + "Providing educational videos that give token communities sustainable ways to earn yield & generate value from their treasuries" + ], + "url": "https://www.youtube.com/channel/UCMyYJ7GUzk7GCgyb9AgOU6w" + } + ], + "gallery": [ + { + "caption": "Dual Investment Pools (DIP)", + "url": "https://i.imgur.com/punX3y0.png", + "height": 157, + "width": 600 + }, + { + "caption": "Staking Options Studio (SOS)", + "url": "https://i.imgur.com/t8h5dFa.png", + "height": 233, + "width": 600 + } + ], + "team": [ + { + "name": "Britt Cyr", + "avatar": "https://pbs.twimg.com/profile_images/1507165603240591367/hQDLyFw4_400x400.jpg", + "description": [ + "MIT Masters & MIT B.Sc in Computer Science, concentration in Theoretical Computer Science (Cryptography)", + "Lead developer at YouTube. Over 7 years launched multiple live streaming projects & scaled the system from 100s of broadcasts to over 100K concurrent broadcasts with over 10M viewers. Managed live streaming ingestion & transcoding on projects, including webrtc mobile live streaming & ultra low latency, reducing latency from 45 seconds to < 1 second. Ex-Google, Ex-Facebook" + ], + "role": "Co-Founder", + "twitter": "@cyrzorhands" + }, + { + "name": "John Kramer", + "avatar": "https://pbs.twimg.com/profile_images/1432394328387858432/YbfgF5gL_400x400.jpg", + "description": [ + "MIT Masters in Finance & MIT B.Sc Aerospace Engineering", + "Prior Head of OTC & DeFi Trading at GSR. Led buildout of options trading capabilities, market making deal structures, and global team of traders & operations. Specialty in illiquid crypto derivatives trading, structured products, bespoke margining & lending. Crypto’s first-ever trades across altcoin options, variance swaps, accumulators, average price options, onchain derivatives/DOVs. Risk managed a portfolio of 300+ illiquid token derivatives with a multi-billion $ AUM." + ], + "role": "Co-Founder", + "twitter": "@jktrader16" + } + ], + "roadmap": { + "items": [ + { + "title": "Dual Token Launch", + "date": "2022-12-01T15:42:21.109Z", + "status": "upcoming", + "resource": { + "title": "Staking Option Fair Launch", + "url": "https://medium.com/@dualfinance/staking-option-fair-launch-f08a2ba958e8" + } + } + ] + }, + "faq": [ + { + "question": "What are DIPs?", + "answer": [ + "Dual Investment Pools, similar in structure to more commonly known Decentralized Option Vaults (DOVs) but with real-time pricing and customizable yields. They are also physically settled, meaning you will end up with either your staked asset or stablecoins upon withdrawing after expiration. Premiums are also paid immediately upon staking so you can put your funds to work for longer." + ] + }, + { + "question": "Will there be a DUAL DAO?", + "answer": [ + "Yes the plan is to fully decentralize every aspect of the project. DUAL token holders will provide the governance function and steward the treasury assets." + ] + }, + { + "question": "What is the mission of the project?", + "answer": [ + "To fix crypto’s broken tokenomic incentive structures through sustainable option based pathways. For a broader understanding of what is meant by that, please review our Whitepaper and other articles on Medium." + ] + }, + { + "question": "How is the premium provided?", + "answer": [ + "Premiums are quoted via an API directly from Option Market Makers or via the Dual Finance Backstop Volatility Model. This premium updates in real-time so you can better time the market." + ] + }, + { + "question": "What are Staking Options?", + "answer": [ + "Staking Options (SOs) are DUAL's incentive for staking funds into a DIP and for usage by other token projects to incentivize their communities. SOs allow users to acquire the DUAL token by exercising their right to buy it at the strike price up until expiration." + ] + }, + { + "question": "What are Rehypothecated Lending Pools?", + "answer": [ + "Rehypothecated Lending Pools (RLPs), a pool of capital that permits uncollateralized borrowing only from counterparties who have unbounded risk exposure to the pool. Dual Finance's RLPs allow market makers of DIPs capped by their long exposure to borrow to support hedging, providing greater capital efficiency and further positive return to Stakers. Users get paid this interest to generate additional yield!" + ] + } + ] + }, + "A3WX4QKcioruP71f4yweusv9jqU9R4LtGfJEHtZhs3Rx": { + "symbol": "MixMob", + "heading": "Remix the world! A new card strategy racing game from a team that worked on HALO, FIFA, Battlefield & PokerStars. Mask Up!", + "about": [ + { + "heading": "Introduction", + "content": [ + "Remix the world! MixMob: Racer 1 is a new card strategy robot racing game – picture Mario Kart meets Clash Royale – from a team that worked on HALO, FIFA, Battlefield & PokerStars. Grab your Mask and MixBots to start your journey." + ] + }, + { + "content": [ + "MixMob is for players who want to play and earn, have fun, collect, strategize, compete, and create influence. MixMob offers a competitive game inside a remix gaming world with community co-creation at its core." + ] + }, + { + "content": [ + "MixMob is backed by leading crypto investors and guilds such as DeFiance, Solana Ventures, Merit Circle, YGG SEA, Arthur Hayes, and Lau Brothers, amongst others." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://www.notion.so/mixmob/Litepaper-88a413da744a4b1793d5934fb1195e0d" + }, + "gallery": [ + { + "caption": "MixMob: Racer 1", + "url": "https://i.imgur.com/OrB5eTE.png", + "height": 390, + "width": 600 + }, + { + "caption": "Multiplayer Arenas", + "url": "https://i.imgur.com/GqQuGeA.png", + "height": 354, + "width": 600 + }, + { + "caption": "Compete for tokens and glory", + "url": "https://i.imgur.com/4YcLNjI.png", + "height": 337, + "width": 600 + }, + { + "caption": "Deploy cards and race your bots for glory and rewards!s are made by racing.", + "url": "https://i.imgur.com/oPgmoIA.png", + "height": 354, + "width": 600 + }, + { + "caption": "Compete against friends in the leaderboards.", + "url": "https://i.imgur.com/FK0j1Px.png", + "height": 356, + "width": 600 + } + ], + "resources": [ + { + "title": "MixMob Alpha V2 Trailer", + "url": "https://vimeo.com/750807146" + }, + { + "title": "MixMob: Uprising Project Teaser", + "url": "https://vimeo.com/677351566" + }, + { + "title": "Play-to-earn game MixMob receives round of funding", + "content": [ + "“This appreciable injection of capital will allow us to achieve our strategic objectives over the coming months and years,” said the platform’s CEO and Game Director Simon Vieira." + ], + "url": "https://venturebeat.com/games/play-to-earn-game-mixmob-receives-round-of-funding/" + } + ], + "team": [ + { + "name": "Simon Vieira", + "avatar": "https://assets.website-files.com/6204753c4ec43e140960751e/62a3d757ddad950f88b2fb0f_Edit-Studio-Portraits-190704-1077%202%205.png", + "description": [ + "Simon has managed multimillion-dollar projects in the video game industry and successfully shipped over 100 games and apps for EA, Pokerstars, Microsoft, and Disney. He has 15 years of experience in the game industry." + ], + "role": "Co-founder & CEO", + "twitter": "@simonvieira" + }, + { + "name": "Pavel Bains", + "avatar": "https://assets.website-files.com/6204753c4ec43e140960751e/62a3d7ccebc0aef27741a677_Untitled-3%201.png", + "description": [ + "Pavel founded Bluzelle and is an investor in gaming, Esports, and crypto. He has managed studios with Disney Interactive and worked with EA, Xbox, and Nintendo." + ], + "role": "Co-founder & EP", + "twitter": "@pavelbains" + } + ], + "roadmap": { + "items": [ + { + "title": "MixBots NFT Drop", + "date": "2022-12-07T15:42:21.109Z", + "status": "inprogress" + }, + { + "title": "Upgrade MixMob:Racer 1 to take it mainstream – first freemium crypto mobile esports game.", + "date": "2023-01-28T15:42:21.109Z", + "status": "inprogress" + }, + { + "title": "Build UGC items and game editor – creative economy", + "date": "2023-06-28T15:42:21.109Z", + "status": "upcoming" + }, + { + "title": "Build MixMob World MMO", + "date": "2023-12-28T15:42:21.109Z", + "status": "upcoming" + } + ] + }, + "faq": [ + { + "question": "What are the key highlights of your project?", + "answer": [ + "• We launched our first 5,000 NFT drop in December 2021, which sold out in less than a day.\n• Raised our seed round of 7.5M in Jan.\n• Our team grew to 40 people, including contractors and part-time talent, we have a vibrant community of around 30,000 members across social media channels, with ~2,000 unique NFT holders.\n• Over 60% of NFT holders participated in our alphas, averaging around 21 min of gameplay per session." + ] + }, + { + "question": "Can you please tell us more about the MixMob Masks and their utility?", + "answer": [ + "MixMob Gen0 masks are one-of-a-kind identities in the game. Mutable NFTs that evolve as players level up on their journey. MixMob masks combine 2D, 3D, sketches, stickers, candy, pop culture, art, music, science... Masks have the following power and utility in the game:\n• Unlock your avatar/identity in the game\n• Exclusive access to our game before anyone else\n• Participate in our staking program\n• Allowlist to all future collection that tide to the game, including MixBots, and cards.\n• Allocation to future token sale\n• In-game currency bonuses\n• Unlock exclusive arenas\n• Access to our gated community and live events" + ] + }, + { + "question": "How is your game sustainable and fun?", + "answer": [ + "Below are the key points on how our game cultivates fun and sustainability.\n• We have created a multiplayer, synchronous, fast-paced, twitch-able skill-based game.\n• Our game has free (no monetary rewards) and low-cost entry modes to play our game for fun.\n• We have built tournament-based arenas with different tiers for players to join for a fee, with a significant percentage of that fee going to the total prize pool – a sustainable and transparent economy based on skill.\n• MixMob offers external sponsored tournament-based arenas with extra prizes (tokens or NFTs) for players to participate in a more competitive environment.\n• UGC modes like our Remix Editor allow players to create and sell content." + ] + } + ] + }, + "53pMaU2DXieGxwXZLMN1rgDECwFrxuYw5u9QgEFCx4Rd": { + "symbol": "Kamino Finance", + "heading": "Kamino is an active liquidity management layer that fully automates concentrated liquidity DEX positions across Solana.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Kamino is built to be Solana's liquidity destination. Kamino vaults automatically manage DEX concentrated liquidity positions, using quantitative models to set & rebalance ranges, while auto-compounding fees & rewards. In essence, Kamino Vaults are one-click strategies that are built to automate the liquidity provision process." + ] + }, + { + "heading": "A Use Case for Every User", + "content": [ + "For liquidity providers and institutionals, Kamino facilitates set-and-forget portfolio growth. For projects, Kamino facilitates deep and optimized liquidity for native tokens. With a wide range of strategies available on the platform, Kamino empowers liquidity to providers to deploy their assets according to their outlook on the market." + ] + }, + { + "heading": "Leverage and composability", + "content": [ + "Every Kamino position is tokenized as a kToken, representing a user's deposit into a certain vault. kTokens are fully fungible SPL tokens that can be used across DeFi to leverage positions, while the kToken itself continues to accumulate yield via auto-compounding. Ultimately, Kamino fuels both liquidity and composability for the Solana DeFi ecosystem." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.kamino.finance" + }, + "gallery": [ + { + "caption": "Kamino Finance Vaults Landing Page", + "url": "https://i.imgur.com/UUvccOv.png", + "height": 345, + "width": 600 + }, + { + "caption": "Kamino Finance Vault Deposit Page", + "url": "https://i.imgur.com/VRoNbmr.png", + "height": 345, + "width": 600 + }, + { + "caption": "Kamino Finance Portfolio and Rewards Page", + "url": "https://i.imgur.com/q5vanAB.png", + "height": 345, + "width": 600 + } + ], + "resources": [ + { + "title": "Hubble Protocol Launches Kamino Finance to Optimize Yields for Liquidity Providers on Solana", + "content": [ + "Hubble Protocol, home of the USDH stablecoin, has launched Kamino Finance: the first concentrated liquidity market maker (CLMM) optimizer of its kind on the Solana blockchain." + ], + "url": "https://cryptonews.com/news/hubble-protocol-launches-kamino-finance-optimize-yields-for-liquidity-providers-solana.htm" + }, + { + "title": "Kamino Finance: A Solana-Based DeFi Platform Offering Real Yield", + "content": [ + "The project aims to revolutionize the way liquidity providers (LPs) can provide concentrated liquidity by making it as easy as pressing a button." + ], + "url": "https://crypto.news/kamino-finance-a-solana-based-defi-platform-offering-real-yields-to-users/" + }, + { + "title": "Solana DeFi Protocols Solend and Kamino Finance Partner for Unique Borrowing Opportunities", + "content": [ + "Solend and Kamino Finance have announced a partnership to create new liquidity solutions for decentralized finance (DeFi) on Solana." + ], + "url": "https://www.einnews.com/pr_news/597514062/solana-defi-protocols-solend-and-kamino-finance-partner-for-unique-borrowing-opportunities" + } + ], + "roadmap": { + "items": [ + { + "title": "Mainnet Launch", + "date": "2022-08-31T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Introducing Kamino", + "url": "https://bit.ly/Kamino-Launch" + } + }, + { + "title": "kTokens Integrated into Hubble Protocol", + "date": "2022-09-22T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "How to Borrow USDH with Kamino kTokens", + "url": "https://bit.ly/kTokens-on-Hubble" + } + }, + { + "title": "$5M TVL", + "date": "2022-10-24T15:42:21.109Z", + "status": "completed" + }, + { + "title": "kTokens Integrated into Solend", + "date": "2022-10-31T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Borrow on Solend with Kamino kTokens as Collateral", + "url": "https://bit.ly/kTokens-on-Solend" + } + }, + { + "title": "Automated SOL staking via Lido", + "date": "2022-10-27T15:42:21.109Z", + "status": "completed", + "resource": { + "title": "Stake SOL with Lido Finance on Kamino", + "url": "https://bit.ly/minting-stsol-lido" + } + } + ] + }, + "faq": [ + { + "question": "Why use Kamino?", + "answer": [ + "For users: Save time and maximize yields. You could sit at your computer 24/7, adjusting your concentrated liquidity positions and compounding your rewards, but you can’t beat Kamino’s efficiency.", + "For projects: Deep liquidity quick. Incentivize users to provide liquidity or provide it yourself. With Kamino managing your position, less capital is needed to negate slippage when swapping your tokens." + ] + }, + { + "question": "How do I use Kamino?", + "answer": [ + "Set it and forget it. Choose a vault and deposit the tokens you want to LP. Kamino will automatically manage the strategy of your position, and auto-compound your rewards. Withdraw your funds whenever you want." + ] + }, + { + "question": "Where does Kamino's yield come from?", + "answer": [ + "Kamino automates concentrated liquidity positions, and auto-compounds all the rewards a user earns, right back into your position. This means you never has to touch their deposit, and it will continue to accrue in value as time goes on. This value is also reflected in the value of the kTokens you receive upon deposit." + ] + }, + { + "question": "What are kTokens?", + "answer": [ + "kTokens are receipt tokens, representing the value deposited in Kamino vaults. Each Kamino vault has its own distinct kToken, which you will receive in your wallet the moment you deposit into a vault. kTokens also reflect the value of auto-compounding in Kamino vaults, making them Solana's first yield bearing asset that accrues yield from concentrated liquidity positions." + ] + }, + { + "question": "Where can I use kTokens?", + "answer": [ + "kTokens are standard, fungible SPL tokens, and there are a range of use-cases in the ecosystem; from minting USDH against them on Hubble Protocol, to depositing them in Solend to borrow a range of assets from the Kamino USDH Pool." + ] + }, + { + "question": "Has Kamino been audited?", + "answer": [ + "Yes, Kamino's audits are available in the documentation." + ] + } + ] + }, + "DKDkC6km37NcExxgBFW1nToSiybPvbu5RwhSSnRWwXYo": { + "symbol": "Moonlit", + "heading": "Find and reward the SUPERSTARS in your Discord with Moonlit.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Moonlit is a collaboration and rewards platform specifically for Discord communities. It's a fun way to engage your community in the serious business of running and growing your DAO." + ] + }, + { + "content": [ + "- Build out your members database automatically\n-Assign and reward teams for working on different projects\n- Advertise for help / ideas within the DAO\n- Easily move tokens between DAO members for rewards, permissions, tips and entry fees" + ] + }, + { + "content": [ + "Use any SPL token (or for pre-mint DAOs use a virtual points system) and watch as your community engages more deeply and more often with everything the DAO is doing.", + "The team behind Moonlit has years of experience building apps that encourage and motivate people to change their behavior. Using this deep understanding of human psychology, Moonlit will make operating your DAO not only easier but also more fun and more engaging for the entire community." + ] + }, + { + "content": [ + "\"Using Moonlit is the only way any of this works\" Nom, MonkeDAO" + ] + } + ], + "team": [ + { + "name": "Anders Murphy", + "avatar": "https://media.licdn.com/dms/image/C5603AQHHnvBThTM0Aw/profile-displayphoto-shrink_800_800/0/1516848243663?e=1672876800&v=beta&t=3YCLoTqhdSFgRRtLkJDzurUVEa7kFtpFpsZvpuyjdVM", + "description": [ + "Full stack software engineer and lean product development practitioner. Previously at FanDuel and HelloRelish. Deep experience in designing for behavioral change. 10 years experience of building mobile apps and excited to bring the masses to crypto via beautifully designed, practical products." + ], + "role": "Co-Founder" + } + ], + "faq": [ + { + "question": "Do we need to have launched a token to use Moonlit?", + "answer": [ + "No. If you're pre-token launch you can use an in-app currency and set an exchange rate in the future for any new token." + ] + }, + { + "question": "Is this just for simple bounties?", + "answer": [ + "No. Moonlit will create an internal economy for your token - earn tokens through contributions to your community and use them to get other community members to help you on projects." + ] + }, + { + "question": "How easy is this to set up?", + "answer": [ + "Super simple! Install a bot in your Discord and you're all set to go. We will provide all the support you need to get your team onboarded and successful right out of the gate. " + ] + }, + { + "question": "Does this add an admin layer to running my community?", + "answer": [ + "No. One of our principles that we have built Moonlit on is that it must make life easier, not harder, for everyone. Moonlit is a way for your members to understand how they can help, and to be recognized by the community for their contribution. It does this in a decentralized but controlled manner using a scale permissions based on contribution." + ] + }, + { + "question": "Is this integrated into Discord?", + "answer": [ + "Absolutely! Members can follow along on Discord, or dive into the details in the Moonlit web app." + ] + }, + { + "question": "Can I use Moonlit on my phone?", + "answer": [ + "Yes! It's designed for phone or desktop. Simple, beautiful and really easy to use." + ] + } + ] + }, + "4pzwicnneaxCL4XVms2gJApfj7jpiFvDMzCWEHYw2rMV" : { + "symbol": "Coin98", + "heading": "Your Crypto Everything App.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Coin98 is the #1 crypto super app designed to seamlessly connect a billion users to the crypto world safely and securely. We offer users a comprehensive and trusted ecosystem of essential services across the globe, including a non-custodial, multi-chain NFT & cryptocurrency wallet, built-in DEXs, Cross-chain Bridge & DApp Browser, a powerful Terminal, attractive Earn, Gift & Campaign, and Others. " + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.coin98.com/" + }, + "resources": [ + { + "title": "Coin98's Linktree", + "url": "https://linktr.ee/coin98" + } + ] + }, + "8gqpog28H6UvefDu7wMbwaRQX7a7rbVtw7z3yX9xjJQa" : { + "symbol": "Genopets", + "heading": "The Free-to-Play, Move-to-Earn NFT mobile game. Steps you take every day fuel your journey in the Genoverse. Move. Play. Create. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Genopets is a Free-to-Play, Move-to-Earn NFT mobile game that makes it fun and rewarding to live an active lifestyle. A Genopet is your digital pet whose evolution and growth is inextricably linked to your own. The steps you take every day power your journey through the Genoverse as you explore, battle, and evolve — earning crypto while you play.", + "Genopets is the gamification of an active lifestyle. Walking around the mall? Jogging at the gym? Running between meetings in your office? No matter how you stay active, your Genopet is always by your side, counting the steps you’ll use to fuel your gameplay.", + "Genopets is a move-to-earn game that does more than count your steps and reward you for how much you walk. The game is predicated on you building a bond with your digital companion and taking care of it every day by taking care of yourself.", + "Paying homage to the nostalgia of taking care of our Tamagotchi, evolving and battling our Pokémon, or even raising our first real-world pet, the emotional connection between one's self and their pet is a powerful force. That emotional force is the premise of Genopets and ultimately what will help motivate you to live a more active lifestyle." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://whitepaper.genopets.me/" + }, + "resources": [ + { + "title": "Genopets wants you and your digital pets to improve together", + "content": [ + "One of Samsung’s latest investments through its Samsung Next arm is Genopets." + ], + "url": "https://venturebeat.com/games/genopets-ben-tse-wants-to-own-his-time/" + }, + { + "title": "Magic Eden introduces semi-fungible tokens (SFTs) marketplace with Genopets", + "content": [ + "Magic Eden has introduced its “semi-fungible token” (SFT) marketplace with the blockchain game Genopets." + ], + "url": "https://venturebeat.com/games/magic-eden-introduces-semi-fungible-tokens-sfts-marketplace-with-genopets/" + } + ] + }, + "5K4VVEeYpANxL79r7rM3heyXqYZkzu2KkD4kFkt1gGpG" : { + "symbol": "Multiverse (Earth From Another Sun)", + "heading": "Earth From Another Sun is an open-world MMO sandbox FPS game where you can command massive armies to fight & conquer the Galaxy.", + "about": [ + { + "heading": "Introduction", + "content": [ + "FEATURES: Earth From Another Sun is a science fiction action-oriented strategy role-playing game featuring an ever-expanding galaxy with unique locations to explore packed with carefully designed NPCs and quests as well as player-created content. Conquer the galaxy fighting alongside the armies you command in exhilarating, meticulously crafted first-person shooter combat. Hundreds of unique weapons, weapon mods, abilities, and enemies that provide a fresh combat experience, a lot of replayability, and lots of different builds to fight alongside your teammates.", + "MULTIPLAYER CO-OP: Play the whole game with up to 3 other friends or strangers and challenge a variety of lairs and battlefields across the galaxy. We're also preparing 10-person co-op strongholds and Xeno lair raids.", + "AN OPEN WORLD OF GALACTIC PROPORTIONS: You will encounter many people, creatures, love interests, treasures, calamities, and other events that will test your strength and resolve. Make allies, pledge service to another faction, or create your own independent nation. Who knows, you might even get married and have genetically altered children along the way!", + "COMBAT VEHICLES, MECHS & DRONES: What would be the Battle of Naboo without the tanks and energy catapults? Plus, hoverbikes are really cool too! Vehicles types we are working on: Hoverbikes, tanks, rovers, mechs, fighter crafts, assault vessels, and space fortresses.", + "FRESH FPS COMBAT: There are many great FPS games out there. So, to make things fresh and interesting, we made sure that you have hundreds of gun mods, powers, gadgets, and passives. Enemies also have a large amount of variety and abilities.", + "LARGE-SCALE SCI-FI BATTLES: Ever wanted to experience what it's like to be a soldier or battlefield commander in the middle of iconic battles from your favorite sci-fi movies? With support for up to 1000 individual units on a battlefield, this is now possible.", + "PLAYERS COME FIRST: We listen to the community intensely and engage in conversations daily. While we do internal QA, it can happen that an update will release with an annoying bug. We will, however, make it our priority and fix it within 24 to 48 hours after discovery, that's the EFAS guarantee. We always make decisions that favor players, and we also regularly implement features requested by the community." + ] + } + ] + }, + "2AgaUrJeZYxQgipGa8s5opQBPRqJBjKwWqv3hwinnefJ" : { + "symbol": "Helio", + "heading": "The Web3 payments API", + "about": [ + { + "heading": "Introduction", + "content": [ + "Helio will accelerate the adoption of Web3 payments & drive the cost of online payments to zero. We want to displace traditional online payment systems.", + "Why? In the US alone, merchants hand over $138B in TX fees each year. We will reduce the cost of an online payment to near zero. Web3 projects waste tons of time building their own payment tooling. 1st-gen crypto pay gateways are weak products with poor UX. We need an alternative that is optimised for Web3 users.", + "What? A complete Web3 payments platform. We make it simple to accept crypto payments. No fees, no logins, no code.", + "How? E-commerce: simple integration options for merchants.", + "Web3 economy: NFT sales with our Pay Links, Discord Subscriptions, Token Utility & dAPP integrations." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.hel.io/introduction/welcome-to-helio" + } + }, + "E5yobpBits2Wm8LbtGSPS6KhKzU3oZRTcbx2XTM6Q1fF" : { + "symbol": "Kaizen Corps", + "heading": "Creators of the strategy game: Domination, which drives our gaming/metaverse infrastructure and ecosystem development for Solana.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Domination is massive collaborative strategy game similar to the board game Risk. We're currently in alpha but hosting new games on a weekly basis. Grab one of our NFTs off Magic Eden at https://magiceden.io/marketplace/kaizen_corps to join the revolution at https://domination.gg.", + "Kaizen Corps is our umbrella organization, whose purpose is to help develop the nacent gaming and metaverse ecosystem for Solana. Many projects are building in silos and building their own components to solve the same sets of problems. Our strategy is to extract the solutions we build for Domination into reusable components (which we're calling NFT legos) to make available to the greater Solana ecosystem for other projects to use and extend." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.domination.gg" + }, + "resources": [ + { + "title": "The Kaizen Corps Medium Page", + "url": "https://kaizencorps.medium.com/" + } + ] + }, + "4xXbWdJbTdvmNNb2ZE1MEk7wtYWj3MJm8SqQ8u3TErvh" : { + "symbol": "YGG SEA", + "heading": "The first subDAO of YGG, with the mission of creating the biggest and most sustainable virtual economy in Southeast Asia!", + "about": [ + { + "heading": "Introduction", + "content": [ + "Yield Guild Games (YGG) is a DAO that invests in non-fungible tokens (NFTs) used in virtual worlds and blockchain-based games.", + "YGG is primarily a community of play-to-earn gamers that act as a guild across many games. Within such games, it collects yield-generating NFTs and loans them to the guild's player base.", + "Yield Guild Game's first regional subDAO is YGG SEA. With the help and advice from its parent DAO - YGG, YGG SEA is dedicated to building the play-to-earn ecosystem in these countries, bringing together gamers from Indonesia, Malaysia, Vietnam, Singapore, and Thailand." + ] + } + ], + "resources": [ + { + "title": "The YGG SEA Medium Page", + "url": "https://medium.com/@yggsea" + }, + { + "title": "The YGG SEA Youtube Channel", + "url": "https://www.youtube.com/c/YGGSEA" + } + ] + }, + "6orGiJYGXYk9GT2NFoTv2ZMYpA6asMieAqdek4YRH2Dn" : { + "symbol": "The Imperium of Rain DAO", + "about": [ + { + "heading": "Introduction", + "content": [ + "The Raindrops Protocol is a series of six a la carte contracts that govern on-chain or proof-on-chain data specifically for gamification, allowing any player or item to be interchangeable with any game client that can process them.", + "The protocol lives on top of the Metaplex Protocol, further decorating existing NFTs with new metadata about whether they are a Player, an Item, or both! All contracts within the Protocol are designed to be composed with other Solana contracts enforcing game-specific rules.", + "The Imperium of Rain is the DAO that controls 51% of the $RAIN token. Proposals can be submitted and voted on to dispense token grants or make protocol modifications. Holders of the Degenerate Trash Panda NFT collection have 1 vote per each NFT held." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.raindrops.xyz" + } + }, + "DPiH3H3c7t47BMxqTxLsuPQpEC6Kne8GA9VXbxpnZxFE" : { + "symbol": "Mango ", + "heading": "Every market, all the power, none of the fuss. Simplifying decentralized finance through easy-to-use products and developer tools.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Mango is a decentralized permissionless protocol driven by a committed developer community focused on building decentralized financial products and open-source developer tooling for the Solana blockchain.", + "Trade spot markets with margin, leveraged perpetual futures, and participate in decentralized money markets, all from one easy-to-use hub." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.mango.markets/" + } + }, + "DReG8cfj6XA73u82AGFnytxGm3XZ3saetGwapRrRkoty" : { + "symbol": "CandyPay", + "heading": "Powering seamless, mobile native NFT and Payments experiences on Solana", + "about": [ + { + "heading": "Introduction", + "content": [ + "CandyPay is powering seamless, mobile native NFT and Payments experiences on Solana! We are building the best in class payments infra for web3 native businesses to accept SOL and SPL payments painlessly, while users can pay in a seamless and fast experience, from the device of their confort and token they love the most!" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.candypay.fun" + } + }, + "9jebQmDLbYRa4vo8rCQpPJu9VxRxWMp1cNTU1nzmrNLY" : { + "symbol": "Dispatch Protocol", + "heading": "Decentralized, censorship resistant, on-chain forums protocol. Reddit for Solana. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Dispatch Protocol is excited to introduce Dispatch Forums! For the first time in blockchain history, communities can launch censorship resistant, on-chain forums where users can earn tokens, gift NFTs, up-vote ideas, and participate in token-gated conversations." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.dispatch.forum" + } + }, + "GHVYhVLqSfqsuNXkKrALXDEX8xq76WGMAtJka5zr3jqw" : { + "symbol": "Sphere", + "heading": "Payments Infrastructure for web3", + "about": [ + { + "heading": "Introduction", + "content": [ + "Sphere is an API and web platform that allows developers and businesses to seamlessly accept and manage their crypto payments. We offer a complete payments stack, including products such as subscriptions, invoicing, checkouts, and more. Developers can import our SDK and get started with beautiful components and simple endpoints to create their payment rails out of the box and focus on their core logic. Merchants will be able to use our custodial accounts, dashboard, and no-code solutions to expand the currencies they accept and drive customer engagement through best-in-class compliance, accounting, and insights. " + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.sphere.engineer/" + } + }, + "7Ad1wQdytLHSFxnUyEHVPUYrNKMect4Qs5pQtYgFCrr3": { + "symbol": "Block Tackle Inc", + "heading": "SkateX is a free-to-play extreme sports video game that uses blockchain technology so players can truly own their digital gear.", + "about": [ + { + "heading": "Introduction", + "content": [ + "SkateX is a new web3 game that combines extreme sports action, a massively social multiplayer experience, and collectible NFTs from today's hottest street artists.", + "At its heart, SkateX is an action game, allowing players to perform tricks, complete challenges, and compete with others. Or, just relax with friends and skate around town showing off your swag. SkateX empowers you to carve your own online path.", + "SkateX skateboard decks come in the form of NFTs that players can own, upgrade and interact with. Ride your board across our meta-city and skate parks, display your boards to show the works of art they are, or sell them when you're ready for a different look. NFT skateboards are just the beginning, we'll be adding other clothing and gear as NFTs that players can own and equip to fully embrace their digital identities.", + "SkateX is being built by a team of gaming industry veterans who helped create hit titles for EA, Kabam, Lucasfilm, Roblox, Supercell and more. We grew up playing extreme sports games like Tony Hawk's Pro Skater, 1080 Snowboarding and Kelly Slater Pro Surfing. With SkateX we plan to bring that standard of fun and addictiveness to entirely new levels thanks to blockchain technology.", + "The world of SkateX will always be evolving with new art, new challenges, and new friends to ride around with. By giving gamers more control over their digital assets, our goal is to create a more exciting and enjoyable game experience for everyone." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://block-tackle.gitbook.io/skatex-litepaper/" + }, + "resources": [ + { + "title": "Block Tackle raises $5M and launches skateboard NFTs", + "content": [ + "Block Tackle, a new game studio making the SkateX blockchain game, is starting the sale of its collection of animated skateboard nonfungible tokens (NFTs)." + ], + "url": "https://venturebeat.com/games/block-tackle-raises-5m-and-launches-drop-of-skateboard-nfts/" + }, + { + "title": "Block Tackle Raises $5M to Develop Solana NFT Skateboarding Game", + "content": [ + "Coinbase Ventures, Solana Ventures, and Animoca back a new studio of game industry veterans building NFT games on Solana." + ], + "url": "https://decrypt.co/95627/block-tackle-solana-nft-skateboarding-game-skatex-coinbase-animoca" + } + ], + "team": [ + { + "name": "Ben Topkins", + "avatar": "https://media.licdn.com/dms/image/C5603AQFD2EHojGO46w/profile-displayphoto-shrink_800_800/0/1575934183705?e=1672876800&v=beta&t=-wNdzhjHyNcKEq2lcm22j2J6nih-V9s7PHr3szC42j0", + "description": [ + "Ben Topkins is the Co-Founder of Block Tackle, heading up operations. Ben is a game industry veteran who has worked at Kabam, Supercell, Roblox, Elex, and the Drone Racing League." + ], + "role": "Co-Founder, Operations", + "twitter": "@bentopkins" + }, + { + "name": "Rob Oshima", + "avatar": "https://venturebeat.com/wp-content/uploads/2022/04/skatex-Rob-Oshima-co-founder-portrait.jpeg?w=400&resize=400%2C400&strip=all", + "description": [ + "Rob Oshima is a Co-Founder of Block Tackle and heads up corporate development efforts. Rob has extensive experience having worked at Kabam, 20th Century Fox, Forte, Apple, and Solana Labs." + ], + "role": "Co-Founder, Corporate Development", + "twitter": "@roboshima" + }, + { + "name": "Curtis Chiu", + "avatar": "https://media-exp1.licdn.com/dms/image/C5603AQHA5xP6UAQY9A/profile-displayphoto-shrink_800_800/0/1649549823708?e=2147483647&v=beta&t=UXZ1eiy8TD2_8VNaLiEfYjLsrnzWc3Dazi_ZA0YYcU0", + "description": [ + "Curtis Chiu is a Co-Founder of Block Tackle and heads up game development efforts. He comes from a work background that includes Konami, Sega, Naver, Kabam, and consulted at Roblox." + ], + "role": "Co-Founder, Head of Studio", + "twitter": "@curtischiu5" + } + ], + "faq": [ + { + "question": "What is SkateX?", + "answer": [ + "SkateX is a free-to-play extreme sports MMO video game that uses blockchain so players can truly own their digital gear. SkateX boards, streetwear and more are NFTs that are actually used in the game. Ride your board, deck it out with stickers, wear whatever truly expresses your digital identity. And most of all – have fun!" + ] + }, + { + "question": "How does the game leverage Web3 technology?", + "answer": [ + "SkateX skateboard decks come in the form of NFTs that players can own, upgrade and interact with. Ride your board across our meta-city and skate parks, display your boards to show the works of art they are, or sell them when you're ready for a different look. NFT skateboards are just the beginning, we'll be adding other clothing and gear as NFTs that players can own and equip to fully embrace their digital identities." + ] + }, + { + "question": "What makes SkateX unique?", + "answer": [ + "SkateX is being built by a team of gaming industry veterans who helped create hit titles for EA, Kabam, Lucasfilm, Roblox, Supercell and more. We grew up playing extreme sports games like Tony Hawk's Pro Skater, 1080 Snowboarding and Kelly Slater Pro Surfing." + ] + }, + { + "question": "What will the SkateX game be like?", + "answer": [ + "SkateX is a skill-based skateboarding game set in an open-world metaverse. Build an avatar and drop in the lobby to skate, join a crew and socialize with friends. Bring your NFT skateboard, upgrade and master new tricks across a variety of PvE and PvP gameplay modes." + ] + }, + { + "question": "How can I get an NFT skateboard?", + "answer": [ + "You can purchase a skateboard from: https://magiceden.io/creators/skatex" + ] + } + ] + }, + "4iUTtxTm6aJRLKJBqQrn36kg84i33xeGmruyQDd2pqbr" : { + "symbol": "SunriseStake", + "heading": "Carbon-neutral Staking on Solana", + "about": [ + { + "heading": "Introduction", + "content": [ + "SunriseStake's mission is to make Solana climate-positive, by funneling stake yield into projects and initiatives that reduce global carbon emissions.", + "Web3 public goods often rely on donations to fund their work.", + "SunriseStake gives an example of an alternative revenue mechanism via stake rewards. Instead of donating principal participants allocate a portion of their yield from staked capital. This injects capital back into the ecosystem and enables donors to participate in a predictable, long-term manner.", + "SunriseStake is built on top of the trusted Marinade Finance staking platform, which strengthens the Solana ecosystem by allocating stake to smaller validators, improving the chain's Nakamoto constant and overall resilience. In return, stakers are granted voting rights in the SunriseStake DAO, allowing them to exert influence on the usage of the stake yield that is collected by the DAO's treasury.", + "The goal of SunriseStake is to invest the treasury funds in climate-positive projects, allowing Solana token holders to passively reduce or offset carbon emissions, while strengthening the Solana blockchain." + ] + } + ], + "resources": [ + { + "title": "Secure Solana and earn rewards without your funds locked in", + "content": [ + "Get mSOL, staked SOL supported all across the Solana ecosystem" + ], + "url": "https://marinade.finance/" + } + ] + }, + "87piQaXhHJffNHLkjixEViCoNWFTpXDPnqNTfzj523aD": { + "symbol": "Neoland", + "heading": "Transform the world into a giant game board", + "about": [ + { + "heading": "Introduction", + "content": [ + "Neopolis is a free-to-play mobile game where players manage and trade real-world buildings. The best players become Landowners and get access to the Neoland mode. Landowners can organize events, providing other Neopolis players with the rewards and resources they need.", + "Neopolis recently hit 2m downloads and 250k active users in a limited soft launch.", + "The game is developed by Revolt Games, a studio of 17 focusing on real-world-based games.", + "With Neopolis and Neoland, the studio is creating a persistent world where players can have fun in a mass-market game (Neopolis) and build their estates by managing their Lands (Neoland)." + ] + } + ] + }, + "6LjHttTUQfps53BjCFibfZx3BnGvCnGeYRaVjLuXv64L": { + "symbol": "RACE Protocol", + "heading": "Redefine web3 game and app development experience with RACE protocol", + "about": [ + { + "heading": "Introduction", + "content": [ + "RACE Protocol makes creating an onchain game a fast and easy experience by offering a set of tools that cover the most complex development parts. Race protocol offers: peer-to-peer randomization tools implemented with users wallet encryption, player decisions that are hidden to other players but immutable and verifiable, serverless onchain gama data storage, set of predefine settlement programs to take care of assets.", + "With RACE protocol all he builders need to care about is designing a game logic and ui to build a truly decentralised game." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://team-race.gitbook.io/" + } + }, + "ASUYfCjE6uNBo5scmiFqC67v7Dyoq3znaZPvohR9yL2j": { + "symbol": "Civic", + "heading": "Civic provides identity management tools for Web3 across chains for both consumers and dApps. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "For consumers, Civic.me offers Dynamic Web3 profiles where you can display NFTs, manage your identity and use on-chain messaging. For dApps, Civic Pass is an integrated permissioning tool for dApps that gives users access to their services." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.civic.com/" + }, + "resources": [ + { + "title": "What is KYC? How Crypto Exchanges Prevent Money Laundering", + "content": [ + "Know-your-customer (KYC) requirements are a growing part of Web3, as crypto becomes more integrated with the existing financial system." + ], + "url": "https://decrypt.co/resources/what-is-kyc-how-crypto-exchanges-prevent-money-laundering" + }, + { + "title": "Where DAOs Excel — And Where They Must Improve", + "content": [ + "DAOs seemingly present elegant solutions to common problems, yet they are still widely misunderstood." + ], + "url": "https://www.newsweek.com/where-daos-excel-where-they-must-improve-1742544" + }, + { + "title": "Civic Adds Verification Platform to Battle Bots and Scams", + "content": [ + "The set of tools is designed to stop bots from taking unfair advantage of NFT drops by limiting the number of wallets an account can use." + ], + "url": "https://decrypt.co/106288/civic-continues-its-campaign-to-battle-bots-and-scams" + } + ] + }, + "EYNTFC5dB6ofU6AgbQgDsRsJ6oXBU783drDYQbdm9kba": { + "symbol": "Coinable", + "heading": "No-code Web3 ecommerce platform built for everyone. Together we build.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Coinable is a Web3 ecommerce platform that makes it easy for anyone to turn the business of their dreams into a reality. Launch a store, integrate a checkout, and start accepting Solana payments today." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.coinablepay.com/" + }, + "resources": [ + { + "title": "The Coinable Medium Page", + "url": "https://medium.com/@coinable" + } + ] + }, + "HvSw2w9Ctfr8ejS8Gm1SvXpNxiQ7Fdgz8W6HmBvqVpC6": { + "symbol": "PBN3 Paul Barron Network", + "heading": "The leading Web3 and Crypto Independent Media Sourse", + "about": [ + { + "heading": "Introduction", + "content": [ + "Over 20 years in technology, media, and business, Paul Barron has created the perfect storm for what has become one of the fastest-growing web3, crypto, and investing platform available. Paul is an astute tech executive, having built consumer science data platforms, media companies, and the longest-running sentiment tool for blockchain. With millions of viewers each month to his popular blockchain and Web3 shows, he has become one of the most important voices in the next generation of tech and finance." + ] + } + ] + }, + "DoFABWkP3qRV2yggE3Tm1MpemKDviwnDaQAVB3gRiPwc": { + "symbol": "BizFirst", + "heading": "BizFirst helps merchants accept USDC payments and run NFT-based loyalty programs on their Store/Website.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Using BizFirst, merchants can:", + "1. Create their BizFirst business wallet", + "2. Accept USDC payments from their store", + "3. Send USDC based invoices", + "4. Run NFT-based loyalty programs." + ] + } + ] + }, + "H5Me9k9Vk42d1eEfmfWX9z8hnFJvzCDN33z3hp6BwexH": { + "symbol": "Alien Chicken Farm (ACF)", + "heading": "ACF is the simplest play-and-earn game.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Alien Chicken Farm is a classic breeding and town-space real-time strategy game. It is the simplest play-and-earn game in the Solana ecosystem and in the larger crypto community. While ACF is fun to play, it presents real opportunities for its players to create a steady stream of passive income by breeding and selling high-value chickens.", + "Players can earn in Alien Chicken Farm by:", + "1. Breeding Chickens and selling them on the ACF Marketplace or any other Metaplex powered marketplace in the Solana ecosystem.", + "2. Collecting rare Chickens.", + "3. Culling Chickens for $FEED tokens that are needed to prepare the chickens and make them ready for breeding." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://whitepaper.alienchickenfarm.com/" + } + }, + "bxPumP2w94Pz9QYYCCTYERgZSnTBWMh8xHwUCBU9N7W": { + "symbol": "SKY Wallet", + "heading": "The Crypto Wallet You Deserve.", + "about": [ + { + "heading": "Introduction", + "content": [ + "With SKY, along with the basic wallet functionalities, you can showcase your NFT collections via a shareable link, create custom USDC/SOL Payment Links, view Token details right from your wallet and much more." + ] + } + ] + }, + "9AmuU93FiiMCY6LA6HK1wBocT4y1C55hbNDC8jWA3qEi": { + "symbol": "RetroTrades", + "heading": "RetroTrades Community Hub", + "about": [ + { + "heading": "Introduction", + "content": [ + "RetroTrades is an NFT-based community that has created several collections, each generating different amounts of our token called $RTRO. We also have an Arcade that offers various games to win $RTRO, Arcade Tickets, and valuable NFTs. You can even spend those Arcade Tickets in the Arcade Shop to purchase those NFTs directly!" + ] + } + ] + }, + "HtQ6TCLsLnR4iw78J8d5qR9Sac2ZfQkqpFqTnj8zgXEx": { + "symbol": "WaterDAO", + "heading": "The Water DAO is a decentralized platform for certifying water sources and issuing water credits. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "The purpose of the Water DAO is to create transparency around sources of water, how they are generated, and establish a water credit classification system. We believe this can be done by creating a trustworthy and verifiable water credit that can be easily purchased and used to offset water usage. This would allow companies to continue to focus on their operational efficiencies while supporting the replacement of their water usage with equally efficient water producers.", + "The purpose of the Water DAO can be summed up through four main goals:", + "Create a universally accepted water credit that is first supported by the Regenerative Finance (ReFi) community and eventually, by larger outside organizations. This credit class can serve as a building block for many types of water credits to be created.", + "The Water DAO will act as a support mechanism to verify credit quality. The DAO will oversee specific verification standards to provide a certain level of quality, standard for the credits issued through the DAO.", + "Incentivize companies to be \"Water Positive\" or at lease Water Neutral. This will come as the DAO expands and gains more influence. The DAO will make the process of becoming \"Water Positive\" a significantly easier process than it was previously, leaving companies fewer excuses to maintain their indifference.", + "Incentivize more environmentally friendly forms of desalination and other water treatments. This is done through a tiered credit system. For example, a water producer using desalination methods that require energy intensive methods and that has a potentially damaging runoff, would only qualify for second tier credits. To receive top tier credits, water producers must power their operations with cleaner and less energy intensive methods while mitigating harmful runoff." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://waterdao.gitbook.io/water-dao-whitepaper/" + } + }, + "Gz9Zoht1gb6RW9hn9ejCup3uMDRqMSnppBWiQr9dHCaK": { + "symbol": "Infinity Labs NFT", + "heading": "Home of the Infinite. A world is unfolding, compounding. First collect & merge to unlock animated artwork on chain. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Infinity Labs built the first of its kinds deflationary collect and merge collection to unlock animated NFTs in the Solana Ecosystem, working with Metaplex on fusion and merging.", + "There are currently 1111 one-of-a-kind animations that may be unlocked by merging two Infinity Labs NFT copies, or \"timelines.\"", + "All 8 copies of the same scenes will be able to gather and combine over time until there exists a single 1111-piece timeline as determined by the community.", + "To Infinity." + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://infinitylabsnft.com/" + }, + "resources": [ + { + "title": "Eve's Breakpoint Talk 2022", + "content": [ + "Our Founder, Eve, was selected as one of the speakers at the conference and spoke in front of attendees about Infinity Labs and the journey so far, among other exciting things." + ], + "url": "https://www.youtube.com/watch?v=M5UiWMj7clE" + }, + { + "title": "The Infinity Labs Medium Page", + "url": "https://infinitylabsnft.medium.com/" + }, + { + "title": "Infinity Labs Solana Ecosystem Page", + "url": "https://solana.com/ecosystem/infinitylabs" + } + ] + }, + "3rQGVXuERbo9jakn5QXYBDFPR3uPXrNhPFQSmTeMNC2X": { + "symbol": "Cyber Feminists", + "heading": "We are Cyber Feminists - an online group of intellectual women at the forefront of technology for human evolution. ", + "about": [ + { + "heading": "Introduction", + "content": [ + "Cyber Feminism is a feminist approach that foregrounds the relationship between cyberspace, the internet, and technology. It was inspired by Donna Haraway's \"A Cyborg Manifesto\" and has seen then been iterated on by artists, technologies, and scholars alike. We believe in the power of technology for human transformation - transformation into something beyond what the flesh of evolution could carve. Women lead this evolution, and always have. " + ] + } + ] + }, + "DhuExYnEG55GzCrEWsUjTF6jDjoXuvWj8Y2x3eb6SZqb": { + "symbol": "Hxro", + "heading": "Hxro is an open primitive powering on-chain derivatives for market-based applications.", + "about": [ + { + "heading": "Introduction", + "content": [ + "Hxro is a open derivatives primitive for market-based applications built on the Solana blockchain. Through a series of native protocols, Hxro provides the framework and infrastructure for a robust, fully-functional decentralized exchange for derivatives contracts (futures and options) and parimutuel contracts.", + "Hxro derivatives are built off of its native open source protocol - Dexterity.", + "Dexterity is a collection of smart contracts on Solana.", + "It provides a framework for trading any instrument with a defined payoff function, including but not limited to options, futures, perpetual swaps, and bonds.", + "The framework has a modularized design that creates a hard separation between the mechanical components of trading market infrastructure (e.g. the order book data structure, position tracking, funding distribution) and the application-specific logic that relates to the instruments and exchange operators (e.g. settlement algorithms, margin calculation, liquidation thresholds, fee model).", + "We believe the flexibility this modular design creates will allow for a wide spectrum of on-chain market types to be created and supported by the protocol, making Dexterity a new fundamental building block for decentralized trading applications" + ] + } + ], + "documentation": { + "title": "Docs", + "url": "https://docs.hxro.network/" + }, + "resources": [ + { + "title": "Breakpoint 2022: The Case for On-Chain Derivatives", + "url": "https://www.youtube.com/watch?v=51LvGbdkzEw" + }, + { + "title": "The Scoop Podcast: How the multi-trillion dollar derivatives industry could be disrupted by decentralized technology", + "content": [ + "Hxro co-founder & CEO Dan Gunsberg joins host Frank Chaparro to unpack the idea behind the Hxro protocol, and to explain how Hxro hopes to solve liquidity problems that currently exist in the decentralized derivatives space." + ], + "url": "https://www.youtube.com/watch?v=_YMbqDzQmW4" + }, + { + "title": "Hxro Network Announces $34M Strategic Round Co-Led by SIG DT, Jump Crypto and Blockchain Capital", + "content": [ + "Hxro announced the closing of a $34 million strategic funding round co-led by SIG DT Investments, Jump Crypto, and Blockchain Capital." + ], + "url": "https://finance.yahoo.com/news/hxro-network-announces-34m-strategic-140000258.html" + } + ] + }, + "Huv6gAgfyjqj24WAypHthD85SGDc9N3WvhwFAxm7eDgn": { + "symbol": "DigitalEyes Market", + "heading": "Solana's first open NFT marketplace.", + "about": [ + { + "heading": "Introduction", + "content": [ + "DigitalEyes is the the ultimate one-stop shop for NFTs on Solana.", + "- Marketplace aggregator for secondary trading", + "- Launchpad for primary NFT drops", + "- Mint Calendar for all upcoming NFT drops", + "- Solo for 1/1 Art", + "- Domains for secondary domain auctions", + "- Fully customizable user profile", + "- Direct on-chain messaging" + ] + } + ] + } +} diff --git a/public/realms/brdot/banner_brdot.png b/public/realms/brdot/banner_brdot.png new file mode 100644 index 0000000000..6c77837d54 Binary files /dev/null and b/public/realms/brdot/banner_brdot.png differ diff --git a/public/realms/brdot/brdot_dao_logo.png b/public/realms/brdot/brdot_dao_logo.png new file mode 100644 index 0000000000..89a817292f Binary files /dev/null and b/public/realms/brdot/brdot_dao_logo.png differ diff --git a/public/realms/cas311.png b/public/realms/cas311.png new file mode 100644 index 0000000000..970878ff23 Binary files /dev/null and b/public/realms/cas311.png differ diff --git a/public/realms/devnet.json b/public/realms/devnet.json index d2bf289be9..d6c8dce3fd 100644 --- a/public/realms/devnet.json +++ b/public/realms/devnet.json @@ -17,6 +17,21 @@ "ogImage": "https://trade.mango.markets/assets/icons/logo.svg", "notificationsEnabled": true }, + { + "symbol": "SERUM", + "displayName": "SerumDAO - Devnet", + "programId": "G41fmJzd29v7Qmdi8ZyTBBYa98ghh3cwHBTexqCG1PQJ", + "communityMint": "CEdTnJ9Yr2G3zWt8J1hA2XbAAgSPVvxtuE9g44sjtecs", + "realmId": "8rTohXsU2L3xaf3KeHiS55DNninzCjDZT8zkpwikHSQt", + "ogImage": "https://assets.website-files.com/61284dcff241c2f0729af9f3/61285237ce2e301255d09108_logo-serum.png" + }, + { + "symbol": "DAO2DAO", + "displayName": "DAO-to-DAO", + "programId": "GTesTBiEWE32WHXXE2S4XbZvA5CrEc4xs6ZgRe895dP", + "realmId": "3SXQuce59HJMy1udz9UaQJKjWrRw2s6q2rEK1S9Ep7cv", + "ogImage": "https://assets.website-files.com/61284dcff241c2f0729af9f3/61285237ce2e301255d09108_logo-serum.png" + }, { "symbol": "SOCEAN", "programId": "GSCN8n6XUGqPqoeubY5GM6e3JgtXbzTcpCUREQ1dVXFG", @@ -98,10 +113,10 @@ }, { "symbol": "MNDE", - "displayName": "Marinade DAO", - "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", - "realmId": "Bdow7yGwdvsAjbTFHk5h8jXd7AW3bbMxwxkawNuoVqE3", - "ogImage": "https://marinade.finance/static/8665458407ac84338260b729267d0c53/ce52d/marinade-logo.avif", + "displayName": "Marinade", + "programId": "GovMaiHfpVPw8BAM1mbdzgmSZYDw2tdP32J2fapoQoYs", + "realmId": "899YG3yk4F66ZgbNWLHriZHTXSKk9e1kvsKEquW7L6Mo", + "ogImage": "/realms/MNDE/img/mnde_logo.png", "website": "https://marinade.finance/", "twitter": "@marinadefinance" }, @@ -164,9 +179,9 @@ }, { "symbol": "PYTH", - "displayName": "Pyth DAO", - "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", - "realmId": "44xGQELUXXD1TiLEMc73RBnCxeW8XKw27LyJNpt2G8bF", + "displayName": "Pyth Network", + "programId": "pytGY6tWRgGinSCvRLnSv4fHfBTMoiDGiCsesmHWM6U", + "realmId": "4ct8XU5tKbMNRphWy4rePsS9kBqPhDdvZoGpmprPaug4", "ogImage": "/realms/PYTH/img/pyth.svg", "website": "https://pyth.network/", "twitter": "@PythNetwork" @@ -187,5 +202,86 @@ "website": "https://yellowman.vercel.app/", "keywords": "YELLOW MAN", "ogImage": "/realms/YMDAO/img/ymdaologo.png" + }, + { + "symbol": "MEAN", + "displayName": "MEAN DAO", + "programId": "MGovW65tDhMMcpEmsegpsdgvzb6zUwGsNjhXFxRAnjd", + "realmId": "GkR6JMPU1b2bFj7j9Db8VAmQdisCCqoTQFfzWi2siwcB", + "website": "https://www.meanfi.com", + "twitter": "@meanfinance", + "ogImage": "/realms/MEAN/logo.svg" + }, + { + "symbol": "SOLDC", + "displayName": "SOLANA DOTA CLUB", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "5aNk7Zig6p3GwQgP4XnxGFg6DgC3jzmM9FURwabjnGTa", + "website": "https://soldc.us", + "twitter": "https://twitter.com/deniz_safak", + "ogImage": "/realms/SOLDCDAO/img/NEWSOLDCDAO.png" + }, + { + "symbol": "HNT", + "voteSymbol": "veHNT", + "allowDiscussion": false, + "displayName": "Helium DAO", + "programId": "hgovkRU6Ghe1Qoyb54HdSLdqN7VtxaifBzRmh9jtd3S", + "realmId": "2VfPJn8ML1hNBnsEBo7SzmG11UJc7gbY8b23A3K8expd", + "website": "https://helium.com", + "twitter": "@Helium", + "ogImage": "/realms/Helium/img/logo.svg", + "test": "test test" + }, + { + "symbol": "IOT", + "voteSymbol": "veIOT", + "allowDiscussion": false, + "displayName": "Helium IOT SubDAO", + "programId": "hgovkRU6Ghe1Qoyb54HdSLdqN7VtxaifBzRmh9jtd3S", + "realmId": "8UQNtD5Zw8ijB7ZpGiPLodKXMxtVyQmtu1AEztd3p6Po", + "website": "https://helium.com", + "twitter": "@Helium", + "ogImage": "/realms/Helium/img/iotlogo.png" + }, + { + "symbol": "MOBILE", + "voteSymbol": "veMOBILE", + "allowDiscussion": false, + "displayName": "Helium MOBILE SubDAO", + "programId": "hgovkRU6Ghe1Qoyb54HdSLdqN7VtxaifBzRmh9jtd3S", + "realmId": "8itzNAn1kMZ5sf18dVd8gGykztWZLVT93Svbdt7Gn2NP", + "website": "https://helium.com", + "twitter": "@Helium", + "ogImage": "/realms/Helium/img/mobilelogo.png" + }, + { + "symbol": "$GARI", + "displayName": "GARI Network DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HvDndGYjZNMVQDsrdAJJR7DtnQSB5rXM9BJBdwuxiXDg", + "ogImage": "/realms/GARI Network DAO/Coin.png", + "website": "https://gari.network/", + "twitter": "@TheGariNetwork" + }, + { + "symbol": "agrippa", + "displayName": "agrippa test dao", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4tvK4JBdTcha81x5jL784sF1aECLbmLT3ScWDZRdz4cd" + }, + { + "symbol": "Drift Protocol", + "bannerImage": "https://i.imgur.com/b9pPf3S.png", + "displayName": "Drift Protocol", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "9nUyxzVL2FUMuWUiVZG66gwK15CJiM3PoLkfrnGfkvt6", + "ogImage": "https://i.imgur.com/HnF1Zzy.png", + "shortDescription": "A lightning-fast and scalable perpetual futures DEX.", + "sortRank": 3, + "website": "https://www.drift.trade/", + "twitter": "@DriftProtocol", + "discord": "http://discord.com/invite/drifting", + "github": "https://github.com/drift-labs/protocol-v2" } ] diff --git a/public/realms/eleusance/eleusance_logo_spl.png b/public/realms/eleusance/eleusance_logo_spl.png new file mode 100644 index 0000000000..e89c269778 Binary files /dev/null and b/public/realms/eleusance/eleusance_logo_spl.png differ diff --git a/public/realms/jungle-defi/jungle.png b/public/realms/jungle-defi/jungle.png new file mode 100644 index 0000000000..684cefa443 Binary files /dev/null and b/public/realms/jungle-defi/jungle.png differ diff --git a/public/realms/laptopDAO/logo.png b/public/realms/laptopDAO/logo.png deleted file mode 100644 index 02edea3326..0000000000 Binary files a/public/realms/laptopDAO/logo.png and /dev/null differ diff --git a/public/realms/mainnet-beta.json b/public/realms/mainnet-beta.json index 4c0b0079a2..0e7ef9d80c 100644 --- a/public/realms/mainnet-beta.json +++ b/public/realms/mainnet-beta.json @@ -1,4 +1,96 @@ [ + { + "symbol": "CAS", + "displayName": "Cyborg Ape Society", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "6ENR4hciiwNTEF2NJCyCjryxVZqd2gWRV1Dt2dsrZNQt", + "bannerImage": "/realms/Ukraine/img/Flag_of_Ukraine.svg", + "ogImage": "https://static.wixstatic.com/media/a456a9_0337b7b036a142baa2abaa4b4df14f5b~mv2.gif", + "website": "https://cyborg-apes.com", + "keywords": "Crypto, Solana, SOL, SPL, Cross-Chain, Trading, Vibes, Data", + "twitter": "@cyborgapes_nft", + "discord": "https://discord.gg/9ue6ktyu", + "shortDescription": "Cyborg Apes Society Mission DAO", + "sortRank": -1000 + }, + { + "symbol": "Frictionless", + "displayName": "Frictionless DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "Hr6PtVoKHTZETmJtjiYu9YeAFCMNUkDTv4qQV2kdDF2C", + "ogImage": "https://shdw-drive.genesysgo.net/5nwi4maAZ3v3EwTJtcg9oFfenQUX7pb9ry4KuhyUSawK/frictionless_logo.png", + "github": "https://github.com/Grape-Labs", + "website": "https://governance.so/frictionless", + "twitter": "@grapeprotocol", + "discord": "@grapedao", + "shortDescription": "Frictionless is revolutionizing governance participation, bridging the gap between web2 and web3" + }, + { + "symbol": "DED", + "displayName": "DED DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "735Kg6893iFH2KuGy6uJrVXYKwBi6ky3KLLNPmJ4TMCD", + "ogImage": "https://arweave.net/LzLM9GSor6FYeeFv5hv2a5oQuwcoyH3WFGbEq6_xGZk" + }, + { + "symbol": "GrapeUX", + "displayName": "Grape UX", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "jtncbMzs2k3wypGiLBtM55ou3mFERpeZniH7V1Bq4zg", + "ogImage": "https://shdw-drive.genesysgo.net/5nwi4maAZ3v3EwTJtcg9oFfenQUX7pb9ry4KuhyUSawK/UX_logo.png", + "github": "https://github.com/Grape-Labs", + "website": "https://governance.so/dao/jtncbMzs2k3wypGiLBtM55ou3mFERpeZniH7V1Bq4zg", + "twitter": "@grapeprotocol", + "discord": "@grapedao", + "shortDescription": "Grape UX DAO has early access to Grape Governance and contributors provide feedback to quickly iterate and improve UX" + }, + { + "symbol": "CollabX", + "displayName": "CollabX", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "BVfB1PfxCdcKozoQQ5kvC9waUY527bZuwJVyT7Qvf8N2", + "ogImage": "https://shdw-drive.genesysgo.net/5nwi4maAZ3v3EwTJtcg9oFfenQUX7pb9ry4KuhyUSawK/logo_collabx.png", + "github": "https://github.com/Grape-Labs", + "website": "https://governance.so/dao/BVfB1PfxCdcKozoQQ5kvC9waUY527bZuwJVyT7Qvf8N2", + "shortDescription": "A small but mighty developer DAO! 🚀 We're like the little engines that could, tirelessly building, testing, and occasionally chewing glass to create a better ecosystem" + }, + { + "symbol": "POLL", + "displayName": "POLL", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "WUd1MpRwqw15cJpodXBiuyGv3rqYW99weEqrvkZpYFW", + "bannerImage": "/realms/Poll DAO/Vote Vote Vote.png", + "website": "-", + "twitter": "@PollDAO", + "discord": "-", + "ogImage": "/realms/Poll DAO/poll.jpg", + "github": "-", + "shortDescription": "Poll it" + }, + { + "symbol": "Dean's List Network State", + "displayName": "Dean's List Network State", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "F9V4Lwo49aUe8fFujMbU6uhdFyDRqKY54WpzdpncUSk9", + "bannerImage": "/realms/Deans_List_Network_State/banner-deanslist.png", + "website": "https://www.deanslist.services/", + "twitter": "@deanslistDAO", + "discord": "https://discord.gg/deanslist", + "ogImage": "/realms/Deans_List_Network_State/avatar-deanslist.png", + "github": "https://github.com/Deans-List/", + "shortDescription": "A Service DAO turned Network State, consisting of Web3 power users providing feedback sessions. Join us in changing the future of work!" + }, + { + "symbol": "Dean's List Solarplex State", + "displayName": "Dean's List Solarplex State", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4U5tep3h2wFrLskrCJAemvFVyLwGvQ8Xbuc8dBEC6smF", + "bannerImage": "/realms/Deans-List-Solarplex-State/img/banner-deanslist-solarplex.png", + "twitter": "@deanslistDAO", + "ogImage": "/realms/Deans-List-Solarplex-State/img/deans_list_solarplex_state.png", + "github": "https://github.com/Deans-List/", + "shortDescription": "Dean's List Solarplex State oversees feedback incentives on Solarplex." + }, { "symbol": "Ukraine", "displayName": "Ukraine.SOL", @@ -7,29 +99,249 @@ "bannerImage": "/realms/Ukraine/img/Flag_of_Ukraine.svg", "ogImage": "/realms/Ukraine/img/Ukraine_Logo.png", "sharedWalletId": "66pJhhESDjdeBBDdkKmxYYd7q6GUggYPWjxpMKNX39KV", - "sortRank": 3 + "sortRank": 2 }, { "symbol": "MNGO", + "category": "defi", + "bannerImage": "https://i.imgur.com/i1gGoIw.jpg", "displayName": "Mango DAO", "programId": "GqTPL6qRf5aUuqscLh8Rg2HTxPUXfhhAXDptTLhp1t2J", "realmId": "DPiH3H3c7t47BMxqTxLsuPQpEC6Kne8GA9VXbxpnZxFE", + "communityMint": "MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac", + "ogImage": "https://i.imgur.com/448n6bC.jpg", + "shortDescription": "Every market, all the power, none of the fuss. Simplifying decentralized finance through easy-to-use products and developer tools.", + "sortRank": 99, "website": "https://mango.markets", "keywords": "Mango Markets, REALM, Governance, Serum, SRM, Serum DEX, DEFI, Decentralized Finance, Decentralised Finance, Crypto, ERC20, Ethereum, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, Fastest, Fast, SerumBTC, SerumUSD, SRM Tokens, SPL Tokens", "twitter": "@mangomarkets", - "ogImage": "https://trade.mango.markets/assets/icons/logo.svg", - "sortRank": 3 + "discord": "https://discord.com/invite/2uwjsBc5yw", + "github": "https://github.com/blockworks-foundation/" + }, + { + "symbol": "OBV2", + "category": "defi", + "displayName": "OpenBook V2 Council", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "EVDdDLdhSMU8nzLEmoRMuH7rReXXgDibAtTPg66m4JHW", + "communityMint": "A5tGJvsUpehqSzzWY2whuPfBvBXTRQsUCDcjZ2HC479m" + }, + { + "symbol": "NLDAO", + "ogImage": "https://arweave.net/SEOxljn_3ij0m9Rzp06l3SBJ692TdQcCsX7oFvx-jfs", + "category": "legal", + "displayName": "Nous Legal DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "Hyi8vJopSGFa36uF1rdvjvG5yptAcFWYTxqr2YF3hA8j", + "communityMint": "Fj1tPZzgBnsbQMWgJM3CNjM8NZ9XHED7hhnHTN6GNZAF" + }, + { + "symbol": "XANDC", + "category": "defi", + "displayName": "Xandeum DevNet DAO", + "programId": "DcG2PZTnj8s4Pnmp7xJswniCskckU5E6XsrKuyD7NYFK", + "realmId": "CFprdZRYitjPYEDUQKDQZwao1jcRcU1z1GsFspMpN8Ci", + "communityMint": "2j437Lt84XvysJiYbXTSJfAMy26Et9HiVGFvGFp8nYWH", + "ogImage": "https://xandeum.com/wp-content/uploads/2023/05/Xandeum-Logo-Standard.png" + }, + { + "symbol": "HPC", + "displayName": "CryptoHelp", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "8DY3XKWmeaJDKyfVwr4cRv2tp7j8m9pyi4QJQZNGyizq", + "communityMint": "EADxj4FGaoe2BmTtigPznGCqZ8Yh4LqBU51NoyCjv1Bc", + "ogImage": "/realms/CryptoHelp/cryptohelp.png", + "shortDescription": "A compassionate, blockchain-powered collective, uniting individuals to swiftly make critical decisions and allocate resources to aid those facing emergencies.", + "sortRank": -1000, + "website": "https://cryptohelp.me", + "keywords": "CryptoHelp, Crowdfunding, help, DAO, Crypto, Solana, REALM, Governance, ERC20, SOL, SPL, Cross-Chain, Support, Fastest, Fast,", + "discord": "https://discord.gg/Tw7dqTJZmZ" + }, + { + "symbol": "MNGO-TC", + "category": "defi", + "displayName": "Mango Treasury Council", + "programId": "GqTPL6qRf5aUuqscLh8Rg2HTxPUXfhhAXDptTLhp1t2J", + "realmId": "7CWXhWsMXbfx8caHcpCbSQKDpsaLNu65YoBLoGfogzk6", + "communityMint": "DYg9LHzbhk9pg7h3Zhda2CW1berCp7NZQYxUEW6Eex35", + "ogImage": "https://i.imgur.com/448n6bC.jpg", + "shortDescription": "Every market, all the power, none of the fuss. Simplifying decentralized finance through easy-to-use products and developer tools.", + "website": "https://mango.markets", + "keywords": "Mango Markets, REALM, Governance, Serum, SRM, Serum DEX, DEFI, Decentralized Finance, Decentralised Finance, Crypto, ERC20, Ethereum, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, Fastest, Fast, SerumBTC, SerumUSD, SRM Tokens, SPL Tokens", + "twitter": "@mangomarkets", + "discord": "https://discord.com/invite/2uwjsBc5yw", + "github": "https://github.com/blockworks-foundation/" + }, + { + "symbol": "MNGO-GM", + "category": "defi", + "displayName": "Mango Game Master", + "programId": "GqTPL6qRf5aUuqscLh8Rg2HTxPUXfhhAXDptTLhp1t2J", + "realmId": "6JFaFouiN4ssPc38ey1hXKSxyFWZzZy9w5Xt5xLzeozm", + "ogImage": "https://i.imgur.com/448n6bC.jpg", + "shortDescription": "Every market, all the power, none of the fuss. Simplifying decentralized finance through easy-to-use products and developer tools.", + "website": "https://mango.markets", + "keywords": "Mango Markets, REALM, Governance, Serum, SRM, Serum DEX, DEFI, Decentralized Finance, Decentralised Finance, Crypto, ERC20, Ethereum, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, Fastest, Fast, SerumBTC, SerumUSD, SRM Tokens, SPL Tokens", + "twitter": "@mangomarkets", + "discord": "https://discord.com/invite/2uwjsBc5yw", + "github": "https://github.com/blockworks-foundation/" + }, + { + "symbol": "Metaplex", + "bannerImage": "https://dao.metaplex.com/img/bg-metaplex.svg", + "displayName": "Metaplex DAO", + "programId": "AEauWRrpn9Cs6GXujzdp1YhMmv2288kBt3SdEcPYEerr", + "realmId": "DA5G7QQbFioZ6K33wQcH8fVdgFcnaDjLD7DLQkapZg5X", + "communityMint": "METAewgxyPbgwsseH8T16a39CQ5VyVxZi9zXiDPY18m", + "ogImage": "/realms/metaplex/img/black-circle.png", + "shortDescription": "Metaplex makes it easy to build your project in minutes and grow your community in the world’s largest NFT ecosystem.", + "sortRank": 3, + "website": "https://www.metaplex.com/", + "twitter": "@metaplex", + "linkedin": "https://www.linkedin.com/company/metaplex-studios/", + "instagram": "https://www.instagram.com/metaplex/", + "discord": "https://discord.gg/metaplex", + "github": "https://github.com/metaplex-foundation/metaplex" + }, + { + "symbol": "TSD", + "bannerImage": "https://i.imgur.com/CuyBXIT.png", + "displayName": "Token Solutions DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "CMWHa4rLaCuur88SyAdTf2FSjvBq7y5GqguLzw7QaLBQ", + "ogImage": "/realms/TokenSolutionsDAO/img/image2.png", + "shortDescription": "A non-custodial, liquidity provider, price sensor bidirectional Token", + "website": "https://www.web3tokensolutions.io/", + "twitter": "@tokensolutions", + "linkedin": "https://www.linkedin.com/in/pablo-f-acebedo/", + "instagram": "https://www.instagram.com/pablofacebedo/", + "github": "https://github.com/pablofelipe01" + }, + { + "symbol": "GRAPE", + "category": "daotools", + "bannerImage": "https://i.imgur.com/OJNVFxE.jpg", + "displayName": "GRAPE", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "By2sVGZXwfQq6rAiAM3rNPJ9iQfb5e2QhnF4YjJ4Bip", + "ogImage": "/realms/Grape/img/grape.png", + "shortDescription": "GRAPE DAO is a power user community for digital governance primitives & tooling", + "sortRank": 3, + "website": "https://grapes.network/", + "twitter": "@grapeprotocol", + "discord": "https://discord.com/invite/grapedao", + "github": "https://github.com/Grape-Labs" + }, + { + "symbol": "SERUM", + "category": "defi", + "bannerImage": "https://i.ibb.co/bNRH0hh/1500x500.jpg", + "displayName": "Project Serum", + "programId": "AVoAYTs36yB5izAaBkxRG67wL1AMwG3vo41hKtUSb8is", + "realmId": "3MMDxjv1SzEFQDKryT7csAvaydYtrgMAc3L9xL9CVLCg", + "ogImage": "https://i.ibb.co/0j2TR8T/serum.jpg", + "shortDescription": "Faster, Cheaper and more Powerful DeFi", + "website": "https://projectserum.com", + "twitter": "@ProjectSerum", + "discord": "https://discord.gg/KGZS5HRAfF", + "github": "https://github.com/project-serum" + }, + { + "symbol": "OPENBOOK", + "displayName": "OpenBook DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "BtD6wKiazt4EEvfw6tqDh1BPSVchGeqyZ1e4HhV9VHJ6", + "ogImage": "/realms/OpenBook/OpenBook-Logomark.svg", + "shortDescription": "Faster, Cheaper and more Powerful DeFi", + "sortRank": 3, + "github": "https://github.com/openbook-dex" + }, + { + "symbol": "SERUM2", + "displayName": "Serum DAO (NEW)", + "programId": "G41fmJzd29v7Qmdi8ZyTBBYa98ghh3cwHBTexqCG1PQJ", + "realmId": "G3FBDbsRiJjcjYuazrH6mRShFMjr9RQn4SxVVxocJavA", + "communityMint": "G6DyPo5NjpW5kAvZwvM7hx1KeTUgGmuykPMdKuwWRvER", + "website": "https://www.projectserum.com/", + "ogImage": "https://assets.website-files.com/61284dcff241c2f0729af9f3/61285237ce2e301255d09108_logo-serum.png" + }, + { + "symbol": "MDLH", + "displayName": "The Mysterious Death of Lord Harrington", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "6Fiy6ZrCKBfcMieNq3S6qSzfpgRTYKn5zPW78VL9FwjL", + "ogImage": "/realms/MDLH/img/MDLH.png", + "bannerImage": "/realms/MDLH/img/banner.jpeg", + "sharedWalletId": "7ifeCFVFsxoQNfqiSBF9qFfHcNSQAyoQU63GV2RmJoUi" + }, + { + "symbol": "Duck Punkz", + "category": "nft", + "displayName": "Duck Punkz", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "6Yj8shsZrjqYQuPkEzcvkmdFq5Nn7RSVQ4EsNqLx7DJQ", + "ogImage": "https://pbs.twimg.com/profile_images/1563167507476713473/ZDruLZv7_400x400.jpg", + "shortDescription": "Crypto Duck Punkz: The Great Quekening ", + "twitter": "@cryptoduckpunkz", + "discord": "http://discord.gg/EYh3j6VQ6J" }, { "symbol": "PSY", "displayName": "Psy Finance", + "category": "defi", + "bannerImage": "https://i.imgur.com/o90sJuC.jpg", "programId": "GovHgfDPyQ1GwazJTDY2avSVY8GGcpmCapmmCsymRaGe", "realmId": "FiG6YoqWnVzUmxFNukcRVXZC51HvLr6mts8nxcm7ScR8", - "website": "https://psyoptions.io", - "keywords": "PsyOptions, PsyFi, PsyFinance, REALM, Governance, Serum, SRM, DEX, DEFI, Decentralized Finance, Decentralised Finance, Crypto, ERC20, Ethereum, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, Fastest, Fast, SerumBTC, SerumUSD, Tokens, Options, Vaults", - "twitter": "@PsyOptions", "ogImage": "https://user-images.githubusercontent.com/32071703/149460918-3694084f-2a37-4c95-93d3-b5aaf078d444.png", - "sortRank": 3 + "shortDescription": "An ecosystem of financial products governed by PSY token holders. ", + "sortRank": 3, + "website": "https://www.psyoptions.io/", + "twitter": "@PsyOptions", + "discord": "https://discord.com/invite/MgDdJKgZJc", + "keywords": "PsyOptions, PsyFi, PsyFinance, REALM, Governance, Serum, SRM, DEX, DEFI, Decentralized Finance, Decentralised Finance, Crypto, ERC20, Ethereum, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, Fastest, Fast, SerumBTC, SerumUSD, Tokens, Options, Vaults" + }, + { + "symbol": "PYTH", + "category": "defi", + "bannerImage": "https://pyth.network/images/pyth-realms-banner.png", + "displayName": "Pyth Network", + "programId": "pytGY6tWRgGinSCvRLnSv4fHfBTMoiDGiCsesmHWM6U", + "realmId": "4ct8XU5tKbMNRphWy4rePsS9kBqPhDdvZoGpmprPaug4", + "ogImage": "/realms/PYTH/img/pyth.svg", + "shortDescription": "The Pyth network aims to bring valuable financial market data to DeFi applications and the general public", + "sortRank": 3, + "website": "https://pyth.network/", + "twitter": "@pythnetwork", + "discord": "https://t.co/RhxhlyMfN2", + "github": "https://github.com/pyth-network/" + }, + { + "symbol": "Hubble Protocol", + "category": "defi", + "bannerImage": "https://i.imgur.com/rXz3mnF.png", + "displayName": "Hubble Protocol", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "AgR2tq1xcbqwmgDcNRaV1BEP5J3kfJfswP5vn6WWe6uC", + "ogImage": "https://i.imgur.com/rk827nw.png", + "shortDescription": "Hubble Protocol is the issuer of USDH, a Solana native crypto-backed stablecoin that anyone can mint by depositing their crypto.", + "sortRank": 3, + "website": "https://hubbleprotocol.io/", + "twitter": "@hubbleprotocol", + "discord": "https://discord.gg/hubbleprotocol", + "github": "https://github.com/hubbleprotocol" + }, + { + "symbol": "WKC", + "category": "defi", + "bannerImage": "https://raw.githubusercontent.com/hetwik/wikicious-assets/main/wikicious.png", + "displayName": "Wikicious DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "8iAceAv7XyRXUsvS2LXjkSy9QAc99csdQpSCNvFGgnk8", + "ogImage": "https://raw.githubusercontent.com/hetwik/wikicious-assets/main/wikicious.png", + "shortDescription": "wikicious is a decentralized crypto exchange and trading platform that runs on solana blockchain", + "website": "https://wikicious.com/", + "twitter": "@wikiciousmarkets", + "github": "https://github.com/wikicious" }, { "symbol": "MangoLiquidityDAO", @@ -39,7 +351,7 @@ "website": "https://mango.markets", "keywords": "Mango Markets, REALM, Governance, Serum, SRM, Serum DEX, DEFI, Decentralized Finance, Decentralised Finance, Crypto, ERC20, Ethereum, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, Fastest, Fast, SerumBTC, SerumUSD, SRM Tokens, SPL Tokens", "twitter": "@mangomarkets", - "ogImage": "https://trade.mango.markets/assets/icons/logo.svg" + "ogImage": "https://i.imgur.com/448n6bC.jpg" }, { "symbol": "MangolanaCouncil", @@ -53,10 +365,25 @@ }, { "symbol": "DTP", + "category": "web3", + "bannerImage": "https://i.imgur.com/nr1riOL.jpg", "displayName": "The Imperium of Rain", "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", "realmId": "6orGiJYGXYk9GT2NFoTv2ZMYpA6asMieAqdek4YRH2Dn", - "ogImage": "/realms/RAIN/img/rain_logo.png" + "ogImage": "/realms/RAIN/img/rain_logo.png", + "shortDescription": "Raindrops Protocol, standardizing gaming across Solana", + "website": "https://raindrops.xyz", + "twitter": "@only_raindrops", + "github": "https://github.com/raindrops-protocol/raindrops" + }, + { + "symbol": "FABS", + "displayName": "Founders Wif Abs", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2iWqzA6j5jDVsbVjBJHM2DFX4qJX7AAohArAR8VLDVV6", + "ogImage": "/realms/FABS/img/fabio.png", + "bannerImage": "/realms/FABS/img/fabs-banner.jpeg", + "twitter": "@fabsonsol" }, { "symbol": "UkraineUnchained", @@ -71,12 +398,16 @@ }, { "symbol": "WEZ", + "category": "web3", "displayName": "Wezesha DAO", "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", - "realmId": "FEtF7V55LorZmUriVVobubPvLXoS7sfP3smzb5zR4BWz", + "realmId": "3QF8K3jK8Kpn7Ls9Wn3FcFWquKGcJHUfnD25bTufWeLL", + "bannerImage": "/realms/WezeshaDAO/img/WezeshaBanner.png", + "shortDescription": "Wezesha means 'to enable' in Swahili. We want to enable tech progress and web3 in the ascending world.", "website": "https://wezesha.co", "keywords": "Wezesha DAO, Wezesha, Wezesha Coin, The Big Five NFTs Club, REALM, Governance, Serum, SRM, Serum DEX, DEFI, Decentralized Finance, Decentralised Finance, Crypto, SPL-TOKEN, Ethereum, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, Fastest, Fast, SerumBTC, SerumUSD, SRM Tokens, SPL Tokens", - "twitter": "@WezeshaCo", + "twitter": "@WezeshaDAO", + "discord": "https://discord.com/invite/erCSgXqhGu", "ogImage": "/realms/WezeshaDAO/img/wezesha_dao_logo.png" }, { @@ -106,7 +437,20 @@ "realmId": "66Du7mXgS2KMQBUk6m9h3TszMjqZqdWhsG3Duuf69VNW", "website": "https://www.orca.so/", "twitter": "@orca_so", - "ogImage": "https://learn.orca.so/static/media/logomark.1ef55f8f.svg" + "ogImage": "https://miro.medium.com/fit/c/176/176/1*-mdTTAgsSuBYSfDqG6Fd1w.png" + }, + { + "symbol": "PHY", + "displayName": "Physis", + "category": "web3", + "sortRank": 3, + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DsWWtZrqXBcqTTPoEyFH793Euq82r95CuXWTwqo3JZur", + "website": "https://phys.is", + "keywords": "Physis, PhysisVerse, PHY, Metaverse, XR, ASTRALIS, AI, Web3, Governance, Solana, SOL", + "twitter": "@PhysisVerse", + "bannerImage": "https://shdw-drive.genesysgo.net/GEmb2ovbEuWijEzapoEaViShkUvwbgpe2ohVTzVLzuU/physis-banner-spray-dao-001.jpg", + "ogImage": "https://shdw-drive.genesysgo.net/GEmb2ovbEuWijEzapoEaViShkUvwbgpe2ohVTzVLzuU/physis-holo-blk-sml.png" }, { "symbol": "JET", @@ -156,10 +500,18 @@ }, { "symbol": "SOCEAN", + "category": "defi", + "bannerImage": "https://i.imgur.com/uSHuzrx.png", + "displayName": "Socean", "programId": "5hAykmD4YGcQ7Am3N7nC9kyELq6CThAkU82nhNKDJiCy", "realmId": "759qyfKDMMuo9v36tW7fbGanL63mZFPNbhU7zjPrkuGK", - "website": "https://www.socean.fi", - "ogImage": "https://socean-git-enhancement-orca-price-feed-lieuzhenghong.vercel.app/static/media/socnRound.c466b499.png" + "ogImage": "https://socean-git-enhancement-orca-price-feed-lieuzhenghong.vercel.app/static/media/socnRound.c466b499.png", + "shortDescription": "Socean Stake Pool gives you the best risk-free yields on Solana.", + "sortRank": 3, + "website": "https://socean.fi", + "twitter": "@soceanfinance", + "discord": "https://discord.gg/socean", + "github": "https://github.com/igneous-labs" }, { "symbol": "Governance", @@ -180,13 +532,6 @@ "realmId": "EtZWAeFFRC5k6uesap1F1gkHFimsL2HqttVTNAeN86o8", "ogImage": "/realms/SCTF1/img/sctf1.svg" }, - { - "symbol": "SERUM", - "programId": "AVoAYTs36yB5izAaBkxRG67wL1AMwG3vo41hKtUSb8is", - "realmId": "3MMDxjv1SzEFQDKryT7csAvaydYtrgMAc3L9xL9CVLCg", - "website": "https://www.projectserum.com/", - "ogImage": "https://assets.website-files.com/61284dcff241c2f0729af9f3/61285237ce2e301255d09108_logo-serum.png" - }, { "symbol": "OMH", "displayName": "Off My Head", @@ -282,16 +627,6 @@ "ogImage": "/realms/strangemood/img/logo.svg", "website": "https://strangemood.org" }, - { - "symbol": "GRAPE", - "displayName": "GRAPE", - "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", - "realmId": "By2sVGZXwfQq6rAiAM3rNPJ9iQfb5e2QhnF4YjJ4Bip", - "ogImage": "/realms/Grape/img/grape.png", - "website": "https://grapes.network/", - "twitter": "@grapeprotocol", - "sortRank": 3 - }, { "symbol": "RED", "displayName": "Realms Ecosystem DAO", @@ -302,15 +637,6 @@ "twitter": "@Realms_DAOs", "sortRank": 2 }, - { - "symbol": "MonkeDAO", - "displayName": "MonkeDAO", - "programId": "GMnke6kxYvqoAXgbFGnu84QzvNHoqqTnijWSXYYTFQbB", - "realmId": "B1CxhV1khhj7n5mi5hebbivesqH9mvXr5Hfh2nD2UCh6", - "ogImage": "/realms/MonkeDAO/img/MonkeDAO_logo.png", - "website": "https://monkedao.io/", - "twitter": "@MonkeDAO" - }, { "symbol": "MonkeDAOVote", "displayName": "MonkeDAO Vote", @@ -339,19 +665,25 @@ }, { "symbol": "MNDE", - "displayName": "Marinade.Finance", - "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", - "realmId": "3gmcbygQUUDgmtDtx41R7xSf3K4oFXrH9icPNijyq9pS", + "category": "defi", + "bannerImage": "/realms/MNDE/img/mnde_header.png", + "displayName": "Marinade", + "programId": "GovMaiHfpVPw8BAM1mbdzgmSZYDw2tdP32J2fapoQoYs", + "realmId": "899YG3yk4F66ZgbNWLHriZHTXSKk9e1kvsKEquW7L6Mo", "ogImage": "/realms/MNDE/img/mnde_logo.png", + "shortDescription": "Secure Solana and earn rewards without your funds locked in.", + "sortRank": 98, "website": "https://marinade.finance/", - "twitter": "@marinadefinance" + "twitter": "@marinadefinance", + "discord": "https://discord.com/invite/6EtUf4Euu6", + "github": "https://github.com/marinade-finance" }, { "symbol": "COCK", "displayName": "Chicken Tribe", "programId": "GCockTxUjxuMdojHiABVZ5NKp6At8eTKDiizbPjiCo4m", "realmId": "FuqmCzaTqH1QbokY3agcYQaJqoWog1UkSrcNCDBPXusu", - "ogImage": "https://chickentribe.com/_next/image?url=%2Fimages%2FChickenTribe_Team01.svg&w=128&q=75", + "ogImage": "https://uploads-ssl.webflow.com/613eaeea238773c51dcfd629/6277729052bcdb44a14659a5_ChickenTribe_SiteLogo%201.svg", "website": "https://chickentribe.com/", "twitter": "@ChickenTribe" }, @@ -417,6 +749,18 @@ "website": "https://app.goblin.gold/", "twitter": "@goblingold_fi" }, + { + "symbol": "pumpkinSOL", + "displayName": "Pumpkin's Pool", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "EpvSHe3dnTQvz5qK8ks7zEbzA3ZABqaXW7fJfr8ULFiy", + "ogImage": "/realms/pumpkinspool/pumpkin_logo_cropped.png", + "bannerImage": "/realms/pumpkinspool/pumpkin_header.png", + "website": "https:/pumpkinspool.eco", + "twitter": "@pumpkinspool", + "discord": "https://discord.gg/pF6pMHApwP", + "shortDescription": "Pumpkin’s Pool delivers top staking returns while supporting animal welfare." + }, { "symbol": "DAINV", "displayName": "Digital Asset Investing", @@ -433,16 +777,6 @@ "realmId": "AvfMYqHjddR93zvmZXcQGUTkRu3GJYppTU93iKhMUWRF", "ogImage": "/realms/KiwiDAO/img/kiwi_logo.png" }, - { - "symbol": "FIDA", - "displayName": "Bonfida DAO", - "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", - "realmId": "6NzVDMfEBJvkFDnjPx53K7mLGW3yQdSjLhsamS8go4cn", - "website": "https://bonfida.org", - "keywords": "Bonfida, REALM, Governance, Serum, SRM, Serum DEX, DEFI, Decentralized Finance, Decentralised Finance, Crypto, ERC20, Ethereum, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, Fastest, Fast, SerumBTC, SerumUSD, SRM Tokens, SPL Tokens", - "twitter": "@bonfida", - "ogImage": "https://bonfida.org/static/media/fida.b16d451b.svg" - }, { "symbol": "N&F", "displayName": "Nick & Family", @@ -499,7 +833,7 @@ "realmId": "EPB9JbK5NiHoHkrRmpo9v4oJ2bKSVjfA731jeBModC1e", "website": "https://meta-collective.digital", "twitter": "@_metaCOLLECTIVE", - "ogImage": "https://governance.meta-collective.digital/realms/META/img/logo.png" + "ogImage": "https://www.meta-collective.digital/assets/home/header-logo.png" }, { "symbol": "UXP", @@ -518,12 +852,17 @@ }, { "symbol": "RatioFinance", + "category": "defi", + "bannerImage": "https://i.imgur.com/WBGCF35.jpg", "displayName": "Ratio Finance", "programId": "HT19EcD68zn7NoCF79b2ucQF8XaMdowyPt5ccS6g1PUx", "realmId": "8HZ4V94dtojrTpdUpWrfstr7bEhRnZZHn8jotfns9L9x", + "ogImage": "/realms/RatioFinance/img/ratiologo.png", + "shortDescription": "Our mission at Ratio Finance is to De-Risk DeFi for all.", + "website": "https://ratio.finance/", "twitter": "@RatioFinance", - "ogImage": "/realms/RatioFinance/img/ratiologo.png" + "discord": "https://discord.com/invite/5v8AYva8nU" }, { "symbol": "PixelBands", @@ -659,13 +998,18 @@ }, { "symbol": "NEOFAIRIES", + "category": "gaming", + "bannerImage": "https://pbs.twimg.com/profile_banners/1441459504311193602/1644861689/1500x500", "displayName": "Neo Fairies", "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", "realmId": "9PmmctkHPN5Br8V4gmjNuUdccrD7TtzfJ7U8mcpoBGXd", - "website": "https://neofairies.com", + "ogImage": "https://pbs.twimg.com/profile_images/1493280200288735234/C8zpit6a_400x400.jpg", + "shortDescription": "A fantasy-punk shared world that’s shaped and owned by community.", + + "website": "http://neofairies.com/", "twitter": "@neofairies", - "keywords": "Neo Fairies, Fairies, Fairy, Fantasy, Punk, Create-To-Own, DAO, Governance, Decentralized Entertainment, Decentralised Entertainment, DeEnt, UOC, User-Owned Content, UGC, IP, Intellectual Property, Creative Development, NFT, Tokens, Crypto", - "ogImage": "/realms/NeoFairies/img/logo.png" + "discord": "https://discord.gg/neofairies", + "keywords": "Neo Fairies, Fairies, Fairy, Fantasy, Punk, Create-To-Own, DAO, Governance, Decentralized Entertainment, Decentralised Entertainment, DeEnt, UOC, User-Owned Content, UGC, IP, Intellectual Property, Creative Development, NFT, Tokens, Crypto" }, { "symbol": "$RRDG", @@ -800,7 +1144,16 @@ "realmId": "4PYdZHs2hwZYibkvEnpVCJpU7bD4aFUkWtYxGFU25ZWu", "website": "https://www.linkedin.com/in/harimasoor/", "twitter": "@HariOnChain", - "ogImage": "/realms/MasoorDAO/MasoorDAO.PNG" + "ogImage": "/realms/MasoorDAO/MasoorDAO.png" + }, + { + "symbol": "AGXT", + "displayName": "Agrichainx Tribe Dao", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "BXBwS8Q7YRc7iHcGcmU1fSVPk9go3TwoB256YfjDBrwc", + "website": "https://tribe.agrichainx.com/", + "twitter": "@agrichainx2022", + "ogImage": "/realms/AgrichainxTribeDao/AgrichainxTribeDao.jpeg" }, { "symbol": "ADAO", @@ -809,7 +1162,7 @@ "realmId": "Cwh2E98xcB5qL8yuGvxdaMezRUQXwdCwcCKhYKqUPqFD", "website": "https://www.youtube.com/channel/UCP6jlgRDcs5S68OVjleMGjg", "twitter": "@MannyAstra", - "ogImage": "/realms/Astra/AstraPodcastLogo.PNG" + "ogImage": "/realms/Astra/AstraPodcastLogo.png" }, { "symbol": "CreatedBy", @@ -840,13 +1193,17 @@ }, { "symbol": "SLND", + "category": "defi", "displayName": "Solend DAO", "programId": "A7kmu2kUcnQwAVn8B4znQmGJeUrsJ1WEhYVMtmiBLkEr", "realmId": "7sf3tcWm58vhtkJMwuw2P3T6UBX7UE5VKxPMnXJUZ1Hn", - "ogImage": "https://solend-image-assets.s3.us-east-2.amazonaws.com/1280-circle.png", - "website": "https://solend.fi/", + "ogImage": "https://i.imgur.com/knGCZ5f.png", + "shortDescription": "Solend is the autonomous interest rate machine for lending on Solana", + "sortRank": 2, + "website": "https://solend.fi", "twitter": "@solendprotocol", - "sortRank": 2 + "discord": "https://discord.gg/solend", + "github": "https://github.com/solendprotocol" }, { "symbol": "FSGOV", @@ -856,16 +1213,16 @@ "website": "https://flipsidecrypto.xyz/", "twitter": "@flipsidecrypto", "ogImage": "/realms/FSLOGO/FLIPSIDE-LOGO-WHITE.png" - }, - { - "symbol": "Dean's List", + }, + { + "symbol": "Legacy Dean's List Classic (moved to new one)", "displayName": "Dean's List", "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", "realmId": "9mS8GuMx2MkZGMSwa2k87HNLTFZ1ssa9mJ1RkGFKcGyQ", - "bannerImage": "/realms/Dean's List Grape/deans list logo.png", + "bannerImage": "/realms/DeanListGrape/deans-list-logo.png", "website": "https://deans-list.strataprotocol.com/", "twitter": "@GrapeDeanslist", - "ogImage": "/realms/Dean's List Grape/deans list logo.png" + "ogImage": "/realms/DeanListGrape/deans-list-logo.png" }, { "symbol": "GrapeCCSubDAO", @@ -875,8 +1232,8 @@ "website": "https://services.grapes.network/", "twitter": "@grapeprotocol", "ogImage": "/realms/GrapeCCSubDAO/GrapeCCSubDAO.png" - }, - { + }, + { "symbol": "AthensDAO", "displayName": "AthensDAO", "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", @@ -886,6 +1243,15 @@ "twitter": "@GrapeAthensDAO", "ogImage": "/realms/AthensDAO/AthensDAO_Logo.jpg" }, + { + "symbol": "Wen DAO", + "displayName": "Wen DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "3GoWL2uR7qx9NLGuZydTuyoxaYSwAQ3HVqCF3Kz6D7F3", + "website": "https://services.grapes.network/", + "twitter": "@grapeprotocol", + "ogImage": "/realms/Wen DAO/Wen DAO.png" + }, { "symbol": "BOOT", "displayName": "Bootstrap DAO", @@ -895,15 +1261,6 @@ "twitter": "@BootstrapDao", "ogImage": "/realms/BootstrapDAO/BootRealms.png" }, - { - "symbol": "laptopDAO", - "displayName": "laptopDAO", - "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", - "realmId": "6JzsaQYYi4vGTZogASscZsBALWbSbJU9tMDRtq6nbeff", - "website": "https://laptop-dao.vercel.app/", - "twitter": "@laptopDAO", - "ogImage": "/realms/laptopDAO/logo.png" - }, { "symbol": "HOADAO", "displayName": "HOA DAO", @@ -942,12 +1299,18 @@ }, { "symbol": "EPCT", + "category": "web3", + "bannerImage": "https://bafybeih52um4tvyggeja36kmbyg5b4pfod547qxdite4krwoe4nwtareji.ipfs.w3s.link/EpicsBetaTwitterHeaderLogo.png", "displayName": "Epics", "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", "realmId": "DCdCsuUjg6MnULfEmBUmvg1heggnLrKSFdp5uTRSKuwR", - "website": "https://epics.dev/", - "twitter": "@EpicsDAO", - "ogImage": "/realms/Epics/Epics-logo.svg" + "ogImage": "/realms/Epics/EpicsLogoSquareInvert.svg", + "shortDescription": "Buidl to Earn. Epics is a decentralized crowdsourcing platform for incentivizing open source software development.", + + "website": "https://epics.dev", + "twitter": "@EpicsDAO2", + "discord": "https://discord.gg/GmHYfyRamx", + "github": "https://github.com/epicsdao" }, { "symbol": "OPANZ", @@ -958,5 +1321,2379 @@ "ogImage": "/realms/OPANZ/OPANZ_Logo.png", "website": "https://auturoa.nz/", "twitter": "@OPANZ999" + }, + { + "symbol": "MEAN", + "category": "daotools", + "bannerImage": "https://i.imgur.com/Fw5LQ5L.png", + "displayName": "MEAN DAO", + "programId": "MGovW65tDhMMcpEmsegpsdgvzb6zUwGsNjhXFxRAnjd", + "realmId": "5o6gEoeJBpuXT1H1ijFTq3KcSGx7ayabdG2hji7cB3FG", + "ogImage": "/realms/MEAN/logo.svg", + "shortDescription": "Mean DAO is a protocol DAO offering Real-time payment infrastructure and Multisig to retail and businesses.", + "sortRank": 3, + "website": "https://www.meanfi.com/", + "twitter": "@meanfinance", + "discord": "https://discord.com/invite/8P4vK6SWz3", + "github": "https://github.com/mean-dao" + }, + { + "symbol": "ANTLERDAO", + "displayName": "AntlerDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DLxgBgdwUzpvoJH4bhJmLonFymSejKUiMBGAQE6XwopU", + "website": "https://www.majesticdeers.com", + "twitter": "@MajesticDeers", + "ogImage": "https://raw.githubusercontent.com/MajesticDeers/governance-ui/main/public/realms/AntlerDAO/Logo.jpg" + }, + { + "symbol": "OPCD", + "displayName": "OPANZ COMMUNITY DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "D2dphGE7euTcC576skADhqQ8rwZ9dPMq6pmoDhdbdsYX", + "bannerImage": "/realms/ODCO/OCDC.png", + "ogImage": "/realms/ODCO/OCDLO.png", + "website": "https://auturoa.nz/", + "twitter": "@OPANZ999" + }, + { + "symbol": "eleusance", + "displayName": "eleusance DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "376quXDrSmhd5655Z7aNVKHfDQR3SNi4pEDxmA7TES5V", + "ogImage": "/realms/eleusance/eleusance_logo_spl.png", + "website": "https://eleusance.io/", + "twitter": "@eleusanceIO" + }, + { + "symbol": "J-JFI", + "displayName": "Jungle DeFi Community DAO", + "programId": "jdaoDN37BrVRvxuXSeyR7xE5Z9CAoQApexGrQJbnj6V", + "realmId": "5g94Ver64ruf9CGBL3k2oQGdKCUt4QKjN7NQojSrHAwH", + "ogImage": "/realms/jungle-defi/jungle.png", + "website": "https://jungledefi.io", + "twitter": "@jungledefi" + }, + { + "symbol": "Blockgame", + "displayName": "Blockgame", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "3EPsh3Nm2sivjjh3pcR4qmFzsMgJ3cDGjwiJeDARuQNR", + "ogImage": "/realms/Blockgame/Blockgame.png", + "website": "https://blockgame.cz" + }, + { + "symbol": "BlockLive", + "category": "web3", + "bannerImage": "https://worldtop.mypinata.cloud/ipfs/QmfA63uoZe8Dh5drYS7haQXJAMETovkoVCxS2MjcMHPPSA", + "displayName": "BlockLive", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "G43QB1csngJDWBhrBCba5tbVcxcPHhGNtGkqfntfP6fg", + "ogImage": "https://worldtop.mypinata.cloud/ipfs/QmXbMPq3Js6iJx6guEZsB8PaAPX6vB1Fr5wMRQnLavoUQk", + "shortDescription": "BlockLive is fast, easy, transparent way to buy and sell live event tickets that you can hold onto for a lifetime.", + "website": "https://blocklive.io/", + "twitter": "@blocklive_", + "discord": "https://discord.gg/pNdYQzwZ", + "github": "https://github.com/BlockLive" + }, + { + "symbol": "Squads", + "category": "daotools", + "bannerImage": "/realms/Squads/banner.png", + "displayName": "Squads", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "BzGL6wbCvBisQ7s1cNQvDGZwDRWwKK6bhrV93RYdetzJ", + "ogImage": "https://i.imgur.com/CWBjdWH.png", + "shortDescription": "The multisig standard you were looking for on Solana", + "sortRank": 3, + "website": "https://squads.so/", + "twitter": "@squadsprotocol", + "discord": "https://discord.com/invite/YPXz64TrKs", + "github": "https://github.com/squads-dapp/squads-mpl" + }, + { + "symbol": "ALLIE", + "displayName": "Allie Coin DAO", + "category": "gaming", + "bannerImage": "/realms/Allie-Coin-DAO/Allie-Coin-Particle-Logo-Compressed.png", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "BZE9AiJrMxUXXjwy9iBPzj34Wh5Zf1wLEFAM4oSSMRLi", + "ogImage": "/realms/Allie-Coin-DAO/Allie-Coin-Logo.png", + "shortDescription": "Allie Coin unlocks a new world of gaming.", + "website": "https://alliecoin.io/", + "twitter": "@allie_coin", + "discord": "https://discord.gg/wAzwpQCNF2" + }, + { + "symbol": "Superteam", + "category": "other", + "bannerImage": "https://i.imgur.com/uTjEbh7.png", + "displayName": "Superteam", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "5NNv1oJ4PFhE2416kTNDzrR9axoHjBTw2CNABqcYpXXL", + "ogImage": "https://superteam.fun/_next/image?url=https%3A%2F%2Fsuper-static-assets.s3.amazonaws.com%2F75e99297-73de-4946-ba6b-0ac603638793%2Fimages%2F259d92ba-12da-42d7-be75-4c9b8b0796dd.png&w=3840&q=80", + "shortDescription": "Superteam is a community dedicated to helping Solana projects launch and grow. ", + "website": "https://superteam.fun/", + "twitter": "@SuperteamDAO", + "discord": "https://discord.com/invite/Mq3ReaekgG ", + "github": "https://github.com/SuperteamDAO" + }, + { + "symbol": "Hello Moon", + "category": "other", + "bannerImage": "https://i.imgur.com/ZiHW6ho.png", + "displayName": "Hello Moon", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "G4CR3KUvqPZWmHbuvWhBPqL4vBBBujviyeTVynN2rhKB", + "ogImage": "https://www.hellomoon.io/Logo.svg", + "shortDescription": "Hello Moon provides innovative datasets on Solana to empower NFT & DeFi investors & traders.", + "sortRank": 3, + "website": "https://www.hellomoon.io/", + "twitter": "@HelloMoon_io", + "discord": "https://discord.gg/hellomoon" + }, + { + "symbol": "Orbis Protocol", + "category": "web3", + "bannerImage": "https://i.imgur.com/m5nTsTB.png", + "displayName": "Orbis Protocol", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "uywFFJL6JFGwbSXgU95C6v8f4L4DqBXV2Z3KZaJSxy1", + "ogImage": "https://pbs.twimg.com/profile_images/1549064242623651845/mp_lIAfL_400x400.png", + "shortDescription": "Orbis Protocol makes it easy to build fast and decentralized social experiences", + "sortRank": 3, + "website": "https://orbis.club", + "twitter": "@OrbisClub", + "github": "https://github.com/OrbisWeb3/" + }, + { + "symbol": "SolanaFM", + "bannerImage": "https://res.cloudinary.com/materwelon/image/upload/c_pad,b_auto:predominant,fl_preserve_transparency/v1669790689/Realms_Banner_yzv3mz.jpg", + "displayName": "SolanaFM", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HP1Y12FPbWMAqqVTpKMXKVk6yK3zJaNSxwUEqLzzzuqc", + "ogImage": "https://media-exp1.licdn.com/dms/image/C560BAQEpuSLgaCfodA/company-logo_200_200/0/1639734210450?e=2147483647&v=beta&t=2JlPgsJlS12Hp_d5JAxUqS2qUtmG4J-WAPWUrpyk0YE", + "shortDescription": "Friendlist Web3 Explorer ", + "sortRank": 3, + "website": "solana.fm", + "twitter": "@solanafm", + "discord": "https://discord.com/invite/3SqREprDJN", + "github": "https://github.com/solana-fm" + }, + { + "symbol": "Unique Venture Clubs", + "category": "daotools", + "bannerImage": "https://i.imgur.com/uSs2TpD.png", + "displayName": "Unique Venture Clubs", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "5Dj3fuNLYxd1tzpPnXiPo88V8JNVHhrDScTLMJpupoXf", + "ogImage": "https://snipboard.io/9tpqwk.jpg", + "shortDescription": "Explore a web3 native way to raise, invest and govern assets. Your partner for every stage of your venture.", + "sortRank": 3, + "website": "https://unique.vc/", + "twitter": "@uniquevcs", + "discord": "https://discord.gg/uniquevcs", + "github": "https://uniquevc.gitbook.io/unique-venture-clubs-docs/" + }, + { + "symbol": "Dual DAO", + "category": "defi", + "bannerImage": "https://pbs.twimg.com/profile_banners/1488237042068819971/1652495773/1500x500", + "displayName": "Dual DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "EGYbpow8V9gt8JFmadFYai4sjfwc7Vc9gazU735hE6u7", + "ogImage": "https://pbs.twimg.com/profile_images/1525300156551274497/FMlM80mn_400x400.jpg", + "shortDescription": "Sustainable Incentive Liquidity Infrastructure for Web3 Communities", + "sortRank": 3, + "website": "https://www.dual.finance/", + "twitter": "@DualFinance", + "discord": "https://discord.com/invite/P3uH9AvEp5", + "github": "https://github.com/Dual-Finance" + }, + { + "symbol": "Lighthouse", + "bannerImage": "https://i.imgur.com/OKIFPm6.jpg", + "category": "daotools", + "displayName": "Lighthouse", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "GXw7esYZ42nRZBFZTnAXa5fkdDgkvdZh7xeVuCEXoJZP", + "ogImage": "https://i.imgur.com/1NzLRGM.png", + "shortDescription": "Lighthouse enables communities to design reputation, rewards and membership systems by attesting to member contributions on-chain.", + "sortRank": 3, + "website": "https://lighthouse.xyz/", + "twitter": "@lighthouse_dao", + "discord": "https://discord.gg/Bv8JhaPF", + "github": "https://github.com/sher9n/Lighthouse" + }, + { + "symbol": "Zeta Markets", + "category": "defi", + "bannerImage": "https://i.imgur.com/W90Xqer.jpg", + "displayName": "Zeta Markets", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HoSfB5xCk8oXRgmspugAx3yRgii8MezimDMfMVK4krBS", + "ogImage": "https://i.imgur.com/SNludGj.jpg", + "shortDescription": "Zeta is the number one decentralised access layer for on chain optionality and perpetual contracts", + "sortRank": 3, + "website": "https://zeta.markets", + "twitter": "@ZetaMarkets", + "discord": "https://discord.com/invite/SacGBFKNzQ", + "github": "https://github.com/zetamarkets" + }, + { + "symbol": "IntoTheVerse", + "category": "gaming", + "bannerImage": "https://i.imgur.com/PwBA2It.png", + "displayName": "IntoTheVerse", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "22nDweMdSCCDoCMFUoS8Zgv7jnZxpLuqGrkL3cmSwuU3", + "ogImage": "https://intotheverse.xyz/static/media/logo.f2cbbe9e72f20f3706c979e20e711a96.svg", + "shortDescription": "Building #Games4Good powered by Blockchain Technology on Solana and Celo", + "sortRank": 3, + "website": "https://intotheverse.xyz/", + "twitter": "@IntoTheVerse_", + "discord": "https://discord.gg/w94EVQRPRf", + "github": "https://github.com/lopeselio/SolanaSummerCap_SolanaRPGQuest" + }, + { + "symbol": "Streamflow", + "category": "web3", + "bannerImage": "https://streamflow.finance/imgs/streamflow-logo-desktop.png", + "displayName": "Streamflow", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "Bwjrnh5dGZ2tHZKjLtMNwwhtk8sCGfR1ZM8ZxcVCe87m", + "ogImage": "https://pbs.twimg.com/profile_images/1396561843146080259/VJNtxnX0_400x400.jpg", + "shortDescription": "Streamflow is the #1 token vesting and streaming platform on Solana.", + "sortRank": 3, + "website": "https://streamflow.finance/", + "twitter": "@streamflow_fi", + "discord": "https://discord.com/invite/ZC7URcQyM7", + "github": "https://github.com/streamflow-finance" + }, + { + "symbol": "Shakudo", + "category": "web3", + "bannerImage": "https://i.imgur.com/tVUlRsv.jpg", + "displayName": "Shakudo", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "7fhfRApHt9N15v6Xccfd8iGnWZ3xvpUgHA8kieT2egBA", + "ogImage": "https://i.imgur.com/TiyZlps.jpg", + "shortDescription": "All data tools integrated into a fully-managed platform allowing data teams to remove DevOps and accelerate development cycles.", + "sortRank": 3, + "website": "http://shakudo.io/", + "twitter": "@shakudo_io", + "discord": "https://discord.com/invite/shakudo" + }, + { + "symbol": "Panzerdogs", + "category": "gaming", + "displayName": "Panzerdogs", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "aoBhePkPBCvrSZrK1ioEz6duUY211jfeBPzMzeGAqT8", + "ogImage": "https://uploads-ssl.webflow.com/62836ced977bb370cdeeecd7/62839a8ffa3bf57b0f3dc040_avatars.gif", + "shortDescription": "Panzerdogs is a Solana NFT gaming project where players can own all of their in-game assets and use them for P2E and P2P battles.", + "website": "https://www.panzerdogs.io/", + "twitter": "@panzerdogs", + "discord": "https://discord.gg/panzerdogs" + }, + { + "symbol": "BetDEX Labs", + "category": "web3", + "bannerImage": "https://pbs.twimg.com/profile_banners/1438537652282724356/1636452537/1500x500", + "displayName": "BetDEX Labs", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "8sMzPkk6TBM943XRXzScqrcZFfmK1pw62gUPdwtVckCJ", + "ogImage": "https://i.imgur.com/A5OANo2.png", + "shortDescription": "BetDEX Labs will launch the BetDEX Exchange in Nov 2022 for Web3 sports betting and is a key contributor to the Monaco Protocol.", + "sortRank": 3, + "website": "https://www.betdex.com", + "twitter": "@betdexlabs", + "discord": "https://discord.gg/eEuvZZatuT", + "github": "https://github.com/BetDexLabs/" + }, + { + "symbol": "Aleph.im", + "category": "web3", + "displayName": "Aleph.im", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2PBLG1LGAQYUd38KjJhyACksZH9S361XunVbD3EGxfJf", + "ogImage": "https://ipfs.io/ipfs/QmQxzDZzQJJ4Jb1npvLYbXZjHDCyqywHWBADcJbGWJGEqW/Aleph.im%20-%20Token/Aleph.im-Token-v1.1.png", + "shortDescription": "Decentralized, open source, web3 cloud infrastructure (Storage, computing) and indexing solution. Decentralize your entire stack!", + "sortRank": 3, + "website": "https://aleph.im/#/", + "twitter": "@aleph_im", + "github": "https://github.com/aleph-im" + }, + { + "symbol": "Dialect", + "category": "web3", + "bannerImage": "/realms/Dialect/img/banner-dialect.png", + "displayName": "Dialect", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "7s5QZmpit4uu1y2bkByXerE2mv3XBHtiNQ4JkDdmKRiQ", + "ogImage": "/realms/Dialect/img/avatar-dialect.png", + "shortDescription": "Dialect is building an open source protocol for Smart Messaging — dynamic, composable dapp notifications and wallet-to-wallet chat", + "sortRank": 3, + "website": "https://dialect.to/", + "twitter": "@saydialect", + "discord": "https://discord.gg/dialect", + "github": "https://github.com/dialectlabs" + }, + { + "symbol": "MonkeDAO", + "category": "nft", + "displayName": "MonkeDAO", + "programId": "GMnke6kxYvqoAXgbFGnu84QzvNHoqqTnijWSXYYTFQbB", + "realmId": "B1CxhV1khhj7n5mi5hebbivesqH9mvXr5Hfh2nD2UCh6", + "ogImage": "/realms/MonkeDAO/img/MonkeDAO_logo.png", + "sortRank": 3, + "website": "https://monkedao.io/", + "twitter": "@MonkeDAO", + "discord": "https://discord.gg/monkedao", + "github": "https://monkedao.gitbook.io/welcome-to-monkedao/" + }, + { + "symbol": "Jupiter Aggregator", + "category": "defi", + "bannerImage": "https://i.imgur.com/2Z17uYm.jpg", + "displayName": "Jupiter Aggregator", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2Z5BXuRCJPqYUCBGyQTwAXHeJoFAnbtvoXja19aZFLKY", + "ogImage": "https://jup.ag/svg/jupiter-logo.svg", + "shortDescription": "The best swap aggregator & infrastructure for Solana - powering best price, token selection and UX for all users and devs.", + "sortRank": 3, + "website": "https://jup.ag/", + "twitter": "@JupiterExchange", + "discord": "https://discord.gg/jup", + "github": "https://github.com/jup-ag" + }, + { + "symbol": "Irreverent Labs", + "category": "gaming", + "bannerImage": "https://i.imgur.com/Db2CIvO.png", + "displayName": "Irreverent Labs", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2dZAfmpEVMa18ESGiMHQxTWpQvdzEdhNdT7Ai6wdNkZ1", + "ogImage": "https://i.imgur.com/P4RC19y.png", + "shortDescription": "Irreverent Labs is creating hilarious automated entertainment from the future. ", + "sortRank": 3, + "website": "https://www.mechafightclub.com", + "twitter": "@mechafightclub", + "discord": "https://discord.gg/mechafightclub" + }, + { + "symbol": "DeFi Land", + "category": "gaming", + "bannerImage": "https://i.imgur.com/NL7yjoC.png", + "displayName": "DeFi Land", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "AxPJNe69VrdqWV1VkgDoRcM6Utizje6HdUqE5paJopap", + "ogImage": "https://i.imgur.com/fxd7mT2.png", + "shortDescription": "DeFi Land is a unique agriculture-simulation game created to gamify all aspects of decentralized finance and web3.", + "sortRank": 3, + "website": "https://defiland.app/", + "twitter": "@DeFi_Land", + "discord": "https://discord.gg/defiland" + }, + { + "symbol": "Gilder", + "category": "daotools", + "bannerImage": "https://pbs.twimg.com/profile_banners/1443288033025937411/1633010666/1500x500", + "displayName": "Gilder", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "6jydyMWSqV2bFHjCHydEQxa9XfXQWDwjVqAdjBEA1BXx", + "ogImage": "https://pbs.twimg.com/profile_images/1458164179244765184/lqJUjPYh_400x400.jpg", + "shortDescription": "Gilder makes interacting and staying connected to your decentralized internet community easy on mobile.", + "sortRank": 3, + "website": "https://gilder.xyz/", + "twitter": "@gilderxyz", + "discord": "https://discord.gg/u7zuwaAb7Z", + "github": "https://github.com/Gilder-Labs/gilder-app" + }, + { + "symbol": "RCH", + "category": "daotools", + "bannerImage": "/realms/RCH/banner.png", + "displayName": "Realms / SPL Governance", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "9efHuf3HAKiMDWNhgJyZW1Zyo8P7rRhAMXoJa9vpRo1e", + "ogImage": "/realms/RCH/icon.png", + "shortDescription": "The standard for enabling modern communities to share ideas, make decisions, and collectively manage treasuries.", + "sortRank": 3, + "website": "https://realms.today/", + "twitter": "@Realms_DAOs", + "discord": "https://discord.gg/zfxTA762", + "github": "https://github.com/solana-labs/governance-ui" + }, + { + "symbol": "WISE", + "displayName": "WisdomDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "8Jx7cvj32DJP8bsMQ3pZvDdx2qfynrkovgVQG8DBmY9P", + "website": "https://www.wisdom-dao.com/", + "twitter": "@WiseEldersDAO", + "ogImage": "/realms/WisdomDAO/og.jpg", + "bannerImage": "/realms/WisdomDAO/banner.jpg" + }, + { + "symbol": "wdmdao", + "displayName": "wdmdao", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "Hx1vKARnpS8nV8qxzqK9DG1kFXbAy49HJtPQKq6UEHa1" + }, + { + "symbol": "GenesysGo", + "category": "web3", + "bannerImage": "https://i.imgur.com/S2ACWLv.jpg", + "displayName": "GenesysGo", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "96VSxgcsxhh8qcFXdT7nMzxA1CMrUBxrxcetqYFqdV5V", + "ogImage": "https://i.imgur.com/topNFE2.jpg", + "shortDescription": "The Shadow Platform is the first Web3 cloud services platform built for speed, scale, and stability. Web3 without compromises!", + "sortRank": 3, + "website": "https://shadow.cloud", + "twitter": "@genesysgo", + "discord": "https://discord.gg/genesysgo", + "github": "https://github.com/GenesysGo" + }, + { + "symbol": "Plantoids", + "category": "nft", + "bannerImage": "https://i.imgur.com/qinA3Qq.png", + "displayName": "Plantoids", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4Mgn32BDz48BNRTJLk7fKg3e5Rtgfvf4WvCisR58fsiw", + "ogImage": "https://i.imgur.com/hU072BV.png", + "shortDescription": "Dynamically growing, genetically unique plants with customizable traits that remove CO2 from the atmosphere as they grow!", + "website": "https://www.plantoids.io", + "twitter": "@PlantoidsNFT", + "discord": "https://discord.gg/twGScVXwty" + }, + { + "symbol": "MiniRoyale", + "category": "gaming", + "bannerImage": "https://i.imgur.com/tDweQEX.png", + "displayName": "Mini Royale: Nations", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "JDAa2nFhyaRsESqYqWoZp6aw8egtcSV2UvKRDgfvgNLY", + "ogImage": "https://i.imgur.com/5ISruUM.png", + "shortDescription": "Mini Royale: Nations is a community-owned skill-based shooter set on top of an ever-evolving social strategy game.", + "website": "https://miniroyale.io/", + "twitter": "@MiniNations", + "discord": "https://discord.gg/miniroyale" + }, + { + "symbol": "EmpireDAO", + "category": "web3", + "displayName": "EmpireDAO ", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "6Ffasv4dQ8ZeRbZXZx2tiHcgJh5Y5VELmxnA7Qh1RWRg", + "shortDescription": "Web3’s Global Home ", + "website": "https://empiredao.xyz/", + "twitter": "@empiredao" + }, + { + "symbol": "Holaplex", + "category": "web3", + "bannerImage": "https://i.imgur.com/uW2laRX.png", + "displayName": "Holaplex", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4H282CCFjstxBd651gdhAydnXcjGk956Dk7p25MqxmfN", + "ogImage": "https://i.imgur.com/v9GE74q.png", + "shortDescription": "Holaplex provides a suite of web3 and NFT commerce solutions for businesses.", + "sortRank": 3, + "website": "https://www.holaplex.com/", + "twitter": "@holaplex", + "github": "https://github.com/holaplex" + }, + { + "symbol": "Angelic", + "category": "gaming", + "displayName": "Angelic ", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HsU14rpiBDC33hBsDPFQdZWaeykmKr67x3D2hA5RJRJD", + "website": "https://angelicthegame.com/", + "twitter": "@angelicthegame", + "discord": "https://dsc.gg/angelicthegame" + }, + { + "symbol": "Blockasset", + "category": "other", + "bannerImage": "https://i.imgur.com/c8C4jhO.png", + "displayName": "Blockasset", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "AvpoeRXmbfrtkF9NQvWkcN4LbWmQHy3ntWnYudEUdU3N", + "ogImage": "https://i.imgur.com/MGcybjN.jpg", + "shortDescription": "Licensed athlete token, NFT & social platform.", + "website": "https://www.blocksset.co/", + "twitter": "@blockassetco", + "discord": "https://www.discord.gg/blockasset" + }, + { + "symbol": "Aten", + "category": "web3", + "bannerImage": "https://3376093563-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fyc0V2H6VuzSAxmtjN5ka%2Fuploads%2FKUNH5H7vfj50awk5UtCo%2FAten%20Twitter%20Header.png?alt=media&token=844cd480-fd3b-4c60-b4c4-a25b45f44e78", + "displayName": "Aten", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "FxccMsauuC2KSsWMvrTytm2eP18oRr1HC1VLCaWEysAR", + "ogImage": "https://3376093563-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fyc0V2H6VuzSAxmtjN5ka%2Fuploads%2F9AgFRI7sWh4xTBRiu2z9%2FLogo%20Icon%20Original%20(2).png?alt=media&token=76b3a796-9225-4ff9-9602-f43027a170d4", + "shortDescription": "A Solana native eCommerce platform!", + "website": "https://aten.app/", + "twitter": "@AtenSolana", + "discord": "https://discord.gg/pUn8uTj8Kv" + }, + { + "symbol": "Virtual Basketball Association", + "category": "gaming", + "bannerImage": "https://i.imgur.com/q6wC2b1.jpg", + "displayName": "Virtual Basketball Association (VBA)", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4pAWUQBEvSo5sAeKt2bT8htJXy55J4inJDQhzwDcHWv3", + "ogImage": "https://i.imgur.com/VZ9Jo9z.jpg", + "shortDescription": "Own and manage a virtual basketball team. Build your roster of players and compete to win cash rewards in live basketball games.", + "website": "https://www.vbagame.com/", + "twitter": "@vbagame", + "discord": "https://discord.gg/vbagame" + }, + { + "symbol": "Ostium", + "category": "defi", + "bannerImage": "https://uploads-ssl.webflow.com/6265f670acb30e9728ef1297/635b174e5c09ce21e0d775e8_22_10_27%20Logo%20Orange%20Black%20Background%20cropped.png", + "displayName": "Ostium", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "GL54h53j3KAJZ8AqihMo4H48DgRR8nmSwXxSz1ALTGXg", + "ogImage": "https://uploads-ssl.webflow.com/6265f670acb30e9728ef1297/635b16d3cf67fdd8839a93cb_22_10_27%20Logo%20Orange%20just%20O.png", + "shortDescription": "A decentralized synthetic asset protocol bringing commodity markets on-chain.", + + "website": "https://www.ostium.io", + "twitter": "@ostium_fi", + "discord": "https://discord.gg/ny3HCfNt", + "github": "https://github.com/0xostium" + }, + { + "symbol": "01 Exchange", + "category": "defi", + "bannerImage": "https://pbs.twimg.com/profile_images/1553029460236337152/QjHF5aPb_400x400.jpg", + "displayName": "01 Exchange", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "EVsSaLkZbnekEnVeMsYEKtj2gYxcuaVYjGLUhVXzKTA9", + + "website": "https://01.xyz/", + "twitter": "@01_exchange" + }, + { + "symbol": "Drippieverse", + "category": "nft", + "bannerImage": "https://i.imgur.com/KoC7nwU.jpg", + "displayName": "Drippieverse", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "EAyrTrS4fEkCCXtbn3qFEtv4LzocYMqeVGYKW7syPt6Y", + "ogImage": "https://i.imgur.com/s5dyeqS.jpg", + "shortDescription": "Bridging fashion and Web3 through a collection of vibey creatures", + + "website": "https://www.drippies.space/", + "twitter": "@drippieverse", + "discord": "https://discord.gg/drippieverse" + }, + { + "symbol": "Degen Legends", + "category": "gaming", + "bannerImage": "https://i.imgur.com/qJKJhe6.jpg", + "displayName": "Degen Legends ", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "8PaQWLgqMyF6oxhteahuhvKag2RcbedsRuy2jMFJoLzU", + "ogImage": "https://i.imgur.com/KDi5P9l.png", + "shortDescription": "Degen Legends is esports & investment gaming organization, born in the heart of the web3 gaming revolution. ", + + "website": "https://www.degenlegends.io/", + "twitter": "@DegenLegends", + "discord": "discord.gg/degenlegends", + "github": "https://github.com/3dgglabs/staging" + }, + { + "symbol": "Francium", + "category": "defi", + "bannerImage": "https://i.imgur.com/bsgHzty.png", + "displayName": "Francium", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "GMpWmXc3sKejmAcAFpcQ4NgCL9Fx3gFR2FeepNUtK5Mh", + "ogImage": "https://raw.githubusercontent.com/Francium-DeFi/materials/main/francium_logo_white_background_with_ring.png.png", + "shortDescription": "Francium is a DeFi yield strategy Platform on Solana. Granted by Solana & Serum.", + + "website": "https://francium.io/", + "twitter": "@Francium_Defi", + "discord": "https://discord.com/invite/francium", + "github": "https://github.com/Francium-DeFi/francium-sdk" + }, + { + "symbol": "Ora", + "category": "web3", + "bannerImage": "https://i.imgur.com/Nk2lRMv.jpg", + "displayName": "Ora", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "9dvvWxLNRv2HWRkc1FJdgpXuF9fDRZMsCbw6vTdHbp5", + "ogImage": "https://i.imgur.com/dwuDf3u.jpg", + "shortDescription": "The Search Engine for Blockchains", + + "website": "https://ora.so", + "twitter": "@oralabs_" + }, + { + "symbol": "Contribute", + "category": "web3", + "bannerImage": "https://i.imgur.com/IMiMXl8.png", + "displayName": "Contribute", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DdNEw88N8VTeYfvxdLBwQ9aR4trejTUapGZRGdaMqyNY", + "ogImage": "https://i.imgur.com/pWJFEOj.png", + "shortDescription": "Connect your Solana wallet to join a gated-access group chat with other, verified NFT collection holders.", + + "website": "https://Contribute.xyz", + "twitter": "@Contribute_xyz", + "github": "https://github.com/ContributeDAO/" + }, + { + "symbol": "Artivive", + "category": "nft", + "bannerImage": "https://artivive.com/assets/uploads/2022/10/artivive_banner_2.jpg", + "displayName": "Artivive", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2XsZGq4GJoaQ7dC91yWuneq4U9VK3wE6XJ185a4D7fwe", + "ogImage": "https://artivive.com/assets/uploads/2022/10/artivive_avatar_1.jpg", + "shortDescription": "Artivive is the AR art platform onboarding 200.000 artists to WEB3", + + "website": "https://artivive.com/", + "twitter": "@ArtiviveApp", + "discord": "https://discord.com/invite/BBTpqxyGW2" + }, + { + "symbol": "Carpool", + "category": "web3", + "displayName": "Carpool", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "AH4qTqRFcoNqmYEi7p8heAGVSPHfJrNUPa8DvjDnBsf3", + "ogImage": "https://storage.googleapis.com/carpool-public-media/carpool-icon.png", + "shortDescription": "Backend as a Service for Solana Developers", + + "website": "https://www.carpool.dev/", + "twitter": "@CarpoolDev", + "discord": "https://discord.gg/h5BphJByAN" + }, + { + "symbol": "Solana Spaces", + "category": "other", + "bannerImage": "https://i.imgur.com/P6rqiCY.jpg", + "displayName": "Solana Spaces", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "58axqgJSAEK3adKL5hx5dYoRqkYMEiEXQZqk9FFFpa7f", + "ogImage": "https://i.imgur.com/PSk30Rp.jpg", + "shortDescription": "Experience the World of Solana. IRL.", + + "website": "https://solanaspaces.com", + "twitter": "@solanaspaces" + }, + { + "symbol": "Portals", + "category": "gaming", + "displayName": "Portals", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "54owXqUwmzR18h4NY6VEp45SNp6qtJUfByDeQuHenhgK", + "shortDescription": "Build your space in the Metaverse", + + "website": "https://theportal.to/", + "twitter": "@_portals_", + "discord": "https://discord.gg/portals" + }, + { + "symbol": "Bridgesplit", + "category": "defi", + "bannerImage": "https://pbs.twimg.com/profile_banners/1359961837576597506/1664761776/1500x500", + "displayName": "Bridgesplit", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2pJND9oPC1F4yWrBsxTDpmMcg6BbFSwvcu1kExBkbVDU", + "ogImage": "https://pbs.twimg.com/profile_images/1576678407366213632/dNd2-caG_400x400.jpg", + "shortDescription": "Bridgesplit is tokenization infrastructure for complex on & off-chain assets, powering indexes, tranching, lending and more.", + + "website": "https://bridgesplit.com", + "twitter": "@bridgesplit", + "discord": "https://discord.gg/bridgesplit", + "github": "https://github.com/bridgesplit" + }, + { + "symbol": "Garbles", + "category": "gaming", + "bannerImage": "https://i.imgur.com/2InC3WL.jpg", + "displayName": "Garbles", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "H3A8YM1ggR7GggD9qX4CEWkvPmkQUXuhGq2AGpbgqM6J", + "ogImage": "https://i.imgur.com/fBOx8Qe.png", + "shortDescription": "The blockchain mobile game that cleans up the planet", + + "website": "https://garbles.fun/", + "twitter": "@garblesfun", + "discord": "https://discord.gg/zQ3CPA7TVu", + "github": "https://github.com/garbles-labs" + }, + { + "symbol": "Star Atlas", + "category": "gaming", + "bannerImage": "https://i.imgur.com/j9CAVdy.jpg", + "displayName": "Star Atlas", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "52KrHUxbakN1rq9XoXQtSUmhdYyUZyp3YkWZQihZMTPu", + "ogImage": "https://i.imgur.com/krF2nOO.png", + "shortDescription": "Next-gen gaming metaverse with triple-A UE5 graphics for creating, playing & learning with others worldwide. Power to the People!", + "sortRank": 3, + "website": "https://staratlas.com/", + "twitter": "@StarAtlas", + "discord": "https://discord.gg/StarAtlas", + "github": "https://github.com/staratlasmeta/" + }, + { + "symbol": "Notifi", + "category": "web3", + "bannerImage": "https://media-exp1.licdn.com/dms/image/C5616AQEBxkDeVsr5SQ/profile-displaybackgroundimage-shrink_350_1400/0/1647984066280?e=1672272000&v=beta&t=glU8tqp2eIAVyX7Ld3jXSniXx3at0gtCYB4Diaj4NZQ", + "displayName": "Notifi", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "7nLVPup5xx5dWWVcDfjyHXHSr4juFM9wn1XaGQYxcYN1", + "ogImage": "https://notifi.network/logo.png", + "shortDescription": "Notifi allows Web3 teams to manage user communication under a unified platform.", + "sortRank": 3, + "website": "https://notifi.network/", + "twitter": "@NotifiNetwork", + "discord": "https://discord.gg/notifi", + "github": "https://github.com/notifi-network" + }, + { + "symbol": "Helius", + "category": "web3", + "bannerImage": "https://cdn.discordapp.com/attachments/948041727279763536/1034984588738568252/dark_banner_blank.png", + "displayName": "Helius", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "VAf2xnozMTWeytjUU4GtoyqrGj63owBENr754Y3bzL5", + "ogImage": "https://cdn.discordapp.com/attachments/948041727279763536/1034984434253967421/Helius_mark_orange_copy_6.png", + "shortDescription": "Making Solana development easier, faster, and more accessible. Webhooks, enhanced APIs, and RPCs.", + "sortRank": 3, + "website": "https://helius.xyz", + "twitter": "@heliuslabs", + "discord": "http://discord.gg/6GXdee3gBj" + }, + { + "symbol": "Zebec ", + "category": "web3", + "bannerImage": "https://pbs.twimg.com/profile_banners/1435632291837976580/1646674524/1500x500", + "displayName": "Zebec ", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "EhDvEUsxDSzU49jnyQ9iTheqQTPtG43gFvwbbrgye8t7", + "ogImage": "https://pbs.twimg.com/profile_images/1580267930666749952/xRSHqD0N_400x400.jpg", + "shortDescription": "Zebec is a continuous settlement protocol on Solana. We are revolutionizing payroll by introducing streaming finance technology.", + + "twitter": "@Zebec_HQ", + "discord": "https://t.co/kwC1Plza41", + "github": "https://github.com/Zebec-protocol/" + }, + { + "symbol": "Snowflake", + "category": "daotools", + "displayName": "Snowflake", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "GZyALQBvdBswSpMLabKEBVgKykkZMgnYcJgFk5dGU4aV", + "ogImage": "https://snowflake.so/assets/snowflake.png", + "shortDescription": "The most trusted multisig platform on Solana with native automation & a rich app store built for every team's needs.", + + "website": "https://snowflake.so", + "twitter": "@snowflake_sol", + "discord": "https://discord.gg/9qWK2BNaMD", + "github": "https://github.com/snowflake-so" + }, + { + "symbol": "Hedge", + "category": "defi", + "bannerImage": "https://i.imgur.com/WDjD99f.jpg", + "displayName": "Hedge", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "H2wGwADHWze2yZRurayzutPnDeKxpvf6WhVJpzixM121", + "ogImage": "https://i.imgur.com/uCHPIk5.png", + "shortDescription": "Low-cost leverage of your crypto assets by minting USH, a decentralized overcollateralized stablecoin that is fully composable. ", + + "website": "https://hedge.so", + "twitter": "@HedgeLabs", + "discord": "https://discord.gg/hedge", + "github": "https://github.com/Hedge-Finance" + }, + { + "symbol": "Solcial", + "category": "other", + "bannerImage": "https://pbs.twimg.com/profile_banners/1386355161505927168/1632734054/1500x500", + "displayName": "Solcial", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DVDoxbAiYv8oyScU1TUL7ZSsVMpU7zARaFTqwqdw5p5R", + "ogImage": "https://pbs.twimg.com/profile_images/1441071172452425742/1_N9szP0_400x400.jpg", + "shortDescription": "web3 social network", + + "website": "https://solcial.io/", + "twitter": "@solcialofficial", + "discord": "https://discord.gg/solcial", + "github": "https://github.com/solcial" + }, + { + "symbol": "Crossmint", + "category": "web3", + "displayName": "Crossmint", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "8V5BthCyL5LFDsWDKhfmAHqEgudSw1pXMC2PmWKAAr3D", + "ogImage": "https://crossmint.notion.site/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F0bbd2497-149e-4c09-899f-db712b7903ec%2Fcrossmint-logo-gradient.svg?table=block&id=35587462-6b8b-47fc-9d2d-785820faa16f&spaceId=d0f95547-f516-4746-9a98-cfb9535377c4&userId=&cache=v2", + "shortDescription": "Crossmint builds infrastructure to make NFTs accessible to everyone: minting APIs, fiat on-ramp, wallets, and more", + + "website": "http://crossmint.com", + "twitter": "@crossmint", + "discord": "https://discord.gg/crossmint" + }, + { + "symbol": "Unloc", + "category": "defi", + "bannerImage": "https://i.imgur.com/9s6W9cb.jpg", + "displayName": "Unloc", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "FiKdbhsKRMTzSfyTDRqBY3cy5GjAqCSXYJYRe2wQQ8Ly", + "ogImage": "https://i.imgur.com/6RCUXM3.jpg", + "shortDescription": "Financial Products & Services for NFT Owners. Initially launching with a fully customizable NFT-collateralized loans platform.", + + "website": "https://unloc.xyz", + "twitter": "@UnlocNFT", + "discord": "https://twitter.com/UnlocNFT", + "github": "https://github.com/UNLOC-DEV" + }, + { + "symbol": "Credix", + "category": "defi", + "displayName": "Credix", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2m2HfiYwMdbwVQ2BsSdqzQihdK2c2JymVy7aREDa9Lzu", + "ogImage": "https://i.imgur.com/avceXLB.png", + "shortDescription": "Credit investing made global ", + + "website": "https://credix.finance", + "twitter": "@Credix_finance", + "github": "https://github.com/credix-finance" + }, + { + "symbol": "Diaspora DAO", + "category": "nft", + "bannerImage": "https://i.imgur.com/ratcY61.jpg", + "displayName": "Diaspora DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "6iMVHPfcBebctV5bvSY23d2nuDuKvzTLP9HNCwWV2gGe", + "ogImage": "https://i.imgur.com/XDe5JAy.png", + "shortDescription": "4,444 Ancestors to guide you on your Journey into Web3", + + "website": "https://www.ourdiaspora.xyz/", + "twitter": "@OurDiaspora", + "github": "https://github.com/diaspora-labs" + }, + { + "symbol": "Rage Effect", + "category": "gaming", + "bannerImage": "https://i.ibb.co/8YkFDzd/RE-background-4.jpg", + "displayName": "Rage Effect", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DXezSkchMaYZTa3WM5xVU1SDQhMsFspMLuyyMuWk2YK9", + "ogImage": "https://i.ibb.co/nwc9YkH/1.png", + "shortDescription": "The First AAA-Quality Free-to-Play NFT MMO Shooter on Solana!", + + "website": "https://rageeffect.io", + "twitter": "@RageEffect_", + "discord": "https://discord.gg/rCCpKpUxb4" + }, + { + "symbol": "Satellite IM", + "category": "web3", + "bannerImage": "https://i.imgur.com/Fe9kDmp.png", + "displayName": "Satellite IM", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "3DLKv41oFs8DiHBkUEdm3MwiyJ9Sp4E6sb8QCAqynnbA", + "ogImage": "https://i.imgur.com/4T6fjCz.png", + "shortDescription": "A fully decentralized peer-to-peer communications platform", + + "website": "https://www.satellite.im/", + "twitter": "@Satellite_im" + }, + { + "symbol": "Block Tackle Inc", + "category": "gaming", + "bannerImage": "https://i.imgur.com/nrN70eL.png", + "displayName": "Block Tackle Inc", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "7Ad1wQdytLHSFxnUyEHVPUYrNKMect4Qs5pQtYgFCrr3", + "ogImage": "https://i.imgur.com/iwthT5U.png", + "shortDescription": "SkateX is a free-to-play extreme sports video game that uses blockchain technology so players can truly own their digital gear.", + + "website": "https://www.skatex.io/", + "twitter": "@PlaySkateX", + "discord": "https://discord.gg/skatex" + }, + { + "symbol": "Rye", + "category": "web3", + "bannerImage": "https://pbs.twimg.com/profile_banners/2408321/1665595450/1500x500", + "displayName": "Rye", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "7KsnMMyrF8wsxsLZNBZ8hRkGe13MdjAT9ko1qDEvkEWQ", + "ogImage": "https://pbs.twimg.com/profile_images/1571859763121758208/32YgNnii_400x400.png", + "shortDescription": "The easiest way to add checkout and shopping data to any app", + + "website": "https://www.rye.com", + "twitter": "@rye", + "discord": "https://discord.gg/HQuXqsGc", + "github": "https://github.com/rye-com" + }, + { + "symbol": "Ludex.gg", + "category": "web3", + "bannerImage": "https://i.imgur.com/qXW8xBH.png", + "displayName": "Ludex.gg", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HJ4YUJFSa1xX5wfbrPQKMTcTTnyT2eMxBk2eyBFGVmR7", + "ogImage": "https://i.imgur.com/iajmud9.png", + "shortDescription": "APIs & SDKs for video game developers to easily implement smart contracts into games with no blockchain knowledge required.", + + "website": "https://ludex.gg/", + "twitter": "@ludexgg", + "discord": "https://discord.com/invite/ludex", + "github": "https://github.com/ludex-labs" + }, + { + "symbol": "Okay Bears", + "category": "nft", + "bannerImage": "https://i.imgur.com/NfXLoSZ.jpg", + "displayName": "Okay Bears", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DntR8BU5tYVhQUNfARFG5VxKrpdRaKY2qKC3v8cYJirm", + "ogImage": "https://i.imgur.com/eKF74mG.png", + "shortDescription": "Okay Bears has the highest trade volume of any NFT collection on Solana and is an emerging global icon of clean, positive cool.", + + "website": "https://okaybears.com", + "twitter": "@okaybears", + "discord": "https://discord.com/invite/okaybears" + }, + { + "symbol": "HEIR Labs Inc", + "category": "web3", + "bannerImage": "https://i.imgur.com/Y86T3Vq.png", + "displayName": "HEIR Labs, Inc.", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "wij7YqAPCYtPk4isjY5TpoMpbYC7xupwuKVzpbnZHp7", + "ogImage": "https://i.imgur.com/RQ9Ys7o.png", + "shortDescription": "HEIR - the best sports culture community for athletes and fans with exclusive content, experience, merchandise, and digital assets", + + "website": "https://www.heir.app/", + "twitter": "@Heir_Company", + "discord": "https://discord.com/channels/943655968183578674/943655968674283608" + }, + { + "symbol": "Raydium", + "category": "defi", + "bannerImage": "https://i.imgur.com/mN0eY0k.png", + "displayName": "Raydium", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "8JZdqeTaMkPaatN8xKRXRHeSGSrNLSMAT5vWQjdNp7K", + "ogImage": "https://raw.githubusercontent.com/raydium-io/media-assets/ac2e46c4d8fc72d935cab0878992ce9a99b88589/logo.svg", + "shortDescription": "Raydium is an Automated Market Maker (AMM) built on the Solana blockchain for the Serum Decentralized Exchange (DEX).", + "sortRank": 3, + "website": "https://raydium.io/", + "twitter": "@RaydiumProtocol", + "discord": "https://discord.com/invite/raydium", + "github": "https://github.com/raydium-io" + }, + { + "symbol": "Bonk", + "displayName": "BonkDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "84pGFuy1Y27ApK67ApethaPvexeDWA66zNV8gm38TVeQ", + "ogImage": "https://i.imgur.com/5JK4nEL.jpeg", + "sortRank": 3 + }, + { + "symbol": "Wordcel Club", + "category": "web3", + "bannerImage": "https://www.wordcelclub.com/_next/static/media/user-default-banner.29900c53.png", + "displayName": "Wordcel Club", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DP2wpegQpLFYq9ntSZewi8XR6AoTdw31dbvinSekZKjr", + "ogImage": "https://pbs.twimg.com/profile_images/1497183193061277697/eaH0ns0y_400x400.png", + "shortDescription": "Building the Layer0 of Social Connections and Information Sharing on Solana.", + "sortRank": 3, + "website": "https://www.wordcelclub.com/", + "twitter": "@wordcel_club", + "discord": "https://discord.com/invite/tCswbSK5W2", + "github": "https://github.com/wordcel" + }, + { + "symbol": "Primitives", + "category": "nft", + "bannerImage": "https://pbs.twimg.com/profile_banners/1446997187196510209/1661804920/1500x500", + "displayName": "Primitives", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "8mrcnaGgMVKsYzWRDzSe47n2hTQjkuhYeXHGgSR1xkHP", + "ogImage": "https://pbs.twimg.com/profile_images/1582121955448209409/r3gbjCkP_400x400.png", + "shortDescription": "primitives is the most joyful place to interact with blockchains :)", + "sortRank": 3, + "website": "https://primitives.xyz/", + "twitter": "@primitives_xyz" + }, + { + "symbol": "Gangbusters Ltd", + "category": "gaming", + "bannerImage": "https://i.imgur.com/ewf4c0M.png", + "displayName": "Gangbusters Ltd", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HWYGhNLKUrrE8RmVkitDZrgsb68Ye8sp5P2pVLb2FyNf", + "ogImage": "https://i.imgur.com/PbV3nRm.png", + "shortDescription": "Community-driven Social Web3 Gaming - Building Everlasting IPs Togehter with Our Fans! ", + + "website": "https://gangbusters.io/", + "twitter": "@gangbusters_io", + "discord": "https://discord.gg/battletabs" + }, + { + "symbol": "Parcl", + "category": "defi", + "bannerImage": "", + "displayName": "Parcl DAO", + "programId": "Di9ZVJeJrRZdQEWzAFYmfjukjR5dUQb7KMaDmv34rNJg", + "realmId": "9Waj7NNTzEhyHf1j1F36xgtnXaLoAxVBFhf6VxE9fgaf", + "ogImage": "https://ipfs.filebase.io/ipfs/QmVDpnYjKMCBdmqGddQNyW8cc3tBU5cKZFiSV5y18J5YnK", + "shortDescription": "Parcl is an investment protocol that allows users to trade the price movements of real estate markets around the world.", + "website": "https://parcl.co", + "twitter": "@parcl", + "discord": "http://discord.gg/parcl", + "github": "https://github.com/ParclFinance/" + }, + { + "symbol": "Enthusiast Gaming", + "category": "gaming", + "bannerImage": "https://i.imgur.com/beNRCQY.png", + "displayName": "Enthusiast Gaming", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "5jHwG4CWkZhJD75M9kiZybGtzr4GC32NwvEq6dmSKefm", + "ogImage": "https://ev.io/sites/default/files/wallet_image/OracleTiny.png", + "shortDescription": "Ev.io is a competitive first person shooter on Solana in which you can earn SOL for getting kills. ", + + "website": "https://ev.io", + "twitter": "@play_evio", + "discord": "http://discord.gg/evio" + }, + { + "symbol": "Glass", + "category": "other", + "displayName": "Glass", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "27tbVohNkTpWiKtz1oGJQPhb3gPSGJfc4e2MtqFcuSuW", + "ogImage": "https://glassimg.imgix.net/new-icon.png?w=108&h=108&fm=webp", + "shortDescription": "Glass is the first video NFT marketplace for video creators, collectors, and traders built on the solana blockchain. ", + + "website": "https://glass.xyz/", + "twitter": "@glassprotocol", + "discord": "https://discord.gg/xn79hkqRFD" + }, + { + "symbol": "Vyper Protocol", + "category": "defi", + "bannerImage": "https://pbs.twimg.com/profile_banners/1465654820568768523/1663331046/1500x500", + "displayName": "Vyper Protocol", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "99vU7SHYJ4tSEqRNjY352Fx7gMSYfgcqxmjBMDyx3q8j", + "ogImage": "https://pbs.twimg.com/profile_images/1470433908185513994/x7Gyha1M_400x400.jpg", + "shortDescription": "A DeFi primitive to create, trade, and settle, on-chain derivatives", + + "website": "https://www.vyperprotocol.io/", + "twitter": "@VyperProtocol", + "discord": "https://discord.com/invite/DuXVSgjmuW", + "github": "https://github.com/vyper-protocol" + }, + { + "symbol": "Hyperspace", + "category": "web3", + "bannerImage": "https://storage.googleapis.com/feliz-crypto/project_photos/twitter%20banner.png", + "displayName": "Hyperspace", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "G2jq991DwNM1irZFwhPtCmzquXwBNQvAg5Sj8tBnqA2H", + "ogImage": "https://storage.googleapis.com/feliz-crypto/project_photos/hyperspace-favicon-black.png", + "shortDescription": "Solana’s most powerful NFT trading platform. Explore and collect NFTs aggregated across all marketplaces.", + "sortRank": 3, + "website": "https://hyperspace.xyz", + "twitter": "@hyperspacexyz", + "discord": "https://discord.gg/3bh6CX5vU6", + "github": "" + }, + { + "symbol": "CAMPUS", + "category": "web3", + "bannerImage": "https://ipfs.io/ipfs/bafkreieivbbl7rpvi6qtzde3mfp7khru5f23otwnjuntwl7fnm5ywz5pje", + "displayName": "CAMPUS", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HivVP77n6hsrgsaJUoHkYRMzgjjfmgWdcRrdrYSm6LLg", + "ogImage": "https://ipfs.io/ipfs/bafkreieiumjwp6dt6xckxvineeqowt6m565c3i25fn2b3hz4wodeirfn5q", + "shortDescription": "Helping brands, influencers, and their fans thrive in the new tokenized economy.", + + "website": "https://campus.io/", + "twitter": "@campusunlocks" + }, + { + "symbol": "Port Finance", + "category": "defi", + "bannerImage": "https://pbs.twimg.com/profile_banners/1390300692317761546/1623766655/1500x500", + "displayName": "Port Finance", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "FneznCHADXLsDjkvq51UmhZMropsXkSbkzJ5qXBMw1RF", + "ogImage": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/PoRTjZMPXb9T7dyU7tpLEZRQj7e6ssfAE62j2oQuc6y/PORT.png", + "sortRank": 3, + "website": "https://port.finance/", + "twitter": "@port_finance", + "discord": "https://discord.gg/nAMXAYhTb2", + "github": "https://github.com/port-finance" + }, + { + "symbol": "Elusiv", + "category": "other", + "bannerImage": "https://i.imgur.com/AFMGnkE.png", + "displayName": "Elusiv", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "J7deUothQNZ2momjrDwetv9RjL714h8U8cSz6oVd3s1m", + "ogImage": "https://i.imgur.com/ggTWLYo.png", + "shortDescription": "Elusiv combines privacy with safety by offering compliance in mind next-generation privacy solutions for a better Web3.", + "sortRank": 3, + "website": "https://elusiv.io/", + "twitter": "@elusivprivacy", + "discord": "https://discord.gg/elusivprivacy", + "github": "https://github.com/elusiv-privacy" + }, + { + "symbol": "Aurory", + "category": "gaming", + "bannerImage": "https://i.seadn.io/gae/9qqR3x65Uu5YmBTQ75hqy_NCVoEmkixVHQl7XcvnPF2yeWEiLpbN3B-zf1IlqwxFQh4TGg85wU_EKtbYAG2P_4nAFQTXyJ5QXmu_8A?auto=format&w=2048", + "displayName": "Aurory", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "C98yb8FSshG7oH5pCMf41ghg199YjsoUozxQ4VdCpwmM", + "ogImage": "https://i.seadn.io/gae/Qzl6u460tNyzWFrlaLQIa2VMBc1HBX5X7IDfEYBbKV3q1p_BDVkqC-A7-DS5RA-IKagzD0m7J-LDpmr_XnY2ocsTcXGM01DXM7lqUg?auto=format&w=2048", + "shortDescription": "Aurory Project is a AAA studio building the web3 gaming platform of the future.", + "sortRank": 3, + "website": "https://aurory.io/", + "twitter": "@AuroryProject", + "discord": "https://discord.gg/aurory" + }, + { + "symbol": "Chillchat", + "category": "web3", + "bannerImage": "https://i.imgur.com/XuWMJZt.png", + "displayName": "Chillchat", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "5KvezmjkfTshcWZ56jt6xj88Nu5Lbgy4gigHenhH8HPb", + "ogImage": "https://i.imgur.com/29MQYJy.png", + "shortDescription": "Chillchat is the collaborative platform to build virtual worlds.", + + "website": "https://chillchat.me/", + "twitter": "@chillchatme", + "discord": "http://discord.gg/chillchat" + }, + { + "symbol": "Grim Syndicate", + "category": "nft", + "bannerImage": "https://i.ibb.co/zHTshFG/banner22.jpg", + "displayName": "Grim Syndicate", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2hzSGHCfkAaGWedSc3Bh9CrmxGaQNCu8wjZPUfvbkYm7", + "ogImage": "https://i.ibb.co/1vB3PVV/grim-copy.png", + "shortDescription": "Global storytelling brand anchored in lore, gaming, and unique NFT experiences.", + + "website": "https://grimsyndicate.com/", + "twitter": "@Grim__Syndicate", + "discord": "https://discord.com/invite/grimsyndicate", + "github": "" + }, + { + "symbol": "Degenerate Ape Academy", + "category": "nft", + "bannerImage": "https://i.imgur.com/wgLWNen.png", + "displayName": "Degenerate Ape Academy ", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "7f47FkSAJqJLNY5p3jKxp7CLbEYbQDhhmKuYDJKrNJEq", + "ogImage": "https://i.imgur.com/j6VhuZJ.png", + "shortDescription": "Degenerate Ape Academy was the first trustless NFT launch on Solana. Owning a Degen Ape is owning part of history, and grants you the highest level of possible entry into both The Degeniverse and the Degen DAOO.", + "sortRank": 3, + "website": "https://www.degenape.academy/", + "twitter": "@degenapeacademy" + }, + { + "symbol": "Audius", + "category": "web3", + "bannerImage": "https://i.imgur.com/7BB6Fqy.png", + "displayName": "Audius", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "5Mt6EghNJHaPbNtHxH7tbbrMdwSP3sXcPRCqwPCbTVN4", + "ogImage": "https://i.imgur.com/6O8aTQB.png", + "shortDescription": "Audius is a fully decentralized music platform. Own the masters & the platform.", + + "website": "https://audius.co/", + "twitter": "@AudiusProject", + "discord": "https://discord.gg/audius", + "github": "https://github.com/AudiusProject" + }, + { + "symbol": "Cega", + "category": "defi", + "bannerImage": "https://pbs.twimg.com/profile_banners/1474053478557356039/1660635909/1500x500", + "displayName": "Cega", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "23DjgMdE4vCCNckzy8F4NvRFMxH6X2LVU6DrC75btVR8", + "ogImage": "https://pbs.twimg.com/profile_images/1539994043706253312/ukuwuvkD_400x400.jpg", + "shortDescription": "Cega is the #1 options protocol on Solana building exotic options structured products offering the best risk-adjusted yield.", + + "website": "https://app.cega.fi/", + "twitter": "@cega_fi", + "discord": "http://discord.gg/cega" + }, + { + "symbol": "Cogni", + "category": "web3", + "bannerImage": "https://i.imgur.com/5nUn2sC.png", + "displayName": "Cogni", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4vXAFpUSfRzxbtriRe7tH6u2Uwbm2SmBsD8EKnWow5qh", + "ogImage": "https://ipfs.io/ipfs/QmQ6VgRFiVTdKbiebxGvhW3Wa3Lkhpe6SkWBPjGnPkTttS/7978.png", + "shortDescription": "Your crypto, paycheck, and debit card – all in one sleek app.", + + "website": "getcogni.com", + "twitter": "@getcogni", + "discord": "https://twitter.com/getcogni" + }, + { + "symbol": "Backpack", + "category": "web3", + "bannerImage": "https://static.ftx.com/nfts/716a70b5-2425-4f17-8a6e-91ce13df44cd.jpeg", + "displayName": "Backpack", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "BqLWTZv8xfJiCtu9gm87T1EqtAnL2cCJ1PS9JoKn3oBy", + "ogImage": "https://static.ftx.com/nfts/e814aeb2-a599-4697-a199-abf077b8cd5f.jpeg", + "shortDescription": "Backpack is a home for your xNFTs.", + "sortRank": 3, + "website": "https://www.backpack.app/", + "twitter": "@xNFT_Backpack", + "discord": "http://discord.gg/waogg", + "github": "https://github.com/coral-xyz/backpack" + }, + { + "symbol": "Magic Eden", + "category": "other", + "bannerImage": "https://i.imgur.com/hDJj3dL.png", + "displayName": "Magic Eden", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "9MwbgfEkV8ZaeycfciBqytcxwfdYHqD2NYjsTZkH4GxA", + "ogImage": "https://i.imgur.com/p9Ludt4.png", + "shortDescription": "Magic Eden is the leading NFT platform for discovery, expression, and ownership across digital cultures.", + "sortRank": 3, + "website": "https://magiceden.io/", + "twitter": "@MagicEden", + "discord": "https://discord.gg/magiceden", + "github": "https://github.com/magiceden" + }, + { + "symbol": "DeGods", + "category": "nft", + "bannerImage": "https://i.imgur.com/g7s83QR.jpg", + "displayName": "DeGods", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "wx9R4TZLgL4VaVK89uW9D9DpMKMUCSm16nABeahk9Ex", + "ogImage": "https://i.imgur.com/wnyQRln.jpg", + "shortDescription": "Degods is on a mission to build the best communities on the internet.", + "sortRank": 3, + "website": "https://www.degods.com/", + "twitter": "@DeGodsNFT", + "discord": "https://t.co/JoIrKmQjvY" + }, + { + "symbol": "Solana Mobile", + "category": "web3", + "bannerImage": "https://i.imgur.com/5c0r8dv.jpeg", + "displayName": "Solana Mobile", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "ALzXvpmcmqmpNcFTbPzZ8ykSxHGqta85gTANfi8YPkPW", + "ogImage": "https://i.imgur.com/Oxsnr1C.png", + "shortDescription": "Solana Mobile is bringing web3 to mobile through the Solana Mobile Stack (SMS) and Saga, a flagship Android smartphone.", + "sortRank": 3, + "website": "https://solanamobile.com", + "twitter": "@solanamobile", + "discord": "https://discord.gg/solanamobile", + "github": "https://github.com/solana-mobile" + }, + { + "symbol": "Taki", + "category": "other", + "bannerImage": "https://pbs.twimg.com/profile_banners/1506155532641394688/1659620042/1500x500", + "displayName": "Taki", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DgWc4yWcqDnG62ZH6bHMeHfZUhBf5y7HZ9uqvgMs8JQW", + "ogImage": "https://www.gitbook.com/cdn-cgi/image/width=40,height=40,fit=contain,dpr=2,format=auto/https%3A%2F%2F2750118695-files.gitbook.io%2F~%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FmqsHMBVHpVSL6OcVoziH%252Ficon%252FHWEliwgNX4tds4jk1BjQ%252FTakiApp.png%3Falt%3Dmedia%26token%3D1458c07d-2031-44c3-9f4f-bd8bb5a8695e", + "shortDescription": "Own your token-powered social network with TAKI.", + "sortRank": 3, + "website": "https://taki.app/", + "twitter": "@takiapp", + "discord": "https://discord.gg/takiapp" + }, + { + "symbol": "Eternal Dragons", + "category": "gaming", + "bannerImage": "https://i.imgur.com/a0q7Nw9.png", + "displayName": "Eternal Dragons", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "9pLvqBe2CxC4HXQD5UQ7YLpQUqC5A9SqU4kNqw9inbNQ", + "ogImage": "https://i.imgur.com/tSTSdAh.png", + "shortDescription": "Eternal Dragons is a Web3 gaming series brought to you by Trailblazer Games, telling the story of the long-lost Eternal Dragons.", + + "website": "https://eternaldragons.com/", + "twitter": "@EternalDragons_", + "discord": "https://discord.com/invite/eternaldragons", + "github": "https://github.com/trailblazer-games/" + }, + { + "symbol": "Tulip", + "category": "defi", + "bannerImage": "https://tulipprotocol.notion.site/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F7f6ad7fd-3750-4908-b3ee-ac18660a69b6%2F1500x500.jpeg?table=block&id=bfb9c7e5-bc09-4b91-97e1-f211d4fa8eb1&spaceId=b22e9cdb-d148-4721-823e-c7a372f168da&width=1880&userId=&cache=v2", + "displayName": "Tulip", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "413KSeuFUBSWDzfjU9BBqBAWYKmoR8mncrhV84WcGNAk", + "ogImage": "https://tulipprotocol.notion.site/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F7fb0fb44-825e-46f3-aae1-b76cc9684547%2Fnew-logo.png?table=block&id=e0916de3-eca0-429b-ab04-6b9df820f4f1&spaceId=b22e9cdb-d148-4721-823e-c7a372f168da&width=1200&userId=&cache=v2", + "shortDescription": "Solana's Yield Aggregation Homestead", + + "website": "https://tulip.garden/", + "twitter": "@TulipProtocol", + "discord": "https://discord.com/invite/tulip", + "github": "https://github.com/sol-farm" + }, + { + "symbol": "Amulet", + "category": "defi", + "bannerImage": "https://pbs.twimg.com/profile_banners/1471061535652986880/1667288086/1500x500", + "displayName": "Amulet", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "3HC3mCQkpAAHQZa3aJjQJFpFNwoLp3ZWnkCYuWzoymo9", + "ogImage": "https://pbs.twimg.com/profile_images/1587347395507113984/_Y2HV3ye_400x400.jpg", + "shortDescription": "Simple, Reliable Cover For Everyone in Web3.Maximum protection and yield, fully protected through Protocol Controlled Reserves", + + "website": "https://amulet.org/", + "twitter": "@AmuletProtocol", + "discord": "https://discord.com/invite/AmuletProtocol", + "github": "https://github.com/Amulet-Protocol" + }, + { + "symbol": "Faraway", + "category": "gaming", + "bannerImage": "https://i.imgur.com/JHiKjpG.png", + "displayName": "Faraway", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4X8PMiLabGjdAHdrKL9SLu1HAMMp9xNcn3DY2mAciT8N", + "ogImage": "https://i.imgur.com/Bn9n7sF.png", + "shortDescription": "Faraway makes fun and social games with player-driven economies", + + "website": "https://faraway.gg/", + "twitter": "@farawaygg" + }, + { + "symbol": "MixMob", + "category": "gaming", + "bannerImage": "https://i.imgur.com/M57B2Xb.jpg", + "displayName": "MixMob", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "A3WX4QKcioruP71f4yweusv9jqU9R4LtGfJEHtZhs3Rx", + "ogImage": "https://i.imgur.com/PHo3WRt.jpg", + "shortDescription": "Remix the world! A new card strategy racing game from a team that worked on HALO, FIFA, Battlefield & PokerStars. Mask Up!", + + "website": "https://www.mixmob.io/", + "twitter": "@MixMobOrigin", + "discord": "discord.gg/mixmob", + "github": "https://github.com/MixMobOrigin" + }, + { + "symbol": "Kamino Finance", + "category": "defi", + "bannerImage": "https://i.imgur.com/wHEZDPh.png", + "displayName": "Kamino Finance", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "53pMaU2DXieGxwXZLMN1rgDECwFrxuYw5u9QgEFCx4Rd", + "ogImage": "https://pbs.twimg.com/profile_images/1563154884718985216/MPPps3IA_400x400.jpg", + "shortDescription": "Kamino is an active liquidity management layer that fully automates concentrated liquidity DEX positions across Solana.", + + "website": "https://bit.ly/Kamino-Site", + "twitter": "@kamino_finance", + "discord": "https://discord.gg/kaminofinance", + "github": "https://github.com/hubbleprotocol/kamino-webapp" + }, + { + "symbol": "Moonlit", + "category": "web3", + "bannerImage": "https://cdn.discordapp.com/attachments/953968357579837441/1034573854581993473/Frame_328.jpg", + "displayName": "Moonlit", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DKDkC6km37NcExxgBFW1nToSiybPvbu5RwhSSnRWwXYo", + "ogImage": "https://cdn.discordapp.com/attachments/953968357579837441/1034573854338715688/Frame_327.jpg", + "shortDescription": "Find and reward the SUPERSTARS in your Discord with Moonlit.", + + "website": "https://www.moonlit.team/", + "twitter": "@moonlit_team", + "discord": "https://discord.gg/ESXqmPy6wV" + }, + { + "symbol": "Coin98", + "category": "other", + "bannerImage": "https://i.imgur.com/3VA0BSX.jpg", + "displayName": "Coin98", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4pzwicnneaxCL4XVms2gJApfj7jpiFvDMzCWEHYw2rMV", + "ogImage": "https://i.imgur.com/cF4oQK7.png", + "shortDescription": "Your Crypto Everything App.", + + "website": "https://coin98.com/", + "twitter": "@coin98_wallet", + "discord": "https://c98.link/discord", + "github": "https://github.com/coin98/" + }, + { + "symbol": "Genopets", + "category": "gaming", + "bannerImage": "https://i.imgur.com/6Qmfw0l.png", + "displayName": "Genopets", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "8gqpog28H6UvefDu7wMbwaRQX7a7rbVtw7z3yX9xjJQa", + "ogImage": "https://i.imgur.com/mEUafGW.png", + "shortDescription": "The Free-to-Play, Move-to-Earn NFT mobile game. Steps you take every day fuel your journey in the Genoverse. Move. Play. Create.", + + "website": "https://www.genopets.me/", + "twitter": "@genopets", + "discord": "https://discord.gg/genopets" + }, + { + "symbol": "Multiverse", + "category": "gaming", + "displayName": "Multiverse (Earth From Another Sun)", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "5K4VVEeYpANxL79r7rM3heyXqYZkzu2KkD4kFkt1gGpG", + "ogImage": "https://i.imgur.com/2d1aeHo.png", + "shortDescription": "Earth From Another Sun is an open-world MMO sandbox FPS game where you can command massive armies to fight & conquer the Galaxy.", + + "website": "https://efas.io/", + "twitter": "@PlayEFAS/", + "discord": "https://discord.gg/EFAS" + }, + { + "symbol": "Helio", + "category": "web3", + "bannerImage": "https://i.imgur.com/NjvYAjs.png", + "displayName": "Helio", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2AgaUrJeZYxQgipGa8s5opQBPRqJBjKwWqv3hwinnefJ", + "ogImage": "https://i.imgur.com/4mcImE9.png", + "shortDescription": "The Web3 payments API", + + "website": "https://www.hel.io/", + "twitter": "@helio_pay", + "discord": "https://discord.gg/helio", + "github": "https://github.com/heliofi" + }, + { + "symbol": "Kaizen Corps", + "category": "gaming", + "bannerImage": "https://kaizen.nyc3.cdn.digitaloceanspaces.com/assets/kc-domination-alpha-banner.png", + "displayName": "Kaizen Corps", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "E5yobpBits2Wm8LbtGSPS6KhKzU3oZRTcbx2XTM6Q1fF", + "ogImage": "https://kaizen.nyc3.cdn.digitaloceanspaces.com/assets/kc-logo-square.png", + "shortDescription": "Creators of the strategy game: Domination, which drives our gaming/metaverse infrastructure and ecosystem development for Solana.", + + "website": "https://domination.gg", + "twitter": "@KaizenCorpsNFT", + "discord": "https://discord.gg/dominationgg", + "github": "https://github.com/kaizencorps" + }, + { + "symbol": "YGG SEA", + "category": "other", + "bannerImage": "https://i.imgur.com/UzcjaFG.png", + "displayName": "YGG SEA", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4xXbWdJbTdvmNNb2ZE1MEk7wtYWj3MJm8SqQ8u3TErvh", + "ogImage": "https://i.imgur.com/Sm74WKk.jpg", + "shortDescription": "The first subDAO of YGG, with the mission of creating the biggest and most sustainable virtual economy in Southeast Asia!", + + "website": "https://yggsea.io/", + "twitter": "@yggsea", + "discord": "https://discord.gg/yggsea", + "github": "" + }, + { + "symbol": "CandyPay", + "category": "other", + "bannerImage": "https://raw.githubusercontent.com/candypay/brand-assets/main/assets/header/dark.png", + "displayName": "CandyPay", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DReG8cfj6XA73u82AGFnytxGm3XZ3saetGwapRrRkoty", + "ogImage": "https://res.cloudinary.com/dnfor6ngq/image/upload/v1659720459/2_cdaoyi.png", + "shortDescription": "Powering seamless, mobile native NFT and Payments experiences on Solana", + + "website": "https://candypay.fun", + "twitter": "@candypayfun", + "discord": "https://discord.gg/VGjPXWUHGT", + "github": "https://github.com/candypay" + }, + { + "symbol": "Sphere", + "category": "web3", + "bannerImage": "https://i.imgur.com/j4xkSPp.jpeg", + "displayName": "Sphere", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "GHVYhVLqSfqsuNXkKrALXDEX8xq76WGMAtJka5zr3jqw", + "ogImage": "https://i.imgur.com/j9HOqJ5.png", + "shortDescription": "Payments Infrastructure for web3", + + "website": "https://sphere.engineer", + "twitter": "@sphere_labs", + "discord": "https://discord.gg/spherelabs", + "github": "https://github.com/Sphere-Laboratories/" + }, + { + "symbol": "Dispatch Protocol", + "category": "web3", + "bannerImage": "https://i.imgur.com/Phypzxt.jpg", + "displayName": "Dispatch Protocol", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "9jebQmDLbYRa4vo8rCQpPJu9VxRxWMp1cNTU1nzmrNLY", + "ogImage": "https://i.imgur.com/6Os7NYz.jpg", + "shortDescription": "Decentralized, censorship resistant, on-chain forums protocol. Reddit for Solana.", + + "website": "https://www.dispatch.forum", + "twitter": "@usedispatch", + "github": "https://github.com/usedispatch" + }, + { + "symbol": "SunriseStake", + "category": "other", + "bannerImage": "https://sunrisestake.com/assets/images/bg.jpg?v=f3159644", + "displayName": "SunriseStake", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4iUTtxTm6aJRLKJBqQrn36kg84i33xeGmruyQDd2pqbr", + "ogImage": "https://app.sunrisestake.com/logo.png", + "shortDescription": "Carbon-neutral Staking on Solana", + + "website": "https://sunrisestake.com", + "twitter": "@sunrisestake" + }, + { + "symbol": "Neoland", + "category": "gaming", + "bannerImage": "https://uploads-ssl.webflow.com/5c49faca5b4d2378c457f3c3/635af6204c392f2cccd8661a_world_map.png", + "displayName": "Neoland", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "87piQaXhHJffNHLkjixEViCoNWFTpXDPnqNTfzj523aD", + "ogImage": "https://uploads-ssl.webflow.com/5c49faca5b4d2378c457f3c3/635af638a86f57d500e39e64_icon_neoland_square.png", + "shortDescription": "Transform the world into a giant game board", + + "website": "neopolis.io", + "twitter": "@neolandgame", + "discord": "https://discord.gg/neoland" + }, + { + "symbol": "RACE Protocol", + "category": "gaming", + "bannerImage": "https://qox3en5puemmcge3p6niyyhzlrjttaiumikzidzd43pb3ejdxata.arweave.net/g6-yN6-hGMEYm3-ajGD5XFM5gRRiFZQPI-beHZEjuCY", + "displayName": "RACE Protocol", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "6LjHttTUQfps53BjCFibfZx3BnGvCnGeYRaVjLuXv64L", + "ogImage": "https://hkxww66li2siqwldmomgiqghcsmgfwsmexcucvy74y7tgeymkc5q.arweave.net/Oq9re8tGpIhZY2OYZEDHFJhi2kwlxUFXH-Y_MxMMULs", + "shortDescription": "Redefine web3 game and app development experience with RACE protocol", + + "website": "https://racepoker.app/", + "twitter": "@RaceGameTeam", + "discord": "https://discord.racepoker.app/", + "github": "https://github.com/RACE-Game " + }, + { + "symbol": "Civic", + "category": "web3", + "bannerImage": "https://i.imgur.com/JyUyqp1.png", + "displayName": "Civic", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "ASUYfCjE6uNBo5scmiFqC67v7Dyoq3znaZPvohR9yL2j", + "ogImage": "https://i.imgur.com/EvHrohQ.png", + "shortDescription": "Civic provides identity management tools for Web3 across chains for both consumers and dApps. ", + "sortRank": 3, + "website": "https://www.civic.com/", + "twitter": "@civickey", + "discord": "https://discord.com/invite/MWmhXauJw8", + "github": "https://github.com/civicteam" + }, + { + "symbol": "Coinable", + "category": "web3", + "displayName": "Coinable", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "EYNTFC5dB6ofU6AgbQgDsRsJ6oXBU783drDYQbdm9kba", + "ogImage": "https://i.imgur.com/sWbDYnS.png", + "shortDescription": "No-code Web3 ecommerce platform built for everyone. Together we build.", + + "website": "https://coinablepay.com", + "twitter": "@coinablepay", + "discord": "https://discord.com/invite/RgU669RNRk", + "github": "https://github.com/coinable" + }, + { + "symbol": "PBN3 Paul Barron Network", + "category": "other", + "displayName": "PBN3 Paul Barron Network", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HvSw2w9Ctfr8ejS8Gm1SvXpNxiQ7Fdgz8W6HmBvqVpC6", + "ogImage": "https://yt3.ggpht.com/yti/AJo0G0n517FVbMu4X145K2--tc-UvT1WtPsnpqsDjkTFyA=s88-c-k-c0x00ffffff-no-rj-mo", + "shortDescription": "The leading Web3 and Crypto Independent Media Sourse", + + "website": "https://www.paulbarronnetwork.com", + "twitter": "@paulbarrontv" + }, + { + "symbol": "BizFirst", + "category": "web3", + "bannerImage": "https://res.cloudinary.com/dpjpqasje/image/upload/v1668059279/Artboard_78_zawke6.png", + "displayName": "BizFirst", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DoFABWkP3qRV2yggE3Tm1MpemKDviwnDaQAVB3gRiPwc", + "ogImage": "https://res.cloudinary.com/dpjpqasje/image/upload/v1668060649/Group_48096200_hhatl0.png", + "shortDescription": "BizFirst helps merchants accept USDC payments and run NFT-based loyalty programs on their Store/Website.", + + "website": "https://www.bizfirst.xyz/", + "twitter": "@MyBizFirst" + }, + { + "symbol": "Alien Chicken Farm (ACF)", + "category": "gaming", + "bannerImage": "https://res.cloudinary.com/dpjpqasje/image/upload/v1668060575/Frame_427318920_xfvicm.png", + "displayName": "Alien Chicken Farm (ACF)", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "H5Me9k9Vk42d1eEfmfWX9z8hnFJvzCDN33z3hp6BwexH", + "ogImage": "https://res.cloudinary.com/dpjpqasje/image/upload/v1668059808/Group_5342_mgjdnv.png", + "shortDescription": "ACF is the simplest play-and-earn game.", + + "website": "https://alienchickenfarm.com", + "twitter": "@playacf" + }, + { + "symbol": "SKY Wallet", + "category": "other", + "bannerImage": "https://res.cloudinary.com/dpjpqasje/image/upload/v1668060575/Frame_427318919_pyorys.png", + "displayName": "SKY Wallet", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "bxPumP2w94Pz9QYYCCTYERgZSnTBWMh8xHwUCBU9N7W", + "ogImage": "https://res.cloudinary.com/dpjpqasje/image/upload/v1668060746/appicon_2_zcpynu.png", + "shortDescription": "The Crypto Wallet You Deserve.", + + "website": "https://www.getsky.app/", + "twitter": "@GetSkyApp", + "discord": "https://twitter.com/GetSkyApp" + }, + { + "symbol": "RetroTrades", + "category": "nft", + "bannerImage": "https://retrotrades.com/storage/large-purple-banner.png", + "displayName": "RetroTrades", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "9AmuU93FiiMCY6LA6HK1wBocT4y1C55hbNDC8jWA3qEi", + "ogImage": "https://retrotrades.com/static/cropped-retrotoken-192x192.png", + "shortDescription": "RetroTrades Community Hub", + + "website": "https://retrotrades.com", + "twitter": "@retrotradesnft", + "discord": "https://discord.gg/retrotrades" + }, + { + "symbol": "WaterDAO", + "category": "daotools", + "bannerImage": "https://www.waterdao.app/images/elements/head_water01.jpg", + "displayName": "WaterDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HtQ6TCLsLnR4iw78J8d5qR9Sac2ZfQkqpFqTnj8zgXEx", + "ogImage": "https://i.imgur.com/ksEqZYk.png", + "shortDescription": "The Water DAO is a decentralized platform for certifying water sources and issuing water credits. ", + + "website": "https://www.waterdao.app/", + "discord": "https://discord.gg/SnmXY6whY9" + }, + { + "symbol": "Infinity Labs NFT", + "category": "nft", + "bannerImage": "https://i.imgur.com/kdc6jgS.png", + "displayName": "Infinity Labs NFT", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "Gz9Zoht1gb6RW9hn9ejCup3uMDRqMSnppBWiQr9dHCaK", + "ogImage": "https://i.imgur.com/Mzze5aD.jpeg", + "shortDescription": "Home of the Infinite. A world is unfolding, compounding. First collect & merge to unlock animated artwork on chain. ", + + "website": "https://infinitylabsnft.com/", + "twitter": "@InfinityLabsNFT", + "discord": "https://discord.gg/d6y3aprk7v" + }, + { + "symbol": "Cyber Feminists", + "category": "nft", + "bannerImage": "https://i.postimg.cc/NfLy3dJD/4.jpg", + "displayName": "Cyber Feminists", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "3rQGVXuERbo9jakn5QXYBDFPR3uPXrNhPFQSmTeMNC2X", + "ogImage": "https://i.postimg.cc/mZmBGRKf/339a-cyberpunk-1.png", + "shortDescription": "We are Cyber Feminists - an online group of intellectual women at the forefront of technology for human evolution. ", + + "website": "https://cyberfeminismindex.com/", + "twitter": "@valeriespina", + "discord": "https://discord.gg/xT7k8vNWCM" + }, + { + "symbol": "Hxro", + "category": "defi", + "bannerImage": "https://i.imgur.com/Jn4gPgD.jpeg", + "displayName": "Hxro", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DhuExYnEG55GzCrEWsUjTF6jDjoXuvWj8Y2x3eb6SZqb", + "ogImage": "https://i.imgur.com/EVb5ZGi.jpeg", + "shortDescription": "Hxro is an open primitive powering on-chain derivatives for market-based applications.", + + "website": "https://hxro.com", + "twitter": "@HxroNetwork?s=20&t=_zzB0Frms7pHMI4GvotWgg", + "discord": "https://discord.gg/hxrolabs" + }, + { + "symbol": "DigitalEyes Market", + "category": "other", + "bannerImage": "https://pbs.twimg.com/profile_banners/1427625193812467718/1668449864/1500x500", + "displayName": "DigitalEyes Market", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "Huv6gAgfyjqj24WAypHthD85SGDc9N3WvhwFAxm7eDgn", + "ogImage": "https://pbs.twimg.com/profile_images/1430306224713740292/q4termyJ_400x400.jpg", + "shortDescription": "Solana's first open NFT marketplace.", + + "website": "https://www.digitaleyes.market/", + "twitter": "@DigitalEyesNFT", + "discord": "https://discord.com/invite/hhbgab4bsD" + }, + { + "symbol": "THIRD", + "category": "defi", + "bannerImage": "https://raw.githubusercontent.com/third-markets/Logo/main/bg-third-logo.png", + "displayName": "Third DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "ERJ8RLGJNHkKBvaqcsaJwChX5f1Y7wmgoZ1WB5TgdiQG", + "communityMint": "7bzmxz5TmbyVQLULo6hLRwi52rKwn4d2RWDces4uvZc4", + "ogImage": "https://raw.githubusercontent.com/third-markets/Logo/main/third_logo_500.png", + "shortDescription": "Trade selected tokens directly from your wallet with lightning speed and near-zero fees", + + "website": "https://third.markets", + "keywords": "Third Markets, Third, REALM, Governance, Swap, Jupiter, jup-ag, Jupiter Aggregator, DEFI, Decentralized Finance, Decentralised Finance, Crypto, ERC20, Ethereum, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, Fastest, Fast, BTC, USD, Tokens, SPL Tokens", + "twitter": "@ThirdMarkets", + "discord": "https://discord.gg/HBefBzQcdy", + "github": "https://github.com/third-markets" + }, + { + "symbol": "xLPFi", + "displayName": "LP Finance xGovernance", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HUDn6xDodk7sSE1ZPNzZEMJh1j8qu5zFxYFXPgAQ1AHE", + "communityMint": "xLPFiPmWve5rUnAYcHZSZWjwgyqEdcV6dDzoBJRtNw9", + "ogImage": "/realms/xLPFi/xLPFi-min.png", + "shortDescription": "LP Finance is a synthetic asset issuance protocol on Solana", + + "website": "https://lp.finance/", + "twitter": "@LPFinance_", + "linkedin": "https://www.linkedin.com/company/lpfinance/", + "instagram": "https://www.instagram.com/lp.finance/", + "discord": "https://discord.gg/N2Uebv58v2", + "github": "https://github.com/LP-Finance-Inc/" + }, + { + "symbol": "Hackerz DAO - High Council", + "displayName": "Hackerz DAO - High Council", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "zv8G3bXWe589fpb51LXfsoK2ACMAEqqHyjdYcxVys5R", + "twitter": "@HackerzDAO", + "discord": "https://discord.gg/zfQWsKMQCn", + "ogImage": "/realms/HackerzDAO/img/HackerzDAO_PFP.png" + }, + { + "symbol": "Hadeswap Governance", + "displayName": "Hadeswap Governance", + "shortDescription": "Largest NFT AMM on Solana", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HgcYAkXFT1ENpUCjBZWc1TjAAFacUwdGZRNhTHx9cuo", + "ogImage": "/realms/HadeswapGovernance/hadeswap_logo.jpg", + "website": "https://hadeswap.com", + "twitter": "@hadeswap" + }, + { + "symbol": "Clack DAO", + "displayName": "Clack DAO", + "shortDescription": "Clack - Meme Token at Solana BlockChain", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "5qfNPr56sGqoH7dTDBqVWqnhHZqYj7AcouoiHFDV9ZU3", + "communityMint": "2Y6sQjp2PiwnQpMPSvGGYFNSQGY24YubNYXtrB9ufon9", + "ogImage": "/realms/ClackDAO/Logo.png", + "discord": "https://discord.gg/BfkCHQkUTq", + "github": "https://github.com/clackinu", + "website": "https://clack.uno", + "twitter": "@clack_inu" + }, + { + "symbol": "BRDOT", + "category": "web3", + "bannerImage": "/realms/brdot/banner_brdot.png", + "displayName": "BRDOT DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "3HDYDcQQ75kLKnQT3EkU8MXWLrYFjE4sF1Bu1m359Gxz", + "ogImage": "/realms/brdot/brdot_dao_logo.png", + "shortDescription": "Bridging the Gap to Connectivity, Freedom, and Development in Latin America", + "discord": "https://discord.gg/XcWVHM2Z", + "github": "https://github.com/brdot", + "website": "https://brdot.com.br" + }, + { + "symbol": "SAO", + "category": "nft", + "displayName": "Sator DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "7yAiT2bUg5MwBzT3K9BvhcZdtHr5z8AnCGWa2iPJjB3T", + "ogImage": "/realms/SatorDAO/SatorLogo.png", + "bannerImage": "https://i.imgur.com/1rNmAIj.jpg", + "shortDescription": "Sator brings traditional TV and movies into Web3 through NFT-VOD and token-gated staking.", + "website": "https://sator.io", + "discord": "https://discord.gg/qftzCFrHNQ", + "twitter": "https://twitter.com/SatorSAO" + }, + { + "symbol": "Safecows", + "category": "web3", + "displayName": "Safecows", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "6RQAna7aWHLVwfYRFGyM8kpnBXNGkMNCGfvuwYuuvpFU", + "ogImage": "/realms/safecows/logo.png", + "bannerImage": "/realms/safecows/banner.png", + "shortDescription": "Take Action for the Zero Hunger by mining for Proof-of-Health over Helium Network.", + "website": "https://safecows.com", + "discord": "https://discord.gg/aQCeMSWs" + }, + { + "symbol": "BlueChickDAO", + "category": "gaming", + "displayName": "The Blue Chick NFTs DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "99c96qFUwLiGcbudDeTLVxYTbtQ4CkDsstvHHmGPGGWj", + "ogImage": "/realms/BlueChickNFTsDAO/BlueChickNFTsDAO.png", + "bannerImage": "/realms/BlueChickNFTsDAO/BlueChickNFTsDAO-banner.png", + "shortDescription": "PVP artillery tactical game with x9999 immutable Blue Chicks. The NFTs and the DAO were actually made by birds!", + "website": "https://bluechicknfts.wtf", + "discord": "https://discord.gg/SHVcwHKUNG", + "twitter": "@blueChickNFTs" + }, + { + "symbol": "HNT", + "voteSymbol": "veHNT", + "allowDiscussion": false, + "displayName": "Helium DAO", + "programId": "hgovkRU6Ghe1Qoyb54HdSLdqN7VtxaifBzRmh9jtd3S", + "realmId": "2VfPJn8ML1hNBnsEBo7SzmG11UJc7gbY8b23A3K8expd", + "website": "https://helium.com", + "twitter": "@Helium", + "ogImage": "/realms/Helium/img/logo.svg" + }, + { + "symbol": "IOT", + "voteSymbol": "veIOT", + "allowDiscussion": false, + "displayName": "Helium IOT SubDAO", + "programId": "hgovkRU6Ghe1Qoyb54HdSLdqN7VtxaifBzRmh9jtd3S", + "realmId": "8UQNtD5Zw8ijB7ZpGiPLodKXMxtVyQmtu1AEztd3p6Po", + "website": "https://helium.com", + "twitter": "@Helium", + "ogImage": "/realms/Helium/img/iotlogo.png" + }, + { + "symbol": "MOBILE", + "voteSymbol": "veMOBILE", + "allowDiscussion": false, + "displayName": "Helium MOBILE SubDAO", + "programId": "hgovkRU6Ghe1Qoyb54HdSLdqN7VtxaifBzRmh9jtd3S", + "realmId": "7yyaEqDNfgqS6cgmPmJGVoU5dkwayPFRq55VmNDR79ij", + "website": "https://helium.com", + "twitter": "@Helium", + "ogImage": "/realms/Helium/img/mobilelogo.png" + }, + { + "symbol": "CRYSTAL", + "displayName": "Polar Dao", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "6xdMASp69Q42BudN7L2u2i92GfEruzCiZBqYaT3hwhZ4", + "website": "https://thepolariansnft.com", + "twitter": "@polariansnft", + "ogImage": "/realms/PolarDao.png" + }, + { + "symbol": "LAVA", + "displayName": "LavaDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "shortDescription": "LavaDAO manages the HeliumDenver event space ecosystem and hackathon.", + "discord": "https://discord.gg/B7DWEgeRum", + "bannerImage": "https://cdn.discordapp.com/attachments/1051281685234327613/1162371467795775498/lavabanner.png?ex=653bb1c9&is=65293cc9&hm=a1560670cb9a170b3cae38bf244e8983c844858361027cd5b817adb8ecea88e0&", + "category": "DePIN", + "sortRank": 3, + "realmId": "HPhQwEU6GEYd82vkXDQ59pjavVJ7vrEsbnj1fwU9USRA", + "website": "https://heliumdenver.com", + "twitter": "@hntdenver", + "ogImage": "/realms/LavaDAO/img/lavalogo.png" + }, + { + "symbol": "PAWN", + "displayName": "Pawn DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "shortDescription": "A Pawn in someone's experiment.", + "discord": "https://discord.gg/Td7QFn2ePz", + "bannerImage": "/realms/PAWN/img/pawns-banner.png", + "category": "Memecoin", + "sortRank": 3, + "realmId": "7rvjS4CgRYUZkSLJAXitmeQCybvfZcYcMjpVRhJ9mFHK", + "twitter": "@pawnspl24", + "ogImage": "/realms/PAWN/img/pawn.png" + }, +{ + "symbol": "PAWNGO", + "displayName": "Pawngo DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "shortDescription": "A very good girl.", + "discord": "https://discord.gg/Td7QFn2ePz", + "bannerImage": "/realms/PAWNGO/img/pawngodao.png", + "category": "Memecoin", + "sortRank": 3, + "realmId": "2cS5Epb9b1hGifzWi6iYmpHbNueM9FReh8kqNaKrcTFJ", + "twitter": "@pawnspl24", + "ogImage": "/realms/PAWNGO/img/pawngo.png" + }, + { + "symbol": "GCDC", + "displayName": "Gay Coinz DAO Coin", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "shortDescription": "We're gonna need a bigger tote!", + "discord": "", + "bannerImage": "/realms/GCDC/img/gaycoinz-banner.png", + "category": "Web3", + "sortRank": 3, + "realmId": "5aXNavdJkzp8j2kPbvQbf15kmxdqJgjXJ8CqJ4S1ZTpG", + "twitter": "", + "ogImage":"/realms/GCDC/img/gaycoinz-logo.png" + }, + { + "symbol": "COMRADE", + "displayName": "ComradeDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2KY6Ka8KNxLEPvD19J5GArVReVWm2VSinNmqvZJMYzRP", + "shortDescription": "ComradeDAO manages the NudieMagazine creator space ecosystem.", + "bannerImage": "https://cdn.discordapp.com/attachments/1051281685234327613/1162374152653639731/comradebanner.png?ex=653bb449&is=65293f49&hm=a39dea9cbcc471e4252883d5706b0521acb62fbc4f0ae6181e4a7ee3b3d3fb8b&", + "category": "Web3", + "sortRank": 3, + "website": "https://thenudiemagazine.com", + "twitter": "@nudie_mag", + "ogImage": "/realms/ComradeDAO/img/comradedaologo.png" + }, + { + "symbol": "RESON", + "displayName": "ResonanceDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "BsAFgmFSFAqMz9zPFA6Q2s7rkgE6pi6WTYHgygtNkN5z", + "shortDescription": "ResonanceDAO manages the Resonance Gaming Ecosystem.", + "bannerImage": "https://cdn.discordapp.com/attachments/1051281685234327613/1162371467795775498/lavabanner.png?ex=653bb1c9&is=65293cc9&hm=a1560670cb9a170b3cae38bf244e8983c844858361027cd5b817adb8ecea88e0&", + "category": "Web3", + "sortRank": 3, + "website": "https://playresonance.com", + "twitter": "@resonancesolana", + "ogImage": "/realms/ResonanceDAO/resonancedaologo.png" + }, + { + "symbol": "VILLAGE", + "displayName": "VillagesDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "Cv526yBpKfyEERuaSBPUHk1bF6vsNVLcSVi8xevJgT8S", + "shortDescription": "VillagesDAO manages the global Villages Fresh Water Project collab with LavaDAO, CryptoChicks NFT, and Aerial IoT.", + "bannerImage": "https://cdn.discordapp.com/attachments/1051281685234327613/1162371468257153076/villagesbanner.png?ex=653bb1c9&is=65293cc9&hm=4098e1484db8e46aee0d026d16d8bb75e333f90f563cbf98c0dc2cdfab6bc086&", + "category": "Web3", + "sortRank": 3, + "website": "https://heliumdenver.com", + "twitter": "@hntdenver", + "ogImage": "/realms/VillagesDAO/villagesdaologo.png" + }, + { + "symbol": "PPWT", + "displayName": "Poodle Paws DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "ABh3GrrTQqnYofrcbhajSbuvDB1si7PHzxL2s4RZ4Ef", + "website": "https://poodlepaws.vercel.app/", + "twitter": "@PoodlePawsWT", + "bannerImage": "https://i.imgur.com/bVHqAmp.png", + "shortDescription": "Poodle Paws DAO envisions becoming the preeminent pet brand in the realm of Web3 and beyond.", + "ogImage": "/realms/PoodlePawsDAO/PoodlePawsDAO.png" + }, + { + "category": "nft", + "discord": "https://discord.gg/Decod3rsNFT", + "displayName": "$VIEWS DAO", + "bannerImage": "/realms/VIEWSDAO/img/views_banner.jpg", + "ogImage": "/realms/VIEWSDAO/img/views_logo.png", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "9mJUsn6pwUytW2TdytEDRajKDHBjqXsbXyKFP28fzaZ6", + "shortDescription": "$VIEWS DAO - Building the Watch-to-Earn meta", + + "symbol": "VIEWSDAO", + "twitter": "@Decod3rsNFT" + }, + { + "symbol": "ALL", + "category": "web3", + "displayName": "AllDomains", + + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "ELEXG9cTEJ2pgxFbEVAwushyoPvE7rrEHBgNKfv8uxzi", + "communityMint": "BaoawH9p2J8yUK9r5YXQs3hQwmUJgscACjmTkh8rMwYL", + "ogImage": "/realms/ALL/img/logo.png", + "bannerImage": "https://i.imgur.com/tbaZ0qN.png", + "shortDescription": "AllDomains is a Solana Protocol that allows users to create human-readable domain names that can be used in place of a Public Key.", + "sortRank": 3, + "website": "https://alldomains.id", + "keywords": "Web3 Identity, REALM, Goverenance, Web3 domains, DAO", + "twitter": "@AllDomains_", + "github": "https://github.com/onsol-labs/" + }, + { + "symbol": "PHNX", + "displayName": "PhoenixDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "FHe1HUmcyhJQDiDTi1Dkt3Jtu25Eo8QzT6kdAVDCiNUB", + "website": "https://phnx.one/", + "twitter": "@Phnxsol", + "ogImage": "/realms/PHNXDAO/phnxLogo.png" + }, + { + "symbol": "OPDA", + "displayName": "OPANZ DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "Ccix1WKGTwCbdChjUSrVVgq4xPzMGzTutqpW1R4hCRGd", + "bannerImage": "/realms/OPANZ/OPANZ_Banner.png", + "ogImage": "/realms/OPANZ/OPANZ_Logo.png", + "website": "https://auturoa.nz/", + "twitter": "@opanzch" + }, + { + "symbol": "SHURA", + "displayName": "Solshure DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "BbLADqNQtWtPVrrxJESwmHRS4MHS1NyqpPDwndtYcZDB", + "ogImage": "/realms/SolshureDAO/img/solshure_dao.png", + "website": "https://solshure.com/", + "twitter": "@Solshure" + }, + { + "symbol": "TBET", + "displayName": "TrustBet", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "9gSewHByQG9YbqpkVWp9qucLoqvQRZ4YKn5b6E5w6okt", + "bannerImage": "/realms/TrustBet/Bannerontransparent.png", + "ogImage": "realms/TrustBet/LRlogo.png", + "communityMint": "xpFbKJa92Ee1NSYEhc3b3BVk4im8YStXRaVW6EoW33w" + }, + { + "symbol": "BLR", + "displayName": "Blockride", + "category": "web3", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "A6ZS5ZdkyAbncb55fKjaUhBcQcovp8XcYT5AEQayv96y", + "bannerImage": "/realms/Blockride/banner.png", + "ogImage": "/realms/Blockride/logo.png", + "twitter": "@blockridenft", + "website": "https://blockride.xyz/", + "sortRank": 3, + "shortDescription": "BLOCKRIDE DAO - Building a modern approach to vehicle financing", + "keywords": "Web3, REALM, Governance, vehicle financing, DAO, Africans, Nigeria, RWA, Solana", + "github": "https://github.com/BlockrideNFT-org" + }, + { + "symbol": "RAAAWR", + "displayName": "Solsaur DAO", + "bannerImage": "/realms/Solsaur/solsaur-realms-banner.png", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "ANqmLV2hQNwFm3jyfqLEBa6KTksosr6uKzcdfg9X6ReR", + "ogImage": "/realms/Solsaur/solsaur.png", + "website": "https://www.solsaur.com", + "twitter": "@solsauras" + }, + { + "symbol": "Conk", + "displayName": "Conk Dao", + "category": "web3", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "A3jzUmuVqbyzqLgHtmMA2igUeACScRiSk71Hy27ehieo", + "bannerImage": "/realms/ConkDao/conk_banner.png", + "ogImage": "/realms/ConkDao/conk.png", + "twitter": "@Conk_Coin", + "website": "https://conkcoin.club", + "sortRank": 3, + "shortDescription": "Conk DAO - The People's Cat Coin", + "keywords": "Web3, REALM, Governance, Meme, DAO, Solana" + }, + { + "symbol": "MEMES", + "displayName": "MemeCoinDAOai", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "Ecar1VyamYnR2UzJzJbQMKR9Zq1U5p1xuUUsnzceDiaH", + "bannerImage": "/realms/MemeCoinDAOai/MemeCoinDAOBanner1_15.png", + "ogImage": "/realms/MemeCoinDAOai/MemeCoinDAOFinalLogo.png", + "website": "https://www.memecoindao.ai", + "twitter": "@MemeCoinDAOai" + }, + { + "symbol": "$GARI", + "displayName": "GARI Network DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "HvDndGYjZNMVQDsrdAJJR7DtnQSB5rXM9BJBdwuxiXDg", + "bannerImage": "https://media1.tenor.com/m/uKCFs6UJgCwAAAAC/gari-gari-token.gif", + "ogImage": "https://gari.network/wp-content/uploads/2023/12/gari-coin-1.png", + "website": "https://gari.network/", + "twitter": "@TheGariNetwork", + "category": "web3" + }, + { + "symbol": "BOHDAO", + "displayName": "Brigade of Honor Dao", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "FSh5XBFUYFMEWP99y4j7W6zERtEnqFVuwfuHgHgJJYWq", + "ogImage": "https://www.brigadeofhonor.com/BOHlogo.png", + "website": "https://www.brigadeofhonor.com/", + "twitter": "@BoHgamingguild" + }, + { + "symbol": "MF", + "displayName": "MOUTAI FUND", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "3JZmKT5xWKESXdC9aVpcv4so2DngpDHqzCm1pzwPU8Jc", + "ogImage": "/realms/MOUTAI/MF.png", + "website": "https://moutaifund.club/", + "twitter": "@MoutaiFund" + }, + { + "symbol": "MOUTAI", + "displayName": "MOUTAI DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "DgsXUhQbGuHxRNcSZJJdVXJcFCeMEFyDNeBYUDS9pHmC", + "ogImage": "/realms/MOUTAI/mdao.jpg", + "website": "https://www.moutaicoin.co/", + "twitter": "@Moutai_Sol" + }, + { + "symbol": "GARBAGE", + "displayName": "GARBAGE DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "GgF6fHb3iM3Um5DtvwbZvpGpYTzYnr1RmZr4NkwHveGp", + "website": "", + "twitter": "" + }, + { + "symbol": "sinDAO", + "displayName": "sinDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "7boMaQ9LG3eHXEsiWWWs7RDP2Z8ASJ3wJevTmuTh1qhL", + "ogImage": "/realms/sinDAO/sindao.png", + "website": "https://sindao.org", + "twitter": "@thesinDAO" + }, + { + "symbol": "TNSR", + "category": "NFT", + "bannerImage": "https://i.imgur.com/PMLtfh6.png", + "displayName": "Tensor DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4sgAydAiSvnpT73rALCcnYGhi5K2LrB9pJFAEbLMfrXt", + "communityMint": "TNSRxcUxoT9xBG3de7PiJyTDYu7kskLqcpddxnEJAS6", + "ogImage": "https://i.imgur.com/IP2FsY7.png", + "shortDescription": "Future of NFT trading. Built on Solana.", + "website": "https://www.tensor.foundation", + "keywords": "Tensor, REALM, Governance, TNSR, Tensor NFT Marketplace, NFT, Crypto, Solana, SOL, Trading, Fastest, Fast", + "twitter": "@TensorFdn", + "discord": "https://discord.gg/a8spfqxEpC", + "github": "https://github.com/tensor-foundation" + }, + { + "symbol": "Jito", + "displayName": "Jito", + "programId": "jtogvBNH3WBSWDYD5FJfQP2ZxNTuf82zL8GkEhPeaJx", + "realmId": "jjCAwuuNpJCNMLAanpwgJZ6cdXzLPXe2GfD6TaDQBXt", + "ogImage": "/realms/Jito/jito.png", + "website": "https://jito.network", + "twitter": "@jito_sol" + }, + { + "symbol": "FIM", + "category": "defi", + "bannerImage": "/realms/FinanceIsMagic/Banner.png", + "displayName": "Finance Is Magic", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "JCv4VFAMUrwwGfjnRsS2DmujNEEfNs9KT3jentpQYnsg", + "communityMint": "64pwL5YCL1ctSVUpNsBAsw7V6ZPiZmrEJ1dNhdsQwKx2", + "ogImage": "/realms/FinanceIsMagic/Logo.png", + "shortDescription": "DeFi magic with memecoins and liquidity.", + "website": "https://fimcoin.com", + "keywords": "DeFi, REALM, Governance, FIM, Decentralized Finance, Crypto, Decentralize, Solana, SOL, SPL, Cross-Chain, Trading, SPL Tokens", + "twitter": "@financeismagic" + }, + { + "symbol": "KING", + "displayName": "Mewfasa DAO", + "category": "web3", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "2Gn1tf4WyFv8tk4kzd7GZCrw44P5d3mq6qEzjWyq159H", + "bannerImage": "/realms/MewfasaDAO/banner-dao.jpg", + "ogImage": "/realms/MewfasaDAO/mewfasadao.jpg", + "twitter": "@MewfasaK53969", + "website": "https://mewfasa.fun/", + "shortDescription": "Mewfasa - The Lion Cat King", + "keywords": "Web3, Governance, Community, Solana" + }, + { + "symbol": "DRIFT", + "bannerImage": "https://i.imgur.com/b9pPf3S.png", + "displayName": "Drift Protocol", + "programId": "dgov7NC8iaumWw3k8TkmLDybvZBCmd1qwxgLAGAsWxf", + "realmId": "FVVXu18aNUqyFCfq8sGktPM62mqJAGaenv4z6UGUs5em", + "ogImage": "https://i.imgur.com/HnF1Zzy.png", + "shortDescription": "A lightning-fast and scalable perpetual futures DEX.", + "sortRank": 4, + "website": "https://www.drift.trade/", + "twitter": "@DriftProtocol", + "discord": "http://discord.com/invite/drifting", + "github": "https://github.com/drift-labs/protocol-v2" + }, + { + "symbol": "GREED", + "displayName": "The $GREED Experiment", + "programId": "GovRp7uazvmYkQ7gqjdfjKFwr6pHDcYFWH3SP9DHzdtR", + "realmId": "8KG5Z3thhSwQCVWdnNdPZV5JQJya2gNaBELjLA8xhEcs", + "ogImage": "https://cdn.blastctrl.com/greed/dao_logo.png", + "bannerImage": "https://cdn.blastctrl.com/greed/dao_banner.png", + "website": "https://x.com/voshy", + "twitter": "@voshy" + }, + { + "symbol": "GUAC", + "displayName": "The Guacamole AvocaDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "Ha56K8MGrJuiJSyK2UaYRpAf7Hu2BZw2XALEmW9EQemu", + "ogImage": "/realms/Guacamole/Guacamole_Token_Logo_Green.png", + "bannerImage": "/realms/Guacamole/Guacamole_Banner.png", + "website": "https://guac.gg", + "twitter": "@guac_gg" + }, + { "symbol": "Advocat", + "displayName": "Advocat DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "FDZPbcWoPfeVZxKev7syLPA7RNiEbK8wW5upW7KnMcSY", + "ogImage": "/realms/Advocat/logo.png", + "bannerImage": "/realms/Advocat/AdvocatBusiness.png", + "website": "https://advocat.live", + "twitter": "@notacatcoin" + }, + { + "symbol": "FOXTAG", + "displayName": "$SOLFOX Official DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "8PzqFQWeiyQLAtiDG4GV8bmS1YDCM7xy6SNz1eMsiw8A", + "ogImage": "/realms/FOXTAG/FOXTAG.png", + "website": "https://solfoxlegion.com", + "twitter": "@solfoxlegion" + }, + { + "symbol": "LABS", + "category": "defi", + "bannerImage": "/realms/EpicentralLabsDAO/EpicentralDAOBanner.png", + "displayName": "EpicentralDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "5PP7vKjJyLw1MR55LoexRsCj3CpZj9MdD6aNXRrvxG42", + "communityMint": "LABSh5DTebUcUbEoLzXKCiXFJLecDFiDWiBGUU1GpxR", + "ogImage": "/realms/EpicentralLabsDAO/Epicentral-Labs-Logo.png", + "shortDescription": "Epicentral Labs introduces innovative solutions and services for new or already existing Solana-based projects with the main goal to connect, collaborate, and educate today's webspace with how blockchain can immerse user experience.", + "website": "https://epicentrallabs.com/", + "keywords": "Epicentral Labs, REALM, Governance, DEFI, Decentralized Finance, Developer Tooling, Crypto, Solana, Ethereum, Decentralize, Community, SOL, SPL, Integrated, Trading, Infrastructure, SPL Tokens", + "twitter": "@EpicentralLabs", + "discord": "https://discord.gg/5asAuY2sR8", + "github": "https://github.com/EpicentralLabs" + }, + { + "symbol": "COAL", + "bannerImage": "/realms/CoalitionDAO/banner.png", + "displayName": "CoalitionDAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "4HRDvxcErtP4MxWqpmem7CfwGU9LbYfJd9JCNz5s5RTd", + "communityMint": "E3yUqBNTZxV8ELvW99oRLC7z4ddbJqqR4NphwrMug9zu", + "ogImage": "/realms/CoalitionDAO/logo.png", + "shortDescription": "A coalition of miners and engineers.", + "website": "https://coal.digital/", + "keywords": "Proof of work, Crypto mining, Community, Governance, Solana", + "twitter": "@coalonsolana", + "discord": "https://discord.gg/WJVYcHHGHr", + "github": "https://github.com/coal-digital" + }, + { + "symbol": "JETSKI", + "bannerImage": "/realms/JetSkiDAO/banner.png", + "displayName": "JetSki DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "FEPMbc7rB8BF3anr9eHHfi2VeZKnCdWKWZW9guu3oxuT", + "communityMint": "E7saHtwrZ3i6QNNB15Kq4R8e4mLz5J5XMtJybHNhpump", + "ogImage": "/realms/JetSkiDAO/logo.jpeg", + "shortDescription": "The first community managed basket DAO on Solana.", + "website": "https://deanslistdao.notion.site/JetSki-DAO-380d86533e154e4c8bbd66a11c54194f", + "twitter": "@JetSkiDAO", + "telegram": "https://t.me/+mlW159EpFtY1N2U0D" + }, + { + "symbol": "IKB", + "bannerImage": "/realms/IKB/ikb_dao_banner.jpg", + "displayName": "International Klein Blue DAO", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "6Tae5nNMnyNpCqrBMHoyNVVRdbYkwnvL9EgzQkin9aHN", + "communityMint": "F7viRR7XKFeDxMG441DC1KDZu8cFjPvGFF6tnKYNVvFc", + "ogImage": "/realms/IKB/ikb_dao_logo.jpg", + "shortDescription": "The first modern art meme token. The IKB DAO federates $IKB token holders, enabling them to collaborate to perform experiments and to support the art community.", + "keywords": "blue, International Klein Blue, art, modern art, artmeme, meme, art community, art experiments", + "website": "https://ikb-token.co", + "twitter": "@ikb_token", + "telegram": "https://t.me/+8Fzp2CFx2yZiMDI5" + }, + { + "symbol": "MRGY", + "displayName": "Mergey", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "GgXxU6HPCMFmwYkuFdbkm8QAvVhWiexraZAy9CX4CYRU", + "communityMint": "4i1ZW16fF5EHunJ9hCV4nqz9ckmeM6hg11BREy5x2Knw", + "ogImage": "/realms/mergey/logo.png", + "shortDescription": "Acquire. Merge. Divest. Permissionless memecoin M&A on Solana.", + "website": "https://mergey.fun", + "twitter": "@mergeydotfun", + "telegram": "https://t.me/+vUtROD2-n_4xNzZh" + }, + { + "symbol": "PIBBLE", + "bannerImage": "/realms/PibbleDAO/Banner.png", + "displayName": "Pibble's Treats", + "programId": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw", + "realmId": "GqPQwmN6VdqPEez9MrHCwLGfjy8z7g1fe432thRBrpLL", + "communityMint": "6qoHodWitraGtWFiLEvUZPz9THQt2vUJzV9Xd68ykAYP", + "ogImage": "/realms/PibbleDAO/logo.png", + "website": "https://pibble.xyz", + "twitter": "@PibbleSolana" } -] + ] diff --git a/public/realms/mergey/logo.png b/public/realms/mergey/logo.png new file mode 100644 index 0000000000..e0f64a8935 Binary files /dev/null and b/public/realms/mergey/logo.png differ diff --git a/public/realms/metaplex/img/black-circle.png b/public/realms/metaplex/img/black-circle.png new file mode 100644 index 0000000000..b5c7e2ca81 Binary files /dev/null and b/public/realms/metaplex/img/black-circle.png differ diff --git a/public/realms/pumpkinspool/pumpkin_header.png b/public/realms/pumpkinspool/pumpkin_header.png new file mode 100644 index 0000000000..0017c2bb15 Binary files /dev/null and b/public/realms/pumpkinspool/pumpkin_header.png differ diff --git a/public/realms/pumpkinspool/pumpkin_logo_cropped.png b/public/realms/pumpkinspool/pumpkin_logo_cropped.png new file mode 100644 index 0000000000..6b0c0cca3f Binary files /dev/null and b/public/realms/pumpkinspool/pumpkin_logo_cropped.png differ diff --git a/public/realms/safecows/banner.png b/public/realms/safecows/banner.png new file mode 100644 index 0000000000..2322025e7e Binary files /dev/null and b/public/realms/safecows/banner.png differ diff --git a/public/realms/safecows/logo.png b/public/realms/safecows/logo.png new file mode 100644 index 0000000000..0c3950cac4 Binary files /dev/null and b/public/realms/safecows/logo.png differ diff --git a/public/realms/sinDAO/sindao.png b/public/realms/sinDAO/sindao.png new file mode 100644 index 0000000000..43294212d0 Binary files /dev/null and b/public/realms/sinDAO/sindao.png differ diff --git a/public/realms/token-overrides.json b/public/realms/token-overrides.json new file mode 100644 index 0000000000..018ea6444a --- /dev/null +++ b/public/realms/token-overrides.json @@ -0,0 +1,15 @@ +{ + "METAewgxyPbgwsseH8T16a39CQ5VyVxZi9zXiDPY18m": { + "symbol": "MPLX", + "extensions": { + "coingeckoId": "metaplex" + } + }, + + "GePFQaZKHcWE5vpxHfviQtH5jgxokSs51Y5Q4zgBiMDs": { + "symbol": "JFI", + "extensions": { + "coingeckoId": "jungle-defi" + } + } +} diff --git a/public/realms/wikicious/wikicious.png b/public/realms/wikicious/wikicious.png new file mode 100644 index 0000000000..45496ba9ee Binary files /dev/null and b/public/realms/wikicious/wikicious.png differ diff --git a/public/realms/xLPFi/xLPFi-min.png b/public/realms/xLPFi/xLPFi-min.png new file mode 100644 index 0000000000..47ace5ed69 Binary files /dev/null and b/public/realms/xLPFi/xLPFi-min.png differ diff --git a/public/verify-wallet/img/Direction--straight--right.svg b/public/verify-wallet/img/Direction--straight--right.svg new file mode 100644 index 0000000000..16a3796cf2 --- /dev/null +++ b/public/verify-wallet/img/Direction--straight--right.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/verify-wallet/img/icon-connected.svg b/public/verify-wallet/img/icon-connected.svg new file mode 100644 index 0000000000..b402bd8c19 --- /dev/null +++ b/public/verify-wallet/img/icon-connected.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/verify-wallet/img/icon-discord-role.svg b/public/verify-wallet/img/icon-discord-role.svg new file mode 100644 index 0000000000..c925c4a886 --- /dev/null +++ b/public/verify-wallet/img/icon-discord-role.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/verify-wallet/img/icon-solana-connected.svg b/public/verify-wallet/img/icon-solana-connected.svg new file mode 100644 index 0000000000..1d8f189e52 --- /dev/null +++ b/public/verify-wallet/img/icon-solana-connected.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/verify-wallet/img/logo-discord.svg b/public/verify-wallet/img/logo-discord.svg new file mode 100644 index 0000000000..630cb8e417 --- /dev/null +++ b/public/verify-wallet/img/logo-discord.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/verify-wallet/img/logo-matchday.png b/public/verify-wallet/img/logo-matchday.png new file mode 100644 index 0000000000..e7439a3445 Binary files /dev/null and b/public/verify-wallet/img/logo-matchday.png differ diff --git a/scripts/api.ts b/scripts/api.ts deleted file mode 100644 index f3c593ebf8..0000000000 --- a/scripts/api.ts +++ /dev/null @@ -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( - rpcContext.programId, - rpcContext.endpoint, - Realm, - [GovernanceAccountType.RealmV1, GovernanceAccountType.RealmV2] - ) -} - -export async function getGovernanceAccounts( - programId: PublicKey, - endpoint: string, - accountClass: GovernanceAccountClass, - accountTypes: GovernanceAccountType[], - filters: MemcmpFilter[] = [] -) { - if (accountTypes.length === 1) { - return getGovernanceAccountsImpl( - programId, - endpoint, - accountClass, - accountTypes[0], - filters - ) - } - - let accounts: Record> = {} - - 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( - 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 - > = new SanitizedObject({}) as Record> - 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 - - 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 -} diff --git a/scripts/governance-notifier.ts b/scripts/governance-notifier.ts index 6fab16cd4a..dbfac98d5c 100644 --- a/scripts/governance-notifier.ts +++ b/scripts/governance-notifier.ts @@ -10,6 +10,8 @@ import { } from '@solana/spl-governance' import { getCertifiedRealmInfo } from '@models/registry/api' import { accountsToPubkeyMap } from '@tools/sdk/accounts' +import { fmtTokenAmount } from '@utils/formatting' +import { formatNumber } from '@utils/formatNumber' const fiveMinutesSeconds = 5 * 60 const toleranceSeconds = 30 @@ -28,12 +30,12 @@ function errorWrapper() { // run every 5 mins, checks if a governance proposal just opened in the last 5 mins // and notifies on WEBHOOK_URL async function runNotifier() { - const REALM_SYMBOL = process.env.REALM_SYMBOL || 'MNGO' + const REALM = process.env.REALM || 'MNGO' const connectionContext = getConnectionContext('mainnet') - const realmInfo = await getCertifiedRealmInfo(REALM_SYMBOL, connectionContext) + const realmInfo = await getCertifiedRealmInfo(REALM, connectionContext) const connection = new Connection(process.env.CLUSTER_URL!) - console.log(`- getting all governance accounts for ${REALM_SYMBOL}`) + console.log(`- getting all governance accounts for ${REALM}`) const governances = await getGovernanceAccounts( connection, realmInfo!.programId, @@ -52,7 +54,7 @@ async function runNotifier() { }) ) - console.log(`- scanning all '${REALM_SYMBOL}' proposals`) + console.log(`- scanning all '${REALM}' proposals`) let countJustOpenedForVoting = 0 let countOpenForVotingSinceSomeTime = 0 let countVotingNotStartedYet = 0 @@ -80,6 +82,56 @@ async function runNotifier() { // voting is closed proposal.account.votingCompletedAt ) { + if ( + nowInSeconds - proposal.account.votingCompletedAt.toNumber() <= + fiveMinutesSeconds + toleranceSeconds + ) { + const votingTokenDecimals = 6 + const yesVotes = fmtTokenAmount( + proposal.account.getYesVoteCount(), + votingTokenDecimals + ) + const noVotes = fmtTokenAmount( + proposal.account.getNoVoteCount(), + votingTokenDecimals + ) + + const minVotesNeeded = + proposal.account.governance.toBase58() === + '7D6tGmaMyC8i73Q8X2Fec2S1Zb5rkyai6pctdMqHpHWT' + ? 50000000 + : 100000000 + const quorumReached = yesVotes >= minVotesNeeded + const isSuccess = yesVotes > noVotes && quorumReached + + const msg = ` + Proposal Ended: ${proposal.account.name} + + Status: ${ + isSuccess + ? 'Success' + : !quorumReached + ? 'Defeated - Quorum Not Reached' + : 'Defeated' + } + + 🗳️ Voting Breakdown: + - Yes Votes: ${formatNumber(yesVotes, undefined, { + minimumFractionDigits: 0, + })} + - No Votes: ${formatNumber(noVotes, undefined, { + minimumFractionDigits: 0, + })} + + 🔗 https://realms.today/dao/${escape( + REALM + )}/proposal/${proposal.pubkey.toBase58()}` + + console.log(msg) + if (process.env.WEBHOOK_URL) { + axios.post(process.env.WEBHOOK_URL, { content: msg }) + } + } countClosed++ continue } @@ -106,7 +158,7 @@ async function runNotifier() { const msg = `“${ proposal.account.name }” proposal just opened for voting 🗳 https://realms.today/dao/${escape( - REALM_SYMBOL + REALM )}/proposal/${proposal.pubkey.toBase58()}` console.log(msg) @@ -122,7 +174,7 @@ async function runNotifier() { // const msg = `“${ // proposal.account.name // }” proposal just opened for voting 🗳 https://realms.today/dao/${escape( - // REALM_SYMBOL + // REALM // )}/proposal/${proposal.pubkey.toBase58()}` // // console.log(msg) @@ -133,7 +185,7 @@ async function runNotifier() { const remainingInSeconds = governancesMap[proposal.account.governance.toBase58()].account.config - .maxVotingTime + + .baseVotingTime + proposal.account.votingAt.toNumber() - nowInSeconds if ( @@ -143,7 +195,7 @@ async function runNotifier() { const msg = `“${ proposal.account.name }” proposal will close for voting 🗳 https://realms.today/dao/${escape( - REALM_SYMBOL + REALM )}/proposal/${proposal.pubkey.toBase58()} in 24 hrs` console.log(msg) diff --git a/scripts/skip-vercel-builds.sh b/scripts/skip-vercel-builds.sh new file mode 100644 index 0000000000..7e9d1431e3 --- /dev/null +++ b/scripts/skip-vercel-builds.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# copied from https://vercel.com/guides/how-do-i-use-the-ignored-build-step-field-on-vercel + +echo "VERCEL_ENV: $VERCEL_ENV" + +if [[ "$VERCEL_ENV" == "production" ]] ; then + # Proceed with the build + echo "✅ - Build can proceed" + exit 1; + +else + # Don't build + echo "🛑 - Build cancelled" + exit 0; +fi \ No newline at end of file diff --git a/stores/useGovernanceAssetsStore.tsx b/stores/useGovernanceAssetsStore.tsx index ad79af521e..7660794963 100644 --- a/stores/useGovernanceAssetsStore.tsx +++ b/stores/useGovernanceAssetsStore.tsx @@ -1,12 +1,20 @@ import create, { State } from 'zustand' +import axios from 'axios' import { getNativeTreasuryAddress, Governance, - GovernanceAccountType, Realm, TOKEN_PROGRAM_ID, + ProgramAccount, + GovernanceAccountType, } from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' +import { + LAMPORTS_PER_SOL, + ParsedAccountData, + PublicKey, + StakeProgram, +} from '@solana/web3.js' +import { AccountInfo, MintInfo } from '@solana/spl-token' import { AUXILIARY_TOKEN_ACCOUNTS, DEFAULT_NATIVE_SOL_MINT, @@ -18,17 +26,14 @@ import { import { AccountInfoGen, getMultipleAccountInfoChunked, + MintAccount, parseMintAccountData, - parseTokenAccountData, + TokenAccount, TokenProgramAccount, } from '@utils/tokens' -import { ParsedAccountData, PublicKey } from '@solana/web3.js' -import { AccountInfo, MintInfo } from '@solana/spl-token' -import { AccountInfo as AccountInfoGeneric } from '@solana/web3.js' -import { TokenAccountLayout } from '@blockworks-foundation/mango-client' -import tokenService from '@utils/services/token' +import { parseTokenAccountData } from '@utils/parseTokenAccountData' +import tokenPriceService from '@utils/services/tokenPrice' import { ConnectionContext } from '@utils/connection' -import axios from 'axios' import { AccountType, AccountTypeGeneric, @@ -39,37 +44,53 @@ import { AccountTypeSol, AccountTypeToken, AssetAccount, + GovernanceProgramAccountWithNativeTreasuryAddress, + AccountTypeStake, + StakeState, } from '@utils/uiTypes/assets' import group from '@utils/group' +import { getFilteredProgramAccounts } from '@utils/helpers' +import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes' +const additionalPossibleMintAccounts = { + Mango: [ + new PublicKey('EGk8Gw7Z484mzAKb7GwCcqrZd4KwwsyU2Dv9woY6uDQu'), + new PublicKey('8gjzxiqcU87cvRc7hFiUJgxqLSV7AQnSttfWC5fD9aim'), + new PublicKey('G1Yc5696GcfL28uAWG6iCaKJwZd8sQzwPJTc2UacsjHN'), + new PublicKey('oW7juZxrhaGvWw5giRp3P3qTHEZpg2t8n8aXTCpBjNK'), + ], +} const tokenAccountOwnerOffset = 32 +const programAccountOwnerOffset = 13 interface SolAccInfo { governancePk: PublicKey acc: any nativeSolAddress: PublicKey } + interface GovernanceAssetsStore extends State { governancesArray: ProgramAccount[] governedTokenAccounts: AssetAccount[] assetAccounts: AssetAccount[] loadGovernedAccounts: boolean + loadTokenAccounts: boolean + loadProgramAccounts: boolean + loadMintAccounts: boolean setGovernancesArray: ( connection: ConnectionContext, realm: ProgramAccount, - governances: { - [governance: string]: ProgramAccount - } + governances: ProgramAccount[] ) => void getGovernedAccounts: ( connection: ConnectionContext, realm: ProgramAccount - ) => void + ) => Promise refetchGovernanceAccounts: ( connection: ConnectionContext, realm: ProgramAccount, governancePk: PublicKey - ) => void + ) => Promise } const defaultState = { @@ -77,33 +98,95 @@ const defaultState = { assetAccounts: [], governedTokenAccounts: [], loadGovernedAccounts: false, + loadTokenAccounts: false, + loadProgramAccounts: false, + loadMintAccounts: false, } const useGovernanceAssetsStore = create((set, _get) => ({ ...defaultState, - setGovernancesArray: (connection, realm, governances) => { - const array = Object.keys(governances) - .filter((gpk) => !HIDDEN_GOVERNANCES.has(gpk)) - .map((key) => governances[key]) + + setGovernancesArray: ( + connection: ConnectionContext, + realm: ProgramAccount, + governances: ProgramAccount[] + ) => { + const array: ProgramAccount[] = governances.filter( + (gov) => !HIDDEN_GOVERNANCES.has(gov.pubkey.toString()) + ) + set((s) => { s.governancesArray = array }) + _get().getGovernedAccounts(connection, realm) }, + getGovernedAccounts: async (connection, realm) => { set((s) => { s.loadGovernedAccounts = true + s.loadTokenAccounts = true + s.loadMintAccounts = true + s.loadProgramAccounts = true s.governedTokenAccounts = [] s.assetAccounts = [] }) + const governancesArray = _get().governancesArray - const accounts = governancesArray.length - ? await getAccountsForGovernances(connection, realm, governancesArray) - : [] + const accounts: AssetAccount[] = [] + const nativeAddresses = await Promise.all([ + ...governancesArray.map((x) => + getNativeTreasuryAddress(realm.owner, x.pubkey) + ), + ]) + const governancesWithNativeTreasuryAddress = governancesArray.map( + (x, index) => ({ + ...x, + nativeTreasuryAddress: nativeAddresses[index], + }) + ) + //due to long request for mint accounts that are owned by every governance + //we fetch + const possibleMintAccountPks = [ + realm.account.communityMint, + realm.account.config.councilMint, + ].filter((x) => typeof x !== 'undefined') as PublicKey[] + + const additionalMintAccounts = + additionalPossibleMintAccounts[realm.account.name] + if (additionalMintAccounts) { + possibleMintAccountPks.push(...additionalMintAccounts) + } + // 1 - Load token accounts behind any type of governance + const governedTokenAccounts = await loadGovernedTokenAccounts( + connection, + realm, + governancesWithNativeTreasuryAddress + ) + // 2 - Call to fetch token prices for every token account's mints + await tokenPriceService.fetchTokenPrices( + governedTokenAccounts.reduce((mints, governedTokenAccount) => { + if (!governedTokenAccount.extensions.mint?.publicKey) { + return mints + } + + return [ + ...mints, + governedTokenAccount.extensions.mint.publicKey.toBase58(), + ] + }, [] as string[]) + ) + accounts.push(...governedTokenAccounts) + const stakeAccounts = await loadStakeAccounts( + connection, + governedTokenAccounts.filter( + (x) => x.isSol + ) + ) + accounts.push(...stakeAccounts) set((s) => { - s.governancesArray = governancesArray - s.loadGovernedAccounts = false + s.loadTokenAccounts = false s.governedTokenAccounts = accounts .filter( (x) => @@ -111,27 +194,73 @@ const useGovernanceAssetsStore = create((set, _get) => ({ x.type === AccountType.NFT || x.type === AccountType.SOL ) - .filter(filterOutHiddenAccs) - s.assetAccounts = accounts.filter(filterOutHiddenAccs) + .filter(filterOutHiddenAccounts) + s.assetAccounts = accounts.filter(filterOutHiddenAccounts) + }) + + // 3 - Load accounts related to mint + const mintAccounts = await loadMintGovernanceAccounts( + connection, + governancesWithNativeTreasuryAddress, + possibleMintAccountPks + ) + accounts.push(...mintAccounts) + set((s) => { + s.loadMintAccounts = false + s.assetAccounts = accounts.filter(filterOutHiddenAccounts) + }) + + // 4 - Load accounts related to program governances + const programAccounts = await getProgramAssetAccounts( + connection, + governancesWithNativeTreasuryAddress + ) + accounts.push(...programAccounts) + set((s) => { + s.loadProgramAccounts = false + s.assetAccounts = accounts.filter(filterOutHiddenAccounts) + }) + + // 5 - Create generic asset accounts for governance's governedAccounts that have not been handled yet + // We do this so theses accounts may be selected + const genericGovernances = getGenericAssetAccounts( + governancesWithNativeTreasuryAddress.filter( + (governance) => + !accounts.some((account) => + account.pubkey.equals(governance.account.governedAccount) + ) + ) + ) + accounts.push(...genericGovernances) + + set((s) => { + s.loadGovernedAccounts = false + s.assetAccounts = accounts.filter(filterOutHiddenAccounts) }) }, - refetchGovernanceAccounts: async (connection, realm, governancePk) => { + refetchGovernanceAccounts: async ( + connection: ConnectionContext, + realm: ProgramAccount, + governancePk: PublicKey + ) => { set((s) => { s.loadGovernedAccounts = false }) - const governancesArray = _get().governancesArray.filter( - (x) => x.pubkey?.toBase58() === governancePk.toBase58() + const governancesArray = _get().governancesArray.filter((x) => + x.pubkey.equals(governancePk) ) const previousAccounts = _get().assetAccounts.filter( - (x) => x.governance?.pubkey?.toBase58() !== governancePk.toBase58() + (x) => !x.governance.pubkey.equals(governancePk) ) + const accounts = await getAccountsForGovernances( connection, realm, governancesArray ) + set((s) => { s.loadGovernedAccounts = false s.governedTokenAccounts = [...previousAccounts, ...accounts] @@ -141,9 +270,9 @@ const useGovernanceAssetsStore = create((set, _get) => ({ x.type === AccountType.NFT || x.type === AccountType.SOL ) - .filter(filterOutHiddenAccs) + .filter(filterOutHiddenAccounts) s.assetAccounts = [...previousAccounts, ...accounts].filter( - filterOutHiddenAccs + filterOutHiddenAccounts ) }) }, @@ -151,53 +280,76 @@ const useGovernanceAssetsStore = create((set, _get) => ({ export default useGovernanceAssetsStore const getTokenAccountObj = async ( - governance: ProgramAccount, + governance: GovernanceProgramAccountWithNativeTreasuryAddress, tokenAccount: TokenProgramAccount, mintAccounts: TokenProgramAccount[] -) => { +): Promise => { const isNftAccount = tokenAccount.account.mint.toBase58() === DEFAULT_NFT_TREASURY_MINT - const mint = mintAccounts.find( - (x) => x.publicKey.toBase58() === tokenAccount.account.mint.toBase58() - ) + + const mint = mintAccounts.find((x) => + x.publicKey.equals(tokenAccount.account.mint) + )! + if (isNftAccount) { - return new AccountTypeNFT(tokenAccount, mint!, governance) + return new AccountTypeNFT(tokenAccount, mint, governance) } if ( - mint?.account.supply && - mint?.account.supply.cmpn(1) !== 0 && + mint.account.supply && + mint.account.supply.cmpn(1) !== 0 && mint.publicKey.toBase58() !== DEFAULT_NATIVE_SOL_MINT ) { return new AccountTypeToken(tokenAccount, mint!, governance) } + + return null } const getSolAccountsObj = async ( connection: ConnectionContext, accounts: AssetAccount[], solAccountsInfo: SolAccInfo[], - mintAccounts: TokenProgramAccount[], - governances: ProgramAccount[] -) => { - const solAccs: AccountTypeSol[] = [] - for (const i of solAccountsInfo) { - const mint = mintAccounts.find((x) => x.publicKey.toBase58() === WSOL_MINT) - const governance = governances.find( - (x) => x.pubkey.toBase58() === i.governancePk.toBase58() - ) + mintAccounts: TokenProgramAccount[], + governances: GovernanceProgramAccountWithNativeTreasuryAddress[] +): Promise => { + const solAccounts: AccountTypeSol[] = [] + + const wsolMintAccount = mintAccounts.find( + (x) => x.publicKey.toBase58() === WSOL_MINT + )! // WSOL should be here + + for (const solAccountInfo of solAccountsInfo) { + const governance = governances.find((x) => + x.pubkey.equals(solAccountInfo.governancePk) + )! // Governance should be here + const account = await getSolAccountObj( - governance!, + governance, connection, - mint!, + wsolMintAccount, accounts, - i + solAccountInfo ) + if (account) { - solAccs.push(account) + solAccounts.push(account) } } - return solAccs as AssetAccount[] + + return solAccounts +} + +// Return array without duplicates +const uniquePublicKey = (array: PublicKey[]): PublicKey[] => { + return Array.from( + array.reduce((mintsPks, publicKey) => { + // Transform to string for Set to be able to identify duplicates + mintsPks.add(publicKey.toBase58()) + + return mintsPks + }, new Set()) + ).map((address) => new PublicKey(address)) } const getTokenAssetAccounts = async ( @@ -205,38 +357,39 @@ const getTokenAssetAccounts = async ( publicKey: PublicKey account: AccountInfo }[], - governances: ProgramAccount[], - realm: ProgramAccount, + governances: GovernanceProgramAccountWithNativeTreasuryAddress[], connection: ConnectionContext ) => { const accounts: AssetAccount[] = [] - const mintsPks = [...tokenAccounts.map((x) => x.account.mint)] - //WSOL is used as mint for sol accounts to calculate amounts - if (!mintsPks.find((x) => x.toBase58() === WSOL_MINT)) { + + const mintsPks = uniquePublicKey( + tokenAccounts.map((tokenAccount) => tokenAccount.account.mint) + ) + + // WSOL must be in the mintsPks array + // WSOL is used as mint for sol accounts to calculate amounts + if (!mintsPks.some((x) => x.toBase58() === WSOL_MINT)) { mintsPks.push(new PublicKey(WSOL_MINT)) } - const mintAccounts = mintsPks.length - ? await getMintAccountsInfo(connection, [...mintsPks]) - : [] - const nativeSolAddresses = await Promise.all( - governances.map((x) => getNativeTreasuryAddress(realm.owner, x!.pubkey)) - ) - const govNativeSolAddress = nativeSolAddresses.map((x, index) => { - return { - governanceAcc: governances[index], - governancePk: governances[index].pubkey, - nativeSolAddress: x, - } - }) - const solAccs = await getSolAccountsInfo(connection, govNativeSolAddress) + + const govNativeSolAddress = governances.map((x) => ({ + governanceAcc: x, + governancePk: x.pubkey, + nativeSolAddress: x.nativeTreasuryAddress, + })) + + const [solAccountsInfo, mintAccounts] = await Promise.all([ + getSolAccountsInfo(connection, govNativeSolAddress), + getMintAccountsInfo(connection, mintsPks), + ]) for (const tokenAccount of tokenAccounts) { let governance = governances.find( (x) => x.pubkey.toBase58() === tokenAccount.account.owner.toBase58() ) - const nativeSolAddress = nativeSolAddresses.find((x) => - x.equals(tokenAccount.account.owner) - ) + const nativeSolAddress = govNativeSolAddress.find((x) => + x.nativeSolAddress.equals(tokenAccount.account.owner) + )?.nativeSolAddress if (!governance && nativeSolAddress) { governance = govNativeSolAddress.find((x) => @@ -261,29 +414,31 @@ const getTokenAssetAccounts = async ( const mint = mintAccounts.find( (x) => x.publicKey.toBase58() === tokenAccount.account.mint.toBase58() ) - const account = new AccountTypeAuxiliaryToken(tokenAccount, mint) - if (account) { - accounts.push(account) + + if (mint) { + const account = new AccountTypeAuxiliaryToken(tokenAccount, mint) + + if (account) { + accounts.push(account) + } } } } + const solAccounts = await getSolAccountsObj( connection, accounts, - solAccs, + solAccountsInfo, mintAccounts, governances ) - if (solAccounts.length) { - accounts.push(...solAccounts) - } - return accounts + return [...accounts, ...solAccounts] } const getMintAccounts = ( - mintGovernances: ProgramAccount[], - mintGovernancesMintInfo: (AccountInfoGeneric | null)[] + mintGovernances: GovernanceProgramAccountWithNativeTreasuryAddress[], + mintGovernancesMintInfo: (MintInfo & { publicKey: PublicKey })[] ) => { const accounts: AccountTypeMint[] = [] mintGovernancesMintInfo.forEach((mintAccountInfo, index) => { @@ -293,9 +448,7 @@ const getMintAccounts = ( `Missing mintAccountInfo for: ${mintGovernnace?.pubkey.toBase58()}` ) } - const data = Buffer.from(mintAccountInfo.data) - const parsedMintInfo = parseMintAccountData(data) as MintInfo - const account = new AccountTypeMint(mintGovernnace!, parsedMintInfo) + const account = new AccountTypeMint(mintGovernnace!, mintAccountInfo) if (account) { accounts.push(account) } @@ -303,319 +456,668 @@ const getMintAccounts = ( return accounts } -const getProgramAssetAccounts = ( - programGovernances: ProgramAccount[] -) => { - const accounts: AccountTypeProgram[] = [] - programGovernances.forEach((programGov) => { - const account = new AccountTypeProgram(programGov!) - if (account) { - accounts.push(account) - } - }) - return accounts -} +const getProgramAssetAccounts = async ( + connection: ConnectionContext, + governancesArray: GovernanceProgramAccountWithNativeTreasuryAddress[] +): Promise => { + const possibleOwnersPk = [ + ...governancesArray.map((x) => x.nativeTreasuryAddress), + ...governancesArray + .filter( + (x) => + x.account.accountType === GovernanceAccountType.ProgramGovernanceV1 || + x.account.accountType === GovernanceAccountType.ProgramGovernanceV2 + ) + .map((x) => x.pubkey), + ] -const getGenericAssetAccounts = ( - genericGovernances: ProgramAccount[] -) => { - const accounts: AccountTypeGeneric[] = [] - genericGovernances.forEach((programGov) => { - const account = new AccountTypeGeneric(programGov) - if (account) { - accounts.push(account) - } - }) - return accounts + const programs = await getProgramAccountInfo(connection, possibleOwnersPk) + + return programs.map( + (program) => + new AccountTypeProgram( + governancesArray.find( + (x) => + x.pubkey.equals(program.owner) || + x.nativeTreasuryAddress.equals(program.owner) + )!, + program.programId, + program.owner + ) + ) } -const getGovernancesByAccountTypes = ( - governancesArray: ProgramAccount[], - types: GovernanceAccountType[] -) => { - const governancesFiltered = governancesArray.filter((gov) => - types.some((t) => gov.account?.accountType === t) +const getGenericAssetAccounts = ( + genericGovernances: GovernanceProgramAccountWithNativeTreasuryAddress[] +): AccountTypeGeneric[] => { + return genericGovernances.map( + (programGov) => new AccountTypeGeneric(programGov) ) - return governancesFiltered } const getSolAccountObj = async ( - governance: ProgramAccount, + governance: GovernanceProgramAccountWithNativeTreasuryAddress, connection: ConnectionContext, mint: TokenProgramAccount, accounts: AssetAccount[], - solAcc: SolAccInfo -) => { - if (solAcc.acc) { - const tokenAccountsOwnedBySolAccountInfo = await connection.current.getTokenAccountsByOwner( - solAcc.nativeSolAddress, - { - programId: TOKEN_PROGRAM_ID, - } - ) - const tokenAccountsOwnedBySolAccounts = tokenAccountsOwnedBySolAccountInfo.value.map( - (x) => { - const publicKey = x.pubkey - const data = Buffer.from(x.account.data) - const account = parseTokenAccountData(publicKey, data) - return { publicKey, account } - } - ) - const groups = group(tokenAccountsOwnedBySolAccounts) - const results = await Promise.all( + { acc, nativeSolAddress }: SolAccInfo +): Promise => { + if (!acc) { + return null + } + + const tokenAccountsOwnedBySolAccountInfo = await connection.current.getTokenAccountsByOwner( + nativeSolAddress, + { + programId: TOKEN_PROGRAM_ID, + } + ) + + const tokenAccountsOwnedBySolAccounts = tokenAccountsOwnedBySolAccountInfo.value.map( + ({ pubkey: publicKey, account: { data: encodedData } }) => { + const data = Buffer.from(encodedData) + const account = parseTokenAccountData(publicKey, data) + return { publicKey, account } + } + ) + + const groups = group(tokenAccountsOwnedBySolAccounts) + + const mintAccounts = ( + await Promise.all( groups.map((group) => { - if (group.length) { - return getMintAccountsInfo( - connection, - group.map((x) => x.account.mint) - ) - } else { + if (!group.length) { return [] } + + return getMintAccountsInfo( + connection, + group.map((x) => x.account.mint) + ) }) ) + ).flat() - const mintAccounts = results.flat() + for (const acc of tokenAccountsOwnedBySolAccounts) { + const account = await getTokenAccountObj(governance, acc, mintAccounts) - for (const acc of tokenAccountsOwnedBySolAccounts) { - const account = await getTokenAccountObj(governance, acc, mintAccounts) - if (account) { - accounts.push(account) - } + if (account) { + accounts.push(account) } - const minRentAmount = await connection.current.getMinimumBalanceForRentExemption( - 0 - ) - const solAccount = solAcc.acc as AccountInfoGen - solAccount.lamports = - solAccount.lamports !== 0 - ? solAccount.lamports - minRentAmount - : solAccount.lamports - - return new AccountTypeSol( - mint!, - solAcc.nativeSolAddress, - solAccount, - governance - ) } + + const minRentAmount = await connection.current.getMinimumBalanceForRentExemption( + 0 + ) + + const solAccount = acc as AccountInfoGen + + solAccount.lamports = + solAccount.lamports !== 0 + ? solAccount.lamports - minRentAmount + : solAccount.lamports + + return new AccountTypeSol(mint, nativeSolAddress, solAccount, governance) } -const getAccountsForGovernances = async ( - connection: ConnectionContext, - realm: ProgramAccount, - governancesArray: ProgramAccount[] -) => { - const mintGovernances = getGovernancesByAccountTypes(governancesArray, [ - GovernanceAccountType.MintGovernanceV1, - GovernanceAccountType.MintGovernanceV2, - ]) - const programGovernances = getGovernancesByAccountTypes(governancesArray, [ - GovernanceAccountType.ProgramGovernanceV1, - GovernanceAccountType.ProgramGovernanceV2, - ]) +const filterOutHiddenAccounts = (x: AssetAccount) => { + const pubkey = typeof x.pubkey === 'string' ? x.pubkey : x.pubkey.toBase58() + return ( + HIDDEN_TREASURES.findIndex((x) => x === pubkey) === -1 && + (!x.extensions.token || + !x.extensions.token?.account.isFrozen || + x.type !== AccountType.GENERIC) + ) +} + +// Return array without duplicates +const uniqueGovernedTokenAccounts = ( + assetAccounts: AssetAccount[] +): AssetAccount[] => { + const existing = new Set() + const deduped: AssetAccount[] = [] - const genericGovernances = getGenericAssetAccounts(governancesArray) + for (const account of assetAccounts) { + if (!existing.has(account.pubkey.toBase58())) { + existing.add(account.pubkey.toBase58()) + deduped.push(account) + } + } - const mintGovernancesMintInfo = await getMultipleAccountInfoChunked( - connection.current, - mintGovernances.map((x) => x.account.governedAccount) + return deduped +} + +const getMintAccountsInfo = async ( + { endpoint, current: { commitment } }: ConnectionContext, + publicKeys: PublicKey[] +): Promise[]> => { + const { data: mintAccountsJson } = await axios.post( + endpoint, + publicKeys.map((pubkey) => { + const id = pubkey.toBase58() + + return { + jsonrpc: '2.0', + id, + method: 'getAccountInfo', + params: [ + id, + { + commitment, + encoding: 'base64', + }, + ], + } + }) ) - const mintAccounts = getMintAccounts(mintGovernances, mintGovernancesMintInfo) - const programAccounts = getProgramAssetAccounts(programGovernances) - const auxiliaryTokenAccounts = AUXILIARY_TOKEN_ACCOUNTS[realm.account.name] - ?.length - ? AUXILIARY_TOKEN_ACCOUNTS[realm.account.name] - : [] - const nativeAccountAddresses = await Promise.all( - governancesArray.map((governance) => - getNativeTreasuryAddress(governance.owner, governance.pubkey) + if (!mintAccountsJson) { + throw new Error( + `Cannot load information about mint accounts ${publicKeys.map((x) => + x.toBase58() + )}` ) - ) + } - const fetchTokenAccounts = (addresses: string[]) => - axios.request({ - url: connection.endpoint, - method: 'POST', - headers: { - 'Content-Type': 'application/json', + return mintAccountsJson.map( + ({ + result: { + value: { + data: [encodedData], + }, }, - data: JSON.stringify( - addresses.map((address) => ({ - jsonrpc: '2.0', - id: 1, - method: 'getProgramAccounts', - params: [ - TOKEN_PROGRAM_ID.toBase58(), + id, + }) => { + const publicKey = new PublicKey(id) + const data = Buffer.from(encodedData, 'base64') + const account = parseMintAccountData(data) + return { publicKey, account } + } + ) +} + +const getTokenAccountsInfo = async ( + { endpoint, current: { commitment } }: ConnectionContext, + publicKeys: PublicKey[] +): Promise[]> => { + const { data: tokenAccountsInfoJson } = await axios.post< + unknown, + { + data: { + result: { + account: { + data: [string, 'base64'] + } + pubkey: string + }[] + }[] + } + >( + endpoint, + publicKeys.map((publicKey) => ({ + jsonrpc: '2.0', + id: 1, + method: 'getProgramAccounts', + params: [ + TOKEN_PROGRAM_ID.toBase58(), + { + commitment, + encoding: 'base64', + filters: [ { - commitment: connection.current.commitment, - encoding: 'base64', - filters: [ - { - dataSize: TokenAccountLayout.span, // number of bytes - }, - { - memcmp: { - offset: tokenAccountOwnerOffset, // number of bytes - bytes: address, // base58 encoded string - }, - }, - ], + // number of bytes + dataSize: 165, + }, + { + memcmp: { + // number of bytes + offset: tokenAccountOwnerOffset, + bytes: publicKey.toBase58(), + }, }, ], - })) - ), - }) + }, + ], + })) + ) - const ownedByGovernancesTokenAccounts = await Promise.all([ - fetchTokenAccounts(nativeAccountAddresses.map((a) => a.toBase58())), - fetchTokenAccounts(governancesArray.map((g) => g.pubkey.toBase58())), - auxiliaryTokenAccounts?.length - ? fetchTokenAccounts(auxiliaryTokenAccounts.map((x) => x.owner)) - : Promise.resolve({ data: [] }), - ]).then(([x, y, z]) => x.data.concat(y.data).concat(z.data)) - - const tokenAccountsJson = ownedByGovernancesTokenAccounts.map((x) => { - const auxiliaryMatch = auxiliaryTokenAccounts.find( - (auxAcc) => auxAcc.owner === x.id + if (!tokenAccountsInfoJson) { + throw new Error( + `Cannot load information about token accounts ${publicKeys.map((x) => + x.toBase58() + )}` ) - if (auxiliaryMatch) { - x.result = x.result?.filter((x) => - auxiliaryMatch.accounts.includes(x.pubkey) - ) - } - return x - }) - const tokenAccountsParsed = tokenAccountsJson.length - ? [...tokenAccountsJson.flatMap((x) => x.result)].map((x) => { - const publicKey = new PublicKey(x.pubkey) - const data = Buffer.from(x.account.data[0], 'base64') + } + + return tokenAccountsInfoJson.reduce((tokenAccountsInfo, { result }) => { + result.forEach( + ({ + account: { + data: [encodedData], + }, + pubkey, + }) => { + const publicKey = new PublicKey(pubkey) + const data = Buffer.from(encodedData, 'base64') const account = parseTokenAccountData(publicKey, data) - return { publicKey, account } - }) - : [] + tokenAccountsInfo.push({ publicKey, account }) + } + ) - const groups = group(tokenAccountsParsed) - const results = await Promise.all( - groups.map((group) => { - return getTokenAssetAccounts(group, governancesArray, realm, connection) - }) + return tokenAccountsInfo + }, [] as TokenProgramAccount[]) +} + +const getSolAccountsInfo = async ( + connection: ConnectionContext, + publicKeys: { governancePk: PublicKey; nativeSolAddress: PublicKey }[] +): Promise => { + const { data: solAccountsJson } = await axios.post< + unknown, + { + data: { + result: { + value: null | { + data: [string, 'base64'] + } + } + }[] + } + >( + connection.endpoint, + publicKeys.map((x) => ({ + jsonrpc: '2.0', + id: 1, + method: 'getAccountInfo', + params: [ + x.nativeSolAddress.toBase58(), + { + commitment: connection.current.commitment, + encoding: 'jsonParsed', + }, + ], + })) ) - const allResults = results.flat() - // remove potential duplicates - const existing = new Set() - const deduped: AssetAccount[] = [] + if (!solAccountsJson.length) { + return [] + } - for (const account of allResults) { - if (!existing.has(account.pubkey.toBase58())) { - existing.add(account.pubkey.toBase58()) - deduped.push(account) + return ( + solAccountsJson + .flatMap(({ result: { value } }, index: number) => { + return { + acc: value, + ...publicKeys[index], + } + }) + // Remove null values + .filter(({ acc }) => acc) + ) +} + +const loadMintGovernanceAccounts = async ( + connection: ConnectionContext, + governances: GovernanceProgramAccountWithNativeTreasuryAddress[], + possibleMintAccountPks: PublicKey[] +) => { + const nativeAccountAddresses = governances.map((x) => x.nativeTreasuryAddress) + const possibleMintAccounts = await getMultipleAccountInfoChunked( + connection.current, + possibleMintAccountPks + ) + const mintGovernances: GovernanceProgramAccountWithNativeTreasuryAddress[] = [] + const mintAccounts: (MintInfo & { publicKey: PublicKey })[] = [] + for (const index in possibleMintAccounts) { + const possibleMintAccount = possibleMintAccounts[index] + const pk = possibleMintAccountPks[index] + if (possibleMintAccount) { + const data = Buffer.from(possibleMintAccount.data) + const parsedMintInfo = parseMintAccountData(data) as MintInfo + const ownerGovernance = governances.find( + (g) => + parsedMintInfo?.mintAuthority && + g.pubkey.equals(parsedMintInfo.mintAuthority) + ) + const solAccountPk = nativeAccountAddresses.find( + (x) => + parsedMintInfo?.mintAuthority && + x.equals(parsedMintInfo.mintAuthority) + ) + if (ownerGovernance || solAccountPk) { + mintGovernances.push( + solAccountPk + ? governances[ + nativeAccountAddresses.findIndex((x) => x.equals(solAccountPk)) + ] + : ownerGovernance! + ) + mintAccounts.push({ ...parsedMintInfo, publicKey: pk }) + } } } + return getMintAccounts(mintGovernances, mintAccounts) +} + +const loadGovernedTokenAccounts = async ( + connection: ConnectionContext, + realm: ProgramAccount, + governancesArray: GovernanceProgramAccountWithNativeTreasuryAddress[] +): Promise => { + console.log('loadGovernedTokenAccounts has been called') + const auxiliaryTokenAccounts: typeof AUXILIARY_TOKEN_ACCOUNTS[keyof typeof AUXILIARY_TOKEN_ACCOUNTS] = AUXILIARY_TOKEN_ACCOUNTS[ + realm.account.name + ]?.length + ? AUXILIARY_TOKEN_ACCOUNTS[realm.account.name] + : [] + + const tokenAccountsOwnedByGovernances = uniquePublicKey([ + ...governancesArray.map((x) => x.nativeTreasuryAddress), + ...governancesArray.map((g) => g.pubkey), + ...auxiliaryTokenAccounts.map((x) => new PublicKey(x.owner)), + ]) + + const tokenAccountsInfo = ( + await Promise.all( + // Load infos in batch, cannot load 9999 accounts within one request + group(tokenAccountsOwnedByGovernances, 100).map((group) => + getTokenAccountsInfo(connection, group) + ) + ) + ).flat() - const tokenAssetAccounts = deduped + const governedTokenAccounts = ( + await Promise.all( + // Load infos in batch, cannot load 9999 accounts within one request + group(tokenAccountsInfo).map((group) => + getTokenAssetAccounts(group, governancesArray, connection) + ) + ) + ).flat() + + // Remove potential accounts duplicate + return uniqueGovernedTokenAccounts(governedTokenAccounts) +} - const governedTokenAccounts = tokenAssetAccounts - await tokenService.fetchTokenPrices( - governedTokenAccounts - .filter((x) => x.extensions.mint?.publicKey) - .map((x) => x.extensions.mint!.publicKey.toBase58()) +const loadStakeAccounts = async ( + connection: ConnectionContext, + solAccounts: AssetAccount[] +) => { + const accountsNotYetStaked = await Promise.all( + solAccounts.map((x) => + getFilteredProgramAccounts(connection.current, StakeProgram.programId, [ + { + memcmp: { + offset: 0, + bytes: bs58.encode([1, 0, 0, 0]), + }, + }, + { + memcmp: { + offset: 44, + bytes: x.extensions.transferAddress, + }, + }, + ]) + ) + ) + const accountsStaked = await Promise.all( + solAccounts.map((x) => + getFilteredProgramAccounts(connection.current, StakeProgram.programId, [ + { + memcmp: { + offset: 0, + bytes: bs58.encode([2, 0, 0, 0]), + }, + }, + { + memcmp: { + offset: 44, + bytes: x.extensions.transferAddress, + }, + }, + ]) + ) + ) + const accountsNotYetStakedMapped = accountsNotYetStaked.flatMap((x, idx) => + x.map((stake) => ({ ...stake, governance: solAccounts[idx].governance })) + ) + const accountsStakedMapped = accountsStaked.flatMap((x, idx) => + x.map((stake) => ({ ...stake, governance: solAccounts[idx].governance })) ) + return [ + ...accountsNotYetStakedMapped.map( + (x) => + new AccountTypeStake( + x.governance, + x.publicKey, + StakeState.Inactive, + null, + x.accountInfo.lamports / LAMPORTS_PER_SOL + ) + ), + ...accountsStakedMapped.map( + (x) => + new AccountTypeStake( + x.governance, + x.publicKey, + StakeState.Active, + PublicKey.decode(x.accountInfo.data.slice(124, 124 + 32)), + x.accountInfo.lamports / LAMPORTS_PER_SOL + ) + ), + ] +} + +const getAccountsForGovernances = async ( + connection: ConnectionContext, + realm: ProgramAccount, + governancesArray: ProgramAccount[] +): Promise< + (AccountTypeMint | AccountTypeProgram | AssetAccount | AccountTypeGeneric)[] +> => { + const nativeAddresses = await Promise.all([ + ...governancesArray.map((x) => + getNativeTreasuryAddress(realm.owner, x.pubkey) + ), + ]) + const governancesWithNativeTreasuryAddress = governancesArray.map( + (x, index) => ({ + ...x, + nativeTreasuryAddress: nativeAddresses[index], + }) + ) + //due to long request for mint accounts that are owned by every governance + //we fetch + const possibleMintAccountPks = [ + realm.account.communityMint, + realm.account.config.councilMint, + ].filter((x) => typeof x !== 'undefined') as PublicKey[] + + const additionalMintAccounts = + additionalPossibleMintAccounts[realm.account.name] + if (additionalMintAccounts) { + possibleMintAccountPks.push(...additionalMintAccounts) + } + // 1 - Load accounts related to program governances + // 2 - Load token accounts behind any type of governance + // 3 - Load accounts related to mint + const [ + programAccounts, + governedTokenAccounts, + mintAccounts, + ] = await Promise.all([ + getProgramAssetAccounts(connection, governancesWithNativeTreasuryAddress), + loadGovernedTokenAccounts( + connection, + realm, + governancesWithNativeTreasuryAddress + ), + loadMintGovernanceAccounts( + connection, + governancesWithNativeTreasuryAddress, + possibleMintAccountPks + ), + ]) + + // 4 - Call to fetch token prices for every token account's mints + await tokenPriceService.fetchTokenPrices( + governedTokenAccounts.reduce((mints, governedTokenAccount) => { + if (!governedTokenAccount.extensions.mint?.publicKey) { + return mints + } + + return [ + ...mints, + governedTokenAccount.extensions.mint.publicKey.toBase58(), + ] + }, [] as string[]) + ) + + const accounts = [ ...mintAccounts, ...programAccounts, ...governedTokenAccounts, - ...genericGovernances, ] + + // 5 - Create generic asset accounts for governance's governedAccounts that have not been handled yet + // We do this so theses accounts may be selected + const genericGovernances = getGenericAssetAccounts( + governancesWithNativeTreasuryAddress.filter( + (governance) => + !accounts.some((account) => + account.pubkey.equals(governance.account.governedAccount) + ) + ) + ) + + return [...accounts, ...genericGovernances] } -const getMintAccountsInfo = async ( - connection: ConnectionContext, - pubkeys: PublicKey[] -) => { - const mintAccountsInfo = await axios.request({ - url: connection.endpoint, - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - data: JSON.stringify([ - ...pubkeys.map((x) => { - return { - jsonrpc: '2.0', - id: x.toBase58(), - method: 'getAccountInfo', - params: [ - x.toBase58(), - { - commitment: connection.current.commitment, - encoding: 'base64', +// TODO BATCH ALERT +// Solution: I cant tell what this is doing. it should probably be murdered. +const getProgramAccountInfo = async ( + { endpoint, current }: ConnectionContext, + publicKeys: PublicKey[] +): Promise<{ owner: PublicKey; programId: PublicKey }[]> => { + let result: { owner: PublicKey; programId: PublicKey }[] = [] + try { + const { data: executableAccountInfoJson } = await axios.post< + unknown, + { + data: { + result: { + account: { + data: [string, 'base64'] + } + pubkey: string + }[] + id: string + }[] + } + >( + endpoint, + publicKeys.map((publicKey) => ({ + jsonrpc: '2.0', + id: publicKey.toBase58(), + method: 'getProgramAccounts', + params: [ + 'BPFLoaderUpgradeab1e11111111111111111111111', + { + commitment: current.commitment, + encoding: 'base64', + filters: [ + { + memcmp: { + offset: programAccountOwnerOffset, + bytes: publicKey.toBase58(), + }, + }, + ], + dataSlice: { + offset: 0, + length: 0, }, - ], - } - }), - ]), - }) - const mintAccountsJson = mintAccountsInfo.data - const mintAccountsParsed = mintAccountsJson?.map((x) => { - const result = x.result - const publicKey = new PublicKey(x.id) - const data = Buffer.from(result.value.data[0], 'base64') - const account = parseMintAccountData(data) - return { publicKey, account } - }) - return mintAccountsParsed -} + }, + ], + })) + ) + if (executableAccountInfoJson && executableAccountInfoJson.length) { + const executableDataPks = executableAccountInfoJson.reduce( + (executableAccountInfo, { result, id }) => { + result.forEach(({ pubkey }) => { + const executableDataPk = new PublicKey(pubkey) + executableAccountInfo.push({ + executableDataPk: executableDataPk, + owner: new PublicKey(id), + }) + }) -const getSolAccountsInfo = async ( - connection: ConnectionContext, - pubkeys: { governancePk: PublicKey; nativeSolAddress: PublicKey }[] -) => { - const solAccountsInfo = await axios.request({ - url: connection.endpoint, - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - data: JSON.stringify([ - ...pubkeys.map((x) => { - return { - jsonrpc: '2.0', - id: 1, - method: 'getAccountInfo', - params: [ - x.nativeSolAddress.toBase58(), - { - commitment: connection.current.commitment, - encoding: 'jsonParsed', + return executableAccountInfo + }, + [] as { owner: PublicKey; executableDataPk: PublicKey }[] + ) + if (executableDataPks.length) { + const { data: programAccountInfoJson } = await axios.post< + unknown, + { + data: { + result: { + account: { + data: [string, 'base64'] + } + pubkey: string + }[] + id: string + }[] + } + >( + endpoint, + executableDataPks.map((obj) => ({ + jsonrpc: '2.0', + id: obj.owner, + method: 'getProgramAccounts', + params: [ + 'BPFLoaderUpgradeab1e11111111111111111111111', + { + commitment: current.commitment, + encoding: 'base64', + filters: [ + { + memcmp: { + offset: 4, + bytes: obj.executableDataPk.toBase58(), + }, + }, + ], + dataSlice: { + offset: 0, + length: 0, + }, + }, + ], + })) + ) + if (programAccountInfoJson && programAccountInfoJson.length) { + const programDataPks = programAccountInfoJson.reduce( + (programAccountInfo, { result, id }) => { + result.forEach(({ pubkey }) => { + const programId = new PublicKey(pubkey) + programAccountInfo.push({ programId, owner: new PublicKey(id) }) + }) + + return programAccountInfo }, - ], + [] as { owner: PublicKey; programId: PublicKey }[] + ) + result = programDataPks } - }), - ]), - }) - const solAccountsJson = solAccountsInfo.data - const solAccountsParsed = solAccountsJson?.length - ? solAccountsJson - .flatMap((x, index) => { - return { - acc: x.result.value, - ...pubkeys[index], - } - }) - .filter((x) => x.acc) - : [] - return solAccountsParsed as SolAccInfo[] -} + } + } + } catch (e) { + console.log('unable to fetch programs owned by DAO', e) + } -const filterOutHiddenAccs = (x: AssetAccount) => { - const pubkey = typeof x.pubkey === 'string' ? x.pubkey : x.pubkey.toBase58() - return ( - HIDDEN_TREASURES.findIndex((x) => x === pubkey) === -1 && - (!x.extensions.token || - !x.extensions.token?.account.isFrozen || - x.type !== AccountType.GENERIC) - ) + return result } diff --git a/stores/useMembersStore.tsx b/stores/useMembersStore.tsx deleted file mode 100644 index 7a7e63e57d..0000000000 --- a/stores/useMembersStore.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import create, { State } from 'zustand' -import { ViewState } from '@components/Members/types' -import { Member, Delegates } from '@utils/uiTypes/members' - -interface MembersStore extends State { - compact: { - currentView: ViewState - currentMember: Member | null - members: Member[] - activeMembers: Member[] - delegates: Delegates | null - } - setCurrentCompactViewMember: (item: Member) => void - setCurrentCompactView: (viewState: ViewState) => void - resetCompactViewState: () => void - setMembers: (members: Member[]) => void - setDelegates: (delegates: Delegates) => void -} - -const compactDefaultState = { - currentView: ViewState.MainView, - currentMember: null, - members: [], - activeMembers: [], - delegates: null, -} - -const useMembersStore = create((set, _get) => ({ - compact: { - ...compactDefaultState, - }, - setCurrentCompactViewMember: (item) => { - set((s) => { - s.compact.currentMember = item - }) - }, - setCurrentCompactView: (viewState) => { - set((s) => { - s.compact.currentView = viewState - }) - }, - resetCompactViewState: () => { - set((s) => { - s.compact = { ...compactDefaultState } - }) - }, - setMembers: (members: Member[]) => { - const activeMembers: Member[] = members.filter( - (x) => !x.councilVotes.isZero() || !x.communityVotes.isZero() - ) - set((s) => { - s.compact.members = members - s.compact.activeMembers = activeMembers - }) - }, - setDelegates: (delegates: Delegates) => { - set((s) => { - s.compact.delegates = delegates - }) - }, -})) - -export default useMembersStore diff --git a/stores/useNotificationStore.tsx b/stores/useNotificationStore.tsx index a4a891d399..e81de5fb6e 100644 --- a/stores/useNotificationStore.tsx +++ b/stores/useNotificationStore.tsx @@ -10,13 +10,6 @@ interface NotificationStore extends State { txid?: string }> set: (x: any) => void - modalState: ModalStates -} - -export enum ModalStates { - Selection = 1, - Dialect = 2, - Notifi = 3, } const useNotificationStore = create( @@ -24,7 +17,6 @@ const useNotificationStore = create( (set, _get) => ({ notifications: [], set: (fn) => set(produce(fn)), - modalState: ModalStates.Selection, }), { name: 'notifications', diff --git a/stores/useSelectedDelegatorStore.tsx b/stores/useSelectedDelegatorStore.tsx new file mode 100644 index 0000000000..6417be84e7 --- /dev/null +++ b/stores/useSelectedDelegatorStore.tsx @@ -0,0 +1,16 @@ +import { PublicKey } from '@solana/web3.js' +import create from 'zustand' + +type Store = { + communityDelegator?: PublicKey + councilDelegator?: PublicKey + setCommunityDelegator: (x?: PublicKey) => void + setCouncilDelegator: (x?: PublicKey) => void +} + +export const useSelectedDelegatorStore = create((set, _get) => ({ + communityDelegator: undefined, + councilDelegator: undefined, + setCommunityDelegator: (x) => set({ communityDelegator: x }), + setCouncilDelegator: (x) => set({ councilDelegator: x }), +})) diff --git a/stores/useSerumGovStore.tsx b/stores/useSerumGovStore.tsx new file mode 100644 index 0000000000..45166a6f5f --- /dev/null +++ b/stores/useSerumGovStore.tsx @@ -0,0 +1,1379 @@ +import { getAssociatedTokenAddress } from '@blockworks-foundation/mango-v4' +import * as anchor from '@coral-xyz/anchor' +import { TOKEN_PROGRAM_ID } from '@solana/spl-token' +import { + Connection, + PublicKey, + SystemProgram, + SYSVAR_CLOCK_PUBKEY, + TokenAmount, + Transaction, + TransactionInstruction, +} from '@solana/web3.js' +import { createAssociatedTokenAccount } from '@utils/associated' +import { notify } from '@utils/notifications' +import { sendTransaction } from '@utils/send' +import { WalletSigner } from '@utils/sendTransactions' +import produce from 'immer' +import create, { State } from 'zustand' +import IDL from '../idls/serum_gov.json' + +export type ConfigAccountType = { + configAuthority: PublicKey + claimDelay: anchor.BN + redeemDelay: anchor.BN + cliffPeriod: anchor.BN + linearVestingPeriod: anchor.BN +} + +export type ClaimTicketType = { + address: PublicKey + owner: PublicKey + depositAccount: PublicKey + gsrmAmount: anchor.BN + claimDelay: number + createdAt: number +} + +export type RedeemTicketType = { + address: PublicKey + owner: PublicKey + depositAccount: PublicKey + redeemIndex: number + amount: anchor.BN + isMsrm: boolean + redeemDelay: number + createdAt: number +} + +export type UserAccountType = { + address: PublicKey + owner: PublicKey + lockIndex: number + vestIndex: number +} + +export type LockedAccountType = { + address: PublicKey + owner: PublicKey + lockIndex: number + redeemIndex: number + createdAt: number + isMsrm: boolean + totalGsrmAmount: anchor.BN + gsrmBurned: anchor.BN +} + +export type VestAccountType = { + address: PublicKey + owner: PublicKey + isMsrm: PublicKey + vestIndex: number + redeemIndex: number + createdAt: number + cliffPeriod: number + linearVestingPeriod: number + totalGsrmAmount: anchor.BN + gsrmBurned: anchor.BN +} + +const DEV_PROGRAM_ID = new PublicKey( + 'EDV6BNBY6pLb4aCJCc5LnELdA9xTywnDZ2m3cWfCbpwZ' +) +const MAIN_PROGRAM_ID = new PublicKey( + 'FBcTbv5rLy7MQkkAU2uDzAEjjZDeu2BVLVRJGxyz6hnV' +) + +const DEV_SRM_MINT = new PublicKey( + '2xKASju8WCUK6zC54TP4h6WhHdqdcWMNoFpqAdvXvHV6' +) +const DEV_MSRM_MINT = new PublicKey( + 'BoFBTKtdMXC4YALXtNV5tmw1xNWtjxTrR17PvZGmKhmP' +) + +const MAIN_SRM_MINT = new PublicKey( + 'SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt' +) +const MAIN_MSRM_MINT = new PublicKey( + 'MSRMcoVyrFxnSgo5uXwone5SKcGhT1KEJMFEkMEWf9L' +) +const [DEV_GSRM_MINT] = PublicKey.findProgramAddressSync( + [Buffer.from('gSRM')], + DEV_PROGRAM_ID +) + +export const SRM_DECIMALS = 6 +export const MSRM_DECIMALS = 0 +export const MSRM_MULTIPLIER = 1_000_000_000_000 + +interface SerumGovStore extends State { + programId: PublicKey + gsrmMint: PublicKey + authority: PublicKey + config: PublicKey + srmMint: PublicKey + msrmMint: PublicKey + + set: (x: any) => void + actions: { + updateSerumGovAccounts: (cluster?: string) => void + getGsrmBalance: ( + connection: Connection, + owner?: PublicKey | null + ) => Promise + getConfigAccount: ( + provider: anchor.AnchorProvider + ) => Promise + getUserAccount: ( + provider: anchor.AnchorProvider, + owner?: PublicKey | null + ) => Promise + getClaimTickets: ( + provider: anchor.AnchorProvider, + owner?: PublicKey | null + ) => Promise + getRedeemTickets: ( + provider: anchor.AnchorProvider, + owner?: PublicKey | null + ) => Promise + getLockedAccounts: ( + provider: anchor.AnchorProvider, + owner?: PublicKey | null + ) => Promise + getVestAccounts: ( + provider: anchor.AnchorProvider, + owner?: PublicKey | null + ) => Promise + claim: ( + connection: Connection, + provider: anchor.AnchorProvider, + claimTicket: ClaimTicketType, + owner?: WalletSigner | null + ) => Promise + redeem: ( + connection: Connection, + provider: anchor.AnchorProvider, + redeemTicket: RedeemTicketType, + owner?: WalletSigner | null + ) => Promise + getClaimInstruction: ( + provider: anchor.AnchorProvider, + claimTicket: ClaimTicketType, + owner: PublicKey + ) => Promise + getRedeemInstruction: ( + provider: anchor.AnchorProvider, + redeemTicket: RedeemTicketType, + owner: PublicKey + ) => Promise + burnLockedGsrm: ( + connection: Connection, + provider: anchor.AnchorProvider, + lockedAccount: LockedAccountType, + amount: anchor.BN, + owner?: WalletSigner | null + ) => Promise + getBurnLockedGsrmInstruction: ( + provider: anchor.AnchorProvider, + lockedAccount: LockedAccountType, + amount: anchor.BN, + owner: PublicKey + ) => Promise + burnVestGsrm: ( + connection: Connection, + provider: anchor.AnchorProvider, + vestAccount: VestAccountType, + amount: anchor.BN, + owner?: WalletSigner | null + ) => Promise + getBurnVestGsrmInstruction: ( + provider: anchor.AnchorProvider, + vestAccount: VestAccountType, + amount: anchor.BN, + owner: PublicKey + ) => Promise + getInitUserInstruction: ( + owner: PublicKey, + payer: PublicKey, + provider: anchor.AnchorProvider + ) => Promise + getGrantLockedInstruction: ( + owner: PublicKey, + payer: PublicKey, + payerTokenAccount: PublicKey, + provider: anchor.AnchorProvider, + amount: anchor.BN, + isMsrm: boolean + ) => Promise + getGrantVestInstruction: ( + owner: PublicKey, + payer: PublicKey, + payerTokenAccount: PublicKey, + provider: anchor.AnchorProvider, + amount: anchor.BN, + isMsrm: boolean + ) => Promise + depositLocked: ( + connection: Connection, + provider: anchor.AnchorProvider, + amount: anchor.BN, + isMsrm: boolean, + owner?: WalletSigner | null + ) => Promise + getUpdateConfigParamInstruction: ( + provider: anchor.AnchorProvider, + configAuthority: PublicKey, + claimDelay: anchor.BN, + redeemDelay: anchor.BN, + cliffPeriod: anchor.BN, + linearVestingPeriod: anchor.BN + ) => Promise + getUpdateConfigAuthorityInstruction: ( + provider: anchor.AnchorProvider, + configAuthority: PublicKey, + newAuthority: PublicKey + ) => Promise + } +} + +const useSerumGovStore = create((set, get) => ({ + programId: DEV_PROGRAM_ID, + gsrmMint: DEV_GSRM_MINT, + authority: PublicKey.findProgramAddressSync( + [Buffer.from('authority')], + DEV_PROGRAM_ID + )[0], + config: PublicKey.findProgramAddressSync( + [Buffer.from('config')], + DEV_PROGRAM_ID + )[0], + srmMint: DEV_SRM_MINT, + msrmMint: DEV_MSRM_MINT, + + set: (fn) => set(produce(fn)), + actions: { + updateSerumGovAccounts: (cluster?: string) => { + const programId = cluster === 'devnet' ? DEV_PROGRAM_ID : MAIN_PROGRAM_ID + + const [gsrmMint] = PublicKey.findProgramAddressSync( + [Buffer.from('gSRM')], + programId + ) + const [config] = PublicKey.findProgramAddressSync( + [Buffer.from('config')], + programId + ) + const [authority] = PublicKey.findProgramAddressSync( + [Buffer.from('authority')], + programId + ) + const set = get().set + set((s) => { + s.programId = programId + s.gsrmMint = gsrmMint + s.config = config + s.authority = authority + s.srmMint = cluster === 'devnet' ? DEV_SRM_MINT : MAIN_SRM_MINT + s.msrmMint = cluster === 'devnet' ? DEV_MSRM_MINT : MAIN_MSRM_MINT + }) + }, + async getGsrmBalance( + connection: Connection, + owner?: PublicKey | null + ): Promise { + if (!owner) return null + + const gsrmMint = get().gsrmMint + + const ata = await getAssociatedTokenAddress(gsrmMint, owner, true) + try { + const tokenBalance = await connection.getTokenAccountBalance( + ata, + 'confirmed' + ) + return tokenBalance.value + } catch (e) { + console.error('Failed to get gSRM balance.', e) + return null + } + }, + + async getConfigAccount( + provider: anchor.AnchorProvider + ): Promise { + const config = get().config + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + try { + const configAccount = await program.account.config.fetch(config) + return { + configAuthority: configAccount.configAuthority as PublicKey, + claimDelay: configAccount.claimDelay as anchor.BN, + redeemDelay: configAccount.redeemDelay as anchor.BN, + cliffPeriod: configAccount.cliffPeriod as anchor.BN, + linearVestingPeriod: configAccount.linearVestingPeriod as anchor.BN, + } + } catch (e) { + console.log('Config account not found') + return null + } + }, + + async getUserAccount( + provider: anchor.AnchorProvider, + owner?: PublicKey | null + ): Promise { + if (!owner) return null + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + const [account] = PublicKey.findProgramAddressSync( + [Buffer.from('user'), owner.toBuffer()], + get().programId + ) + try { + const userAccount = await program.account.user.fetch(account) + return { + address: account, + owner: owner, + lockIndex: (userAccount.lockIndex as anchor.BN).toNumber(), + vestIndex: (userAccount.vestIndex as anchor.BN).toNumber(), + } + } catch (e) { + console.error('Failed to get user account', e) + return null + } + }, + + async getClaimTickets( + provider: anchor.AnchorProvider, + owner?: PublicKey | null + ): Promise { + if (!owner) return [] + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + try { + const tickets = await program.account.claimTicket.all([ + { + memcmp: { + offset: 8, + bytes: owner.toBase58(), + }, + }, + ]) + return tickets.map((t) => ({ + address: t.publicKey, + owner: (t.account as any).owner, + depositAccount: (t.account as any).depositAccount, + gsrmAmount: (t.account as any).gsrmAmount, + claimDelay: (t.account as any).claimDelay.toNumber(), + createdAt: (t.account as any).createdAt.toNumber(), + })) + } catch (e) { + console.error('Failed to get claim tickets', e) + return [] + } + }, + + async getRedeemTickets( + provider: anchor.AnchorProvider, + owner?: PublicKey | null + ): Promise { + if (!owner) return [] + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + const tickets = await program.account.redeemTicket.all([ + { + memcmp: { + offset: 8, + bytes: owner.toBase58(), + }, + }, + ]) + return tickets.map((t) => ({ + address: t.publicKey, + owner: (t.account as any).owner, + depositAccount: (t.account as any).depositAccount, + redeemIndex: (t.account as any).redeemIndex.toNumber(), + isMsrm: (t.account as any).isMsrm, + amount: (t.account as any).amount, + redeemDelay: (t.account as any).redeemDelay.toNumber(), + createdAt: (t.account as any).createdAt.toNumber(), + })) + }, + + async getLockedAccounts( + provider: anchor.AnchorProvider, + owner?: PublicKey | null + ): Promise { + if (!owner) return [] + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + + const accounts = await program.account.lockedAccount.all([ + { + memcmp: { + offset: 8, + bytes: owner.toBase58(), + }, + }, + ]) + return accounts.map((a) => ({ + address: a.publicKey, + owner: (a.account as any).owner, + lockIndex: (a.account as any).lockIndex.toNumber(), + redeemIndex: (a.account as any).redeemIndex.toNumber(), + createdAt: (a.account as any).createdAt.toNumber(), + isMsrm: (a.account as any).isMsrm, + totalGsrmAmount: (a.account as any).totalGsrmAmount, + gsrmBurned: (a.account as any).gsrmBurned, + })) + }, + + async getVestAccounts( + provider: anchor.AnchorProvider, + owner?: PublicKey | null + ): Promise { + if (!owner) return [] + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + + const accounts = await program.account.vestAccount.all([ + { + memcmp: { + offset: 8, + bytes: owner.toBase58(), + }, + }, + ]) + return accounts.map((a) => ({ + address: a.publicKey, + owner: (a.account as any).owner, + isMsrm: (a.account as any).isMsrm, + vestIndex: (a.account as any).vestIndex.toNumber(), + redeemIndex: (a.account as any).redeemIndex.toNumber(), + cliffPeriod: (a.account as any).cliffPeriod.toNumber(), + linearVestingPeriod: (a.account as any).linearVestingPeriod.toNumber(), + createdAt: (a.account as any).createdAt.toNumber(), + totalGsrmAmount: (a.account as any).totalGsrmAmount, + gsrmBurned: (a.account as any).gsrmBurned, + })) + }, + + async claim( + connection: Connection, + provider: anchor.AnchorProvider, + claimTicket: ClaimTicketType, + owner?: WalletSigner | null + ): Promise { + const gsrmMint = get().gsrmMint + + if (owner && owner.publicKey) { + try { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + const ownerGsrmAccount = await getAssociatedTokenAddress( + gsrmMint, + owner.publicKey, + true + ) + const instructions: TransactionInstruction[] = [] + try { + await connection.getTokenAccountBalance( + ownerGsrmAccount, + 'confirmed' + ) + } catch (e) { + const [ix] = await createAssociatedTokenAccount( + owner.publicKey, + owner.publicKey, + gsrmMint + ) + instructions.push(ix) + } + const ix = await program.methods + .claim() + .accounts({ + owner: owner.publicKey, + claimTicket: claimTicket.address, + authority: get().authority, + gsrmMint: gsrmMint, + ownerGsrmAccount: ownerGsrmAccount, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + instructions.push(ix) + + const tx = new Transaction().add(...instructions.map((i) => i)) + + await sendTransaction({ + transaction: tx, + wallet: owner, + connection, + }) + } catch (e) { + console.error(e) + notify({ type: 'error', message: 'Failed to claim ticket.' }) + } + } else { + notify({ type: 'error', message: 'Please connect wallet to claim.' }) + } + }, + + async redeem( + connection: Connection, + provider: anchor.AnchorProvider, + redeemTicket: RedeemTicketType, + owner?: WalletSigner | null + ): Promise { + if (owner && owner.publicKey) { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + try { + if (!redeemTicket.isMsrm) { + const ownerSrmAccount = await getAssociatedTokenAddress( + get().srmMint, + owner.publicKey, + true + ) + const instructions: TransactionInstruction[] = [] + try { + await connection.getTokenAccountBalance( + ownerSrmAccount, + 'confirmed' + ) + } catch (e) { + const [ix] = await createAssociatedTokenAccount( + owner.publicKey, + owner.publicKey, + get().srmMint + ) + instructions.push(ix) + } + const [srmVault] = PublicKey.findProgramAddressSync( + [Buffer.from('vault'), get().srmMint.toBuffer()], + program.programId + ) + const ix = await program.methods + .redeemSrm() + .accounts({ + owner: owner.publicKey, + authority: get().authority, + config: get().config, + redeemTicket: redeemTicket.address, + srmMint: get().srmMint, + srmVault, + ownerSrmAccount, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + + instructions.push(ix) + + const tx = new Transaction().add(...instructions.map((i) => i)) + await sendTransaction({ + transaction: tx, + wallet: owner, + connection, + }) + } else { + const ownerMsrmAccount = await getAssociatedTokenAddress( + get().msrmMint, + owner.publicKey, + true + ) + const instructions: TransactionInstruction[] = [] + try { + await connection.getTokenAccountBalance( + ownerMsrmAccount, + 'confirmed' + ) + } catch (e) { + const [ix] = await createAssociatedTokenAccount( + owner.publicKey, + owner.publicKey, + get().msrmMint + ) + instructions.push(ix) + } + const [msrmVault] = PublicKey.findProgramAddressSync( + [Buffer.from('vault'), get().msrmMint.toBuffer()], + program.programId + ) + const ix = await program.methods + .redeemMsrm() + .accounts({ + owner: owner.publicKey, + authority: get().authority, + config: get().config, + redeemTicket: redeemTicket.address, + msrmMint: get().msrmMint, + msrmVault, + ownerMsrmAccount, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + + instructions.push(ix) + + const tx = new Transaction().add(...instructions.map((i) => i)) + await sendTransaction({ + transaction: tx, + wallet: owner, + connection, + }) + } + } catch (e) { + console.error(e) + notify({ type: 'error', message: 'Failed to redeem ticket.' }) + } + } else { + notify({ type: 'error', message: 'Please connect wallet to claim.' }) + } + }, + + async getClaimInstruction( + provider: anchor.AnchorProvider, + claimTicket: ClaimTicketType, + owner: PublicKey + ): Promise { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + + const gsrmMint = get().gsrmMint + + const ownerGsrmAccount = await getAssociatedTokenAddress( + gsrmMint, + owner, + true + ) + const ix = await program.methods + .claim() + .accounts({ + owner: owner, + claimTicket: claimTicket.address, + authority: get().authority, + gsrmMint: gsrmMint, + ownerGsrmAccount: ownerGsrmAccount, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + return ix + }, + + async getRedeemInstruction( + provider: anchor.AnchorProvider, + redeemTicket: RedeemTicketType, + owner: PublicKey + ): Promise { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + let ix: TransactionInstruction + if (!redeemTicket.isMsrm) { + const ownerSrmAccount = await getAssociatedTokenAddress( + get().srmMint, + owner, + true + ) + const [srmVault] = PublicKey.findProgramAddressSync( + [Buffer.from('vault'), get().srmMint.toBuffer()], + program.programId + ) + ix = await program.methods + .redeemSrm() + .accounts({ + owner: owner, + authority: get().authority, + config: get().config, + redeemTicket: redeemTicket.address, + srmMint: get().srmMint, + srmVault, + ownerSrmAccount, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + } else { + const ownerMsrmAccount = await getAssociatedTokenAddress( + get().msrmMint, + owner, + true + ) + const [msrmVault] = PublicKey.findProgramAddressSync( + [Buffer.from('vault'), get().msrmMint.toBuffer()], + program.programId + ) + ix = await program.methods + .redeemMsrm() + .accounts({ + owner: owner, + authority: get().authority, + config: get().config, + redeemTicket: redeemTicket.address, + msrmMint: get().msrmMint, + msrmVault, + ownerMsrmAccount, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + } + + return ix + }, + + async burnLockedGsrm( + connection: Connection, + provider: anchor.AnchorProvider, + lockedAccount: LockedAccountType, + amount: anchor.BN, + owner?: WalletSigner | null + ): Promise { + const gsrmMint = get().gsrmMint + + if (owner && owner.publicKey) { + try { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + const ownerGsrmAccount = await getAssociatedTokenAddress( + gsrmMint, + owner.publicKey, + true + ) + const [redeemTicket] = PublicKey.findProgramAddressSync( + [ + Buffer.from('redeem_ticket'), + lockedAccount.address.toBuffer(), + new anchor.BN(lockedAccount.redeemIndex).toArrayLike( + Buffer, + 'le', + 8 + ), + ], + program.programId + ) + const tx = await program.methods + .burnLockedGsrm(amount) + .accounts({ + owner: owner.publicKey, + authority: get().authority, + config: get().config, + gsrmMint: gsrmMint, + ownerGsrmAccount: ownerGsrmAccount, + lockedAccount: lockedAccount.address, + redeemTicket: redeemTicket, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .transaction() + await sendTransaction({ + transaction: tx, + wallet: owner, + connection, + }) + } catch (e) { + console.error(e) + notify({ type: 'error', message: 'Failed to burn locked gSRM.' }) + } + } else { + notify({ type: 'error', message: 'Please connect wallet to claim.' }) + } + }, + + async getBurnLockedGsrmInstruction( + provider: anchor.AnchorProvider, + lockedAccount: LockedAccountType, + amount: anchor.BN, + owner: PublicKey + ): Promise { + const gsrmMint = get().gsrmMint + + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + const ownerGsrmAccount = await getAssociatedTokenAddress( + gsrmMint, + owner, + true + ) + const [redeemTicket] = PublicKey.findProgramAddressSync( + [ + Buffer.from('redeem_ticket'), + lockedAccount.address.toBuffer(), + new anchor.BN(lockedAccount.redeemIndex).toArrayLike(Buffer, 'le', 8), + ], + program.programId + ) + const ix = await program.methods + .burnLockedGsrm(amount) + .accounts({ + owner: owner, + authority: get().authority, + config: get().config, + gsrmMint: gsrmMint, + ownerGsrmAccount: ownerGsrmAccount, + lockedAccount: lockedAccount.address, + redeemTicket: redeemTicket, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + + return ix + }, + + async burnVestGsrm( + connection: Connection, + provider: anchor.AnchorProvider, + vestAccount: VestAccountType, + amount: anchor.BN, + owner?: WalletSigner | null + ): Promise { + const gsrmMint = get().gsrmMint + + if (owner && owner.publicKey) { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + const ownerGsrmAccount = await getAssociatedTokenAddress( + gsrmMint, + owner.publicKey, + true + ) + const [redeemTicket] = PublicKey.findProgramAddressSync( + [ + Buffer.from('redeem_ticket'), + vestAccount.address.toBuffer(), + new anchor.BN(vestAccount.redeemIndex).toArrayLike(Buffer, 'le', 8), + ], + program.programId + ) + const tx = await program.methods + .burnVestGsrm(amount) + .accounts({ + owner: owner.publicKey, + authority: get().authority, + config: get().config, + gsrmMint: gsrmMint, + ownerGsrmAccount, + vestAccount: vestAccount.address, + redeemTicket: redeemTicket, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .transaction() + + await sendTransaction({ + transaction: tx, + wallet: owner, + connection, + }) + } else { + notify({ type: 'error', message: 'Please connect wallet to claim.' }) + } + }, + + async getBurnVestGsrmInstruction( + provider: anchor.AnchorProvider, + vestAccount: VestAccountType, + amount: anchor.BN, + owner: PublicKey + ): Promise { + const gsrmMint = get().gsrmMint + + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + + const ownerGsrmAccount = await getAssociatedTokenAddress( + gsrmMint, + owner, + true + ) + + const [redeemTicket] = PublicKey.findProgramAddressSync( + [ + Buffer.from('redeem_ticket'), + vestAccount.address.toBuffer(), + new anchor.BN(vestAccount.redeemIndex).toArrayLike(Buffer, 'le', 8), + ], + program.programId + ) + + const ix = await program.methods + .burnVestGsrm(amount) + .accounts({ + owner: owner, + authority: get().authority, + config: get().config, + gsrmMint: gsrmMint, + ownerGsrmAccount, + vestAccount: vestAccount.address, + redeemTicket: redeemTicket, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + + return ix + }, + + async getInitUserInstruction( + owner: PublicKey, + payer: PublicKey, + provider: anchor.AnchorProvider + ): Promise { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + + const [ownerUserAccount] = PublicKey.findProgramAddressSync( + [Buffer.from('user'), owner.toBuffer()], + program.programId + ) + + const ix = await program.methods + .initUser(owner) + .accounts({ + payer, + userAccount: ownerUserAccount, + systemProgram: SystemProgram.programId, + }) + .instruction() + + return ix + }, + + async getGrantLockedInstruction( + owner: PublicKey, + payer: PublicKey, + payerTokenAccount: PublicKey, + provider: anchor.AnchorProvider, + amount: anchor.BN, + isMsrm: boolean + ): Promise { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + + const userAccount = await get().actions.getUserAccount(provider, owner) + // if (!userAccount) throw new Error('User account not found.') + + const [userAccountAddress] = PublicKey.findProgramAddressSync( + [Buffer.from('user'), owner.toBuffer()], + get().programId + ) + + const [lockedAccount] = PublicKey.findProgramAddressSync( + [ + Buffer.from('locked_account'), + owner.toBuffer(), + new anchor.BN(userAccount ? userAccount.lockIndex : 0).toArrayLike( + Buffer, + 'le', + 8 + ), + ], + program.programId + ) + + const [claimTicket] = PublicKey.findProgramAddressSync( + [Buffer.from('claim_ticket'), lockedAccount.toBuffer()], + program.programId + ) + + let ix: TransactionInstruction + if (!isMsrm) { + const [srmVault] = PublicKey.findProgramAddressSync( + [Buffer.from('vault'), get().srmMint.toBuffer()], + program.programId + ) + ix = await program.methods + .depositLockedSrm(amount) + .accounts({ + payer, + owner, + ownerUserAccount: userAccount + ? userAccount.address + : userAccountAddress, + srmMint: get().srmMint, + payerSrmAccount: payerTokenAccount, + authority: get().authority, + config: get().config, + srmVault, + lockedAccount, + claimTicket: claimTicket, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + } else { + const [msrmVault] = PublicKey.findProgramAddressSync( + [Buffer.from('vault'), get().msrmMint.toBuffer()], + program.programId + ) + ix = await program.methods + .depositLockedMsrm(amount) + .accounts({ + payer, + owner, + ownerUserAccount: userAccount + ? userAccount.address + : userAccountAddress, + msrmMint: get().msrmMint, + payerMsrmAccount: payerTokenAccount, + authority: get().authority, + config: get().config, + msrmVault, + lockedAccount, + claimTicket: claimTicket, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + } + + return ix + }, + + async getGrantVestInstruction( + owner: PublicKey, + payer: PublicKey, + payerTokenAccount: PublicKey, + provider: anchor.AnchorProvider, + amount: anchor.BN, + isMsrm: boolean + ): Promise { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + + const userAccount = await get().actions.getUserAccount(provider, owner) + + const [userAccountAddress] = PublicKey.findProgramAddressSync( + [Buffer.from('user'), owner.toBuffer()], + get().programId + ) + + const [vestAccount] = PublicKey.findProgramAddressSync( + [ + Buffer.from('vest_account'), + owner.toBuffer(), + new anchor.BN(userAccount ? userAccount.vestIndex : 0).toArrayLike( + Buffer, + 'le', + 8 + ), + ], + program.programId + ) + + const [claimTicket] = PublicKey.findProgramAddressSync( + [Buffer.from('claim_ticket'), vestAccount.toBuffer()], + program.programId + ) + + let ix: TransactionInstruction + + if (!isMsrm) { + const [srmVault] = PublicKey.findProgramAddressSync( + [Buffer.from('vault'), get().srmMint.toBuffer()], + program.programId + ) + + ix = await program.methods + .depositVestSrm(amount) + .accounts({ + payer, + owner, + ownerUserAccount: userAccount + ? userAccount.address + : userAccountAddress, + vestAccount, + claimTicket: claimTicket, + srmMint: get().srmMint, + payerSrmAccount: payerTokenAccount, + authority: get().authority, + config: get().config, + srmVault, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + } else { + const [msrmVault] = PublicKey.findProgramAddressSync( + [Buffer.from('vault'), get().srmMint.toBuffer()], + program.programId + ) + ix = await program.methods + .depositVestMsrm(amount) + .accounts({ + payer, + owner, + ownerUserAccount: userAccount + ? userAccount.address + : userAccountAddress, + msrmMint: get().srmMint, + payerMsrmAccount: payerTokenAccount, + authority: get().authority, + config: get().config, + msrmVault, + vestAccount, + claimTicket: claimTicket, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + } + + return ix + }, + + async depositLocked( + connection, + provider, + amount, + isMsrm, + owner? + ): Promise { + if (!owner || !owner.publicKey) { + notify({ type: 'error', message: 'Please connect your wallet.' }) + return + } + try { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + + const instructions: TransactionInstruction[] = [] + + const ownerAta = await getAssociatedTokenAddress( + !isMsrm ? get().srmMint : get().msrmMint, + owner.publicKey + ) + + const [vault] = PublicKey.findProgramAddressSync( + [ + Buffer.from('vault'), + !isMsrm ? get().srmMint.toBuffer() : get().srmMint.toBuffer(), + ], + program.programId + ) + + const [userAccountAddress] = PublicKey.findProgramAddressSync( + [Buffer.from('user'), owner.publicKey.toBuffer()], + program.programId + ) + const userAccount = await get().actions.getUserAccount( + provider, + owner?.publicKey + ) + + if (!userAccount) { + const ix = await program.methods + .initUser(owner.publicKey) + .accounts({ + payer: owner.publicKey, + userAccount: userAccountAddress, + systemProgram: SystemProgram.programId, + }) + .instruction() + instructions.push(ix) + } + + const lockIndexBuffer = userAccount + ? new anchor.BN(userAccount.lockIndex).toArrayLike(Buffer, 'le', 8) + : new anchor.BN('0').toArrayLike(Buffer, 'le', 8) + + const [lockedAccount] = PublicKey.findProgramAddressSync( + [ + Buffer.from('locked_account'), + owner.publicKey.toBuffer(), + lockIndexBuffer, + ], + program.programId + ) + + const [claimTicket] = PublicKey.findProgramAddressSync( + [Buffer.from('claim_ticket'), lockedAccount.toBuffer()], + program.programId + ) + + if (!isMsrm) { + const ix = await program.methods + .depositLockedSrm(amount) + .accounts({ + payer: owner.publicKey, + owner: owner.publicKey, + ownerUserAccount: userAccount + ? userAccount.address + : userAccountAddress, + srmMint: get().srmMint, + payerSrmAccount: ownerAta, + authority: get().authority, + config: get().config, + srmVault: vault, + lockedAccount, + claimTicket, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + instructions.push(ix) + } else { + const ix = await program.methods + .depositLockedMsrm(amount) + .accounts({ + payer: owner.publicKey, + owner: owner.publicKey, + ownerUserAccount: userAccount + ? userAccount.address + : userAccountAddress, + msrmMint: get().msrmMint, + payerMsrmAccount: ownerAta, + authority: get().authority, + config: get().config, + msrmVault: vault, + lockedAccount, + claimTicket, + clock: SYSVAR_CLOCK_PUBKEY, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .instruction() + instructions.push(ix) + } + + const tx = new Transaction().add(...instructions) + + await sendTransaction({ + transaction: tx, + wallet: owner, + connection, + }) + } catch (e) { + console.error(e) + notify({ type: 'error', message: 'Failed to lock tokens' }) + } + }, + + async getUpdateConfigParamInstruction( + provider: anchor.AnchorProvider, + configAuthority: PublicKey, + claimDelay: anchor.BN, + redeemDelay: anchor.BN, + cliffPeriod: anchor.BN, + linearVestingPeriod: anchor.BN + ): Promise { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + + const ix = await program.methods + .updateConfigParams( + claimDelay, + redeemDelay, + cliffPeriod, + linearVestingPeriod + ) + .accounts({ + config: get().config, + configAuthority, + }) + .instruction() + + return ix + }, + + async getUpdateConfigAuthorityInstruction( + provider: anchor.AnchorProvider, + configAuthority: PublicKey, + newAuthority: PublicKey + ): Promise { + const program = new anchor.Program( + IDL as anchor.Idl, + get().programId, + provider + ) + + const ix = await program.methods + .updateConfigAuthority(newAuthority) + .accounts({ + config: get().config, + configAuthority, + }) + .instruction() + + return ix + }, + }, +})) + +export default useSerumGovStore diff --git a/stores/useTreasuryAccountStore.tsx b/stores/useTreasuryAccountStore.tsx index e20f8d2415..8f5398731c 100644 --- a/stores/useTreasuryAccountStore.tsx +++ b/stores/useTreasuryAccountStore.tsx @@ -1,91 +1,34 @@ import create, { State } from 'zustand' -import { getNfts } from '@utils/tokens' -import tokenService from '@utils/services/token' -import { ConfirmedSignatureInfo, PublicKey } from '@solana/web3.js' +import tokenPriceService, { + TokenInfoWithoutDecimals, +} from '@utils/services/tokenPrice' +import { ConfirmedSignatureInfo } from '@solana/web3.js' import { notify } from '@utils/notifications' -import { NFTWithMint } from '@utils/uiTypes/nfts' -import { TokenInfo } from '@solana/spl-token-registry' import { WSOL_MINT } from '@components/instructions/tools' import { AccountType, AssetAccount } from '@utils/uiTypes/assets' -import { ConnectionContext } from '@utils/connection' interface TreasuryAccountStore extends State { currentAccount: AssetAccount | null mintAddress: string - tokenInfo?: TokenInfo + tokenInfo?: TokenInfoWithoutDecimals recentActivity: ConfirmedSignatureInfo[] - allNfts: NFTWithMint[] - governanceNfts: { - [governance: string]: NFTWithMint[] - } - isLoadingNfts: boolean isLoadingRecentActivity: boolean isLoadingTokenAccounts: boolean setCurrentAccount: (account: AssetAccount, connection) => void handleFetchRecentActivity: (account: AssetAccount, connection) => void - getNfts: ( - nftsGovernedTokenAccounts: AssetAccount[], - connection: ConnectionContext - ) => void } +/** + * @deprecated + */ const useTreasuryAccountStore = create((set, _get) => ({ currentAccount: null, mintAddress: '', tokenInfo: undefined, recentActivity: [], - allNfts: [], - governanceNfts: {}, - isLoadingNfts: false, isLoadingRecentActivity: false, isLoadingTokenAccounts: false, - getNfts: async (nftsGovernedTokenAccounts, connection) => { - set((s) => { - s.isLoadingNfts = true - }) - let realmNfts: NFTWithMint[] = [] - const nftsPerPubkey = {} - for (const acc of nftsGovernedTokenAccounts) { - const governance = acc.governance.pubkey.toBase58() - try { - const nfts = acc.governance.pubkey - ? await getNfts(acc.governance.pubkey, connection) - : [] - if (acc.isSol) { - const solAccountNfts = acc.extensions.transferAddress - ? await getNfts( - new PublicKey(acc.extensions.transferAddress!), - connection - ) - : [] - realmNfts = [...realmNfts, ...solAccountNfts] - - nftsPerPubkey[acc.extensions.transferAddress!.toBase58()] = [ - ...solAccountNfts, - ] - } - realmNfts = [...realmNfts, ...nfts] - if (governance) { - if (nftsPerPubkey[governance]) { - nftsPerPubkey[governance] = [...nftsPerPubkey[governance], ...nfts] - } else { - nftsPerPubkey[governance] = [...nfts] - } - } - } catch (e) { - console.log(e) - notify({ - message: `Unable to fetch nfts for governance ${governance}`, - }) - } - } - set((s) => { - s.allNfts = realmNfts - s.governanceNfts = nftsPerPubkey - s.isLoadingNfts = false - }) - }, setCurrentAccount: async (account, connection) => { if (!account) { set((s) => { @@ -103,7 +46,7 @@ const useTreasuryAccountStore = create((set, _get) => ({ if (account.type === AccountType.SOL) { mintAddress = WSOL_MINT } - const tokenInfo = tokenService.getTokenInfo(mintAddress) + const tokenInfo = tokenPriceService.getTokenInfo(mintAddress) set((s) => { s.currentAccount = account s.mintAddress = mintAddress diff --git a/stores/useVotePluginsClientStore.tsx b/stores/useVotePluginsClientStore.tsx deleted file mode 100644 index df18f4d2c2..0000000000 --- a/stores/useVotePluginsClientStore.tsx +++ /dev/null @@ -1,230 +0,0 @@ -import create, { State } from 'zustand' -import { - NftVoterClient, - GatewayClient, -} from '@solana/governance-program-library' -import { SwitchboardQueueVoterClient } from '../SwitchboardVotePlugin/SwitchboardQueueVoterClient' -import { getRegistrarPDA, Registrar } from 'VoteStakeRegistry/sdk/accounts' -import { getRegistrarPDA as getPluginRegistrarPDA } from '@utils/plugin/accounts' -import { AnchorProvider, Wallet } from '@project-serum/anchor' -import { tryGetNftRegistrar, tryGetRegistrar } from 'VoteStakeRegistry/sdk/api' -import { SignerWalletAdapter } from '@solana/wallet-adapter-base' -import { ConnectionContext } from '@utils/connection' -import { ProgramAccount, Realm } from '@solana/spl-governance' -import { VotingClient, VotingClientProps } from '@utils/uiTypes/VotePlugin' -import { PythClient } from 'pyth-staking-api' -import { PublicKey } from '@solana/web3.js' -import { tryGetGatewayRegistrar } from '../GatewayPlugin/sdk/api' -import { VsrClient } from 'VoteStakeRegistry/sdk/client' - -interface UseVotePluginsClientStore extends State { - state: { - //diffrent plugins to choose because we will still have functions related only to one plugin - vsrClient: VsrClient | undefined - nftClient: NftVoterClient | undefined - gatewayClient: GatewayClient | undefined - switchboardClient: SwitchboardQueueVoterClient | undefined - pythClient: PythClient | undefined - voteStakeRegistryRegistrar: Registrar | null - nftMintRegistrar: any - gatewayRegistrar: any - currentRealmVotingClient: VotingClient - voteStakeRegistryRegistrarPk: PublicKey | null - } - handleSetVsrClient: ( - wallet: SignerWalletAdapter | undefined, - connection: ConnectionContext, - programId?: PublicKey - ) => void - handleSetNftClient: ( - wallet: SignerWalletAdapter | undefined, - connection: ConnectionContext - ) => void - handleSetSwitchboardClient: ( - wallet: SignerWalletAdapter | undefined, - connection: ConnectionContext - ) => void - handleSetGatewayClient: ( - wallet: SignerWalletAdapter | undefined, - connection: ConnectionContext - ) => void - handleSetPythClient: ( - wallet: SignerWalletAdapter | undefined, - connection: ConnectionContext - ) => void - handleSetVsrRegistrar: ( - client: VsrClient, - realm: ProgramAccount | undefined - ) => void - handleSetNftRegistrar: ( - client: NftVoterClient, - realm: ProgramAccount | undefined - ) => void - handleSetGatewayRegistrar: ( - client: GatewayClient, - realm: ProgramAccount | undefined - ) => void - handleSetCurrentRealmVotingClient: ({ - client, - realm, - walletPk, - }: VotingClientProps) => void -} - -const defaultState = { - vsrClient: undefined, - nftClient: undefined, - gatewayClient: undefined, - switchboardClient: undefined, - pythClient: undefined, - voteStakeRegistryRegistrar: null, - voteStakeRegistryRegistrarPk: null, - nftMintRegistrar: null, - gatewayRegistrar: null, - currentRealmVotingClient: new VotingClient({ - client: undefined, - realm: undefined, - walletPk: undefined, - }), -} - -const useVotePluginsClientStore = create( - (set, _get) => ({ - state: { - ...defaultState, - }, - handleSetVsrClient: async (wallet, connection, programId) => { - const options = AnchorProvider.defaultOptions() - const provider = new AnchorProvider( - connection.current, - (wallet as unknown) as Wallet, - options - ) - const vsrClient = await VsrClient.connect( - provider, - programId, - connection.cluster === 'devnet' - ) - set((s) => { - s.state.vsrClient = vsrClient - }) - }, - handleSetVsrRegistrar: async (client, realm) => { - const clientProgramId = client!.program.programId - const { registrar } = await getRegistrarPDA( - realm!.pubkey, - realm!.account.communityMint, - clientProgramId - ) - const existingRegistrar = await tryGetRegistrar(registrar, client!) - set((s) => { - s.state.voteStakeRegistryRegistrar = existingRegistrar - s.state.voteStakeRegistryRegistrarPk = registrar - }) - }, - handleSetNftClient: async (wallet, connection) => { - const options = AnchorProvider.defaultOptions() - const provider = new AnchorProvider( - connection.current, - (wallet as unknown) as Wallet, - options - ) - const nftClient = await NftVoterClient.connect( - provider, - connection.cluster === 'devnet' - ) - set((s) => { - s.state.nftClient = nftClient - }) - }, - handleSetNftRegistrar: async (client, realm) => { - const clientProgramId = client!.program.programId - const { registrar } = await getPluginRegistrarPDA( - realm!.pubkey, - realm!.account.communityMint, - clientProgramId - ) - const existingRegistrar = await tryGetNftRegistrar(registrar, client!) - set((s) => { - s.state.nftMintRegistrar = existingRegistrar - }) - }, - handleSetGatewayRegistrar: async (client, realm) => { - const clientProgramId = client!.program.programId - const { registrar } = await getPluginRegistrarPDA( - realm!.pubkey, - realm!.account.communityMint, - clientProgramId - ) - const existingRegistrar = await tryGetGatewayRegistrar(registrar, client!) - set((s) => { - s.state.gatewayRegistrar = existingRegistrar - }) - }, - handleSetSwitchboardClient: async (wallet, connection) => { - const options = AnchorProvider.defaultOptions() - const provider = new AnchorProvider( - connection.current, - (wallet as unknown) as Wallet, - options - ) - const switchboardClient = await SwitchboardQueueVoterClient.connect( - provider, - connection.cluster === 'devnet' - ) - set((s) => { - s.state.switchboardClient = switchboardClient - }) - }, - handleSetPythClient: async (wallet, connection) => { - if ( - connection.cluster === 'localnet' || - connection.cluster === 'devnet' - ) { - const options = AnchorProvider.defaultOptions() - const provider = new AnchorProvider( - connection.current, - (wallet as unknown) as Wallet, - options - ) - try { - const pythClient = await PythClient.connect( - provider, - connection.cluster - ) - set((s) => { - s.state.pythClient = pythClient - }) - } catch (e) { - console.error(e) - } - } - }, - handleSetCurrentRealmVotingClient: ({ client, realm, walletPk }) => { - set((s) => { - s.state.currentRealmVotingClient = new VotingClient({ - client, - realm, - walletPk, - }) - }) - }, - handleSetGatewayClient: async (wallet, connection) => { - const options = AnchorProvider.defaultOptions() - const provider = new AnchorProvider( - connection.current, - (wallet as unknown) as Wallet, - options - ) - const gatewayClient = await GatewayClient.connect( - provider, - connection.cluster === 'devnet' - ) - set((s) => { - s.state.gatewayClient = gatewayClient - }) - }, - }) -) - -export default useVotePluginsClientStore diff --git a/stores/useWalletStore.tsx b/stores/useWalletStore.tsx deleted file mode 100644 index 709bddd3d2..0000000000 --- a/stores/useWalletStore.tsx +++ /dev/null @@ -1,570 +0,0 @@ -import create, { State } from 'zustand' -import produce from 'immer' -import { PublicKey } from '@solana/web3.js' -import { - TokenProgramAccount, - TokenAccount, - MintAccount, - tryGetMint, - getOwnedTokenAccounts, -} from '../utils/tokens' - -import { - getGovernance, - getGovernanceAccount, - getGovernanceAccounts, - getGovernanceProgramVersion, - Governance, - GOVERNANCE_CHAT_PROGRAM_ID, - Proposal, - ProposalTransaction, - Realm, - RealmConfigAccount, - SignatoryRecord, - TokenOwnerRecord, - VoteRecord, -} from '@solana/spl-governance' -import { ProgramAccount } from '@solana/spl-governance' -import { getGovernanceChatMessages } from '@solana/spl-governance' -import { ChatMessage } from '@solana/spl-governance' -import { GoverningTokenRole } from '@solana/spl-governance' -import { SignerWalletAdapter } from '@solana/wallet-adapter-base' -import { getCertifiedRealmInfo } from '@models/registry/api' -import { tryParsePublicKey } from '@tools/core/pubkey' -import type { ConnectionContext } from 'utils/connection' -import { getConnectionContext } from 'utils/connection' -import { pubkeyFilter } from '@solana/spl-governance' -import { - getTokenOwnerRecordsForRealmMintMapByOwner, - getVoteRecordsByProposalMapByVoter, - getVoteRecordsByVoterMapByProposal, -} from '@models/api' -import { accountsToPubkeyMap } from '@tools/sdk/accounts' -import { HIDDEN_PROPOSALS } from '@components/instructions/tools' -import { sleep } from '@blockworks-foundation/mango-client' -import { getRealmConfigAccountOrDefault } from '@tools/governance/configs' -import { getProposals } from '@utils/GovernanceTools' - -interface WalletStore extends State { - connected: boolean - connection: ConnectionContext - current: SignerWalletAdapter | undefined - - ownVoteRecordsByProposal: { [proposal: string]: ProgramAccount } - realms: { [realm: string]: ProgramAccount } - selectedRealm: { - realm?: ProgramAccount - config?: ProgramAccount - mint?: MintAccount - programId?: PublicKey - councilMint?: MintAccount - governances: { [governance: string]: ProgramAccount } - proposals: { [proposal: string]: ProgramAccount } - /// Community token records by owner - tokenRecords: { [owner: string]: ProgramAccount } - /// Council token records by owner - councilTokenOwnerRecords: { - [owner: string]: ProgramAccount - } - mints: { [pubkey: string]: MintAccount } - programVersion: number - } - selectedProposal: { - proposal: ProgramAccount | undefined - governance: ProgramAccount | undefined - realm: ProgramAccount | undefined - instructions: { [instruction: string]: ProgramAccount } - voteRecordsByVoter: { [voter: string]: ProgramAccount } - signatories: { [signatory: string]: ProgramAccount } - chatMessages: { [message: string]: ProgramAccount } - descriptionLink?: string - proposalMint?: MintAccount - loading: boolean - tokenType?: GoverningTokenRole - proposalOwner: ProgramAccount | undefined - } - providerUrl: string | undefined - tokenAccounts: TokenProgramAccount[] - set: (x: any) => void - actions: any - selectedCouncilDelegate: string | undefined - selectedCommunityDelegate: string | undefined - councilDelegateVoteRecordsByProposal: { - [proposal: string]: ProgramAccount - } - communityDelegateVoteRecordsByProposal: { - [proposal: string]: ProgramAccount - } -} - -const INITIAL_REALM_STATE = { - realm: undefined, - mint: undefined, - programId: undefined, - councilMint: undefined, - governances: {}, - proposals: {}, - tokenRecords: {}, - councilTokenOwnerRecords: {}, - loading: true, - mints: {}, - programVersion: 1, - config: undefined, -} - -const INITIAL_PROPOSAL_STATE = { - proposal: undefined, - governance: undefined, - realm: undefined, - instructions: {}, - voteRecordsByVoter: {}, - signatories: {}, - chatMessages: {}, - descriptionLink: undefined, - proposalMint: undefined, - loading: true, - proposalOwner: undefined, -} - -const useWalletStore = create((set, get) => ({ - connected: false, - connection: getConnectionContext('mainnet'), - current: undefined, - realms: {}, - ownVoteRecordsByProposal: {}, - selectedRealm: INITIAL_REALM_STATE, - selectedProposal: INITIAL_PROPOSAL_STATE, - providerUrl: undefined, - tokenAccounts: [], - switchboardProgram: undefined, - selectedCouncilDelegate: undefined, - selectedCommunityDelegate: undefined, - councilDelegateVoteRecordsByProposal: {}, - communityDelegateVoteRecordsByProposal: {}, - set: (fn) => set(produce(fn)), - actions: { - async fetchRealmBySymbol(cluster: string, symbol: string) { - const actions = get().actions - let connection = get().connection - const set = get().set - const newConnection = getConnectionContext(cluster) - if ( - connection.cluster !== newConnection.cluster || - connection.endpoint !== newConnection.endpoint - ) { - set((s) => { - s.connection = newConnection - }) - connection = get().connection - } - let programId: PublicKey | undefined - let realmId = tryParsePublicKey(symbol) - if (!realmId) { - const realmInfo = await getCertifiedRealmInfo(symbol, newConnection) - realmId = realmInfo?.realmId - programId = realmInfo?.programId - } else { - const realmAccountInfo = await connection.current.getAccountInfo( - realmId - ) - programId = realmAccountInfo?.owner - } - if (realmId && programId) { - const programVersion = await getGovernanceProgramVersion( - connection.current, - programId! - ) - set((s) => { - s.selectedRealm.programVersion = programVersion - }) - await actions.fetchAllRealms(programId) - actions.fetchRealm(programId, realmId) - } - }, - async fetchWalletTokenAccounts() { - const connection = get().connection.current - const connected = get().connected - const wallet = get().current - const walletOwner = wallet?.publicKey - const set = get().set - - if (connected && walletOwner) { - const ownedTokenAccounts = await getOwnedTokenAccounts( - connection, - walletOwner - ) - - set((state) => { - state.tokenAccounts = ownedTokenAccounts - }) - } else { - set((state) => { - state.tokenAccounts = [] - }) - } - }, - async fetchDelegateVoteRecords() { - const connection = get().connection.current - const connected = get().connected - const programId = get().selectedRealm.programId - const realmId = get().selectedRealm.realm?.pubkey - const selectedCouncilDelegate = get().selectedCouncilDelegate - const selectedCommunityDelegate = get().selectedCommunityDelegate - - const set = get().set - - if (connected && selectedCouncilDelegate && programId && realmId) { - const councilDelegateVoteRecordsByProposal = await getVoteRecordsByVoterMapByProposal( - connection, - programId, - new PublicKey(selectedCouncilDelegate) - ) - - set((state) => { - state.councilDelegateVoteRecordsByProposal = councilDelegateVoteRecordsByProposal - }) - } else { - set((state) => { - state.councilDelegateVoteRecordsByProposal = [] - }) - } - - if (connected && selectedCommunityDelegate && programId && realmId) { - const communityDelegateVoteRecordsByProposal = await getVoteRecordsByVoterMapByProposal( - connection, - programId, - new PublicKey(selectedCommunityDelegate) - ) - - set((state) => { - state.communityDelegateVoteRecordsByProposal = communityDelegateVoteRecordsByProposal - }) - } else { - set((state) => { - state.communityDelegateVoteRecordsByProposal = [] - }) - } - }, - - // selectedCouncilDelegate: string | undefined - // selectedCommunityDelegate: string | undefined - - async fetchOwnVoteRecords() { - const connection = get().connection.current - const connected = get().connected - const programId = get().selectedRealm.programId - const realmId = get().selectedRealm.realm?.pubkey - const realmMintPk = get().selectedRealm.realm?.account.communityMint - const wallet = get().current - const walletOwner = wallet?.publicKey - const set = get().set - - if (connected && walletOwner && programId && realmId) { - const [ownVoteRecordsByProposal, tokenRecords] = await Promise.all([ - getVoteRecordsByVoterMapByProposal( - connection, - programId, - walletOwner - ), - getTokenOwnerRecordsForRealmMintMapByOwner( - connection, - programId, - realmId, - realmMintPk - ), - ]) - set((state) => { - state.ownVoteRecordsByProposal = ownVoteRecordsByProposal - state.selectedRealm.tokenRecords = tokenRecords - }) - } else { - set((state) => { - state.ownVoteRecordsByProposal = [] - }) - } - }, - deselectRealm() { - const set = get().set - set((s) => { - s.selectedRealm = INITIAL_REALM_STATE - }) - }, - - // TODO: When this happens fetch vote records for selected delegate? - selectCouncilDelegate(councilDelegate) { - const set = get().set - set((s) => { - s.selectedCouncilDelegate = councilDelegate - }) - }, - selectCommunityDelegate(communityDelegate) { - const set = get().set - set((s) => { - s.selectedCommunityDelegate = communityDelegate - }) - }, - async fetchAllRealms(programId: PublicKey) { - const connection = get().connection.current - const set = get().set - - const realms = await getGovernanceAccounts(connection, programId, Realm) - - set((s) => { - s.realms = accountsToPubkeyMap(realms) - }) - }, - async fetchRealm(programId: PublicKey, realmId: PublicKey) { - const set = get().set - const connection = get().connection.current - const connectionContext = get().connection - const realms = get().realms - const realm = realms[realmId.toBase58()] - const mintsArray = ( - await Promise.all([ - realm?.account.communityMint - ? tryGetMint(connection, realm.account.communityMint) - : undefined, - realm?.account.config?.councilMint - ? tryGetMint(connection, realm.account.config.councilMint) - : undefined, - ]) - ).filter(Boolean) - - set((s) => { - s.selectedRealm.mints = Object.fromEntries( - mintsArray.map((m) => [m!.publicKey.toBase58(), m!.account]) - ) - }) - - const realmMints = get().selectedRealm.mints - const realmMintPk = realm.account.communityMint - const realmMint = realmMints[realmMintPk.toBase58()] - const realmCouncilMintPk = realm.account.config.councilMint - const realmCouncilMint = - realmCouncilMintPk && realmMints[realmCouncilMintPk.toBase58()] - const [ - governances, - tokenRecords, - councilTokenOwnerRecords, - config, - ] = await Promise.all([ - getGovernanceAccounts(connection, programId, Governance, [ - pubkeyFilter(1, realmId)!, - ]), - - getTokenOwnerRecordsForRealmMintMapByOwner( - connection, - programId, - realmId, - realmMintPk - ), - - getTokenOwnerRecordsForRealmMintMapByOwner( - connection, - programId, - realmId, - realmCouncilMintPk - ), - getRealmConfigAccountOrDefault(connection, programId, realmId), - ]) - - const governancesMap = accountsToPubkeyMap(governances) - - set((s) => { - s.selectedRealm.config = config - s.selectedRealm.realm = realm - s.selectedRealm.mint = realmMint - s.selectedRealm.programId = programId - s.selectedRealm.councilMint = realmCouncilMint - s.selectedRealm.governances = governancesMap - s.selectedRealm.tokenRecords = tokenRecords - s.selectedRealm.councilTokenOwnerRecords = councilTokenOwnerRecords - }) - get().actions.fetchOwnVoteRecords() - - const proposalsByGovernance = await getProposals( - governances.map((x) => x.pubkey), - connectionContext, - programId - ) - - const proposals = accountsToPubkeyMap( - proposalsByGovernance - .flatMap((p) => p) - .filter((p) => !HIDDEN_PROPOSALS.has(p.pubkey.toBase58())) - ) - - set((s) => { - s.selectedRealm.proposals = proposals - s.selectedRealm.loading = false - }) - }, - - async refetchProposals() { - console.log('REFETCH PROPOSALS') - await sleep(200) - const set = get().set - const connection = get().connection.current - const connectionContext = get().connection - const realmId = get().selectedRealm.realm?.pubkey - const programId = get().selectedRealm.programId - const governances = await getGovernanceAccounts( - connection, - programId!, - Governance, - [pubkeyFilter(1, realmId)!] - ) - const proposalsByGovernance = await getProposals( - governances.map((x) => x.pubkey), - connectionContext, - programId! - ) - const proposals = accountsToPubkeyMap( - proposalsByGovernance - .flatMap((p) => p) - .filter((p) => !HIDDEN_PROPOSALS.has(p.pubkey.toBase58())) - ) - - await set((s) => { - s.selectedRealm.proposals = proposals - }) - await get().actions.fetchOwnVoteRecords() - }, - // Fetches and updates governance for the selected realm - async fetchRealmGovernance(governancePk: PublicKey) { - const connection = get().connection.current - const set = get().set - - const governance = await getGovernance(connection, governancePk) - - set((s) => { - s.selectedRealm.governances[governancePk.toBase58()] = governance - }) - - return governance - }, - - async fetchProposal(proposalPk: string) { - if (HIDDEN_PROPOSALS.has(proposalPk)) { - return - } - - const connection = get().connection.current - const realmMints = get().selectedRealm.mints - const set = get().set - - set((s) => { - s.selectedProposal = INITIAL_PROPOSAL_STATE - }) - - const proposalPubKey = new PublicKey(proposalPk) - - const proposal = await getGovernanceAccount( - connection, - proposalPubKey, - Proposal - ) - - const proposalMint = - realmMints[proposal.account.governingTokenMint.toBase58()] - - const programId = proposal.owner - - const [ - governance, - instructions, - voteRecordsByVoter, - signatories, - chatMessages, - proposalOwner, - ] = await Promise.all([ - getGovernanceAccount( - connection, - proposal.account.governance, - Governance - ), - getGovernanceAccounts(connection, programId, ProposalTransaction, [ - pubkeyFilter(1, proposalPubKey)!, - ]), - getVoteRecordsByProposalMapByVoter( - connection, - programId, - proposalPubKey - ), - getGovernanceAccounts(connection, programId, SignatoryRecord, [ - pubkeyFilter(1, proposalPubKey)!, - ]), - getGovernanceChatMessages( - connection, - GOVERNANCE_CHAT_PROGRAM_ID, - proposalPubKey - ), - getGovernanceAccount( - connection, - proposal.account.tokenOwnerRecord, - TokenOwnerRecord - ), - ]) - - const realm = await getGovernanceAccount( - connection, - governance.account.realm, - Realm - ) - - const tokenType = realm.account.communityMint.equals( - proposal.account.governingTokenMint - ) - ? GoverningTokenRole.Community - : GoverningTokenRole.Council - - set((s) => { - s.selectedProposal.proposal = proposal - s.selectedProposal.descriptionLink = proposal.account.descriptionLink - s.selectedProposal.governance = governance - s.selectedProposal.realm = realm - s.selectedProposal.instructions = accountsToPubkeyMap(instructions) - s.selectedProposal.voteRecordsByVoter = voteRecordsByVoter - s.selectedProposal.signatories = accountsToPubkeyMap(signatories) - s.selectedProposal.chatMessages = accountsToPubkeyMap(chatMessages) - s.selectedProposal.proposalMint = proposalMint - s.selectedProposal.loading = false - s.selectedProposal.tokenType = tokenType - s.selectedProposal.proposalOwner = proposalOwner - }) - }, - async fetchChatMessages(proposalPubKey: PublicKey) { - const connection = get().connection.current - const set = get().set - - const chatMessages = await getGovernanceChatMessages( - connection, - GOVERNANCE_CHAT_PROGRAM_ID, - proposalPubKey - ) - - set((s) => { - s.selectedProposal.chatMessages = chatMessages - }) - }, - async fetchVoteRecords(proposal: ProgramAccount) { - const connection = get().connection.current - const set = get().set - - const programId = proposal.owner - const voteRecordsByVoter = await getVoteRecordsByProposalMapByVoter( - connection, - programId, - proposal.pubkey - ) - - console.log('voteRecords', voteRecordsByVoter) - - set((s) => { - s.selectedProposal.voteRecordsByVoter = voteRecordsByVoter - }) - }, - }, -})) - -export default useWalletStore diff --git a/styles/index.css b/styles/index.css index 3514234dbd..ede89b7679 100644 --- a/styles/index.css +++ b/styles/index.css @@ -24,6 +24,7 @@ --fgd-2: theme('colors.dark-theme.fgd-2'); --fgd-3: theme('colors.dark-theme.fgd-3'); --fgd-4: theme('colors.dark-theme.fgd-4'); + --discord: theme('colors.dark-theme.discord'); } [data-theme='Light'] { @@ -46,6 +47,7 @@ --fgd-2: theme('colors.light-theme.fgd-2'); --fgd-3: theme('colors.light-theme.fgd-3'); --fgd-4: theme('colors.light-theme.fgd-4'); + --discord: theme('colors.light-theme.discord'); } /* base */ @@ -55,7 +57,7 @@ } body { - @apply text-base tracking-wide bg-bkg-1 text-fgd-1 font-body; + @apply text-base tracking-wide font-body; } h1 { @@ -86,10 +88,6 @@ tbody { @apply text-2xl font-bold; } -button { - @apply tracking-wide; -} - .default-transition { @apply transition-all duration-300; } @@ -126,6 +124,88 @@ button { @apply block mb-2 text-sm; } +.markdown table { + margin: 10px 0; + border: 1px solid #ccc; + @apply border-bkg-4; + border-collapse: collapse; + padding: 0; + width: 100%; + table-layout: fixed; +} + +table caption { + font-size: 1.5em; + margin: 0.5em 0 0.75em; +} + +table tr { + border: 1px solid #ddd; + @apply border-bkg-4; + padding: 0.35em; +} + +table th, +table td { + padding: 0.625em; + text-align: center; +} + +table th { + font-size: 0.85em; + letter-spacing: 0.1em; + text-transform: uppercase; +} + +@media screen and (max-width: 600px) { + table { + border: 0; + } + + table caption { + font-size: 1.3em; + } + + table thead { + border: none; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + } + + table tr { + border-bottom: 3px solid #ddd; + display: block; + margin-bottom: 0.625em; + } + + table td { + border-bottom: 1px solid #ddd; + display: block; + font-size: 0.8em; + text-align: right; + } + + table td::before { + /* + * aria-label has no advantage, it won't be read inside a table + content: attr(aria-label); + */ + content: attr(data-label); + float: left; + font-weight: bold; + text-transform: uppercase; + } + + table td:last-child { + border-bottom: 0; + } +} + :placeholder-shown { @apply font-body; } @@ -171,6 +251,10 @@ body::-webkit-scrollbar-corner { background: var(--bkg-4); } +.no-scrollbar::-webkit-scrollbar { + display: none; +} + .pointer { cursor: pointer; } @@ -296,8 +380,19 @@ https://developer.mozilla.org/en-US/docs/Web/CSS/word-break#values */ overflow-wrap: anywhere; } +.gatewayButton > span:hover{ + @apply !text-fgd-1; +} + .gatewayButton > span { - @apply !text-bkg-2 !pl-0 !text-sm; + @apply !text-primary-light !pl-0 hover:!text-fgd-1; + margin-left: 23px; +} + +.gatewayButton > svg { + filter: brightness(0) saturate(100%) invert(71%) sepia(67%) saturate(514%) hue-rotate(161deg) brightness(97%) contrast(90%); + min-width: 24px; + padding-top: 4px; } .react-grid-item.react-grid-placeholder { @@ -314,3 +409,92 @@ https://developer.mozilla.org/en-US/docs/Web/CSS/word-break#values */ .react-resizable-handle-se::after { border-color: white !important; } + +@import url('@dialectlabs/react-ui/index.css'); + +.dialect input { + border: none; +} + +.dialect input:focus { + outline: none; + box-shadow: none; +} + +.dialect { + --dt-bg-primary: #17161c; + --dt-bg-secondary: #201f27; + --dt-bg-tertiary: #2a2d34; + --dt-bg-brand: #81ccf6; + --dt-input-primary: #40474f; + --dt-input-secondary: #17161c; + --dt-input-checked: #81ccf6; + --dt-input-unchecked: #6c727f; + --dt-input-disabled: #363d44; + --dt-button-primary: #81ccf6; + --dt-button-primary-hover: #81ccf6; + --dt-button-primary-disabled: #81ccf6; + --dt-button-secondary: #201f27; + --dt-button-secondary-hover: #2a2d34; + --dt-button-secondary-disabled: #201f27; + --dt-text-primary: #ffffff; + --dt-text-secondary: #d6d6d6; + --dt-text-tertiary: #b3b7bd; + --dt-text-quaternary: #7a7a7a; + --dt-text-inverse: #101010; + --dt-text-accent: #81ccf6; + --dt-stroke-primary: #2a2d34; + --dt-icon-primary: #fcfcfc; + --dt-icon-secondary: #6c727f; + --dt-icon-tertiary: #6c727f; + --dt-icon-inverse: #17161c; + --dt-accent-brand: #81ccf6; + --dt-accent-success: #30c89a; + --dt-accent-warning: #f7a531; + --dt-accent-error: #ff5353; + --dt-brand-transparent: #00e4ff1a; + --dt-success-transparent: #30c89a1a; + --dt-warning-transparent: #f7a5311a; + --dt-error-transparent: #e540331a; +} + +:root[data-theme='Light'] .dialect { + --dt-bg-primary: #fcfcfc; + --dt-bg-secondary: #f0f0f0; + --dt-bg-tertiary: #f0f0f0; + --dt-bg-brand: #42bae1; + --dt-input-primary: #d6d6d6; + --dt-input-secondary: #fcfcfc; + --dt-input-checked: #42bae1; + --dt-input-unchecked: #adadad; + --dt-input-disabled: #b3b7bd; + --dt-button-primary: #42bae1; + --dt-button-primary-hover: #42bae1; + --dt-button-primary-disabled: #42bae1; + --dt-button-secondary: #e0e0e0; + --dt-button-secondary-hover: #d6d6d6; + --dt-button-secondary-disabled: #f0f0f0; + --dt-text-primary: #17161c; + --dt-text-secondary: #2f343a; + --dt-text-tertiary: #7a7a7a; + --dt-text-quaternary: #adadad; + --dt-text-inverse: #ffffff; + --dt-text-accent: #42bae1; + --dt-stroke-primary: #e0e0e0; + --dt-icon-primary: #ffffff; + --dt-icon-secondary: #adadad; + --dt-icon-tertiary: #adadad; + --dt-icon-inverse: #ffffff; + --dt-accent-brand: #42bae1; + --dt-accent-success: #6cbf00; + --dt-accent-warning: #f48f25; + --dt-accent-error: #e54033; + --dt-brand-transparent: #00e4ff1a; + --dt-success-transparent: #6cbf001a; + --dt-warning-transparent: #f7a5311a; + --dt-error-transparent: #e540331a; +} + +.dialect > div > button { + border-radius: 999px !important; +} diff --git a/tailwind.config.js b/tailwind.config.js index c12d7ba354..c15cf91ca8 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,9 +1,15 @@ +const lineClamp = require('@tailwindcss/line-clamp') +const forms = require('@tailwindcss/forms') + module.exports = { + darkMode: 'class', content: [ './pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}', './Strategies/**/*.{js,ts,jsx,tsx}', './VoteStakeRegistry/**/*.{js,ts,jsx,tsx}', + './hub/**/*.{js,ts,jsx,tsx}', + './verify-wallet/**/*.{js,ts,jsx,tsx}', ], future: { removeDeprecatedGapUtilities: true, @@ -21,6 +27,7 @@ module.exports = { help: 'help', }, colors: { + discord: '#7289da', 'dark-theme': { primary: { light: '#5DC9EB', dark: '#cecece' }, 'secondary-1': { light: '#AFD803', dark: '#6CBF00' }, @@ -38,6 +45,7 @@ module.exports = { red: '#FF7C7C', green: '#30C89A', blue: '#00e4ff', + discord: '#7289da', }, 'light-theme': { primary: { light: '#5DC9EB', dark: '#101010' }, @@ -55,6 +63,7 @@ module.exports = { red: '#cb676f', green: '#6BBF5F', blue: '#3F77DE', + discord: '#7289da', }, 'mango-theme': { primary: { light: '#F2C94C', dark: '#EEB91B' }, @@ -98,12 +107,54 @@ module.exports = { 'night-grey': '#201F27', 'bkg-black': '#212429', 'secondary-grey': '#D5D4D7', + 'red-50': '#fef2f2', + 'red-100': '#fee2e2', + 'red-200': '#fecaca', + 'red-300': '#fca5a5', + 'red-400': '#f87171', + 'red-500': '#ef4444', + 'red-600': '#dc2626', + 'red-700': '#b91c1c', + 'red-800': '#991b1b', + 'red-900': '#7f1d1d', + 'green-50': '#f0fdf4', + 'green-100': '#dcfce7', + 'green-200': '#bbf7d0', + 'green-300': '#86efac', + 'green-400': '#4ade80', + 'green-500': '#22c55e', + 'green-600': '#16a34a', + 'green-700': '#15803d', + 'green-800': '#166534', + 'green-900': '#14532d', + 'orange-50': '#fff7ed', + 'orange-100': '#ffedd5', + 'orange-200': '#fed7aa', + 'orange-300': '#fdba74', + 'orange-400': '#fb923c', + 'orange-500': '#f97316', + 'orange-600': '#ea580c', + 'orange-700': '#c2410c', + 'orange-800': '#9a3412', + 'orange-900': '#7c2d12', + 'blue-50': '#eff6ff', + 'blue-100': '#dbeafe', + 'blue-200': '#bfdbfe', + 'blue-300': '#93c5fd', + 'blue-400': '#60a5fa', + 'blue-500': '#3b82f6', + 'blue-600': '#2563eb', + 'blue-700': '#1d4ed8', + 'blue-800': '#1e40af', + 'blue-900': '#1e3a8a', }, animation: { 'connect-wallet-ping': 'connect-wallet-ping 1.5s cubic-bezier(0, 0, 0.2, 1) infinite', gradient: 'gradient 4s ease-in-out infinite', loader: 'loader 0.6s infinite alternate', + 'staggered-bounce': 'staggered-bounce 1600ms infinite', + 'move-stripes': 'move-stripes 2s linear infinite', }, keyframes: { 'connect-wallet-ping': { @@ -129,6 +180,20 @@ module.exports = { transform: 'translate3d(0, 0, 0)', }, }, + 'staggered-bounce': { + '0%, 25%': { + transform: 'translateY(0)', + 'animation-timing-function': 'cubic-bezier(0, 0, 0.2, 1)', + }, + '12.5%': { + transform: 'translateY(-50%)', + 'animation-timing-function': 'cubic-bezier(0.8, 0, 1, 1)', + }, + }, + 'move-stripes': { + '0%': { backgroundPosition: '0 0' }, + '100%': { backgroundPosition: '44px 0' }, + }, }, fontFamily: { rota: ['Rota', 'sans-serif'], @@ -136,5 +201,5 @@ module.exports = { }, }, }, - plugins: [], + plugins: [lineClamp, forms], } diff --git a/test/pages/index.test.tsx b/test/pages/index.test.tsx index b9f0fd4b07..5b023298fa 100644 --- a/test/pages/index.test.tsx +++ b/test/pages/index.test.tsx @@ -13,6 +13,23 @@ describe('Home page redirects to', () => { process.env.REALM = originalRealm }) + const originalError = console.error + beforeAll(() => { + console.error = (...args) => { + if ( + /Warning: ReactDOM.render is no longer supported in React 18./.test( + args[0] + ) + ) { + return + } + originalError.call(console, ...args) + } + }) + + afterAll(() => { + console.error = originalError + }) test('/realms when process.env.REALM is not set', async () => { delete process.env.REALM render() diff --git a/tools/constants.ts b/tools/constants.ts index 86c2b74e54..225e808265 100644 --- a/tools/constants.ts +++ b/tools/constants.ts @@ -1,13 +1,23 @@ +import { PublicKey } from '@solana/web3.js' import BN from 'bn.js' -/** - * The minimum amount of community tokens to create governance and proposals, for tokens with 0 supply - * Note: This is deprectaed value and should not be used any longer - */ -export const MIN_COMMUNITY_TOKENS_TO_CREATE_W_0_SUPPLY = 1000000 - /** * u64::MAX value used to denote disabled threshold */ export const DISABLED_VOTER_WEIGHT = new BN('18446744073709551615') +export const DISABLED_VALUE = new BN('18446744073709551615') + +// The wallet can be any existing account for the simulation +// Note: when running a local validator ensure the account is copied from devnet: --clone ENmcpFCpxN1CqyUjuog9yyUVfdXBKF3LVCwLr7grJZpk -ud +export const SIMULATION_WALLET = 'ENmcpFCpxN1CqyUjuog9yyUVfdXBKF3LVCwLr7grJZpk' + +export const DEFAULT_NFT_VOTER_PLUGIN = + 'GnftV5kLjd67tvHpNGyodwWveEKivz3ZWvvE3Z4xi2iw' + +export const DEFAULT_NFT_VOTER_PLUGIN_V2 = + 'GnftVc21v2BRchsRa9dGdrVmJPLZiRHe9j2offnFTZFg' + +export const JUPITER_REFERRAL_PK = new PublicKey( + 'EV4qhLE2yPKdUPdQ74EWJUn21xT3eGQxG3DRR1g9NNFc' +) diff --git a/tools/core/script.ts b/tools/core/script.ts index f3e5675b6b..d185b812cc 100644 --- a/tools/core/script.ts +++ b/tools/core/script.ts @@ -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(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( - source: readonly T[], - getKey: (item: T) => K -) { - return Array.from(arrayToMap(source, getKey).values()) -} - export function arrayToRecord( source: readonly T[], getKey: (item: T) => string diff --git a/tools/core/strings.ts b/tools/core/strings.ts index 0004f14741..bd5c7d0603 100644 --- a/tools/core/strings.ts +++ b/tools/core/strings.ts @@ -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) -} diff --git a/tools/feeEstimate.ts b/tools/feeEstimate.ts new file mode 100644 index 0000000000..3227c6cd70 --- /dev/null +++ b/tools/feeEstimate.ts @@ -0,0 +1,57 @@ +import { + Connection, + LAMPORTS_PER_SOL, + PublicKey, + RecentPrioritizationFees, +} from '@solana/web3.js' +import { getClient, getGroupForClient } from '@utils/mangoV4Tools' +import { groupBy, mapValues, maxBy, sampleSize } from 'lodash' + +export const getFeeEstimate = async (connection: Connection) => { + const defaultFee = 50000 + try { + //Use mango client to find good fee + const MAINNET_MANGO_GROUP = new PublicKey( + '78b8f4cGCwmZ9ysPFMWLaLTkkaYnUjwMJYStWe5RTSSX' + ) + const MAX_PRIORITY_FEE_KEYS = 128 + const client = await getClient(connection) + const group = await getGroupForClient(client, MAINNET_MANGO_GROUP) + const feeMultiplier = 2 + const altResponse = await connection.getAddressLookupTable( + group.addressLookupTables[0] + ) + const altKeys = altResponse.value?.state.addresses + if (!altKeys) return defaultFee + + const addresses = sampleSize(altKeys, MAX_PRIORITY_FEE_KEYS) + const fees = await connection.getRecentPrioritizationFees({ + lockedWritableAccounts: addresses, + }) + + if (fees.length < 1) return defaultFee + + // get max priority fee per slot (and sort by slot from old to new) + const maxFeeBySlot = mapValues(groupBy(fees, 'slot'), (items) => + maxBy(items, 'prioritizationFee') + ) + const maximumFees = Object.values(maxFeeBySlot).sort( + (a, b) => a!.slot - b!.slot + ) as RecentPrioritizationFees[] + + // get median of last 20 fees + const recentFees = maximumFees.slice(Math.max(maximumFees.length - 20, 0)) + const mid = Math.floor(recentFees.length / 2) + const medianFee = + recentFees.length % 2 !== 0 + ? recentFees[mid].prioritizationFee + : (recentFees[mid - 1].prioritizationFee + + recentFees[mid].prioritizationFee) / + 2 + const feeEstimate = Math.ceil(medianFee * feeMultiplier) + + return Math.min(feeEstimate, LAMPORTS_PER_SOL * 0.001) + } catch (e) { + return defaultFee + } +} diff --git a/tools/governance/configs.ts b/tools/governance/configs.ts index 7ce361e86c..f48fa96e54 100644 --- a/tools/governance/configs.ts +++ b/tools/governance/configs.ts @@ -13,13 +13,10 @@ import { Connection, PublicKey } from '@solana/web3.js' export function createGovernanceThresholds( programVersion: number, - communityYesVotePercentage: number + communityYesVotePercentage: 'disabled' | number, + // ignored if program version < v3 + councilYesVotePercentage?: 'disabled' | number ) { - const communityVoteThreshold = new VoteThreshold({ - value: communityYesVotePercentage, - type: VoteThresholdType.YesVotePercentage, - }) - // For backward compatybility with spl-gov versions <= 2 // for Council vote and Veto vote thresholds we have to pass YesVotePerentage(0) const undefinedThreshold = new VoteThreshold({ @@ -27,22 +24,35 @@ export function createGovernanceThresholds( value: 0, }) - // TODO: For spl-gov v3 add suport for seperate council vote threshold in the UI - // Until it's supported we default it to community vote threshold + const communityVoteThreshold = + programVersion >= PROGRAM_VERSION_V3 + ? communityYesVotePercentage !== 'disabled' + ? new VoteThreshold({ + value: communityYesVotePercentage, + type: VoteThresholdType.YesVotePercentage, + }) + : new VoteThreshold({ type: VoteThresholdType.Disabled }) + : new VoteThreshold({ + value: communityYesVotePercentage as number, + type: VoteThresholdType.YesVotePercentage, + }) + const councilVoteThreshold = programVersion >= PROGRAM_VERSION_V3 - ? communityVoteThreshold + ? councilYesVotePercentage !== 'disabled' && + councilYesVotePercentage !== undefined + ? new VoteThreshold({ + value: councilYesVotePercentage, + type: VoteThresholdType.YesVotePercentage, + }) + : new VoteThreshold({ type: VoteThresholdType.Disabled }) : undefinedThreshold - // TODO: For spl-gov v3 add suport for seperate council Veto vote threshold in the UI - // Until it's supported we default it to community vote threshold const councilVetoVoteThreshold = programVersion >= PROGRAM_VERSION_V3 - ? communityVoteThreshold + ? councilVoteThreshold : undefinedThreshold - // TODO: For spl-gov v3 add suport for seperate Community Veto vote threshold in the UI - // Until it's supported we default it to disabled Community vote threshold const communityVetoVoteThreshold = programVersion >= PROGRAM_VERSION_V3 ? new VoteThreshold({ type: VoteThresholdType.Disabled }) @@ -56,7 +66,7 @@ export function createGovernanceThresholds( } } -export function createDefaultRealmConfigAccount(realmPk: PublicKey) { +function createDefaultRealmConfigAccount(realmPk: PublicKey) { const defaultTokenConfig = new GoverningTokenConfig({ voterWeightAddin: undefined, maxVoterWeightAddin: undefined, diff --git a/tools/governance/prepareRealmCreation.ts b/tools/governance/prepareRealmCreation.ts index 590fcf22aa..7a616076d2 100644 --- a/tools/governance/prepareRealmCreation.ts +++ b/tools/governance/prepareRealmCreation.ts @@ -6,27 +6,29 @@ import { } from '@solana/web3.js' import { - getGovernanceProgramVersion, GovernanceConfig, GoverningTokenConfigAccountArgs, + GoverningTokenType, SetRealmAuthorityAction, + TOKEN_PROGRAM_ID, + VoteThresholdType, VoteTipping, WalletSigner, withCreateGovernance, - withCreateMintGovernance, withCreateNativeTreasury, withCreateRealm, + withCreateTokenOwnerRecord, withDepositGoverningTokens, withSetRealmAuthority, } from '@solana/spl-governance' import { getWalletPublicKey } from '@utils/sendTransactions' -import { tryGetMint } from '@utils/tokens' import { parseMintMaxVoteWeight } from '@tools/governance/units' import { getTimestampFromDays, getMintNaturalAmountFromDecimalAsBN, + getTimestampFromHours, } from '@tools/sdk/units' import { withCreateMint } from '@tools/sdk/splToken/withCreateMint' import { withCreateAssociatedTokenAccount } from '@tools/sdk/splToken/withCreateAssociatedTokenAccount' @@ -35,10 +37,17 @@ import { DISABLED_VOTER_WEIGHT } from '@tools/constants' import BN from 'bn.js' import { createGovernanceThresholds } from './configs' +import { Token } from '@solana/spl-token' +import { fetchProgramVersion } from '@hooks/queries/useProgramVersionQuery' +import { fetchMintInfoByPubkey } from '@hooks/queries/mintInfo' -interface RealmCreation { +export interface Web3Context { connection: Connection wallet: WalletSigner +} +interface RealmCreationV2 { + _programVersion: 2 + programIdAddress: string realmName: string @@ -47,17 +56,30 @@ interface RealmCreation { nftCollectionCount?: number existingCommunityMintPk: PublicKey | undefined - communityMintSupplyFactor: number | undefined - communityYesVotePercentage: number + communityYesVotePercentage: 'disabled' | number transferCommunityMintAuthority: boolean + useSupplyFactor: boolean + communityMintSupplyFactor: number | undefined + communityAbsoluteMaxVoteWeight: number | undefined + createCouncil: boolean existingCouncilMintPk: PublicKey | undefined transferCouncilMintAuthority: boolean councilWalletPks: PublicKey[] - communityTokenConfig?: GoverningTokenConfigAccountArgs + communityTokenConfig: GoverningTokenConfigAccountArgs + skipRealmAuthority?: boolean } +type RealmCreationV3 = { + _programVersion: 3 + councilTokenConfig: GoverningTokenConfigAccountArgs + councilYesVotePercentage: 'disabled' | number +} & Omit + +export type RealmCreation = RealmCreationV2 | RealmCreationV3 + +export const DEFAULT_MINT_DECIMALS = 6; export async function prepareRealmCreation({ connection, @@ -71,16 +93,21 @@ export async function prepareRealmCreation({ nftCollectionCount = 0, existingCommunityMintPk, communityYesVotePercentage, - communityMintSupplyFactor: rawCMSF, transferCommunityMintAuthority, + useSupplyFactor, + communityMintSupplyFactor, + communityAbsoluteMaxVoteWeight, + createCouncil, existingCouncilMintPk, transferCouncilMintAuthority, councilWalletPks, - communityTokenConfig = undefined, -}: RealmCreation) { + communityTokenConfig, + skipRealmAuthority, + ...params +}: RealmCreation & Web3Context) { const realmInstructions: TransactionInstruction[] = [] const realmSigners: Keypair[] = [] @@ -90,49 +117,55 @@ export async function prepareRealmCreation({ const mintsSetupSigners: Keypair[] = [] const initialCouncilTokenAmount = 1 - const communityMintSupplyFactor = parseMintMaxVoteWeight(rawCMSF) - const walletPk = getWalletPublicKey(wallet) + const walletPk = getWalletPublicKey(wallet as any) const programIdPk = new PublicKey(programIdAddress) - const programVersion = await getGovernanceProgramVersion( - connection, - programIdPk - ) + const programVersion = await fetchProgramVersion(connection, programIdPk) + if (programVersion !== params._programVersion) + throw new Error('form state and queried program version mismatch') console.log( 'Prepare realm - program and version', programIdAddress, programVersion ) - const communityMintAccount = - existingCommunityMintPk && - (await tryGetMint(connection, existingCommunityMintPk)) - const zeroCommunityTokenSupply = existingCommunityMintPk - ? communityMintAccount?.account.supply.isZero() - : true - const communityMintDecimals = communityMintAccount?.account?.decimals || 6 - // If we're using an existing community mint check if we can create a governance for it - // 1) The mint must have mintAuthority - // 2) The current wallet must be the authority - let createCommunityMintGovernance = communityMintAccount?.account.mintAuthority?.equals( - walletPk + const { + communityVoteThreshold, + councilVoteThreshold, + councilVetoVoteThreshold, + communityVetoVoteThreshold, + } = createGovernanceThresholds( + programVersion, + communityYesVotePercentage, + params._programVersion === 3 ? params.councilYesVotePercentage : 'disabled' + ) + + const existingCommunityMint = existingCommunityMintPk + ? (await fetchMintInfoByPubkey(connection, existingCommunityMintPk)).result + : undefined + + const existingCouncilMint = existingCouncilMintPk + ? (await fetchMintInfoByPubkey(connection, existingCouncilMintPk)).result + : undefined + + const communityMintDecimals = existingCommunityMint?.decimals || DEFAULT_MINT_DECIMALS + + const communityMaxVoteWeightSource = parseMintMaxVoteWeight( + useSupplyFactor, + communityMintDecimals, + communityMintSupplyFactor, + communityAbsoluteMaxVoteWeight ) console.log('Prepare realm - community mint address', existingCommunityMintPk) - console.log('Prepare realm - community mint account', communityMintAccount) + console.log('Prepare realm - community mint account', existingCommunityMint) - const councilMintAccount = - existingCouncilMintPk && - (await tryGetMint(connection, existingCouncilMintPk)) - const zeroCouncilTokenSupply = existingCommunityMintPk - ? councilMintAccount?.account.supply.isZero() - : true - const councilMintHasMintAuthority = councilMintAccount - ? !!councilMintAccount.account.mintAuthority + const councilMintHasMintAuthority = existingCouncilMint + ? !!existingCouncilMint.mintAuthority : true console.log('Prepare realm - council mint address', existingCouncilMintPk) - console.log('Prepare realm - council mint account', councilMintAccount) + console.log('Prepare realm - council mint account', existingCouncilMint) let communityMintPk = existingCommunityMintPk @@ -147,36 +180,13 @@ export async function prepareRealmCreation({ communityMintDecimals, walletPk ) - // If we create the mint then always create a governance for it - createCommunityMintGovernance = true } - console.log( - 'Prepare realm - zero community token supply', - zeroCommunityTokenSupply, - ' | zero council token supply', - zeroCouncilTokenSupply - ) console.log('Prepare realm - council mint address', existingCouncilMintPk) // Create council mint let councilMintPk - if ( - zeroCommunityTokenSupply && - zeroCouncilTokenSupply && - nftCollectionCount === 0 && - councilWalletPks.length === 0 - ) { - councilWalletPks.push(wallet.publicKey as PublicKey) - councilMintPk = await withCreateMint( - connection, - mintsSetupInstructions, - mintsSetupSigners, - walletPk, - null, - 0, - walletPk - ) - } else if (!existingCouncilMintPk && createCouncil) { + + if (!existingCouncilMintPk && createCouncil) { councilMintPk = await withCreateMint( connection, mintsSetupInstructions, @@ -190,31 +200,51 @@ export async function prepareRealmCreation({ councilMintPk = existingCouncilMintPk } - let walletAtaPk: PublicKey | undefined - const tokenAmount = 1 - - console.log('Prepare realm - council members', councilWalletPks) - for (const teamWalletPk of councilWalletPks) { - const ataPk = await withCreateAssociatedTokenAccount( - councilMembersInstructions, - councilMintPk, - teamWalletPk, - walletPk - ) - - // Mint 1 council token to each team member - await withMintTo( - councilMembersInstructions, - councilMintPk, - ataPk, - walletPk, - tokenAmount - ) - - if (teamWalletPk.equals(walletPk)) { - walletAtaPk = ataPk - } + // START check if realm is governable ---------------- + const communityEnabledInConfig = communityTokenConfig + ? communityTokenConfig.tokenType !== GoverningTokenType.Dormant + : false + // community can govern if... + const communityCanGovern = + // its enabled + communityEnabledInConfig && + // ...and has a vote threshold + communityVoteThreshold.type !== VoteThresholdType.Disabled && + (communityVoteThreshold.value ?? 0 > 0) && + // ... and has supply + (existingCommunityMint?.supply.gtn(0) ?? false) + + const incomingCouncilMembers = councilWalletPks.length + const councilEnabledInConfig = + params._programVersion !== 2 + ? params.councilTokenConfig.tokenType === GoverningTokenType.Membership + : communityTokenConfig + ? // if version 2, council just uses community config + communityTokenConfig.tokenType !== GoverningTokenType.Dormant + : false // just assume if no community config is supplied for some reason, we can't count on anything. + // council can govern if... + const councilCanGovern = + // it has a mint... + councilMintPk && + // its enabled... + councilEnabledInConfig && // NOTE: technically it can be enabled, but undefined. + // ...and has a vote threshold + councilVoteThreshold.type !== VoteThresholdType.Disabled && + (councilVoteThreshold.value ?? 0 > 0) && + // and either the council mint has supply... OR + ((existingCouncilMint?.supply.gtn(0) ?? false) || + // there are incoming council members + incomingCouncilMembers > 0) + + console.log('Prepare realm - can community govern?', communityCanGovern) + if ( + !communityCanGovern && + nftCollectionCount === 0 && // note this is not the most thorough check possible for nft realms + !councilCanGovern + ) { + throw new Error('no tokens exist that could govern this DAO') } + // END --------------------------------------------- // Convert to mint natural amount const minCommunityTokensToCreateAsMintValue = @@ -234,115 +264,198 @@ export async function prepareRealmCreation({ communityMintPk, walletPk, councilMintPk, - communityMintSupplyFactor, + communityMaxVoteWeightSource, minCommunityTokensToCreateAsMintValue, - communityTokenConfig + communityTokenConfig, + params._programVersion === 3 ? params.councilTokenConfig : undefined ) - // If the current wallet is in the team then deposit the council token - if (walletAtaPk) { - await withDepositGoverningTokens( - realmInstructions, - programIdPk, - programVersion, - realmPk, - walletAtaPk, - councilMintPk, - walletPk, - walletPk, - walletPk, - new BN(initialCouncilTokenAmount) - ) + const doesRealmExist = await connection.getAccountInfo(realmPk) + + if (doesRealmExist?.data) { + throw new Error('Realm with the same name already exists.') } - const { - communityVoteThreshold, - councilVoteThreshold, - councilVetoVoteThreshold, - communityVetoVoteThreshold, - } = createGovernanceThresholds(programVersion, communityYesVotePercentage) + console.log('Prepare realm - council members', councilWalletPks) + for (const teamWalletPk of councilWalletPks) { + // In version 3 we just deposit council tokens directly into the DAO + if (programVersion >= 3) { + // This is a workaround for an unnecessary signer check in DepositGoverningTokens. + if (teamWalletPk !== walletPk) { + await withCreateTokenOwnerRecord( + realmInstructions, + programIdPk, + programVersion, + realmPk, + teamWalletPk, + councilMintPk, + walletPk + ) + } + + await withDepositGoverningTokens( + realmInstructions, + programIdPk, + programVersion, + realmPk, + councilMintPk, + councilMintPk, + teamWalletPk, + walletPk, + walletPk, + new BN(initialCouncilTokenAmount) + ) + // TODO remove workaround once unnecessary signer bug in sdk is fixed + // this is a workaround + const buggedIx = realmInstructions[realmInstructions.length - 1] + // make teamWalletPk not a signer + buggedIx.keys = buggedIx.keys.map((key) => + key.pubkey.equals(teamWalletPk) && !key.pubkey.equals(walletPk) + ? { ...key, isSigner: false } + : key + ) + } + + // before version 3, we have to mint the tokens to wallets + else { + const ataPk = await withCreateAssociatedTokenAccount( + councilMembersInstructions, + councilMintPk, + teamWalletPk, + walletPk + ) + + // Mint 1 council token to each team member + await withMintTo( + councilMembersInstructions, + councilMintPk, + ataPk, + walletPk, + initialCouncilTokenAmount + ) + if (teamWalletPk.equals(walletPk)) { + await withDepositGoverningTokens( + realmInstructions, + programIdPk, + programVersion, + realmPk, + ataPk, + councilMintPk, + walletPk, + walletPk, + walletPk, + new BN(initialCouncilTokenAmount) + ) + } + } + } + + const VOTING_COOLOFF_TIME_DEFAULT = getTimestampFromHours(12) // Put community and council mints under the realm governance with default config const config = new GovernanceConfig({ communityVoteThreshold: communityVoteThreshold, minCommunityTokensToCreateProposal: minCommunityTokensToCreateAsMintValue, // Do not use instruction hold up time minInstructionHoldUpTime: 0, - // max voting time 3 days - maxVotingTime: getTimestampFromDays(maxVotingTimeInDays), - communityVoteTipping: VoteTipping.Strict, + // maxVotingTime = baseVotingTime + votingCoolOffTime + // since this is actually baseVotingTime, we have to manually subtract the cooloff time. + baseVotingTime: + getTimestampFromDays(maxVotingTimeInDays) - VOTING_COOLOFF_TIME_DEFAULT, + communityVoteTipping: VoteTipping.Disabled, councilVoteTipping: VoteTipping.Strict, minCouncilTokensToCreateProposal: new BN(initialCouncilTokenAmount), councilVoteThreshold: councilVoteThreshold, councilVetoVoteThreshold: councilVetoVoteThreshold, communityVetoVoteThreshold: communityVetoVoteThreshold, + votingCoolOffTime: VOTING_COOLOFF_TIME_DEFAULT, + depositExemptProposalCount: 10, }) - const communityMintGovPk = createCommunityMintGovernance - ? await withCreateMintGovernance( - realmInstructions, - programIdPk, - programVersion, - realmPk, - communityMintPk, - config, - transferCommunityMintAuthority, - walletPk, - PublicKey.default, - walletPk, - walletPk - ) - : await withCreateGovernance( - realmInstructions, - programIdPk, - programVersion, - realmPk, - communityMintPk, - config, - PublicKey.default, - walletPk, - walletPk - ) + const mainGovernancePk = await withCreateGovernance( + realmInstructions, + programIdPk, + programVersion, + realmPk, + undefined, + config, + PublicKey.default, + walletPk, + walletPk + ) - await withCreateNativeTreasury( + const nativeTreasuryAddress = await withCreateNativeTreasury( realmInstructions, programIdPk, programVersion, - communityMintGovPk, + mainGovernancePk, walletPk ) + if (transferCommunityMintAuthority) { + const ix = Token.createSetAuthorityInstruction( + TOKEN_PROGRAM_ID, + communityMintPk, + nativeTreasuryAddress, + 'MintTokens', + walletPk, + [] + ) + if (existingCommunityMint?.freezeAuthority) { + const freezeMintAuthorityPassIx = Token.createSetAuthorityInstruction( + TOKEN_PROGRAM_ID, + communityMintPk, + nativeTreasuryAddress, + 'FreezeAccount', + walletPk, + [] + ) + realmInstructions.push(freezeMintAuthorityPassIx) + } + realmInstructions.push(ix) + } - if (councilMintPk && councilMintHasMintAuthority) { - await withCreateMintGovernance( - realmInstructions, - programIdPk, - programVersion, - realmPk, + if ( + councilMintPk && + councilMintHasMintAuthority && + transferCouncilMintAuthority + ) { + const ix = Token.createSetAuthorityInstruction( + TOKEN_PROGRAM_ID, councilMintPk, - config, - transferCouncilMintAuthority, + nativeTreasuryAddress, + 'MintTokens', walletPk, - PublicKey.default, - walletPk, - walletPk + [] ) + if (existingCouncilMint?.freezeAuthority) { + const freezeMintAuthorityPassIx = Token.createSetAuthorityInstruction( + TOKEN_PROGRAM_ID, + councilMintPk, + nativeTreasuryAddress, + 'FreezeAccount', + walletPk, + [] + ) + realmInstructions.push(freezeMintAuthorityPassIx) + } + realmInstructions.push(ix) } // Set the community governance as the realm authority - if (transferCommunityMintAuthority) { + if (!skipRealmAuthority) { withSetRealmAuthority( realmInstructions, programIdPk, programVersion, realmPk, walletPk, - communityMintGovPk, + mainGovernancePk, SetRealmAuthorityAction.SetChecked ) } return { - communityMintGovPk, + mainGovernancePk, communityMintPk, councilMintPk, realmPk, diff --git a/tools/governance/units.ts b/tools/governance/units.ts index 54253e216b..c614a80778 100644 --- a/tools/governance/units.ts +++ b/tools/governance/units.ts @@ -1,22 +1,43 @@ -import { MintMaxVoteWeightSource } from '@solana/spl-governance' +import { + MintMaxVoteWeightSource, + MintMaxVoteWeightSourceType, +} from '@solana/spl-governance' import BN from 'bn.js' import { BigNumber } from 'bignumber.js' import { DISABLED_VOTER_WEIGHT } from '@tools/constants' import { MintInfo } from '@solana/spl-token' -import { fmtMintAmount } from '@tools/sdk/units' +import { + fmtMintAmount, + parseMintNaturalAmountFromDecimalAsBN, +} from '@tools/sdk/units' -export const parseMintMaxVoteWeight = (mintMaxVoteWeight) => { - let value = MintMaxVoteWeightSource.FULL_SUPPLY_FRACTION.value - if (mintMaxVoteWeight) { - const fraction = new BigNumber(mintMaxVoteWeight) - .shiftedBy(MintMaxVoteWeightSource.SUPPLY_FRACTION_DECIMALS) - .toString() - value = new BN(fraction) - } - - return new MintMaxVoteWeightSource({ - value, - }) +export const parseMintMaxVoteWeight = ( + useSupplyFactor: boolean, + communityMintDecimals: number, + supplyFactor?: number, + absoluteValue?: number +) => { + if (useSupplyFactor) { + return supplyFactor + ? new MintMaxVoteWeightSource({ + type: MintMaxVoteWeightSourceType.SupplyFraction, + value: new BN( + new BigNumber(supplyFactor.toString()) + .shiftedBy(MintMaxVoteWeightSource.SUPPLY_FRACTION_DECIMALS) + .toString() + ), + }) + : MintMaxVoteWeightSource.FULL_SUPPLY_FRACTION + } else + return new MintMaxVoteWeightSource({ + type: MintMaxVoteWeightSourceType.Absolute, + value: absoluteValue + ? parseMintNaturalAmountFromDecimalAsBN( + absoluteValue, + communityMintDecimals + ) + : new BN(1000), + }) } /// Chekcs if the given voter_weight is the disabled weight threshold diff --git a/tools/nftMinter.ts b/tools/nftMinter.ts index 6f54febf11..d8ce683880 100644 --- a/tools/nftMinter.ts +++ b/tools/nftMinter.ts @@ -1,170 +1,175 @@ import Arweave from 'arweave' -import { - CreateNftOutput, - findMasterEditionV2Pda, - findMetadataPda, - Metaplex, - Nft, - walletAdapterIdentity, -} from '@metaplex-foundation/js' -import { ConnectionContext } from '@utils/connection' -import { PublicKey } from '@solana/web3.js' -import { SignerWalletAdapter } from '@solana/wallet-adapter-base' -import { createVerifyCollectionInstruction } from '@metaplex-foundation/mpl-token-metadata' -import { - sendTransactionsV2, - SequenceType, - transactionInstructionsToTypedInstructionsSets, -} from '@utils/sendTransactions' -import { chunks } from '@utils/helpers' - -//Just some shity script to generate verified nfts with same pic x times -//Extracting pure instructions from metaplex to run this with crank was to time consuming so -//recommended use is autoclicker or keypair wallet to approve all transactions its one tx per 1 nft. -const nftNumber = 120 - -//collection key pk of your created collection that you are the owner and can verify new nfts with this key. -const collectionKeyPk = '3iBYdnzA418tD2o7vm85jBeXgxbdUyXzX9Qfm2XJuKME' - -//any img from web. -const nftImgUrl = - 'https://bafkreialxgkg6evd4hhc2awf4cq77vmtkdb3w76ajy2lsoem4afurptlom.ipfs.dweb.link/?ext=jpeg' - -//use your own arweave wallet and do not commit your wallet to repo. -const arweaveWalletJson: any = {} - -//i just place btn with onclick anywhere in ui to use it. -export const generateNft = async ( - connection: ConnectionContext, - userWallet: SignerWalletAdapter -) => { - const arweave = Arweave.init({ - host: 'arweave.net', - port: 443, - protocol: 'https', - timeout: 20000, // Network request timeouts in milliseconds - logging: false, // Disable network request logging - }) - - const metaplex = new Metaplex(connection.current) - metaplex.use(walletAdapterIdentity(userWallet)) - - const request = new XMLHttpRequest() - //read img to blob - request.open('GET', nftImgUrl, true) - request.responseType = 'blob' - request.send() - - request.onload = function () { - const reader = new FileReader() - reader.readAsArrayBuffer(request.response) - - reader.onload = async function () { - //save img of nft to arweave - const imageUrl = await uploadToArweave( - arweave, - reader.result!, - 'image/png' - ) - - //metadata with img url from arweave - const metadataRequest = JSON.stringify({ - name: 'My_nft', - description: 'nft_description', - image: imageUrl, - properties: { - category: '', - }, - }) - //save metadata to arweave - const metadataUrl = await uploadToArweave( - arweave, - metadataRequest, - 'application/json' - ) - - const nftsToVerify: (CreateNftOutput & { - nft: Nft - })[] = [] - - for (let i = 0; i < nftNumber; i++) { - try { - //create nfts - const mintNFTResponse = await metaplex - .nfts() - .create({ - //if you want mint to someone else then the connected wallet you can set owner here. - // owner: new PublicKey( - // '' - // ), - uri: metadataUrl!, - sellerFeeBasisPoints: 500, - name: `nft_nr_${nftNumber}`, - collection: collectionKeyPk - ? { - //you can't create verified nft right away so setting this to true will throw error. - verified: false, - key: new PublicKey(collectionKeyPk), - } - : undefined, - }) - .run() - console.log(mintNFTResponse) - nftsToVerify.push(mintNFTResponse) - } catch (e) { - console.log(e) - } - } - - const verifyInstructions = [ - ...nftsToVerify.map((x) => - //to set verified to true you need to run this seperated instruction - createVerifyCollectionInstruction({ - metadata: findMetadataPda(x.nft.mintAddress), - collectionAuthority: userWallet.publicKey!, - payer: userWallet.publicKey!, - collectionMint: x.nft.collection!.key, - collection: findMetadataPda(x.nft.collection!.key), - collectionMasterEditionAccount: findMasterEditionV2Pda( - x.nft.collection!.key - ), - }) - ), - ] - const nftsAccountsChunks = chunks(verifyInstructions, 10) - const signerChunks = Array(nftsAccountsChunks.length).fill([]) - - sendTransactionsV2({ - showUiComponent: true, - connection: connection.current, - wallet: userWallet, - TransactionInstructions: [...nftsAccountsChunks].map((x) => - transactionInstructionsToTypedInstructionsSets( - x, - SequenceType.Parallel - ) - ), - signersSet: signerChunks, - }) - } - } -} - -const uploadToArweave = async ( - arweave: Arweave, - data: string | ArrayBuffer | Uint8Array, - contentType: string -) => { - const transaction = await arweave.createTransaction({ - data: data, - }) - transaction.addTag('Content-Type', contentType) - - await arweave.transactions.sign(transaction, arweaveWalletJson) - await arweave.transactions.post(transaction) - - const id = transaction.id - const url = id ? `https://arweave.net/${id}` : undefined - - return url -} +// import { +// CreateNftOutput, +// findMasterEditionV2Pda, +// findMetadataPda, +// Metaplex, +// Nft, +// walletAdapterIdentity, +// } from '@metaplex-foundation/js' +// import { ConnectionContext } from '@utils/connection' +// import { PublicKey } from '@solana/web3.js' +// import { SignerWalletAdapter } from '@solana/wallet-adapter-base' +// import { createVerifyCollectionInstruction } from '@metaplex-foundation/mpl-token-metadata' +// import { +// sendTransactionsV3, +// SequenceType, +// txBatchesToInstructionSetWithSigners, +// } from '@utils/sendTransactions' +// import { chunks } from '@utils/helpers' + +// //Just some shity script to generate verified nfts with same pic x times +// //Extracting pure instructions from metaplex to run this with crank was to time consuming so +// //recommended use is autoclicker or keypair wallet to approve all transactions its one tx per 1 nft. +// const nftNumber = 120 + +// //collection key pk of your created collection that you are the owner and can verify new nfts with this key. +// const collectionKeyPk = '3iBYdnzA418tD2o7vm85jBeXgxbdUyXzX9Qfm2XJuKME' + +// //any img from web. +// const nftImgUrl = +// 'https://bafkreialxgkg6evd4hhc2awf4cq77vmtkdb3w76ajy2lsoem4afurptlom.ipfs.dweb.link/?ext=jpeg' + +// //use your own arweave wallet and do not commit your wallet to repo. +// const arweaveWalletJson: any = {} + +// //i just place btn with onclick anywhere in ui to use it. +// export const generateNft = async ( +// connection: ConnectionContext, +// userWallet: SignerWalletAdapter +// ) => { +// const arweave = Arweave.init({ +// host: 'arweave.net', +// port: 443, +// protocol: 'https', +// timeout: 20000, // Network request timeouts in milliseconds +// logging: false, // Disable network request logging +// }) + +// const metaplex = new Metaplex(connection.current) +// metaplex.use(walletAdapterIdentity(userWallet)) + +// const request = new XMLHttpRequest() +// //read img to blob +// request.open('GET', nftImgUrl, true) +// request.responseType = 'blob' +// request.send() + +// request.onload = function () { +// const reader = new FileReader() +// reader.readAsArrayBuffer(request.response) + +// reader.onload = async function () { +// //save img of nft to arweave +// const imageUrl = await uploadToArweave( +// arweave, +// reader.result!, +// 'image/png' +// ) + +// //metadata with img url from arweave +// const metadataRequest = JSON.stringify({ +// name: 'My_nft', +// description: 'nft_description', +// image: imageUrl, +// properties: { +// category: '', +// }, +// }) +// //save metadata to arweave +// const metadataUrl = await uploadToArweave( +// arweave, +// metadataRequest, +// 'application/json' +// ) + +// const nftsToVerify: (CreateNftOutput & { +// nft: Nft +// })[] = [] + +// for (let i = 0; i < nftNumber; i++) { +// try { +// //create nfts +// const mintNFTResponse = await metaplex +// .nfts() +// .create({ +// //if you want mint to someone else then the connected wallet you can set owner here. +// // owner: new PublicKey( +// // '' +// // ), +// uri: metadataUrl!, +// sellerFeeBasisPoints: 500, +// name: `nft_nr_${nftNumber}`, +// collection: collectionKeyPk +// ? { +// //you can't create verified nft right away so setting this to true will throw error. +// verified: false, +// key: new PublicKey(collectionKeyPk), +// } +// : undefined, +// }) +// .run() +// console.log(mintNFTResponse) +// nftsToVerify.push(mintNFTResponse) +// } catch (e) { +// console.log(e) +// } +// } + +// const verifyInstructions = [ +// ...nftsToVerify.map((x) => +// //to set verified to true you need to run this seperated instruction +// createVerifyCollectionInstruction({ +// metadata: findMetadataPda(x.nft.mintAddress), +// collectionAuthority: userWallet.publicKey!, +// payer: userWallet.publicKey!, +// collectionMint: x.nft.collection!.key, +// collection: findMetadataPda(x.nft.collection!.key), +// collectionMasterEditionAccount: findMasterEditionV2Pda( +// x.nft.collection!.key +// ), +// }) +// ), +// ] +// const nftsAccountsChunks = chunks(verifyInstructions, 10).map( +// (txBatch, batchIdx) => { +// return { +// instructionsSet: txBatchesToInstructionSetWithSigners( +// txBatch, +// [], +// batchIdx +// ), +// sequenceType: SequenceType.Parallel, +// } +// } +// ) + +// await sendTransactionsV3({ +// connection: connection.current, +// wallet: userWallet!, +// transactionInstructions: nftsAccountsChunks, +// }) +// } +// } +// } + +// const uploadToArweave = async ( +// arweave: Arweave, +// data: string | ArrayBuffer | Uint8Array, +// contentType: string +// ) => { +// const transaction = await arweave.createTransaction({ +// data: data, +// }) +// transaction.addTag('Content-Type', contentType) + +// await arweave.transactions.sign(transaction, arweaveWalletJson) +// await arweave.transactions.post(transaction) + +// const id = transaction.id +// const url = id ? `https://arweave.net/${id}` : undefined + +// return url +// } +//TODO fix when needed +console.log(Arweave) diff --git a/tools/nftVoteCalc.ts b/tools/nftVoteCalc.ts index 497d3cd4ec..6c3ba46ccf 100644 --- a/tools/nftVoteCalc.ts +++ b/tools/nftVoteCalc.ts @@ -1,4 +1,4 @@ -import { NftVoterClient } from '@solana/governance-program-library' +import { NftVoterClient } from '@utils/uiTypes/NftVoterClient' import { ChatMessageBody } from '@solana/spl-governance' import { Connection, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js' import { notify } from '@utils/notifications' @@ -7,6 +7,7 @@ import { getNftVoteRecordProgramAddress, getUsedNftsForProposal, } from 'NftVotePlugin/accounts' +import { getVotingNfts } from '@hooks/queries/plugins/nftVoter' //lamports costs hardcoded for now. //TODO figure out better cost handling @@ -17,23 +18,26 @@ const commentAvgCharacterCost = 6960 const singleTransactionCosts = 5000 export const calcCostOfNftVote = async ( + connection: Connection, comment: ChatMessageBody | undefined, numberOfTransactions: number, proposalPk: PublicKey, - votingPlugin: VotingClient + votingPlugin: VotingClient, + realmPk: PublicKey, + userPk: PublicKey ) => { let nftToVoteCount = 0 - const voterNfts = votingPlugin.votingNfts + const votingNfts = await getVotingNfts(connection, realmPk, userPk) const nftsAlreadyUsedToVote = await getUsedNftsForProposal( votingPlugin.client as NftVoterClient, proposalPk ) if (nftsAlreadyUsedToVote.length > 0) { - for (const nft of voterNfts) { + for (const nft of votingNfts) { const { nftVoteRecord } = await getNftVoteRecordProgramAddress( proposalPk, - nft.mintAddress, + nft.id, votingPlugin.client!.program.programId! ) if ( @@ -45,7 +49,7 @@ export const calcCostOfNftVote = async ( } } } else { - nftToVoteCount = voterNfts.length + nftToVoteCount = votingNfts.length } let baseCost = castVoteIxAndUpdateVoterWeightIxCost diff --git a/tools/routing.ts b/tools/routing.ts index 2ad2cc1a05..fe218f958b 100644 --- a/tools/routing.ts +++ b/tools/routing.ts @@ -3,5 +3,5 @@ import { RealmInfo } from 'models/registry/api' export function getRealmExplorerHost(realmInfo: RealmInfo | undefined) { return realmInfo?.symbol === 'MNGO' ? 'dao.mango.markets' - : 'realms-explorer.com' + : 'solscan.io' } diff --git a/tools/sagaPhone/mortar.ts b/tools/sagaPhone/mortar.ts deleted file mode 100644 index f82d8a0d0e..0000000000 --- a/tools/sagaPhone/mortar.ts +++ /dev/null @@ -1,139 +0,0 @@ -import BN from 'bn.js' - -import { - Connection, - Keypair, - PublicKey, - SystemProgram, - TransactionInstruction, -} from '@solana/web3.js' -import { Program, AnchorProvider } from '@project-serum/anchor' - -import { IDL, Mortar } from './schema' -import { ASSOCIATED_TOKEN_PROGRAM_ID, Token } from '@solana/spl-token' -import { tryGetTokenAccount } from '@utils/tokens' - -export const TOKEN_PROGRAM_ID = new PublicKey( - 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' -) - -export const MORTAR_PROGRAM_ID = new PublicKey( - '781wH11JGQgEoBkBzuc8uoQLtp8KxeHk1yZiS1JhFYKy' -) - -export const SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = new PublicKey( - 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL' -) - -export const USDC_MINT_ID = new PublicKey( - 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' -) - -export const USDC_DEVNET = new PublicKey( - 'HykjxVsY6NkdiHNcsENe1uHyesyW55ZYcHvdmsbt1uwK' -) - -export const MAINNET_ISSUER = new PublicKey( - 'FjnhLGXvCJzQ7EyTRwFWXz84WSJeTJBDoDzdqEpnt7Qv' -) - -export const DEVNET_ISSUER = new PublicKey( - '8aymYFSYaAW3g85itE5v6tewgNhTKKJpQB94WYD8KcAd' -) - -export const getATAKeySync = (mint: PublicKey, owner: PublicKey): PublicKey => { - return PublicKey.findProgramAddressSync( - [owner.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mint.toBuffer()], - SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID - )[0] -} - -export const getIssuerKey = (initializer: PublicKey, nonce: BN): PublicKey => { - return PublicKey.findProgramAddressSync( - [initializer.toBuffer(), Buffer.from(nonce.toArray('le', 8))], - MORTAR_PROGRAM_ID - )[0] -} - -export const getReceiptKey = ( - purchaser: PublicKey, - issuer: PublicKey -): PublicKey => { - return PublicKey.findProgramAddressSync( - [purchaser.toBuffer(), issuer.toBuffer()], - MORTAR_PROGRAM_ID - )[0] -} - -export const getPurchaseInstructions = async ( - feePayer: PublicKey, - issuer: PublicKey, - purchaser: PublicKey, - mint: PublicKey, // issuer.paymentMint - quantity: BN, - connection: Connection -): Promise => { - const program = new Program( - IDL, - MORTAR_PROGRAM_ID, - new AnchorProvider(null as any, Keypair.generate() as any, {}) - ) - - const transactionInstructions: TransactionInstruction[] = [] - - const receipt = getReceiptKey(purchaser, issuer) - - const receiptTokens = getATAKeySync(mint, receipt) - const purchaserTokens = getATAKeySync(mint, purchaser) - - const tokenAccount = await tryGetTokenAccount(connection, receiptTokens) - if (!tokenAccount) { - transactionInstructions.push( - Token.createAssociatedTokenAccountInstruction( - ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID - TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID - mint, // mint - receiptTokens, // ata - receipt, // owner of token account - feePayer // fee payer - ) - ) - } - - if (tokenAccount?.account.amount.isZero() || !tokenAccount) { - transactionInstructions.push( - program.instruction.purchaseWithPayer({ - accounts: { - issuer, - purchaser, - payer: feePayer, - receipt, - receiptTokens, - purchaserTokens, - systemProgram: SystemProgram.programId, - tokenProgram: TOKEN_PROGRAM_ID, - }, - }) - ) - } - - if ( - !quantity.eq(new BN(1)) || - (tokenAccount && !tokenAccount?.account.amount.isZero()) - ) { - transactionInstructions.push( - program.instruction.updateQuantity(quantity, { - accounts: { - issuer, - purchaser, - receipt, - receiptTokens, - purchaserTokens, - tokenProgram: TOKEN_PROGRAM_ID, - }, - }) - ) - } - - return transactionInstructions -} diff --git a/tools/sagaPhone/schema.ts b/tools/sagaPhone/schema.ts deleted file mode 100644 index c371d201a1..0000000000 --- a/tools/sagaPhone/schema.ts +++ /dev/null @@ -1,733 +0,0 @@ -export type Mortar = { - version: '0.1.0' - name: 'mortar' - instructions: [ - { - name: 'initialize' - accounts: [ - { - name: 'initializer' - isMut: true - isSigner: true - }, - { - name: 'paymentMint' - isMut: false - isSigner: false - }, - { - name: 'issuer' - isMut: true - isSigner: false - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'nonce' - type: 'u64' - }, - { - name: 'deposit' - type: 'u64' - }, - { - name: 'closingTime' - type: { - option: 'i64' - } - } - ] - }, - { - name: 'purchase' - accounts: [ - { - name: 'issuer' - isMut: true - isSigner: false - }, - { - name: 'purchaser' - isMut: true - isSigner: true - }, - { - name: 'receipt' - isMut: true - isSigner: false - }, - { - name: 'receiptTokens' - isMut: true - isSigner: false - }, - { - name: 'purchaserTokens' - isMut: true - isSigner: false - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - } - ] - args: [] - }, - { - name: 'refund' - accounts: [ - { - name: 'issuer' - isMut: false - isSigner: false - }, - { - name: 'purchaser' - isMut: false - isSigner: true - }, - { - name: 'receipt' - isMut: true - isSigner: false - }, - { - name: 'receiptTokens' - isMut: true - isSigner: false - }, - { - name: 'purchaserTokens' - isMut: true - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - } - ] - args: [] - }, - { - name: 'purchaseWithPayer' - accounts: [ - { - name: 'issuer' - isMut: true - isSigner: false - }, - { - name: 'purchaser' - isMut: false - isSigner: true - }, - { - name: 'payer' - isMut: true - isSigner: true - }, - { - name: 'receipt' - isMut: true - isSigner: false - }, - { - name: 'receiptTokens' - isMut: true - isSigner: false - }, - { - name: 'purchaserTokens' - isMut: true - isSigner: false - }, - { - name: 'systemProgram' - isMut: false - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - } - ] - args: [] - }, - { - name: 'updateQuantity' - accounts: [ - { - name: 'issuer' - isMut: false - isSigner: false - }, - { - name: 'purchaser' - isMut: false - isSigner: true - }, - { - name: 'receipt' - isMut: false - isSigner: false - }, - { - name: 'receiptTokens' - isMut: true - isSigner: false - }, - { - name: 'purchaserTokens' - isMut: true - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - } - ] - args: [ - { - name: 'newQuantity' - type: 'u64' - } - ] - }, - { - name: 'refundWithPayer' - accounts: [ - { - name: 'issuer' - isMut: false - isSigner: false - }, - { - name: 'purchaser' - isMut: false - isSigner: true - }, - { - name: 'payer' - isMut: true - isSigner: false - }, - { - name: 'receipt' - isMut: true - isSigner: false - }, - { - name: 'receiptTokens' - isMut: true - isSigner: false - }, - { - name: 'purchaserTokens' - isMut: true - isSigner: false - }, - { - name: 'tokenProgram' - isMut: false - isSigner: false - } - ] - args: [] - } - ] - accounts: [ - { - name: 'issuer' - type: { - kind: 'struct' - fields: [ - { - name: 'initializer' - type: 'publicKey' - }, - { - name: 'nonce' - type: 'u64' - }, - { - name: 'bump' - type: 'u8' - }, - { - name: 'paymentMint' - type: 'publicKey' - }, - { - name: 'deposit' - type: 'u64' - }, - { - name: 'ticketsIssued' - type: 'u64' - }, - { - name: 'closingTime' - type: { - option: 'i64' - } - } - ] - } - }, - { - name: 'receipt' - type: { - kind: 'struct' - fields: [ - { - name: 'purchaser' - type: 'publicKey' - }, - { - name: 'issuer' - type: 'publicKey' - }, - { - name: 'bump' - type: 'u8' - }, - { - name: 'ticketNumber' - type: 'u64' - } - ] - } - }, - { - name: 'receiptWithPayer' - type: { - kind: 'struct' - fields: [ - { - name: 'purchaser' - type: 'publicKey' - }, - { - name: 'issuer' - type: 'publicKey' - }, - { - name: 'bump' - type: 'u8' - }, - { - name: 'ticketNumber' - type: 'u64' - }, - { - name: 'payer' - type: 'publicKey' - } - ] - } - } - ] - errors: [ - { - code: 6000 - name: 'MissingBumpSeed' - msg: 'Missing anchor bump seed' - }, - { - code: 6001 - name: 'ArithmeticOverflow' - msg: 'Arithmetic overflow' - }, - { - code: 6002 - name: 'IssuerClosed' - msg: 'Issuer closed' - }, - { - code: 6003 - name: 'InvalidQuantity' - msg: 'Invalid quantity' - } - ] -} - -export const IDL: Mortar = { - version: '0.1.0', - name: 'mortar', - instructions: [ - { - name: 'initialize', - accounts: [ - { - name: 'initializer', - isMut: true, - isSigner: true, - }, - { - name: 'paymentMint', - isMut: false, - isSigner: false, - }, - { - name: 'issuer', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'nonce', - type: 'u64', - }, - { - name: 'deposit', - type: 'u64', - }, - { - name: 'closingTime', - type: { - option: 'i64', - }, - }, - ], - }, - { - name: 'purchase', - accounts: [ - { - name: 'issuer', - isMut: true, - isSigner: false, - }, - { - name: 'purchaser', - isMut: true, - isSigner: true, - }, - { - name: 'receipt', - isMut: true, - isSigner: false, - }, - { - name: 'receiptTokens', - isMut: true, - isSigner: false, - }, - { - name: 'purchaserTokens', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - ], - args: [], - }, - { - name: 'refund', - accounts: [ - { - name: 'issuer', - isMut: false, - isSigner: false, - }, - { - name: 'purchaser', - isMut: false, - isSigner: true, - }, - { - name: 'receipt', - isMut: true, - isSigner: false, - }, - { - name: 'receiptTokens', - isMut: true, - isSigner: false, - }, - { - name: 'purchaserTokens', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - ], - args: [], - }, - { - name: 'purchaseWithPayer', - accounts: [ - { - name: 'issuer', - isMut: true, - isSigner: false, - }, - { - name: 'purchaser', - isMut: false, - isSigner: true, - }, - { - name: 'payer', - isMut: true, - isSigner: true, - }, - { - name: 'receipt', - isMut: true, - isSigner: false, - }, - { - name: 'receiptTokens', - isMut: true, - isSigner: false, - }, - { - name: 'purchaserTokens', - isMut: true, - isSigner: false, - }, - { - name: 'systemProgram', - isMut: false, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - ], - args: [], - }, - { - name: 'updateQuantity', - accounts: [ - { - name: 'issuer', - isMut: false, - isSigner: false, - }, - { - name: 'purchaser', - isMut: false, - isSigner: true, - }, - { - name: 'receipt', - isMut: false, - isSigner: false, - }, - { - name: 'receiptTokens', - isMut: true, - isSigner: false, - }, - { - name: 'purchaserTokens', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: 'newQuantity', - type: 'u64', - }, - ], - }, - { - name: 'refundWithPayer', - accounts: [ - { - name: 'issuer', - isMut: false, - isSigner: false, - }, - { - name: 'purchaser', - isMut: false, - isSigner: true, - }, - { - name: 'payer', - isMut: true, - isSigner: false, - }, - { - name: 'receipt', - isMut: true, - isSigner: false, - }, - { - name: 'receiptTokens', - isMut: true, - isSigner: false, - }, - { - name: 'purchaserTokens', - isMut: true, - isSigner: false, - }, - { - name: 'tokenProgram', - isMut: false, - isSigner: false, - }, - ], - args: [], - }, - ], - accounts: [ - { - name: 'issuer', - type: { - kind: 'struct', - fields: [ - { - name: 'initializer', - type: 'publicKey', - }, - { - name: 'nonce', - type: 'u64', - }, - { - name: 'bump', - type: 'u8', - }, - { - name: 'paymentMint', - type: 'publicKey', - }, - { - name: 'deposit', - type: 'u64', - }, - { - name: 'ticketsIssued', - type: 'u64', - }, - { - name: 'closingTime', - type: { - option: 'i64', - }, - }, - ], - }, - }, - { - name: 'receipt', - type: { - kind: 'struct', - fields: [ - { - name: 'purchaser', - type: 'publicKey', - }, - { - name: 'issuer', - type: 'publicKey', - }, - { - name: 'bump', - type: 'u8', - }, - { - name: 'ticketNumber', - type: 'u64', - }, - ], - }, - }, - { - name: 'receiptWithPayer', - type: { - kind: 'struct', - fields: [ - { - name: 'purchaser', - type: 'publicKey', - }, - { - name: 'issuer', - type: 'publicKey', - }, - { - name: 'bump', - type: 'u8', - }, - { - name: 'ticketNumber', - type: 'u64', - }, - { - name: 'payer', - type: 'publicKey', - }, - ], - }, - }, - ], - errors: [ - { - code: 6000, - name: 'MissingBumpSeed', - msg: 'Missing anchor bump seed', - }, - { - code: 6001, - name: 'ArithmeticOverflow', - msg: 'Arithmetic overflow', - }, - { - code: 6002, - name: 'IssuerClosed', - msg: 'Issuer closed', - }, - { - code: 6003, - name: 'InvalidQuantity', - msg: 'Invalid quantity', - }, - ], -} diff --git a/tools/sdk/solend/depositReserveLiquidityAndObligationCollateral.ts b/tools/sdk/solend/depositReserveLiquidityAndObligationCollateral.ts index ff73cedfa4..57f25bbfb5 100644 --- a/tools/sdk/solend/depositReserveLiquidityAndObligationCollateral.ts +++ b/tools/sdk/solend/depositReserveLiquidityAndObligationCollateral.ts @@ -1,4 +1,4 @@ -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { PublicKey } from '@solana/web3.js' import { depositReserveLiquidityAndObligationCollateralInstruction } from '@solendprotocol/solend-sdk' import { SupportedMintName } from './configuration' diff --git a/tools/sdk/solend/withdrawObligationCollateralAndRedeemReserveLiquidity.ts b/tools/sdk/solend/withdrawObligationCollateralAndRedeemReserveLiquidity.ts index 2208a7fc52..c0f513ee7f 100644 --- a/tools/sdk/solend/withdrawObligationCollateralAndRedeemReserveLiquidity.ts +++ b/tools/sdk/solend/withdrawObligationCollateralAndRedeemReserveLiquidity.ts @@ -1,4 +1,4 @@ -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { PublicKey } from '@solana/web3.js' import { withdrawObligationCollateralAndRedeemReserveLiquidity as originalWithdrawFunction } from '@solendprotocol/solend-sdk' import { findATAAddrSync } from '@utils/ataTools' diff --git a/tools/sdk/units.ts b/tools/sdk/units.ts index 1c073f16d6..d01ba1d2b4 100644 --- a/tools/sdk/units.ts +++ b/tools/sdk/units.ts @@ -1,6 +1,6 @@ -import { BN, ProgramAccount } from '@project-serum/anchor' +import { BN, ProgramAccount } from '@coral-xyz/anchor' import { MintInfo } from '@solana/spl-token' -import { TokenInfo } from '@solana/spl-token-registry' +import { TokenInfoWithoutDecimals } from '@utils/services/tokenPrice' import { BigNumber } from 'bignumber.js' const SECONDS_PER_DAY = 86400 @@ -9,14 +9,29 @@ export function getDaysFromTimestamp(unixTimestamp: number) { return unixTimestamp / SECONDS_PER_DAY } +export function getHoursFromTimestamp(unixTimestamp: number) { + return unixTimestamp / (60 * 60) +} + export function getTimestampFromDays(days: number) { return days * SECONDS_PER_DAY } +export function getTimestampFromHours(hours: number) { + return hours * 60 * 60 +} + export function fmtBnMintDecimals(amount: BN, decimals: number) { return new BigNumber(amount.toString()).shiftedBy(-decimals).toFormat() } +export function fmtBnMintDecimalsUndelimited(amount: BN, decimals: number) { + return new BigNumber(amount.toString()) + .shiftedBy(-decimals) + .toFormat() + .replaceAll(',', '') +} + export function fmtBNAmount(amount: BN | number | string) { return new BigNumber(amount.toString()).toFormat() } @@ -31,7 +46,7 @@ export function fmtMintAmount(mint: MintInfo | undefined, mintAmount: BN) { export function fmtTokenInfoWithMint( amount: BN, mintInfo: ProgramAccount, - tokenInfo: TokenInfo | undefined = undefined + tokenInfo: TokenInfoWithoutDecimals | undefined = undefined ) { return `${fmtBnMintDecimals(amount, mintInfo.account.decimals)} ${ tokenInfo?.symbol @@ -44,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()) @@ -120,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 ) { @@ -137,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) { diff --git a/tools/validators/accounts/token.ts b/tools/validators/accounts/token.ts index 498d7c7341..3c91a196d7 100644 --- a/tools/validators/accounts/token.ts +++ b/tools/validators/accounts/token.ts @@ -1,7 +1,5 @@ // Copied from Explorer code https://github.com/solana-labs/solana/blob/master/explorer/src/validators/accounts/token.ts -import { PublicKey } from '@solana/web3.js' -import { TokenProgramAccount, TokenAccount } from '@utils/tokens' import { Infer, number, @@ -13,7 +11,6 @@ import { } from 'superstruct' import { PublicKeyFromString } from '../pubkey' -export type TokenAccountState = Infer const AccountState = enums(['initialized', 'uninitialized', 'frozen']) const TokenAmount = type({ @@ -23,7 +20,7 @@ const TokenAmount = type({ }) export type TokenAccountInfo = Infer -export const TokenAccountInfo = type({ +const TokenAccountInfo = type({ mint: PublicKeyFromString, owner: PublicKeyFromString, tokenAmount: TokenAmount, @@ -34,12 +31,3 @@ export const TokenAccountInfo = type({ delegatedAmount: optional(TokenAmount), closeAuthority: optional(PublicKeyFromString), }) - -export function validateTokenAccountMint( - tokenAccount: TokenProgramAccount, - mint: PublicKey | undefined -) { - if (mint && tokenAccount.account.mint.toBase58() !== mint.toBase58()) { - throw new Error("Account mint doesn't match source account") - } -} diff --git a/tools/validators/accounts/upgradeable-program.ts b/tools/validators/accounts/upgradeable-program.ts index cb5a8299a1..21b545e011 100644 --- a/tools/validators/accounts/upgradeable-program.ts +++ b/tools/validators/accounts/upgradeable-program.ts @@ -1,8 +1,6 @@ // Copied from Explorer code https://github.com/solana-labs/solana/blob/master/explorer/src/validators/accounts/upgradeable-program.ts -import { ParsedAccountData, AccountInfo, PublicKey } from '@solana/web3.js' - -import { type, number, literal, nullable, Infer, create } from 'superstruct' +import { type, number, literal, nullable, Infer } from 'superstruct' import { PublicKeyFromString } from '../pubkey' export type ProgramAccountInfo = Infer @@ -40,29 +38,3 @@ export const ProgramBufferAccount = type({ type: literal('buffer'), info: ProgramBufferAccountInfo, }) - -export function validateProgramBufferAccount( - info: AccountInfo, - bufferAuthority: PublicKey -) { - if ( - !('parsed' in info.data && info.data.program === 'bpf-upgradeable-loader') - ) { - throw new Error('Invalid program buffer account') - } - - let buffer: ProgramBufferAccount - - try { - buffer = create(info.data.parsed, ProgramBufferAccount) - } catch { - throw new Error('Invalid program buffer account') - } - - if (buffer.info.authority?.toBase58() !== bufferAuthority.toBase58()) { - throw new Error( - `Buffer authority must be set to governance account - ${bufferAuthority.toBase58()}` - ) - } -} diff --git a/tools/validators/pubkey.ts b/tools/validators/pubkey.ts index a6db5b3cdc..5bcf451982 100644 --- a/tools/validators/pubkey.ts +++ b/tools/validators/pubkey.ts @@ -1,6 +1,9 @@ import { coerce, instance, string } from 'superstruct' import { PublicKey } from '@solana/web3.js' +import { getConnectionContext } from '@utils/connection' +import { resolveDomain } from '@utils/domains' + export const PublicKeyFromString = coerce( instance(PublicKey), string(), @@ -14,3 +17,19 @@ export const tryParseKey = (key: string): PublicKey | null => { return null } } + +export const tryParseDomain = async ( + domain: string +): Promise => { + const { current: connection } = getConnectionContext('mainnet') + try { + const publicKey = await resolveDomain( + connection, + domain.toLowerCase().trim() + ) + + return publicKey ?? null + } catch (error) { + return null + } +} diff --git a/tsconfig.json b/tsconfig.json index c5b2ff3b6b..f4e8171cc9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "sourceMap": true, "baseUrl": ".", "target": "es6", "lib": ["dom", "dom.iterable", "esnext"], @@ -16,7 +17,10 @@ "jsx": "preserve", "paths": { "@components/*": ["components/*"], + "@constants/*": ["constants/*"], "@hooks/*": ["hooks/*"], + "@hub/*": ["hub/*"], + "@verify-wallet/*": ["verify-wallet/*"], "@tools/*": ["tools/*"], "@models/*": ["models/*"], "@utils/*": ["utils/*"] @@ -24,7 +28,7 @@ "incremental": true, "isolatedModules": true }, - "exclude": ["node_modules", ".next", "out", "docs"], + "exclude": ["node_modules/**/*", ".next", "out", "docs"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"], "ts-node": { "require": ["tsconfig-paths/register"], diff --git a/utils/Foresight/index.tsx b/utils/Foresight/index.tsx deleted file mode 100644 index 494b848005..0000000000 --- a/utils/Foresight/index.tsx +++ /dev/null @@ -1,415 +0,0 @@ -import _ from 'lodash' -import useGovernanceAssets from '@hooks/useGovernanceAssets' -import { - governance as foresightGov, - consts as foresightConsts, -} from '@foresight-tmp/foresight-sdk' -import { isFormValid } from '@utils/formValidation' -import { AssetAccount } from '@utils/uiTypes/assets' -import { - Governance, - ProgramAccount, - serializeInstructionToBase64, -} from '@solana/spl-governance' -import GovernedAccountSelect from '../../pages/dao/[symbol]/proposal/components/GovernedAccountSelect' -import { Dispatch, useContext, useEffect, useState } from 'react' -import { - ForesightHasCategoryId, - ForesightHasGovernedAccount, - ForesightHasMarketId, - ForesightHasMarketListId, - ForesightMakeResolveMarketParams, - ForesightMakeSetMarketMetadataParams, - UiInstruction, -} from '@utils/uiTypes/proposalCreationTypes' -import Input from '@components/inputs/Input' -import { SignerWalletAdapter } from '@solana/wallet-adapter-base' -import { PublicKey, TransactionInstruction } from '@solana/web3.js' -import * as yup from 'yup' -import { ObjectSchema, StringSchema, NumberSchema } from 'yup' -import useRealm from '@hooks/useRealm' -import useWalletStore from 'stores/useWalletStore' -import { NewProposalContext } from '../../pages/dao/[symbol]/proposal/new' -import Select from '@components/inputs/Select' -import TextareaProps from '@components/inputs/Textarea' - -type EmptyObject = Record -type SetFormErrors = Dispatch> - -export function getFilteredTokenAccounts(): AssetAccount[] { - const { governedTokenAccountsWithoutNfts } = useGovernanceAssets() - return governedTokenAccountsWithoutNfts.filter((x) => { - const transferAddress = x.extensions.transferAddress - return ( - transferAddress?.equals(foresightGov.DEVNET_TREASURY) || - transferAddress?.equals(foresightGov.MAINNET_TREASURY) - ) - }) -} - -type HandleSetForm = ({ - propertyName, - value, -}: { - propertyName: string - value: any -}) => void - -type HandleSetInstructions = ( - val: { - governedAccount: ProgramAccount | undefined - getInstruction: GetInstruction - }, - index: number -) => void - -function makeValidateInstruction( - schema: ObjectSchema, - form: ForesightHasGovernedAccount, - setFormErrors: SetFormErrors -): () => Promise { - async function validateInstruction(): Promise { - const { isValid, validationErrors } = await isFormValid(schema, form) - setFormErrors(validationErrors) - return isValid - } - return validateInstruction -} - -function makeHandleSetFormWithErrors( - form: T, - setForm: Dispatch>, - setFormErrors: SetFormErrors -): HandleSetForm { - function handleSetForm({ - propertyName, - value, - }: { - propertyName: string - value: any - }) { - setFormErrors({}) - setForm({ ...form, [propertyName]: value }) - } - return handleSetForm -} - -type GetInstruction = () => Promise - -type IxCreator = ( - form: T -) => Promise - -function makeGetInstruction( - ixCreator: IxCreator, - form: T, - programId: PublicKey | undefined, - wallet: SignerWalletAdapter | undefined, - schema: ObjectSchema, - setFormErrors: SetFormErrors -): GetInstruction { - const validateInstruction = makeValidateInstruction( - schema, - form, - setFormErrors - ) - async function getInstruction(): Promise { - const isValid = await validateInstruction() - let serializedInstruction = '' - if (isValid && programId && wallet?.publicKey) { - const ix = await ixCreator(form) - serializedInstruction = serializeInstructionToBase64(ix) - } - return getUiInstruction(serializedInstruction, isValid, form) - } - return getInstruction -} - -type NonDefault = Omit< - T, - 'governedAccount' -> -type ValueOf = T[keyof T] -type AllowedSchema = NumberSchema | StringSchema - -function defaultValToYupSchema( - val: ValueOf> -): AllowedSchema { - if (typeof val === 'number') { - return yup.number().required() - } - return yup.string().required() -} - -type formEntryToSchema = { - [name in keyof NonDefault]: AllowedSchema -} - -export function commonAssets( - formDefaults: NonDefault, - index: number, - governance: ProgramAccount | null -): { - inputProps: InputProps - effector: (ixCreator: IxCreator) => void - governedAccountSelect: JSX.Element - wallet: SignerWalletAdapter | undefined -} { - const extraSchemaFields: formEntryToSchema = _.mapValues( - formDefaults, - defaultValToYupSchema - ) - const schema = getSchema(extraSchemaFields) - const wallet = useWalletStore((s) => s.current) - const filteredTokenAccounts = getFilteredTokenAccounts() - const [formErrors, setFormErrors] = useState({}) - const { handleSetInstructions } = useContext(NewProposalContext) - const [form, setForm] = useState({ - governedAccount: filteredTokenAccounts[0], - ...formDefaults, - } as T) - const handleSetForm = makeHandleSetFormWithErrors( - form, - setForm, - setFormErrors - ) - const inputProps = { - form, - handleSetForm, - formErrors, - } - function effector(ixCreator: IxCreator): void { - ForesightUseEffects( - handleSetForm, - form, - handleSetInstructions, - ixCreator, - wallet, - schema, - setFormErrors, - index - ) - } - const governedAccountSelect = ( - - ) - return { - inputProps, - effector, - governedAccountSelect, - wallet, - } -} - -function ForesightUseEffects( - handleSetForm: HandleSetForm, - form: T, - handleSetInstructions: HandleSetInstructions, - ixCreator: IxCreator, - wallet: SignerWalletAdapter | undefined, - schema: ObjectSchema, - setFormErrors: SetFormErrors, - index: number -): void { - const { realmInfo } = useRealm() - const programId: PublicKey | undefined = realmInfo?.programId - const getInstruction = makeGetInstruction( - ixCreator, - form, - programId, - wallet, - schema, - setFormErrors - ) - useEffect(() => { - handleSetForm({ - propertyName: 'programId', - value: programId?.toString(), - }) - }, [programId]) - - useEffect(() => { - handleSetInstructions( - { governedAccount: form.governedAccount?.governance, getInstruction }, - index - ) - }, [form]) -} - -export function getSchema( - extraFields: { - [name in keyof Omit]: StringSchema | NumberSchema - } -) { - return yup.object().shape({ - governedAccount: yup - .object() - .nullable() - .required('Program governed account is required'), - ...extraFields, - }) -} - -function getUiInstruction( - serializedInstruction: string, - isValid: boolean, - form: ForesightHasGovernedAccount -): UiInstruction { - return { - serializedInstruction: serializedInstruction, - isValid, - governance: form.governedAccount?.governance, - } -} - -function ForesightGovernedAccountSelect(props: { - filteredTokenAccounts: AssetAccount[] - form: ForesightHasGovernedAccount - handleSetForm: HandleSetForm - index: number - governance: ProgramAccount | null -}) { - const shouldBeGoverned = props.index !== 0 && props.governance - return ( - { - props.handleSetForm({ value, propertyName: 'governedAccount' }) - }} - value={props.form.governedAccount} - shouldBeGoverned={shouldBeGoverned} - governance={props.governance} - > - ) -} - -type InputProps = { - form: T - handleSetForm: HandleSetForm - formErrors: EmptyObject -} - -export function ForesightCategoryIdInput( - props: InputProps -) { - return ( - + + + + ), + }, + serviceEndpoint: { + label: 'Endpoint', + initialValue: '', + inputType: 'text', + name: 'serviceEndpoint', + type: InstructionInputType.INPUT, + additionalComponent: ( + + + + + + ), + }, + serviceType: { + label: 'Type', + initialValue: '', + inputType: 'text', + name: 'serviceType', + type: InstructionInputType.INPUT, + additionalComponent: ( + + + + + + ), + }, + alias: { + label: 'Alias', + initialValue: '', + inputType: 'text', + name: 'alias', + type: InstructionInputType.INPUT, + additionalComponent: ( + + + + + + ), + }, +} + +// Given a governed account, return a Wallet that can be passed into the sol-did-client +// The eventual signer of the transaction is the governed account PDA, so passing this as the +// wallet into the sol-did-client ensures the correct public key is set as the signer in the instructions. +// The transactions are not signed now, but only after voting, so the signTransaction functions are no-ops. +export const governedAccountToWallet = ( + governedAccount: AssetAccount +): Wallet => ({ + publicKey: governedAccount.governance.pubkey, + // noop signers, as we use this just to pass the public key + signTransaction: async (tx) => tx, + signAllTransactions: async (txs) => txs, +}) diff --git a/utils/instructions/Mean/createPaymentStreaming.ts b/utils/instructions/Mean/createPaymentStreaming.ts new file mode 100644 index 0000000000..0d16b45361 --- /dev/null +++ b/utils/instructions/Mean/createPaymentStreaming.ts @@ -0,0 +1,23 @@ +import { PaymentStreaming } from '@mean-dao/payment-streaming' +import { PublicKey } from '@solana/web3.js' +import { ConnectionContext } from '@utils/connection' + +const STREAM_V2_PROGRAM_ADDRESS_DEVNET = + 'MSPdQo5ZdrPh6rU1LsvUv5nRhAnj1mj6YQEqBUq8YwZ' +const STREAM_V2_PROGRAM_ADDRESS_MAINNET = + 'MSPCUMbLfy2MeT6geLMMzrUkv1Tx88XRApaVRdyxTuu' + +export default function (connection: ConnectionContext) { + const streamV2ProgramAddressString = + connection.cluster === 'mainnet' + ? STREAM_V2_PROGRAM_ADDRESS_MAINNET + : STREAM_V2_PROGRAM_ADDRESS_DEVNET + + const streamV2ProgramAddress = new PublicKey(streamV2ProgramAddressString) + + return new PaymentStreaming( + connection.current, + streamV2ProgramAddress, + 'confirmed' + ) +} diff --git a/utils/instructions/Mean/getMeanCreateAccountInstruction.ts b/utils/instructions/Mean/getMeanCreateAccountInstruction.ts new file mode 100644 index 0000000000..cdb58e9bdb --- /dev/null +++ b/utils/instructions/Mean/getMeanCreateAccountInstruction.ts @@ -0,0 +1,103 @@ +import { serializeInstructionToBase64 } from '@solana/spl-governance' +import { PublicKey } from '@solana/web3.js' + +import { parseMintNaturalAmountFromDecimal } from '@tools/sdk/units' +import { ConnectionContext } from '@utils/connection' +import { validateInstruction } from '@utils/instructionTools' +import { AssetAccount } from '@utils/uiTypes/assets' +import { + MeanCreateAccount, + UiInstruction, +} from '@utils/uiTypes/proposalCreationTypes' +import createPaymentStreaming from './createPaymentStreaming' + +interface Args { + connection: ConnectionContext + form: MeanCreateAccount + setFormErrors: any // TODO + schema: any // TODO +} + +function getGovernedAccountPk(acc: AssetAccount): PublicKey { + return (acc.isSol + ? acc.extensions.transferAddress + : acc.extensions?.token?.account?.owner) as PublicKey +} + +export default async function getMeanCreateAccountInstruction({ + connection, + form, + schema, + setFormErrors, +}: Args): Promise { + const isValid = await validateInstruction({ schema, form, setFormErrors }) + + const serializedInstruction = '' + const governedTokenAccount = form.governedTokenAccount + + if ( + isValid && + governedTokenAccount && + form.label && + form.amount && + governedTokenAccount.extensions.mint + ) { + const paymentStreaming = createPaymentStreaming(connection) + const feePayer = getGovernedAccountPk(governedTokenAccount) + const mint = governedTokenAccount.extensions.mint.publicKey + const label = form.label + const owner = governedTokenAccount.governance.pubkey + const type = form.type + + console.log('111111', { owner, feePayer, mint }, label, type) + const { + transaction: transaction1, + psAccount, + } = await paymentStreaming.buildCreateAccountTransaction( + { owner, feePayer, mint }, + label, + type + ) + + const contributor = feePayer + + const amount = parseMintNaturalAmountFromDecimal( + form.amount, + governedTokenAccount.extensions.mint.account.decimals + ) + console.log( + '2222[', + { psAccount, psAccountMint: mint, contributor, feePayer }, + amount + ) + const { + transaction: transaction2, + } = await paymentStreaming.buildAddFundsToAccountTransaction( + { psAccount, psAccountMint: mint, contributor, feePayer }, + amount + ) + + const additionalSerializedInstructions = [ + ...transaction1.instructions, + ...transaction2.instructions, + ].map(serializeInstructionToBase64) + + const obj: UiInstruction = { + serializedInstruction, + isValid: true, + governance: governedTokenAccount?.governance, + additionalSerializedInstructions, + chunkBy: 1, + } + return obj + } + + const obj: UiInstruction = { + serializedInstruction, + isValid: false, + governance: governedTokenAccount?.governance, + additionalSerializedInstructions: [], + chunkBy: 1, + } + return obj +} diff --git a/utils/instructions/Mean/getMeanCreateStreamInstruction.ts b/utils/instructions/Mean/getMeanCreateStreamInstruction.ts new file mode 100644 index 0000000000..ae4accd57a --- /dev/null +++ b/utils/instructions/Mean/getMeanCreateStreamInstruction.ts @@ -0,0 +1,127 @@ +import { PaymentStreamingAccount } from '@mean-dao/payment-streaming' +import { serializeInstructionToBase64 } from '@solana/spl-governance' +import { PublicKey } from '@solana/web3.js' + +import { parseMintNaturalAmountFromDecimal } from '@tools/sdk/units' +import { ConnectionContext } from '@utils/connection' +import { validateInstruction } from '@utils/instructionTools' +import { AssetAccount } from '@utils/uiTypes/assets' +import { + MeanCreateStream, + UiInstruction, +} from '@utils/uiTypes/proposalCreationTypes' +import createPaymentStreaming from './createPaymentStreaming' + +interface Args { + connection: ConnectionContext + form: MeanCreateStream + setFormErrors: any // TODO + schema: any // TODO +} + +function getGovernedAccountPk(acc: AssetAccount): PublicKey { + return (acc.isSol + ? acc.extensions.transferAddress + : acc.extensions?.token?.account?.owner) as PublicKey +} + +const getRateIntervalInSeconds = ( + interval: MeanCreateStream['rateInterval'] +) => { + switch (interval) { + case 0: + return 60 + case 1: + return 3600 + case 2: + return 86400 + case 3: + return 604800 + case 4: + return 2629750 + case 5: + return 31557000 + } +} + +export default async function getMeanCreateStreamInstruction({ + connection, + form, + schema, + setFormErrors, +}: //setFormErrors +Args): Promise { + const isValid = await validateInstruction({ schema, form, setFormErrors }) + + const serializedInstruction = '' + const governedTokenAccount = form.governedTokenAccount + + const formPaymentStreamingAccount = form.paymentStreamingAccount as + | PaymentStreamingAccount + | undefined + + if ( + isValid && + governedTokenAccount && + formPaymentStreamingAccount && + form.destination && + form.streamName && + governedTokenAccount.extensions.mint && + form.allocationAssigned && + form.rateAmount && + form.mintInfo + ) { + const paymentStreaming = createPaymentStreaming(connection) + + const feePayer = getGovernedAccountPk(governedTokenAccount) + const owner = governedTokenAccount.governance.pubkey + const psAccount = new PublicKey(formPaymentStreamingAccount.id) + const beneficiary = new PublicKey(form.destination) + const streamName = form.streamName + const allocationAssigned = parseMintNaturalAmountFromDecimal( + form.allocationAssigned, + form.mintInfo.decimals + ) + const rateAmount = parseMintNaturalAmountFromDecimal( + form.rateAmount, + form.mintInfo.decimals + ) + const rateIntervalInSeconds = getRateIntervalInSeconds(form.rateInterval) + const startUtc = new Date(form.startDate) + const usePda = true + + const { transaction } = await paymentStreaming.buildCreateStreamTransaction( + { psAccount, owner, feePayer, beneficiary }, + streamName, + rateAmount, + rateIntervalInSeconds, + allocationAssigned, + startUtc, + undefined, + undefined, + undefined, + usePda + ) + + const additionalSerializedInstructions = transaction.instructions.map( + serializeInstructionToBase64 + ) + + const obj: UiInstruction = { + serializedInstruction, + isValid: true, + governance: governedTokenAccount?.governance, + additionalSerializedInstructions, + } + return obj + } + + const obj: UiInstruction = { + serializedInstruction, + isValid: false, + governance: governedTokenAccount?.governance, + additionalSerializedInstructions: [], + } + + return obj +} diff --git a/utils/instructions/Mean/getMeanFundAccountInstruction.ts b/utils/instructions/Mean/getMeanFundAccountInstruction.ts new file mode 100644 index 0000000000..5fa054d4f7 --- /dev/null +++ b/utils/instructions/Mean/getMeanFundAccountInstruction.ts @@ -0,0 +1,86 @@ +import { PaymentStreamingAccount } from '@mean-dao/payment-streaming' +import { serializeInstructionToBase64 } from '@solana/spl-governance' +import { PublicKey } from '@solana/web3.js' + +import { parseMintNaturalAmountFromDecimal } from '@tools/sdk/units' +import { ConnectionContext } from '@utils/connection' +import { validateInstruction } from '@utils/instructionTools' +import { AssetAccount } from '@utils/uiTypes/assets' +import { + MeanFundAccount, + UiInstruction, +} from '@utils/uiTypes/proposalCreationTypes' +import createPaymentStreaming from './createPaymentStreaming' + +function getGovernedAccountPk(acc: AssetAccount): PublicKey { + return (acc.isSol + ? acc.extensions.transferAddress + : acc.extensions?.token?.account?.owner) as PublicKey +} + +interface Args { + connection: ConnectionContext + form: MeanFundAccount + setFormErrors: any // TODO + schema: any // TODO +} +export default async function getMeanCreateAccountInstruction({ + connection, + form, + setFormErrors, + schema, +}: Args): Promise { + const isValid = await validateInstruction({ schema, form, setFormErrors }) + + const serializedInstruction = '' + const governedTokenAccount = form.governedTokenAccount + + const formPaymentStreamingAccount = form.paymentStreamingAccount as + | PaymentStreamingAccount + | undefined + + if ( + isValid && + governedTokenAccount && + formPaymentStreamingAccount && + form.amount && + governedTokenAccount.extensions.mint + ) { + const paymentStreaming = createPaymentStreaming(connection) + const feePayer = getGovernedAccountPk(governedTokenAccount) + const contributor = feePayer + const mint = governedTokenAccount.extensions.mint.publicKey + const psAccount = new PublicKey(formPaymentStreamingAccount.id) + const amount = parseMintNaturalAmountFromDecimal( + form.amount, + governedTokenAccount.extensions.mint.account.decimals + ) + const { + transaction, + } = await paymentStreaming.buildAddFundsToAccountTransaction( + { psAccount, psAccountMint: mint, contributor, feePayer }, + amount + ) + + const additionalSerializedInstructions = transaction.instructions.map( + serializeInstructionToBase64 + ) + + const obj: UiInstruction = { + serializedInstruction, + isValid: true, + governance: governedTokenAccount?.governance, + additionalSerializedInstructions, + } + return obj + } + + const obj: UiInstruction = { + serializedInstruction, + isValid: false, + governance: governedTokenAccount?.governance, + additionalSerializedInstructions: [], + } + + return obj +} diff --git a/utils/instructions/Mean/getMeanTransferStreamInstruction.ts b/utils/instructions/Mean/getMeanTransferStreamInstruction.ts new file mode 100644 index 0000000000..3a1114a15f --- /dev/null +++ b/utils/instructions/Mean/getMeanTransferStreamInstruction.ts @@ -0,0 +1,77 @@ +import { Stream } from '@mean-dao/payment-streaming' +import { serializeInstructionToBase64 } from '@solana/spl-governance' +import { PublicKey } from '@solana/web3.js' + +import { ConnectionContext } from '@utils/connection' +import { validateInstruction } from '@utils/instructionTools' +import { AssetAccount } from '@utils/uiTypes/assets' +import { + MeanTransferStream, + UiInstruction, +} from '@utils/uiTypes/proposalCreationTypes' +import createPaymentStreaming from './createPaymentStreaming' + +interface Args { + connection: ConnectionContext + form: MeanTransferStream + setFormErrors: any // TODO + schema: any // TODO +} + +function getGovernedAccountPk(acc: AssetAccount): PublicKey { + return (acc.isSol + ? acc.extensions.transferAddress + : acc.extensions?.token?.account?.owner) as PublicKey +} + +export default async function getMeanWithdrawFromAccountInstruction({ + connection, + form, + setFormErrors, + schema, +}: Args): Promise { + const isValid = await validateInstruction({ schema, form, setFormErrors }) + + const serializedInstruction = '' + const governedTokenAccount = form.governedTokenAccount + const formStream = form.stream as Stream | undefined + + if (isValid && governedTokenAccount && formStream && form.destination) { + const paymentStreaming = createPaymentStreaming(connection) + + const beneficiary = getGovernedAccountPk(governedTokenAccount) + const feePayer = beneficiary + const stream = new PublicKey(formStream.id) + const newBeneficiary = new PublicKey(form.destination) + + const { + transaction, + } = await paymentStreaming.buildTransferStreamTransaction({ + beneficiary, + newBeneficiary, + stream, + feePayer, + }) + + const additionalSerializedInstructions = transaction.instructions.map( + serializeInstructionToBase64 + ) + + const obj: UiInstruction = { + serializedInstruction, + isValid: true, + governance: governedTokenAccount?.governance, + additionalSerializedInstructions, + } + return obj + } + + const obj: UiInstruction = { + serializedInstruction, + isValid: false, + governance: governedTokenAccount?.governance, + additionalSerializedInstructions: [], + } + + return obj +} diff --git a/utils/instructions/Mean/getMeanWithdrawFromAccountInstruction.ts b/utils/instructions/Mean/getMeanWithdrawFromAccountInstruction.ts new file mode 100644 index 0000000000..eb0d4183cd --- /dev/null +++ b/utils/instructions/Mean/getMeanWithdrawFromAccountInstruction.ts @@ -0,0 +1,89 @@ +import { PaymentStreamingAccount } from '@mean-dao/payment-streaming' +import { serializeInstructionToBase64 } from '@solana/spl-governance' +import { PublicKey } from '@solana/web3.js' + +import { parseMintNaturalAmountFromDecimal } from '@tools/sdk/units' +import { ConnectionContext } from '@utils/connection' +import { validateInstruction } from '@utils/instructionTools' +import { AssetAccount } from '@utils/uiTypes/assets' +import { + MeanWithdrawFromAccount, + UiInstruction, +} from '@utils/uiTypes/proposalCreationTypes' +import createPaymentStreaming from './createPaymentStreaming' + +interface Args { + connection: ConnectionContext + form: MeanWithdrawFromAccount + setFormErrors: any // TODO + schema: any // TODO +} + +function getGovernedAccountPk(acc: AssetAccount): PublicKey { + return (acc.isSol + ? acc.extensions.transferAddress + : acc.extensions?.token?.account?.owner) as PublicKey +} + +export default async function getMeanWithdrawFromAccountInstruction({ + connection, + form, + setFormErrors, + schema, +}: Args): Promise { + const isValid = await validateInstruction({ schema, form, setFormErrors }) + + const serializedInstruction = '' + const governedTokenAccount = form.governedTokenAccount + + const formPaymentStreamingAccount = form.paymentStreamingAccount as + | PaymentStreamingAccount + | undefined + + if ( + isValid && + governedTokenAccount && + formPaymentStreamingAccount && + form.amount && + form.destination && + form.mintInfo + ) { + const paymentStreaming = createPaymentStreaming(connection) + const feePayer = getGovernedAccountPk(governedTokenAccount) + const psAccount = new PublicKey(formPaymentStreamingAccount.id) // treasury + const amount = parseMintNaturalAmountFromDecimal( + form.amount, + form.mintInfo.decimals + ) + const autoWSol = true + const destination = new PublicKey(form.destination) + const { + transaction, + } = await paymentStreaming.buildWithdrawFromAccountTransaction( + { psAccount, feePayer, destination }, + amount, + autoWSol + ) + + const additionalSerializedInstructions = transaction.instructions.map( + serializeInstructionToBase64 + ) + + const obj: UiInstruction = { + serializedInstruction, + isValid: true, + governance: governedTokenAccount?.governance, + additionalSerializedInstructions, + } + return obj + } + + const obj: UiInstruction = { + serializedInstruction, + isValid: false, + governance: governedTokenAccount?.governance, + additionalSerializedInstructions: [], + } + + return obj +} diff --git a/utils/instructions/Mean/getMint.tsx b/utils/instructions/Mean/getMint.tsx new file mode 100644 index 0000000000..f5057320b5 --- /dev/null +++ b/utils/instructions/Mean/getMint.tsx @@ -0,0 +1,13 @@ +import { PaymentStreamingAccount } from '@mean-dao/payment-streaming' +import { AssetAccount } from '@utils/uiTypes/assets' + +export default function getMint( + accounts: AssetAccount[] = [], + paymentStreamingAccount: PaymentStreamingAccount +) { + return accounts.find( + (a) => + a.extensions.mint?.publicKey.toBase58() === + paymentStreamingAccount?.mint.toString() + )?.extensions.mint?.account +} diff --git a/utils/instructions/NftVoter/castNftVote.ts b/utils/instructions/NftVoter/castNftVote.ts new file mode 100644 index 0000000000..178aa090af --- /dev/null +++ b/utils/instructions/NftVoter/castNftVote.ts @@ -0,0 +1,254 @@ +import { getAssociatedTokenAddress } from '@blockworks-foundation/mango-v4' +import { DasNftObject } from '@hooks/queries/digitalAssets' +import { fetchNFTbyMint } from '@hooks/queries/nft' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { chunks } from '@utils/helpers' +import { + NftVoteRecord, + getNftActionTicketProgramAddress, + getNftVoteRecordProgramAddress, +} from 'NftVotePlugin/accounts' +import { PROGRAM_ID as ACCOUNT_COMPACTION_PROGRAM_ID } from '@solana/spl-account-compression' +import { SYSTEM_PROGRAM_ID } from '@solana/spl-governance' +import { NftVoter } from 'idls/nft_voter' +import { NftVoterV2 } from 'idls/nft_voter_v2' +import { Program } from '@coral-xyz/anchor' +import { + AccountData, + UpdateVoterWeightRecordTypes, +} from '@utils/uiTypes/VotePlugin' +import { getCnftParamAndProof } from 'NftVotePlugin/getCnftParamAndProof' + +export const getCastNftVoteInstruction = async ( + program: Program, + walletPk: PublicKey, + registrar: PublicKey, + proposal: PublicKey, + tokenOwnerRecord: PublicKey, + voterWeightPk: PublicKey, + votingNfts: DasNftObject[], + nftVoteRecordsFiltered: NftVoteRecord[] +) => { + console.log('getCastNftVoteInstruction') + const clientProgramId = program.programId + const remainingAccounts: AccountData[] = [] + for (let i = 0; i < votingNfts.length; i++) { + const nft = votingNfts[i] + // const tokenAccount = await nft.getAssociatedTokenAccount() + const tokenAccount = await getAssociatedTokenAddress( + new PublicKey(nft.id), + walletPk, + true + ) + const metadata = await fetchNFTbyMint( + program.provider.connection, + new PublicKey(nft.id) + ) + const { nftVoteRecord } = await getNftVoteRecordProgramAddress( + proposal, + nft.id, + clientProgramId + ) + if ( + !nftVoteRecordsFiltered.find( + (x) => x.publicKey.toBase58() === nftVoteRecord.toBase58() + ) + ) + remainingAccounts.push( + new AccountData(tokenAccount), + new AccountData(metadata?.result?.metadataAddress || ''), + new AccountData(nftVoteRecord, false, true) + ) + } + + const castNftVoteIxs: TransactionInstruction[] = [] + //1 nft is 3 accounts + const nftChunks = chunks(remainingAccounts, 12) + for (const chunk of [...nftChunks]) { + castNftVoteIxs.push( + await program.methods + .castNftVote(proposal) + .accounts({ + registrar, + voterWeightRecord: voterWeightPk, + voterTokenOwnerRecord: tokenOwnerRecord, + voterAuthority: walletPk, + payer: walletPk, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .remainingAccounts(chunk) + .instruction() + ) + } + + // this is required in the case where all nfts are counted already + const emptyCastNftVote = await program.methods + .castNftVote(proposal) + .accounts({ + registrar, + voterWeightRecord: voterWeightPk, + voterTokenOwnerRecord: tokenOwnerRecord, + voterAuthority: walletPk, + payer: walletPk, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .instruction() + + return castNftVoteIxs.length ? castNftVoteIxs : [emptyCastNftVote] +} + +export const getCastNftVoteInstructionV2 = async ( + program: Program, + walletPk: PublicKey, + registrar: PublicKey, + proposal: PublicKey, + tokenOwnerRecord: PublicKey, + voterWeightPk: PublicKey, + votingNfts: DasNftObject[], + nftVoteRecordsFiltered: NftVoteRecord[] +) => { + console.log('getCastNftVoteInstructionV2') + const clientProgramId = program.programId + const castNftVoteTicketIxs: TransactionInstruction[] = [] + const castVoteRemainingAccounts: AccountData[] = [] + const type: UpdateVoterWeightRecordTypes = 'castVote' + const ticketType = `nft-${type}-ticket` + // create nft weight records for all nfts + const nfts = votingNfts.filter((x) => !x.compression.compressed) + const nftRemainingAccounts: AccountData[] = [] + for (const nft of nfts) { + const { nftVoteRecord } = await getNftVoteRecordProgramAddress( + proposal, + nft.id, + clientProgramId + ) + if ( + !nftVoteRecordsFiltered.find( + (x) => x.publicKey.toBase58() === nftVoteRecord.toBase58() + ) + ) { + const { nftActionTicket } = getNftActionTicketProgramAddress( + ticketType, + registrar, + walletPk, + nft.id, + clientProgramId + ) + + const tokenAccount = await getAssociatedTokenAddress( + new PublicKey(nft.id), + walletPk, + true + ) + const metadata = await fetchNFTbyMint( + program.provider.connection, + new PublicKey(nft.id) + ) + + nftRemainingAccounts.push( + new AccountData(tokenAccount), + new AccountData(metadata?.result?.metadataAddress || ''), + new AccountData(nftActionTicket, false, true) + ) + + castVoteRemainingAccounts.push( + new AccountData(nftActionTicket, false, true), + new AccountData(nftVoteRecord, false, true) + ) + } + } + + const createNftVoteTicketChunks = chunks(nftRemainingAccounts, 15) + for (const chunk of [...createNftVoteTicketChunks]) { + castNftVoteTicketIxs.push( + await program.methods + .createNftActionTicket({ [type]: {} }) + .accounts({ + registrar, + voterWeightRecord: voterWeightPk, + voterAuthority: walletPk, + payer: walletPk, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .remainingAccounts(chunk) + .instruction() + ) + } + + // create nft weight record for all compressed nfts + const cnfts = votingNfts.filter((x) => x.compression.compressed) + for (const cnft of cnfts) { + const { nftVoteRecord } = await getNftVoteRecordProgramAddress( + proposal, + cnft.id, + clientProgramId + ) + if ( + !nftVoteRecordsFiltered.find( + (x) => x.publicKey.toBase58() === nftVoteRecord.toBase58() + ) + ) { + const { nftActionTicket } = getNftActionTicketProgramAddress( + ticketType, + registrar, + walletPk, + cnft.id, + clientProgramId + ) + + const { param, additionalAccounts } = await getCnftParamAndProof( + program.provider.connection, + cnft + ) + + // CreateCnftActionTicket requires a non-null collection, + // but getCnftParamAndProof returns a nullable one + if (!param.collection.key) throw new Error("Collection key not found"); + // Typescript doesn't infer this in its current version, but this is basically + // casting the collection key to non-null. + const typesafeParams = [param as typeof param & { collection: typeof param.collection & { key : PublicKey }}] + + const instruction = await program.methods + .createCnftActionTicket({ [type]: {} }, typesafeParams) + .accounts({ + registrar, + voterWeightRecord: voterWeightPk, + payer: walletPk, + compressionProgram: ACCOUNT_COMPACTION_PROGRAM_ID, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .remainingAccounts([ + ...additionalAccounts.map((x) => new AccountData(x)), + new AccountData(nftActionTicket, false, true), + ]) + .instruction() + castNftVoteTicketIxs.push(instruction) + + castVoteRemainingAccounts.push( + new AccountData(nftActionTicket, false, true), + new AccountData(nftVoteRecord, false, true) + ) + } + } + + const castNftVoteIxs: TransactionInstruction[] = [] + const castVoteRemainingAccountsChunks = chunks(castVoteRemainingAccounts, 12) + for (const chunk of [...castVoteRemainingAccountsChunks]) { + castNftVoteIxs.push( + await program.methods + .castNftVote(proposal) + .accounts({ + registrar, + voterWeightRecord: voterWeightPk, + voterTokenOwnerRecord: tokenOwnerRecord, + voterAuthority: walletPk, + payer: walletPk, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .remainingAccounts(chunk) + .instruction() + ) + } + + return { castNftVoteTicketIxs, castNftVoteIxs } +} diff --git a/utils/instructions/NftVoter/updateVoterWeight.ts b/utils/instructions/NftVoter/updateVoterWeight.ts new file mode 100644 index 0000000000..04f33d24af --- /dev/null +++ b/utils/instructions/NftVoter/updateVoterWeight.ts @@ -0,0 +1,175 @@ +import { getAssociatedTokenAddress } from '@blockworks-foundation/mango-v4' +import { DasNftObject } from '@hooks/queries/digitalAssets' +import { fetchNFTbyMint } from '@hooks/queries/nft' +import { PublicKey, TransactionInstruction } from '@solana/web3.js' +import { chunks } from '@utils/helpers' +import { getNftActionTicketProgramAddress } from 'NftVotePlugin/accounts' +import { PROGRAM_ID as ACCOUNT_COMPACTION_PROGRAM_ID } from '@solana/spl-account-compression' +import { SYSTEM_PROGRAM_ID } from '@solana/spl-governance' +import { NftVoter } from 'idls/nft_voter' +import { NftVoterV2 } from 'idls/nft_voter_v2' +import { Program } from '@coral-xyz/anchor' +import { + AccountData, + UpdateVoterWeightRecordTypes, +} from '@utils/uiTypes/VotePlugin' +import { getCnftParamAndProof } from 'NftVotePlugin/getCnftParamAndProof' + +export const getUpdateVoterWeightRecordInstruction = async ( + program: Program, + walletPk: PublicKey, + registrar: PublicKey, + voterWeightPk: PublicKey, + votingNfts: DasNftObject[], + type: UpdateVoterWeightRecordTypes +) => { + console.log('getUpdateVoterWeightRecordInstruction') + const remainingAccounts: AccountData[] = [] + for (let i = 0; i < votingNfts.length; i++) { + const nft = votingNfts[i] + // const tokenAccount = await nft.getAssociatedTokenAccount() + const tokenAccount = await getAssociatedTokenAddress( + new PublicKey(nft.id), + walletPk, + true + ) + + const metadata = await fetchNFTbyMint( + program.provider.connection, + new PublicKey(nft.id) + ) + + remainingAccounts.push( + new AccountData(tokenAccount), + new AccountData(metadata?.result?.metadataAddress || '') + ) + } + const updateVoterWeightRecordIx = await program.methods + // The cast to any works around an anchor issue with interpreting enums + .updateVoterWeightRecord({ [type]: {} } as any) + .accounts({ + registrar: registrar, + voterWeightRecord: voterWeightPk, + }) + .remainingAccounts(remainingAccounts.slice(0, 10)) + .instruction() + return updateVoterWeightRecordIx +} + +export const getUpdateVoterWeightRecordInstructionV2 = async ( + program: Program, + walletPk: PublicKey, + registrar: PublicKey, + voterWeightPk: PublicKey, + votingNfts: DasNftObject[], + type: UpdateVoterWeightRecordTypes +) => { + console.log('getUpdateVoterWeightRecordInstructionV2') + const createNftTicketIxs: TransactionInstruction[] = [] + const ticketType = `nft-${type}-ticket` + const firstTenNfts = votingNfts.slice(0, 10) + const nftActionTicketAccounts: AccountData[] = [] + + const nfts = firstTenNfts.filter((x) => !x.compression.compressed) + const nftRemainingAccounts: AccountData[] = [] + const clientProgramId = program.programId + for (const nft of nfts) { + const { nftActionTicket } = getNftActionTicketProgramAddress( + ticketType, + registrar, + walletPk, + nft.id, + clientProgramId + ) + + const tokenAccount = await getAssociatedTokenAddress( + new PublicKey(nft.id), + walletPk, + true + ) + const metadata = await fetchNFTbyMint( + program.provider.connection, + new PublicKey(nft.id) + ) + nftRemainingAccounts.push( + new AccountData(tokenAccount), + new AccountData(metadata?.result?.metadataAddress || ''), + new AccountData(nftActionTicket, false, true) + ) + + nftActionTicketAccounts.push(new AccountData(nftActionTicket, false, true)) + } + + const nftChunks = chunks(nftRemainingAccounts, 15) + for (const chunk of [...nftChunks]) { + createNftTicketIxs.push( + await program.methods + // The cast to any works around an anchor issue with interpreting enums + .createNftActionTicket({ [type]: {} } as any) + .accounts({ + registrar, + voterWeightRecord: voterWeightPk, + voterAuthority: walletPk, + payer: walletPk, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .remainingAccounts(chunk) + .instruction() + ) + } + + const compressedNfts = firstTenNfts.filter((x) => x.compression.compressed) + for (const cnft of compressedNfts) { + const { nftActionTicket } = getNftActionTicketProgramAddress( + ticketType, + registrar, + walletPk, + cnft.id, + clientProgramId + ) + + const { param, additionalAccounts } = await getCnftParamAndProof( + program.provider.connection, + cnft + ) + + // CreateCnftActionTicket requires a non-null collection, + // but getCnftParamAndProof returns a nullable one + if (!param.collection.key) throw new Error("Collection key not found"); + // Typescript doesn't infer this in its current version, but this is basically + // casting the collection key to non-null. + const typesafeParams = [param as typeof param & { collection: typeof param.collection & { key : PublicKey }}] + + const instruction = await program.methods + // The cast to any works around an anchor issue with interpreting enums + .createCnftActionTicket({ [type]: {} } as any, typesafeParams) + .accounts({ + registrar, + voterWeightRecord: voterWeightPk, + payer: walletPk, + compressionProgram: ACCOUNT_COMPACTION_PROGRAM_ID, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .remainingAccounts([ + ...additionalAccounts.map((x) => new AccountData(x)), + new AccountData(nftActionTicket, false, true), + ]) + .instruction() + createNftTicketIxs.push(instruction) + + nftActionTicketAccounts.push(new AccountData(nftActionTicket, false, true)) + } + + const updateVoterWeightRecordIx = await program.methods + // The cast to any works around an anchor issue with interpreting enums + .updateVoterWeightRecord({ [type]: {} } as any) + .accounts({ + registrar: registrar, + voterWeightRecord: voterWeightPk, + payer: walletPk, + }) + .remainingAccounts(nftActionTicketAccounts) + .instruction() + + return { createNftTicketIxs, updateVoterWeightRecordIx } +} diff --git a/utils/instructions/PsyFinance/PoseidonIdl.ts b/utils/instructions/PsyFinance/PoseidonIdl.ts new file mode 100644 index 0000000000..b283c37e83 --- /dev/null +++ b/utils/instructions/PsyFinance/PoseidonIdl.ts @@ -0,0 +1,1949 @@ +export type Poseidon = { + version: '0.1.0' + name: 'poseidon' + instructions: [ + { + name: 'initBoundedStrategy' + accounts: [ + { + name: 'payer' + isMut: true + isSigner: true + }, + { + name: 'authority' + isMut: false + isSigner: false + pda: { + seeds: [ + { + kind: 'account' + type: 'publicKey' + account: 'BoundedStrategy' + path: 'strategy' + }, + { + kind: 'const' + type: 'string' + value: 'authority' + } + ] + } + }, + { + name: 'mint' + isMut: false + isSigner: false + }, + { + name: 'serumMarket' + isMut: false + isSigner: false + }, + { + name: 'orderPayer' + isMut: true + isSigner: false + pda: { + seeds: [ + { + kind: 'account' + type: 'publicKey' + account: 'BoundedStrategy' + path: 'strategy' + }, + { + kind: 'const' + type: 'string' + value: 'orderPayer' + } + ] + } + }, + { + name: 'strategy' + isMut: true + isSigner: false + pda: { + seeds: [ + { + kind: 'account' + type: 'publicKey' + path: 'serum_market' + }, + { + kind: 'account' + type: 'publicKey' + account: 'Mint' + path: 'mint' + }, + { + kind: 'arg' + type: 'u64' + path: 'bound_price' + }, + { + kind: 'arg' + type: 'i64' + path: 'reclaim_date' + }, + { + kind: 'const' + type: 'string' + value: 'boundedStrategy' + } + ] + } + }, + { + name: 'reclaimAccount' + isMut: true + isSigner: false + }, + { + name: 'depositAccount' + isMut: false + isSigner: false + docs: ['The account where swapped assets will be transferred to'] + }, + { + name: 'openOrders' + isMut: true + isSigner: false + docs: ['The OpenOrders account to initialize'] + pda: { + seeds: [ + { + kind: 'account' + type: 'publicKey' + account: 'BoundedStrategy' + path: 'strategy' + }, + { + kind: 'const' + type: 'string' + value: 'openOrders' + } + ] + } + }, + { + name: 'dexProgram' + isMut: false + isSigner: false + docs: ['The Serum program'] + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + }, + { + name: 'rent' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'transferAmount' + type: 'u64' + }, + { + name: 'boundPrice' + type: 'u64' + }, + { + name: 'reclaimDate' + type: 'i64' + }, + { + name: 'orderSide' + type: 'u8' + }, + { + name: 'bound' + type: 'u8' + }, + { + name: 'openOrdersSpace' + type: 'u64' + } + ] + }, + { + name: 'boundedTrade' + accounts: [ + { + name: 'payer' + isMut: false + isSigner: true + docs: ['Anyone can fire this transaction'] + }, + { + name: 'strategy' + isMut: false + isSigner: false + docs: ['The BoundedStrategy account'] + }, + { + name: 'serumMarket' + isMut: true + isSigner: false + }, + { + name: 'bids' + isMut: true + isSigner: false + docs: ["The Serum Market's bids account"] + }, + { + name: 'asks' + isMut: true + isSigner: false + docs: ["The Serum Market's asks accoutn"] + }, + { + name: 'openOrders' + isMut: true + isSigner: false + }, + { + name: 'orderPayer' + isMut: true + isSigner: false + }, + { + name: 'authority' + isMut: false + isSigner: false + }, + { + name: 'requestQueue' + isMut: true + isSigner: false + }, + { + name: 'eventQueue' + isMut: true + isSigner: false + }, + { + name: 'coinVault' + isMut: true + isSigner: false + }, + { + name: 'pcVault' + isMut: true + isSigner: false + }, + { + name: 'serumVaultSigner' + isMut: false + isSigner: false + }, + { + name: 'depositAccount' + isMut: true + isSigner: false + }, + { + name: 'dexProgram' + isMut: false + isSigner: false + docs: ['The Serum program'] + }, + { + name: 'tokenProgramId' + isMut: false + isSigner: false + docs: ['The SPL Token program id'] + }, + { + name: 'rent' + isMut: false + isSigner: false + } + ] + args: [] + }, + { + name: 'reclaim' + accounts: [ + { + name: 'receiver' + isMut: true + isSigner: false + docs: ['The account that will receive the SOL'] + }, + { + name: 'strategy' + isMut: true + isSigner: false + docs: ['The BoundedStrategy account'] + }, + { + name: 'authority' + isMut: false + isSigner: false + docs: ['The PDA that has authority over the order payer'] + }, + { + name: 'orderPayer' + isMut: true + isSigner: false + docs: ['The account where the assets to trade with are'] + }, + { + name: 'openOrders' + isMut: true + isSigner: false + }, + { + name: 'serumMarket' + isMut: false + isSigner: false + }, + { + name: 'reclaimAccount' + isMut: true + isSigner: false + docs: ['The account that will receive the assets'] + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + }, + { + name: 'dexProgram' + isMut: false + isSigner: false + } + ] + args: [] + }, + { + name: 'srSettleFunds' + accounts: [ + { + name: 'reclaimAccount' + isMut: true + isSigner: false + docs: ['Either the PC or Coin wallet from the strategy'] + }, + { + name: 'strategy' + isMut: false + isSigner: false + docs: ['The BoundedStrategy account'] + }, + { + name: 'serumMarket' + isMut: true + isSigner: false + }, + { + name: 'openOrders' + isMut: true + isSigner: false + }, + { + name: 'authority' + isMut: false + isSigner: false + }, + { + name: 'coinVault' + isMut: true + isSigner: false + }, + { + name: 'pcVault' + isMut: true + isSigner: false + }, + { + name: 'serumVaultSigner' + isMut: false + isSigner: false + }, + { + name: 'depositAccount' + isMut: true + isSigner: false + }, + { + name: 'dexProgram' + isMut: false + isSigner: false + docs: ['The Serum program'] + }, + { + name: 'tokenProgramId' + isMut: false + isSigner: false + docs: ['The SPL Token program id'] + } + ] + args: [] + }, + { + name: 'initBoundedStrategyV2' + accounts: [ + { + name: 'payer' + isMut: true + isSigner: true + }, + { + name: 'collateralAccount' + isMut: true + isSigner: false + pda: { + seeds: [ + { + kind: 'account' + type: 'publicKey' + account: 'BoundedStrategyV2' + path: 'strategy' + }, + { + kind: 'const' + type: 'string' + value: 'orderPayer' + } + ] + } + }, + { + name: 'mint' + isMut: false + isSigner: false + }, + { + name: 'strategy' + isMut: true + isSigner: false + docs: [ + "TODO: The BoundedStrategy seeds will likely need another key. Otherwise DAO's and other", + 'users will be uniquely constrained by these values.' + ] + pda: { + seeds: [ + { + kind: 'account' + type: 'publicKey' + account: 'Mint' + path: 'mint' + }, + { + kind: 'arg' + type: 'u64' + path: 'bounded_price_numerator' + }, + { + kind: 'arg' + type: 'u64' + path: 'bounded_price_denominator' + }, + { + kind: 'arg' + type: 'i64' + path: 'reclaim_date' + }, + { + kind: 'const' + type: 'string' + value: 'boundedStrategy' + } + ] + } + }, + { + name: 'reclaimAccount' + isMut: true + isSigner: false + }, + { + name: 'depositAccount' + isMut: false + isSigner: false + docs: ['The account where swapped assets will be transferred to'] + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'transferAmount' + type: 'u64' + }, + { + name: 'boundedPriceNumerator' + type: 'u64' + }, + { + name: 'boundedPriceDenominator' + type: 'u64' + }, + { + name: 'reclaimDate' + type: 'i64' + } + ] + }, + { + name: 'boundedTradeV2' + accounts: [ + { + name: 'payer' + isMut: false + isSigner: true + docs: ['Anyone can fire this transaction'] + }, + { + name: 'strategy' + isMut: false + isSigner: false + docs: ['The BoundedStrategy account'] + }, + { + name: 'orderPayer' + isMut: true + isSigner: false + }, + { + name: 'depositAccount' + isMut: true + isSigner: false + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'additionalData' + type: 'bytes' + } + ] + }, + { + name: 'reclaimV2' + accounts: [ + { + name: 'receiver' + isMut: true + isSigner: false + docs: ['The account that will receive the SOL'] + }, + { + name: 'strategy' + isMut: true + isSigner: false + docs: ['The BoundedStrategyV2 account'] + }, + { + name: 'collateralAccount' + isMut: true + isSigner: false + docs: ['The account where the assets to trade with are'] + }, + { + name: 'reclaimAccount' + isMut: true + isSigner: false + docs: ['The account that will receive the assets'] + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + } + ] + args: [] + } + ] + accounts: [ + { + name: 'boundedStrategyV2' + type: { + kind: 'struct' + fields: [ + { + name: 'collateralMint' + type: 'publicKey' + }, + { + name: 'collateralAccount' + docs: ['The token account where the assets to be traded are held'] + type: 'publicKey' + }, + { + name: 'reclaimDate' + docs: ["The date at which the DAO's assets can be reclaimed"] + type: 'i64' + }, + { + name: 'reclaimAddress' + docs: [ + 'The address that the assets are transferred to when being reclaimed.' + ] + type: 'publicKey' + }, + { + name: 'depositAddress' + docs: ['The address where the swapped asset should be deposited'] + type: 'publicKey' + }, + { + name: 'boundedPriceNumerator' + docs: [ + 'Using a numerator and denominator we can back out a price without having to use floating', + 'point math or account for token decimals when price checking.', + '', + '### Example:', + 'Buying SOL with USDC for $92.75', + 'Use a numerator of 92_750_000 because USDC has 6 decimals. So 92_750_000 is 92.75 USDC.', + "Use a denominator of 1_000_000_000 because SOL has 9 decimal places. So that's 1 SOL.", + '92.75 USDC / 1 SOL' + ] + type: 'u64' + }, + { + name: 'boundedPriceDenominator' + type: 'u64' + }, + { + name: 'bump' + docs: ["The bump for the strategy's derived address"] + type: 'u8' + } + ] + } + }, + { + name: 'boundedStrategy' + type: { + kind: 'struct' + fields: [ + { + name: 'authority' + docs: [ + 'The PDA authority that owns the order_payer and open_orders account' + ] + type: 'publicKey' + }, + { + name: 'serumMarket' + docs: ['The Serum market where the execution will take place'] + type: 'publicKey' + }, + { + name: 'openOrders' + docs: [ + 'The open_orders account that is owned by the authority and used to place orders' + ] + type: 'publicKey' + }, + { + name: 'orderPayer' + docs: [ + 'The SPL TokenAccount that contains the tokens that will be put into Serum for trading' + ] + type: 'publicKey' + }, + { + name: 'orderSide' + docs: [ + 'The side of the order book the market order will be placed', + '0 for Bid, 1 for Ask' + ] + type: 'u8' + }, + { + name: 'reclaimDate' + docs: ["The date at which the DAO's assets can be reclaimed"] + type: 'i64' + }, + { + name: 'reclaimAddress' + docs: [ + 'The address that the assets are transferred to when being reclaimed.' + ] + type: 'publicKey' + }, + { + name: 'depositAddress' + docs: ['The address where the swapped asset should be deposited'] + type: 'publicKey' + }, + { + name: 'bound' + docs: ['0 for lower bound, 1 for upper bound'] + type: 'u8' + }, + { + name: 'boundedPrice' + docs: [ + 'The price of the base asset that governs the bound. The decimals are', + "equivalent to the price on the Serum Market's order book" + ] + type: 'u64' + }, + { + name: 'authorityBump' + type: 'u8' + }, + { + name: 'serumDexId' + docs: [ + 'The address of the serum dex program this strategy trades on' + ] + type: 'publicKey' + } + ] + } + } + ] + types: [ + { + name: 'U64F64' + type: { + kind: 'struct' + fields: [ + { + name: 'val' + type: 'u128' + } + ] + } + }, + { + name: 'DexList' + type: { + kind: 'enum' + variants: [ + { + name: 'OpenBookV3' + }, + { + name: 'Raydium' + } + ] + } + }, + { + name: 'CurveType' + type: { + kind: 'enum' + variants: [ + { + name: 'ConstantProduct' + }, + { + name: 'Stable' + } + ] + } + }, + { + name: 'FeeTier' + type: { + kind: 'enum' + variants: [ + { + name: 'Base' + }, + { + name: '_SRM2' + }, + { + name: '_SRM3' + }, + { + name: '_SRM4' + }, + { + name: '_SRM5' + }, + { + name: '_SRM6' + }, + { + name: '_MSRM' + }, + { + name: 'Stable' + } + ] + } + }, + { + name: 'FeeTier' + type: { + kind: 'enum' + variants: [ + { + name: 'Base' + }, + { + name: 'SRM2' + }, + { + name: 'SRM3' + }, + { + name: 'SRM4' + }, + { + name: 'SRM5' + }, + { + name: 'SRM6' + }, + { + name: 'MSRM' + }, + { + name: 'Stable' + } + ] + } + } + ] + errors: [ + { + code: 6000 + name: 'IncorrectSystemProgram' + msg: 'Must use correct SystemProgram' + }, + { + code: 6001 + name: 'BadReclaimAddress' + msg: "Reclaim account's Mint must match" + }, + { + code: 6002 + name: 'ReclaimDateHasPassed' + msg: 'Reclaim date must be in the future' + }, + { + code: 6003 + name: 'BoundPriceIsZero' + msg: 'Bound price must be greater than 0' + }, + { + code: 6004 + name: 'NonBinaryOrderSide' + msg: 'Order side must be 0 or 1' + }, + { + code: 6005 + name: 'NonBinaryBound' + msg: 'Bound must be 0 or 1' + }, + { + code: 6006 + name: 'MarketPriceIsOutOfBounds' + msg: 'Market price is out of bounds' + }, + { + code: 6007 + name: 'NoLowerBoundedBids' + msg: 'Lower bounded bids are blocked' + }, + { + code: 6008 + name: 'NoUpperBoundedAsks' + msg: 'Upper bounded asks are blocked' + }, + { + code: 6009 + name: 'ReclaimDateHasNotPassed' + msg: 'Cannot reclaim assets before the reclaim date' + }, + { + code: 6010 + name: 'TransferAmountCantBe0' + msg: 'Transfer amount cannot be 0' + }, + { + code: 6011 + name: 'BidsRequireQuoteCurrency' + msg: 'Strategy requires the quote currency to place bids' + }, + { + code: 6012 + name: 'AsksRequireBaseCurrency' + msg: 'Strategy requires the base currency to place asks' + }, + { + code: 6013 + name: 'OrderPayerMisMatch' + msg: 'Order payer does not match the strategy' + }, + { + code: 6014 + name: 'AuthorityMisMatch' + msg: 'Authority does not match the strategy' + }, + { + code: 6015 + name: 'DepositAddressMisMatch' + msg: 'Depsoit address does not match the strategy' + }, + { + code: 6016 + name: 'WrongReclaimAddress' + msg: 'Cannot reclaim to different address' + }, + { + code: 6017 + name: 'BadDepositAddress' + msg: 'Deposit address must have same owner as reclaim address' + }, + { + code: 6018 + name: 'WrongOpenOrdersKey' + msg: 'open orders does not match strategy' + }, + { + code: 6019 + name: 'FailedToLoadOpenBookDexMarket' + msg: 'Failed to load OpenBook DEX Market' + }, + { + code: 6020 + name: 'BadOpenOrdersKey' + msg: 'OpenOrders account does not match derived address' + }, + { + code: 6021 + name: 'UknownDexId' + msg: 'Uknown DEX Program ID' + }, + { + code: 6022 + name: 'OutputMintMismatch' + msg: 'Output mint does not match route' + }, + { + code: 6023 + name: 'InputMintMismatch' + msg: 'Input mint does not match route' + }, + { + code: 6024 + name: 'IncorrectKeysForLeg' + msg: "The Leg's accounts aren't correct or ordered properly" + }, + { + code: 6025 + name: 'BadTokenAccountKeyForLeg' + msg: 'The intermediary token account key is incorrect' + }, + { + code: 6026 + name: 'BadLutProgramAddress' + msg: 'Bad LUT program address' + }, + { + code: 6027 + name: 'TooManyAccounts' + msg: 'Cannot handle more than 30 accounts' + } + ] +} + +export const IDL: Poseidon = { + version: '0.1.0', + name: 'poseidon', + instructions: [ + { + name: 'initBoundedStrategy', + accounts: [ + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'authority', + isMut: false, + isSigner: false, + pda: { + seeds: [ + { + kind: 'account', + type: 'publicKey', + account: 'BoundedStrategy', + path: 'strategy', + }, + { + kind: 'const', + type: 'string', + value: 'authority', + }, + ], + }, + }, + { + name: 'mint', + isMut: false, + isSigner: false, + }, + { + name: 'serumMarket', + isMut: false, + isSigner: false, + }, + { + name: 'orderPayer', + isMut: true, + isSigner: false, + pda: { + seeds: [ + { + kind: 'account', + type: 'publicKey', + account: 'BoundedStrategy', + path: 'strategy', + }, + { + kind: 'const', + type: 'string', + value: 'orderPayer', + }, + ], + }, + }, + { + name: 'strategy', + isMut: true, + isSigner: false, + pda: { + seeds: [ + { + kind: 'account', + type: 'publicKey', + path: 'serum_market', + }, + { + kind: 'account', + type: 'publicKey', + account: 'Mint', + path: 'mint', + }, + { + kind: 'arg', + type: 'u64', + path: 'bound_price', + }, + { + kind: 'arg', + type: 'i64', + path: 'reclaim_date', + }, + { + kind: 'const', + type: 'string', + value: 'boundedStrategy', + }, + ], + }, + }, + { + name: 'reclaimAccount', + isMut: true, + isSigner: false, + }, + { + name: 'depositAccount', + isMut: false, + isSigner: false, + docs: ['The account where swapped assets will be transferred to'], + }, + { + name: 'openOrders', + isMut: true, + isSigner: false, + docs: ['The OpenOrders account to initialize'], + pda: { + seeds: [ + { + kind: 'account', + type: 'publicKey', + account: 'BoundedStrategy', + path: 'strategy', + }, + { + kind: 'const', + type: 'string', + value: 'openOrders', + }, + ], + }, + }, + { + name: 'dexProgram', + isMut: false, + isSigner: false, + docs: ['The Serum program'], + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + { + name: 'rent', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'transferAmount', + type: 'u64', + }, + { + name: 'boundPrice', + type: 'u64', + }, + { + name: 'reclaimDate', + type: 'i64', + }, + { + name: 'orderSide', + type: 'u8', + }, + { + name: 'bound', + type: 'u8', + }, + { + name: 'openOrdersSpace', + type: 'u64', + }, + ], + }, + { + name: 'boundedTrade', + accounts: [ + { + name: 'payer', + isMut: false, + isSigner: true, + docs: ['Anyone can fire this transaction'], + }, + { + name: 'strategy', + isMut: false, + isSigner: false, + docs: ['The BoundedStrategy account'], + }, + { + name: 'serumMarket', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + docs: ["The Serum Market's bids account"], + }, + { + name: 'asks', + isMut: true, + isSigner: false, + docs: ["The Serum Market's asks accoutn"], + }, + { + name: 'openOrders', + isMut: true, + isSigner: false, + }, + { + name: 'orderPayer', + isMut: true, + isSigner: false, + }, + { + name: 'authority', + isMut: false, + isSigner: false, + }, + { + name: 'requestQueue', + isMut: true, + isSigner: false, + }, + { + name: 'eventQueue', + isMut: true, + isSigner: false, + }, + { + name: 'coinVault', + isMut: true, + isSigner: false, + }, + { + name: 'pcVault', + isMut: true, + isSigner: false, + }, + { + name: 'serumVaultSigner', + isMut: false, + isSigner: false, + }, + { + name: 'depositAccount', + isMut: true, + isSigner: false, + }, + { + name: 'dexProgram', + isMut: false, + isSigner: false, + docs: ['The Serum program'], + }, + { + name: 'tokenProgramId', + isMut: false, + isSigner: false, + docs: ['The SPL Token program id'], + }, + { + name: 'rent', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'reclaim', + accounts: [ + { + name: 'receiver', + isMut: true, + isSigner: false, + docs: ['The account that will receive the SOL'], + }, + { + name: 'strategy', + isMut: true, + isSigner: false, + docs: ['The BoundedStrategy account'], + }, + { + name: 'authority', + isMut: false, + isSigner: false, + docs: ['The PDA that has authority over the order payer'], + }, + { + name: 'orderPayer', + isMut: true, + isSigner: false, + docs: ['The account where the assets to trade with are'], + }, + { + name: 'openOrders', + isMut: true, + isSigner: false, + }, + { + name: 'serumMarket', + isMut: false, + isSigner: false, + }, + { + name: 'reclaimAccount', + isMut: true, + isSigner: false, + docs: ['The account that will receive the assets'], + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'dexProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'srSettleFunds', + accounts: [ + { + name: 'reclaimAccount', + isMut: true, + isSigner: false, + docs: ['Either the PC or Coin wallet from the strategy'], + }, + { + name: 'strategy', + isMut: false, + isSigner: false, + docs: ['The BoundedStrategy account'], + }, + { + name: 'serumMarket', + isMut: true, + isSigner: false, + }, + { + name: 'openOrders', + isMut: true, + isSigner: false, + }, + { + name: 'authority', + isMut: false, + isSigner: false, + }, + { + name: 'coinVault', + isMut: true, + isSigner: false, + }, + { + name: 'pcVault', + isMut: true, + isSigner: false, + }, + { + name: 'serumVaultSigner', + isMut: false, + isSigner: false, + }, + { + name: 'depositAccount', + isMut: true, + isSigner: false, + }, + { + name: 'dexProgram', + isMut: false, + isSigner: false, + docs: ['The Serum program'], + }, + { + name: 'tokenProgramId', + isMut: false, + isSigner: false, + docs: ['The SPL Token program id'], + }, + ], + args: [], + }, + { + name: 'initBoundedStrategyV2', + accounts: [ + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'collateralAccount', + isMut: true, + isSigner: false, + pda: { + seeds: [ + { + kind: 'account', + type: 'publicKey', + account: 'BoundedStrategyV2', + path: 'strategy', + }, + { + kind: 'const', + type: 'string', + value: 'orderPayer', + }, + ], + }, + }, + { + name: 'mint', + isMut: false, + isSigner: false, + }, + { + name: 'strategy', + isMut: true, + isSigner: false, + docs: [ + "TODO: The BoundedStrategy seeds will likely need another key. Otherwise DAO's and other", + 'users will be uniquely constrained by these values.', + ], + pda: { + seeds: [ + { + kind: 'account', + type: 'publicKey', + account: 'Mint', + path: 'mint', + }, + { + kind: 'arg', + type: 'u64', + path: 'bounded_price_numerator', + }, + { + kind: 'arg', + type: 'u64', + path: 'bounded_price_denominator', + }, + { + kind: 'arg', + type: 'i64', + path: 'reclaim_date', + }, + { + kind: 'const', + type: 'string', + value: 'boundedStrategy', + }, + ], + }, + }, + { + name: 'reclaimAccount', + isMut: true, + isSigner: false, + }, + { + name: 'depositAccount', + isMut: false, + isSigner: false, + docs: ['The account where swapped assets will be transferred to'], + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'transferAmount', + type: 'u64', + }, + { + name: 'boundedPriceNumerator', + type: 'u64', + }, + { + name: 'boundedPriceDenominator', + type: 'u64', + }, + { + name: 'reclaimDate', + type: 'i64', + }, + ], + }, + { + name: 'boundedTradeV2', + accounts: [ + { + name: 'payer', + isMut: false, + isSigner: true, + docs: ['Anyone can fire this transaction'], + }, + { + name: 'strategy', + isMut: false, + isSigner: false, + docs: ['The BoundedStrategy account'], + }, + { + name: 'orderPayer', + isMut: true, + isSigner: false, + }, + { + name: 'depositAccount', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'additionalData', + type: 'bytes', + }, + ], + }, + { + name: 'reclaimV2', + accounts: [ + { + name: 'receiver', + isMut: true, + isSigner: false, + docs: ['The account that will receive the SOL'], + }, + { + name: 'strategy', + isMut: true, + isSigner: false, + docs: ['The BoundedStrategyV2 account'], + }, + { + name: 'collateralAccount', + isMut: true, + isSigner: false, + docs: ['The account where the assets to trade with are'], + }, + { + name: 'reclaimAccount', + isMut: true, + isSigner: false, + docs: ['The account that will receive the assets'], + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + ], + accounts: [ + { + name: 'boundedStrategyV2', + type: { + kind: 'struct', + fields: [ + { + name: 'collateralMint', + type: 'publicKey', + }, + { + name: 'collateralAccount', + docs: ['The token account where the assets to be traded are held'], + type: 'publicKey', + }, + { + name: 'reclaimDate', + docs: ["The date at which the DAO's assets can be reclaimed"], + type: 'i64', + }, + { + name: 'reclaimAddress', + docs: [ + 'The address that the assets are transferred to when being reclaimed.', + ], + type: 'publicKey', + }, + { + name: 'depositAddress', + docs: ['The address where the swapped asset should be deposited'], + type: 'publicKey', + }, + { + name: 'boundedPriceNumerator', + docs: [ + 'Using a numerator and denominator we can back out a price without having to use floating', + 'point math or account for token decimals when price checking.', + '', + '### Example:', + 'Buying SOL with USDC for $92.75', + 'Use a numerator of 92_750_000 because USDC has 6 decimals. So 92_750_000 is 92.75 USDC.', + "Use a denominator of 1_000_000_000 because SOL has 9 decimal places. So that's 1 SOL.", + '92.75 USDC / 1 SOL', + ], + type: 'u64', + }, + { + name: 'boundedPriceDenominator', + type: 'u64', + }, + { + name: 'bump', + docs: ["The bump for the strategy's derived address"], + type: 'u8', + }, + ], + }, + }, + { + name: 'boundedStrategy', + type: { + kind: 'struct', + fields: [ + { + name: 'authority', + docs: [ + 'The PDA authority that owns the order_payer and open_orders account', + ], + type: 'publicKey', + }, + { + name: 'serumMarket', + docs: ['The Serum market where the execution will take place'], + type: 'publicKey', + }, + { + name: 'openOrders', + docs: [ + 'The open_orders account that is owned by the authority and used to place orders', + ], + type: 'publicKey', + }, + { + name: 'orderPayer', + docs: [ + 'The SPL TokenAccount that contains the tokens that will be put into Serum for trading', + ], + type: 'publicKey', + }, + { + name: 'orderSide', + docs: [ + 'The side of the order book the market order will be placed', + '0 for Bid, 1 for Ask', + ], + type: 'u8', + }, + { + name: 'reclaimDate', + docs: ["The date at which the DAO's assets can be reclaimed"], + type: 'i64', + }, + { + name: 'reclaimAddress', + docs: [ + 'The address that the assets are transferred to when being reclaimed.', + ], + type: 'publicKey', + }, + { + name: 'depositAddress', + docs: ['The address where the swapped asset should be deposited'], + type: 'publicKey', + }, + { + name: 'bound', + docs: ['0 for lower bound, 1 for upper bound'], + type: 'u8', + }, + { + name: 'boundedPrice', + docs: [ + 'The price of the base asset that governs the bound. The decimals are', + "equivalent to the price on the Serum Market's order book", + ], + type: 'u64', + }, + { + name: 'authorityBump', + type: 'u8', + }, + { + name: 'serumDexId', + docs: [ + 'The address of the serum dex program this strategy trades on', + ], + type: 'publicKey', + }, + ], + }, + }, + ], + types: [ + { + name: 'U64F64', + type: { + kind: 'struct', + fields: [ + { + name: 'val', + type: 'u128', + }, + ], + }, + }, + { + name: 'DexList', + type: { + kind: 'enum', + variants: [ + { + name: 'OpenBookV3', + }, + { + name: 'Raydium', + }, + ], + }, + }, + { + name: 'CurveType', + type: { + kind: 'enum', + variants: [ + { + name: 'ConstantProduct', + }, + { + name: 'Stable', + }, + ], + }, + }, + { + name: 'FeeTier', + type: { + kind: 'enum', + variants: [ + { + name: 'Base', + }, + { + name: '_SRM2', + }, + { + name: '_SRM3', + }, + { + name: '_SRM4', + }, + { + name: '_SRM5', + }, + { + name: '_SRM6', + }, + { + name: '_MSRM', + }, + { + name: 'Stable', + }, + ], + }, + }, + { + name: 'FeeTier', + type: { + kind: 'enum', + variants: [ + { + name: 'Base', + }, + { + name: 'SRM2', + }, + { + name: 'SRM3', + }, + { + name: 'SRM4', + }, + { + name: 'SRM5', + }, + { + name: 'SRM6', + }, + { + name: 'MSRM', + }, + { + name: 'Stable', + }, + ], + }, + }, + ], + errors: [ + { + code: 6000, + name: 'IncorrectSystemProgram', + msg: 'Must use correct SystemProgram', + }, + { + code: 6001, + name: 'BadReclaimAddress', + msg: "Reclaim account's Mint must match", + }, + { + code: 6002, + name: 'ReclaimDateHasPassed', + msg: 'Reclaim date must be in the future', + }, + { + code: 6003, + name: 'BoundPriceIsZero', + msg: 'Bound price must be greater than 0', + }, + { + code: 6004, + name: 'NonBinaryOrderSide', + msg: 'Order side must be 0 or 1', + }, + { + code: 6005, + name: 'NonBinaryBound', + msg: 'Bound must be 0 or 1', + }, + { + code: 6006, + name: 'MarketPriceIsOutOfBounds', + msg: 'Market price is out of bounds', + }, + { + code: 6007, + name: 'NoLowerBoundedBids', + msg: 'Lower bounded bids are blocked', + }, + { + code: 6008, + name: 'NoUpperBoundedAsks', + msg: 'Upper bounded asks are blocked', + }, + { + code: 6009, + name: 'ReclaimDateHasNotPassed', + msg: 'Cannot reclaim assets before the reclaim date', + }, + { + code: 6010, + name: 'TransferAmountCantBe0', + msg: 'Transfer amount cannot be 0', + }, + { + code: 6011, + name: 'BidsRequireQuoteCurrency', + msg: 'Strategy requires the quote currency to place bids', + }, + { + code: 6012, + name: 'AsksRequireBaseCurrency', + msg: 'Strategy requires the base currency to place asks', + }, + { + code: 6013, + name: 'OrderPayerMisMatch', + msg: 'Order payer does not match the strategy', + }, + { + code: 6014, + name: 'AuthorityMisMatch', + msg: 'Authority does not match the strategy', + }, + { + code: 6015, + name: 'DepositAddressMisMatch', + msg: 'Depsoit address does not match the strategy', + }, + { + code: 6016, + name: 'WrongReclaimAddress', + msg: 'Cannot reclaim to different address', + }, + { + code: 6017, + name: 'BadDepositAddress', + msg: 'Deposit address must have same owner as reclaim address', + }, + { + code: 6018, + name: 'WrongOpenOrdersKey', + msg: 'open orders does not match strategy', + }, + { + code: 6019, + name: 'FailedToLoadOpenBookDexMarket', + msg: 'Failed to load OpenBook DEX Market', + }, + { + code: 6020, + name: 'BadOpenOrdersKey', + msg: 'OpenOrders account does not match derived address', + }, + { + code: 6021, + name: 'UknownDexId', + msg: 'Uknown DEX Program ID', + }, + { + code: 6022, + name: 'OutputMintMismatch', + msg: 'Output mint does not match route', + }, + { + code: 6023, + name: 'InputMintMismatch', + msg: 'Input mint does not match route', + }, + { + code: 6024, + name: 'IncorrectKeysForLeg', + msg: "The Leg's accounts aren't correct or ordered properly", + }, + { + code: 6025, + name: 'BadTokenAccountKeyForLeg', + msg: 'The intermediary token account key is incorrect', + }, + { + code: 6026, + name: 'BadLutProgramAddress', + msg: 'Bad LUT program address', + }, + { + code: 6027, + name: 'TooManyAccounts', + msg: 'Cannot handle more than 30 accounts', + }, + ], +} diff --git a/utils/instructions/PsyFinance/PsyAmericanIdl.ts b/utils/instructions/PsyFinance/PsyAmericanIdl.ts new file mode 100644 index 0000000000..6157655dde --- /dev/null +++ b/utils/instructions/PsyFinance/PsyAmericanIdl.ts @@ -0,0 +1,1707 @@ +export type PsyAmerican = { + version: '0.2.6' + name: 'psy_american' + instructions: [ + { + name: 'initializeMarket' + accounts: [ + { + name: 'authority' + isMut: true + isSigner: true + }, + { + name: 'underlyingAssetMint' + isMut: false + isSigner: false + }, + { + name: 'quoteAssetMint' + isMut: false + isSigner: false + }, + { + name: 'optionMint' + isMut: true + isSigner: false + }, + { + name: 'writerTokenMint' + isMut: true + isSigner: false + }, + { + name: 'quoteAssetPool' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetPool' + isMut: true + isSigner: false + }, + { + name: 'optionMarket' + isMut: true + isSigner: false + }, + { + name: 'feeOwner' + isMut: false + isSigner: false + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + }, + { + name: 'associatedTokenProgram' + isMut: false + isSigner: false + }, + { + name: 'rent' + isMut: false + isSigner: false + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + }, + { + name: 'clock' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'underlyingAmountPerContract' + type: 'u64' + }, + { + name: 'quoteAmountPerContract' + type: 'u64' + }, + { + name: 'expirationUnixTimestamp' + type: 'i64' + }, + { + name: 'bumpSeed' + type: 'u8' + } + ] + }, + { + name: 'mintOption' + accounts: [ + { + name: 'userAuthority' + isMut: true + isSigner: true + }, + { + name: 'underlyingAssetMint' + isMut: false + isSigner: false + }, + { + name: 'underlyingAssetPool' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetSrc' + isMut: true + isSigner: false + }, + { + name: 'optionMint' + isMut: true + isSigner: false + }, + { + name: 'mintedOptionDest' + isMut: true + isSigner: false + }, + { + name: 'writerTokenMint' + isMut: true + isSigner: false + }, + { + name: 'mintedWriterTokenDest' + isMut: true + isSigner: false + }, + { + name: 'optionMarket' + isMut: false + isSigner: false + }, + { + name: 'feeOwner' + isMut: true + isSigner: false + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + }, + { + name: 'associatedTokenProgram' + isMut: false + isSigner: false + }, + { + name: 'clock' + isMut: false + isSigner: false + }, + { + name: 'rent' + isMut: false + isSigner: false + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'size' + type: 'u64' + } + ] + }, + { + name: 'mintOptionV2' + accounts: [ + { + name: 'userAuthority' + isMut: false + isSigner: true + }, + { + name: 'underlyingAssetMint' + isMut: false + isSigner: false + }, + { + name: 'underlyingAssetPool' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetSrc' + isMut: true + isSigner: false + }, + { + name: 'optionMint' + isMut: true + isSigner: false + }, + { + name: 'mintedOptionDest' + isMut: true + isSigner: false + }, + { + name: 'writerTokenMint' + isMut: true + isSigner: false + }, + { + name: 'mintedWriterTokenDest' + isMut: true + isSigner: false + }, + { + name: 'optionMarket' + isMut: false + isSigner: false + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'size' + type: 'u64' + } + ] + }, + { + name: 'exerciseOption' + accounts: [ + { + name: 'userAuthority' + isMut: false + isSigner: true + }, + { + name: 'optionAuthority' + isMut: true + isSigner: true + }, + { + name: 'optionMarket' + isMut: false + isSigner: false + }, + { + name: 'optionMint' + isMut: true + isSigner: false + }, + { + name: 'exerciserOptionTokenSrc' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetPool' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetDest' + isMut: true + isSigner: false + }, + { + name: 'quoteAssetPool' + isMut: true + isSigner: false + }, + { + name: 'quoteAssetSrc' + isMut: true + isSigner: false + }, + { + name: 'feeOwner' + isMut: true + isSigner: false + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + }, + { + name: 'clock' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'size' + type: 'u64' + } + ] + }, + { + name: 'exerciseOptionV2' + accounts: [ + { + name: 'userAuthority' + isMut: false + isSigner: true + }, + { + name: 'optionAuthority' + isMut: false + isSigner: true + }, + { + name: 'optionMarket' + isMut: false + isSigner: false + }, + { + name: 'optionMint' + isMut: true + isSigner: false + }, + { + name: 'exerciserOptionTokenSrc' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetPool' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetDest' + isMut: true + isSigner: false + }, + { + name: 'quoteAssetPool' + isMut: true + isSigner: false + }, + { + name: 'quoteAssetSrc' + isMut: true + isSigner: false + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'size' + type: 'u64' + } + ] + }, + { + name: 'closePostExpiration' + accounts: [ + { + name: 'userAuthority' + isMut: false + isSigner: true + }, + { + name: 'optionMarket' + isMut: false + isSigner: false + }, + { + name: 'writerTokenMint' + isMut: true + isSigner: false + }, + { + name: 'writerTokenSrc' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetPool' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetDest' + isMut: true + isSigner: false + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + }, + { + name: 'clock' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'size' + type: 'u64' + } + ] + }, + { + name: 'closeOptionPosition' + accounts: [ + { + name: 'userAuthority' + isMut: false + isSigner: true + }, + { + name: 'optionMarket' + isMut: false + isSigner: false + }, + { + name: 'writerTokenMint' + isMut: true + isSigner: false + }, + { + name: 'writerTokenSrc' + isMut: true + isSigner: false + }, + { + name: 'optionTokenMint' + isMut: true + isSigner: false + }, + { + name: 'optionTokenSrc' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetPool' + isMut: true + isSigner: false + }, + { + name: 'underlyingAssetDest' + isMut: true + isSigner: false + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'size' + type: 'u64' + } + ] + }, + { + name: 'burnWriterForQuote' + accounts: [ + { + name: 'userAuthority' + isMut: false + isSigner: true + }, + { + name: 'optionMarket' + isMut: false + isSigner: false + }, + { + name: 'writerTokenMint' + isMut: true + isSigner: false + }, + { + name: 'writerTokenSrc' + isMut: true + isSigner: false + }, + { + name: 'quoteAssetPool' + isMut: true + isSigner: false + }, + { + name: 'writerQuoteDest' + isMut: true + isSigner: false + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'size' + type: 'u64' + } + ] + }, + { + name: 'initSerumMarket' + accounts: [ + { + name: 'userAuthority' + isMut: true + isSigner: true + }, + { + name: 'optionMarket' + isMut: true + isSigner: false + }, + { + name: 'serumMarket' + isMut: true + isSigner: false + }, + { + name: 'systemProgram' + isMut: false + isSigner: false + }, + { + name: 'tokenProgram' + isMut: false + isSigner: false + }, + { + name: 'dexProgram' + isMut: false + isSigner: false + }, + { + name: 'rent' + isMut: false + isSigner: false + }, + { + name: 'pcMint' + isMut: false + isSigner: false + }, + { + name: 'optionMint' + isMut: false + isSigner: false + }, + { + name: 'requestQueue' + isMut: true + isSigner: false + }, + { + name: 'eventQueue' + isMut: true + isSigner: false + }, + { + name: 'bids' + isMut: true + isSigner: false + }, + { + name: 'asks' + isMut: true + isSigner: false + }, + { + name: 'coinVault' + isMut: true + isSigner: false + }, + { + name: 'pcVault' + isMut: true + isSigner: false + }, + { + name: 'vaultSigner' + isMut: false + isSigner: false + }, + { + name: 'marketAuthority' + isMut: false + isSigner: false + } + ] + args: [ + { + name: 'marketSpace' + type: 'u64' + }, + { + name: 'vaultSignerNonce' + type: 'u64' + }, + { + name: 'coinLotSize' + type: 'u64' + }, + { + name: 'pcLotSize' + type: 'u64' + }, + { + name: 'pcDustThreshold' + type: 'u64' + } + ] + } + ] + accounts: [ + { + name: 'optionMarket' + type: { + kind: 'struct' + fields: [ + { + name: 'optionMint' + type: 'publicKey' + }, + { + name: 'writerTokenMint' + type: 'publicKey' + }, + { + name: 'underlyingAssetMint' + type: 'publicKey' + }, + { + name: 'quoteAssetMint' + type: 'publicKey' + }, + { + name: 'underlyingAmountPerContract' + type: 'u64' + }, + { + name: 'quoteAmountPerContract' + type: 'u64' + }, + { + name: 'expirationUnixTimestamp' + type: 'i64' + }, + { + name: 'underlyingAssetPool' + type: 'publicKey' + }, + { + name: 'quoteAssetPool' + type: 'publicKey' + }, + { + name: 'mintFeeAccount' + type: 'publicKey' + }, + { + name: 'exerciseFeeAccount' + type: 'publicKey' + }, + { + name: 'expired' + type: 'bool' + }, + { + name: 'bumpSeed' + type: 'u8' + } + ] + } + } + ] + errors: [ + { + code: 6000 + name: 'ExpirationIsInThePast' + msg: 'Expiration must be in the future' + }, + { + code: 6001 + name: 'QuoteAndUnderlyingAssetMustDiffer' + msg: 'Same quote and underlying asset, cannot create market' + }, + { + code: 6002 + name: 'QuoteOrUnderlyingAmountCannotBe0' + msg: 'Quote amount and underlying amount per contract must be > 0' + }, + { + code: 6003 + name: 'OptionMarketMustBeMintAuthority' + msg: 'OptionMarket must be the mint authority' + }, + { + code: 6004 + name: 'OptionMarketMustOwnUnderlyingAssetPool' + msg: 'OptionMarket must own the underlying asset pool' + }, + { + code: 6005 + name: 'OptionMarketMustOwnQuoteAssetPool' + msg: 'OptionMarket must own the quote asset pool' + }, + { + code: 6006 + name: 'ExpectedSPLTokenProgramId' + msg: 'Stop trying to spoof the SPL Token program! Shame on you' + }, + { + code: 6007 + name: 'MintFeeMustBeOwnedByFeeOwner' + msg: 'Mint fee account must be owned by the FEE_OWNER' + }, + { + code: 6008 + name: 'ExerciseFeeMustBeOwnedByFeeOwner' + msg: 'Exercise fee account must be owned by the FEE_OWNER' + }, + { + code: 6009 + name: 'MintFeeTokenMustMatchUnderlyingAsset' + msg: 'Mint fee token must be the same as the underlying asset' + }, + { + code: 6010 + name: 'ExerciseFeeTokenMustMatchQuoteAsset' + msg: 'Exercise fee token must be the same as the quote asset' + }, + { + code: 6011 + name: 'OptionMarketExpiredCantMint' + msg: "OptionMarket is expired, can't mint" + }, + { + code: 6012 + name: 'UnderlyingPoolAccountDoesNotMatchMarket' + msg: 'Underlying pool account does not match the value on the OptionMarket' + }, + { + code: 6013 + name: 'OptionTokenMintDoesNotMatchMarket' + msg: 'OptionToken mint does not match the value on the OptionMarket' + }, + { + code: 6014 + name: 'WriterTokenMintDoesNotMatchMarket' + msg: 'WriterToken mint does not match the value on the OptionMarket' + }, + { + code: 6015 + name: 'MintFeeKeyDoesNotMatchOptionMarket' + msg: 'MintFee key does not match the value on the OptionMarket' + }, + { + code: 6016 + name: 'SizeCantBeLessThanEqZero' + msg: 'The size argument must be > 0' + }, + { + code: 6017 + name: 'ExerciseFeeKeyDoesNotMatchOptionMarket' + msg: 'exerciseFee key does not match the value on the OptionMarket' + }, + { + code: 6018 + name: 'QuotePoolAccountDoesNotMatchMarket' + msg: 'Quote pool account does not match the value on the OptionMarket' + }, + { + code: 6019 + name: 'UnderlyingDestMintDoesNotMatchUnderlyingAsset' + msg: 'Underlying destination mint must match underlying asset mint address' + }, + { + code: 6020 + name: 'FeeOwnerDoesNotMatchProgram' + msg: "Fee owner does not match the program's fee owner" + }, + { + code: 6021 + name: 'OptionMarketExpiredCantExercise' + msg: "OptionMarket is expired, can't exercise" + }, + { + code: 6022 + name: 'OptionMarketNotExpiredCantClose' + msg: "OptionMarket has not expired, can't close" + }, + { + code: 6023 + name: 'NotEnoughQuoteAssetsInPool' + msg: 'Not enough assets in the quote asset pool' + }, + { + code: 6024 + name: 'InvalidAuth' + msg: 'Invalid auth token provided' + }, + { + code: 6025 + name: 'CoinMintIsNotOptionMint' + msg: 'Coin mint must match option mint' + }, + { + code: 6026 + name: 'CannotPruneActiveMarket' + msg: "Cannot prune the market while it's still active" + }, + { + code: 6027 + name: 'NumberOverflow' + msg: 'Numberical overflow' + } + ] +} + +export const PsyAmericanIdl: PsyAmerican = { + version: '0.2.6', + name: 'psy_american', + instructions: [ + { + name: 'initializeMarket', + accounts: [ + { + name: 'authority', + isMut: true, + isSigner: true, + }, + { + name: 'underlyingAssetMint', + isMut: false, + isSigner: false, + }, + { + name: 'quoteAssetMint', + isMut: false, + isSigner: false, + }, + { + name: 'optionMint', + isMut: true, + isSigner: false, + }, + { + name: 'writerTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'quoteAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'optionMarket', + isMut: true, + isSigner: false, + }, + { + name: 'feeOwner', + isMut: false, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'associatedTokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'rent', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + { + name: 'clock', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'underlyingAmountPerContract', + type: 'u64', + }, + { + name: 'quoteAmountPerContract', + type: 'u64', + }, + { + name: 'expirationUnixTimestamp', + type: 'i64', + }, + { + name: 'bumpSeed', + type: 'u8', + }, + ], + }, + { + name: 'mintOption', + accounts: [ + { + name: 'userAuthority', + isMut: true, + isSigner: true, + }, + { + name: 'underlyingAssetMint', + isMut: false, + isSigner: false, + }, + { + name: 'underlyingAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetSrc', + isMut: true, + isSigner: false, + }, + { + name: 'optionMint', + isMut: true, + isSigner: false, + }, + { + name: 'mintedOptionDest', + isMut: true, + isSigner: false, + }, + { + name: 'writerTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'mintedWriterTokenDest', + isMut: true, + isSigner: false, + }, + { + name: 'optionMarket', + isMut: false, + isSigner: false, + }, + { + name: 'feeOwner', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'associatedTokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'clock', + isMut: false, + isSigner: false, + }, + { + name: 'rent', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'size', + type: 'u64', + }, + ], + }, + { + name: 'mintOptionV2', + accounts: [ + { + name: 'userAuthority', + isMut: false, + isSigner: true, + }, + { + name: 'underlyingAssetMint', + isMut: false, + isSigner: false, + }, + { + name: 'underlyingAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetSrc', + isMut: true, + isSigner: false, + }, + { + name: 'optionMint', + isMut: true, + isSigner: false, + }, + { + name: 'mintedOptionDest', + isMut: true, + isSigner: false, + }, + { + name: 'writerTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'mintedWriterTokenDest', + isMut: true, + isSigner: false, + }, + { + name: 'optionMarket', + isMut: false, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'size', + type: 'u64', + }, + ], + }, + { + name: 'exerciseOption', + accounts: [ + { + name: 'userAuthority', + isMut: false, + isSigner: true, + }, + { + name: 'optionAuthority', + isMut: true, + isSigner: true, + }, + { + name: 'optionMarket', + isMut: false, + isSigner: false, + }, + { + name: 'optionMint', + isMut: true, + isSigner: false, + }, + { + name: 'exerciserOptionTokenSrc', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetDest', + isMut: true, + isSigner: false, + }, + { + name: 'quoteAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'quoteAssetSrc', + isMut: true, + isSigner: false, + }, + { + name: 'feeOwner', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + { + name: 'clock', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'size', + type: 'u64', + }, + ], + }, + { + name: 'exerciseOptionV2', + accounts: [ + { + name: 'userAuthority', + isMut: false, + isSigner: true, + }, + { + name: 'optionAuthority', + isMut: false, + isSigner: true, + }, + { + name: 'optionMarket', + isMut: false, + isSigner: false, + }, + { + name: 'optionMint', + isMut: true, + isSigner: false, + }, + { + name: 'exerciserOptionTokenSrc', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetDest', + isMut: true, + isSigner: false, + }, + { + name: 'quoteAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'quoteAssetSrc', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'size', + type: 'u64', + }, + ], + }, + { + name: 'closePostExpiration', + accounts: [ + { + name: 'userAuthority', + isMut: false, + isSigner: true, + }, + { + name: 'optionMarket', + isMut: false, + isSigner: false, + }, + { + name: 'writerTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'writerTokenSrc', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetDest', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'clock', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'size', + type: 'u64', + }, + ], + }, + { + name: 'closeOptionPosition', + accounts: [ + { + name: 'userAuthority', + isMut: false, + isSigner: true, + }, + { + name: 'optionMarket', + isMut: false, + isSigner: false, + }, + { + name: 'writerTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'writerTokenSrc', + isMut: true, + isSigner: false, + }, + { + name: 'optionTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'optionTokenSrc', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingAssetDest', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'size', + type: 'u64', + }, + ], + }, + { + name: 'burnWriterForQuote', + accounts: [ + { + name: 'userAuthority', + isMut: false, + isSigner: true, + }, + { + name: 'optionMarket', + isMut: false, + isSigner: false, + }, + { + name: 'writerTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'writerTokenSrc', + isMut: true, + isSigner: false, + }, + { + name: 'quoteAssetPool', + isMut: true, + isSigner: false, + }, + { + name: 'writerQuoteDest', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'size', + type: 'u64', + }, + ], + }, + { + name: 'initSerumMarket', + accounts: [ + { + name: 'userAuthority', + isMut: true, + isSigner: true, + }, + { + name: 'optionMarket', + isMut: true, + isSigner: false, + }, + { + name: 'serumMarket', + isMut: true, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'dexProgram', + isMut: false, + isSigner: false, + }, + { + name: 'rent', + isMut: false, + isSigner: false, + }, + { + name: 'pcMint', + isMut: false, + isSigner: false, + }, + { + name: 'optionMint', + isMut: false, + isSigner: false, + }, + { + name: 'requestQueue', + isMut: true, + isSigner: false, + }, + { + name: 'eventQueue', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'coinVault', + isMut: true, + isSigner: false, + }, + { + name: 'pcVault', + isMut: true, + isSigner: false, + }, + { + name: 'vaultSigner', + isMut: false, + isSigner: false, + }, + { + name: 'marketAuthority', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'marketSpace', + type: 'u64', + }, + { + name: 'vaultSignerNonce', + type: 'u64', + }, + { + name: 'coinLotSize', + type: 'u64', + }, + { + name: 'pcLotSize', + type: 'u64', + }, + { + name: 'pcDustThreshold', + type: 'u64', + }, + ], + }, + ], + accounts: [ + { + name: 'optionMarket', + type: { + kind: 'struct', + fields: [ + { + name: 'optionMint', + type: 'publicKey', + }, + { + name: 'writerTokenMint', + type: 'publicKey', + }, + { + name: 'underlyingAssetMint', + type: 'publicKey', + }, + { + name: 'quoteAssetMint', + type: 'publicKey', + }, + { + name: 'underlyingAmountPerContract', + type: 'u64', + }, + { + name: 'quoteAmountPerContract', + type: 'u64', + }, + { + name: 'expirationUnixTimestamp', + type: 'i64', + }, + { + name: 'underlyingAssetPool', + type: 'publicKey', + }, + { + name: 'quoteAssetPool', + type: 'publicKey', + }, + { + name: 'mintFeeAccount', + type: 'publicKey', + }, + { + name: 'exerciseFeeAccount', + type: 'publicKey', + }, + { + name: 'expired', + type: 'bool', + }, + { + name: 'bumpSeed', + type: 'u8', + }, + ], + }, + }, + ], + errors: [ + { + code: 6000, + name: 'ExpirationIsInThePast', + msg: 'Expiration must be in the future', + }, + { + code: 6001, + name: 'QuoteAndUnderlyingAssetMustDiffer', + msg: 'Same quote and underlying asset, cannot create market', + }, + { + code: 6002, + name: 'QuoteOrUnderlyingAmountCannotBe0', + msg: 'Quote amount and underlying amount per contract must be > 0', + }, + { + code: 6003, + name: 'OptionMarketMustBeMintAuthority', + msg: 'OptionMarket must be the mint authority', + }, + { + code: 6004, + name: 'OptionMarketMustOwnUnderlyingAssetPool', + msg: 'OptionMarket must own the underlying asset pool', + }, + { + code: 6005, + name: 'OptionMarketMustOwnQuoteAssetPool', + msg: 'OptionMarket must own the quote asset pool', + }, + { + code: 6006, + name: 'ExpectedSPLTokenProgramId', + msg: 'Stop trying to spoof the SPL Token program! Shame on you', + }, + { + code: 6007, + name: 'MintFeeMustBeOwnedByFeeOwner', + msg: 'Mint fee account must be owned by the FEE_OWNER', + }, + { + code: 6008, + name: 'ExerciseFeeMustBeOwnedByFeeOwner', + msg: 'Exercise fee account must be owned by the FEE_OWNER', + }, + { + code: 6009, + name: 'MintFeeTokenMustMatchUnderlyingAsset', + msg: 'Mint fee token must be the same as the underlying asset', + }, + { + code: 6010, + name: 'ExerciseFeeTokenMustMatchQuoteAsset', + msg: 'Exercise fee token must be the same as the quote asset', + }, + { + code: 6011, + name: 'OptionMarketExpiredCantMint', + msg: "OptionMarket is expired, can't mint", + }, + { + code: 6012, + name: 'UnderlyingPoolAccountDoesNotMatchMarket', + msg: + 'Underlying pool account does not match the value on the OptionMarket', + }, + { + code: 6013, + name: 'OptionTokenMintDoesNotMatchMarket', + msg: 'OptionToken mint does not match the value on the OptionMarket', + }, + { + code: 6014, + name: 'WriterTokenMintDoesNotMatchMarket', + msg: 'WriterToken mint does not match the value on the OptionMarket', + }, + { + code: 6015, + name: 'MintFeeKeyDoesNotMatchOptionMarket', + msg: 'MintFee key does not match the value on the OptionMarket', + }, + { + code: 6016, + name: 'SizeCantBeLessThanEqZero', + msg: 'The size argument must be > 0', + }, + { + code: 6017, + name: 'ExerciseFeeKeyDoesNotMatchOptionMarket', + msg: 'exerciseFee key does not match the value on the OptionMarket', + }, + { + code: 6018, + name: 'QuotePoolAccountDoesNotMatchMarket', + msg: 'Quote pool account does not match the value on the OptionMarket', + }, + { + code: 6019, + name: 'UnderlyingDestMintDoesNotMatchUnderlyingAsset', + msg: + 'Underlying destination mint must match underlying asset mint address', + }, + { + code: 6020, + name: 'FeeOwnerDoesNotMatchProgram', + msg: "Fee owner does not match the program's fee owner", + }, + { + code: 6021, + name: 'OptionMarketExpiredCantExercise', + msg: "OptionMarket is expired, can't exercise", + }, + { + code: 6022, + name: 'OptionMarketNotExpiredCantClose', + msg: "OptionMarket has not expired, can't close", + }, + { + code: 6023, + name: 'NotEnoughQuoteAssetsInPool', + msg: 'Not enough assets in the quote asset pool', + }, + { + code: 6024, + name: 'InvalidAuth', + msg: 'Invalid auth token provided', + }, + { + code: 6025, + name: 'CoinMintIsNotOptionMint', + msg: 'Coin mint must match option mint', + }, + { + code: 6026, + name: 'CannotPruneActiveMarket', + msg: "Cannot prune the market while it's still active", + }, + { + code: 6027, + name: 'NumberOverflow', + msg: 'Numberical overflow', + }, + ], +} diff --git a/utils/instructions/PsyFinance/hooks.ts b/utils/instructions/PsyFinance/hooks.ts new file mode 100644 index 0000000000..d215bd8486 --- /dev/null +++ b/utils/instructions/PsyFinance/hooks.ts @@ -0,0 +1,82 @@ +import { + Program, + ProgramAccount as AnchorProgramAccount, +} from '@coral-xyz/anchor' +import { useEffect, useMemo, useState } from 'react' +import useWalletDeprecated from '@hooks/useWalletDeprecated' +import { OptionMarket, PSY_AMERICAN_PROGRAM_ID } from './index' +import { PsyAmericanIdl } from './PsyAmericanIdl' +import useGovernanceAssets from '@hooks/useGovernanceAssets' +import { AssetAccount } from '@utils/uiTypes/assets' + +/** + * Return entire list of PsyOption American options. + */ +export const useOptionAccounts = () => { + const { anchorProvider } = useWalletDeprecated() + const [options, setOptions] = useState< + AnchorProgramAccount[] | null + >(null) + + useEffect(() => { + const program = new Program( + PsyAmericanIdl, + PSY_AMERICAN_PROGRAM_ID, + anchorProvider + ) + ;(async () => { + const _options = (await program.account.optionMarket.all()) as + | AnchorProgramAccount[] + | null + setOptions(_options) + })() + }, [anchorProvider]) + + return options +} + +/** + * Governed accounts for writer tokens only. + */ +export const useGovernedWriterTokenAccounts = ( + options: AnchorProgramAccount[] | null +) => { + const { governedTokenAccountsWithoutNfts } = useGovernanceAssets() + return useMemo(() => { + const _accounts: AssetAccount[] = [] + options?.forEach((option) => { + const govWriterTokenAccount = governedTokenAccountsWithoutNfts.find( + (gAcct) => + gAcct.extensions.token?.account.mint.equals( + option.account.writerTokenMint + ) + ) + if (govWriterTokenAccount) { + _accounts.push(govWriterTokenAccount) + } + }) + return _accounts + }, [governedTokenAccountsWithoutNfts, options]) +} + +/** + * Governed accounts for option tokens only. + */ +export const useGovernedOptionTokenAccounts = ( + options: AnchorProgramAccount[] | null +) => { + const { governedTokenAccountsWithoutNfts } = useGovernanceAssets() + return useMemo(() => { + const _accounts: AssetAccount[] = [] + options?.forEach((option) => { + const govOptionTokenAccount = governedTokenAccountsWithoutNfts.find( + (gAcct) => + gAcct.extensions.token?.account.mint.equals(option.account.optionMint) + ) + if (govOptionTokenAccount) { + _accounts.push(govOptionTokenAccount) + } + }) + return _accounts + }, [governedTokenAccountsWithoutNfts, options]) +} diff --git a/utils/instructions/PsyFinance/index.ts b/utils/instructions/PsyFinance/index.ts new file mode 100644 index 0000000000..b6f88eb11e --- /dev/null +++ b/utils/instructions/PsyFinance/index.ts @@ -0,0 +1,285 @@ +import { BN, Program, Provider, web3 } from '@coral-xyz/anchor' +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + Token, + TOKEN_PROGRAM_ID, +} from '@solana/spl-token' +import { + AccountMeta, + PublicKey, + SystemProgram, + SYSVAR_CLOCK_PUBKEY, + SYSVAR_RENT_PUBKEY, + TransactionInstruction, +} from '@solana/web3.js' +import { PsyAmerican } from './PsyAmericanIdl' +import { OptionMarket, OptionMarketWithKey } from './types' + +export { PsyAmericanIdl } from './PsyAmericanIdl' +export * from './types' +export * from './hooks' + +export const PSY_AMERICAN_PROGRAM_ID = new PublicKey( + 'R2y9ip6mxmWUj4pt54jP2hz2dgvMozy9VTSwMWE7evs' +) +const FEE_OWNER_KEY = new PublicKey( + '6c33US7ErPmLXZog9SyChQUYUrrJY51k4GmzdhrbhNnD' +) + +/* Most utility functions are copy/pasta from `@mithraic-labs/psy-american` package */ + +export const getOptionByKey = async ( + program: Program, + key: PublicKey +): Promise => { + try { + const optionAccount = ((await program.account.optionMarket.fetch( + key + )) as unknown) as OptionMarket + + return { + ...optionAccount, + key, + } + } catch (err) { + return null + } +} + +/** + * Get the deterministic address for an Option based on its properties. + * @returns + */ +export const deriveOptionKeyFromParams = async ({ + expirationUnixTimestamp, + programId, + quoteAmountPerContract, + quoteMint, + underlyingAmountPerContract, + underlyingMint, +}: { + /** The OptionMarket expiration timestamp in seconds */ + expirationUnixTimestamp: BN + /** The Psy American program ID */ + programId: PublicKey + /** The quote asset amount per option contract */ + quoteAmountPerContract: BN + /** The quote asset mint address */ + quoteMint: PublicKey + /** The underlying asset amount per option contract */ + underlyingAmountPerContract: BN + /** The underlying asset mint address */ + underlyingMint: PublicKey +}): Promise<[PublicKey, number]> => { + return PublicKey.findProgramAddress( + [ + underlyingMint.toBuffer(), + quoteMint.toBuffer(), + underlyingAmountPerContract.toArrayLike(Buffer, 'le', 8), + quoteAmountPerContract.toArrayLike(Buffer, 'le', 8), + expirationUnixTimestamp.toArrayLike(Buffer, 'le', 8), + ], + programId + ) +} + +/** + * Note this is legacy and no fees are on V2 instructions + * @deprecated + */ +const feeAmountPerContract = (assetQuantity: BN) => { + return assetQuantity.div(new BN(10_000 / 5)) +} + +/** + * Initialize a new Option + * + * @param program - The Psy American program + * @param params + * @returns + */ +// Should probably dedupe the code between these functions +export const initializeOptionInstruction = async ( + program: Program, + { + expirationUnixTimestamp, + quoteAmountPerContract, + quoteMint, + underlyingAmountPerContract, + underlyingMint, + }: { + /** The option market expiration timestamp in seconds */ + expirationUnixTimestamp: BN + /** The quote amount per contract for the OptionMarket + * Strike price is derived from underlyingAmountPerContract & quoteAmountPerContract */ + quoteAmountPerContract: BN + /** The quote asset mint */ + quoteMint: PublicKey + /** The underlying amount per contract for the OptionMarket. * + * Strike price is derived from underlyingAmountPerContract & quoteAmountPerContract */ + underlyingAmountPerContract: BN + /** The underlying mint address */ + underlyingMint: PublicKey + } +): Promise<{ + optionMarketKey: PublicKey + optionMintKey: PublicKey + quoteAssetPoolKey: PublicKey + tx: TransactionInstruction + underlyingAssetPoolKey: PublicKey + writerMintKey: PublicKey +}> => { + const textEncoder = new TextEncoder() + + // generate Program Derived Address for the new option + const [optionMarketKey, bumpSeed] = await deriveOptionKeyFromParams({ + programId: program.programId, + underlyingMint, + quoteMint, + underlyingAmountPerContract, + quoteAmountPerContract, + expirationUnixTimestamp, + }) + + // generate Program Derived Address for the Option Token + const [optionMintKey] = await web3.PublicKey.findProgramAddress( + [optionMarketKey.toBuffer(), textEncoder.encode('optionToken')], + program.programId + ) + // generate Program Derived Address for the Writer Token + const [writerMintKey] = await web3.PublicKey.findProgramAddress( + [optionMarketKey.toBuffer(), textEncoder.encode('writerToken')], + program.programId + ) + + // generate Program Derived Address for the vault that will hold the quote asset + const [quoteAssetPoolKey] = await web3.PublicKey.findProgramAddress( + [optionMarketKey.toBuffer(), textEncoder.encode('quoteAssetPool')], + program.programId + ) + + // generate Program Derived Address for the vault that will hold the underlying asset + const [underlyingAssetPoolKey] = await web3.PublicKey.findProgramAddress( + [optionMarketKey.toBuffer(), textEncoder.encode('underlyingAssetPool')], + program.programId + ) + + // Determine whether the mint/exercise fee accounts need to be initialized. + // Add the instructions and necessary accounts if the accounts need to + // be created. + const remainingAccounts: AccountMeta[] = [] + const instructions: TransactionInstruction[] = [] + const mintFeePerContract = feeAmountPerContract(underlyingAmountPerContract) + if (mintFeePerContract.gtn(0)) { + const mintFeeKey = await Token.getAssociatedTokenAddress( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + underlyingMint, + FEE_OWNER_KEY, + true + ) + remainingAccounts.push({ + pubkey: mintFeeKey, + isWritable: true, + isSigner: false, + }) + const ix = await getOrAddAssociatedTokenAccountTx( + mintFeeKey, + underlyingMint, + program.provider, + FEE_OWNER_KEY + ) + if (ix) { + instructions.push(ix) + } + } + + const exerciseFeePerContract = feeAmountPerContract(quoteAmountPerContract) + if (exerciseFeePerContract.gtn(0)) { + const exerciseFeeKey = await Token.getAssociatedTokenAddress( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + quoteMint, + FEE_OWNER_KEY, + true + ) + remainingAccounts.push({ + pubkey: exerciseFeeKey, + isWritable: false, + isSigner: false, + }) + const ix = await getOrAddAssociatedTokenAccountTx( + exerciseFeeKey, + quoteMint, + program.provider, + FEE_OWNER_KEY + ) + if (ix) { + instructions.push(ix) + } + } + + const tx = await program.instruction.initializeMarket( + underlyingAmountPerContract, + quoteAmountPerContract, + expirationUnixTimestamp, + bumpSeed, + { + accounts: { + // @ts-ignore + authority: program.provider.wallet.publicKey, + feeOwner: FEE_OWNER_KEY, + optionMarket: optionMarketKey, + optionMint: optionMintKey, + quoteAssetMint: quoteMint, + quoteAssetPool: quoteAssetPoolKey, + underlyingAssetMint: underlyingMint, + underlyingAssetPool: underlyingAssetPoolKey, + writerTokenMint: writerMintKey, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + clock: SYSVAR_CLOCK_PUBKEY, + rent: SYSVAR_RENT_PUBKEY, + systemProgram: SystemProgram.programId, + tokenProgram: TOKEN_PROGRAM_ID, + }, + instructions: instructions.length ? instructions : undefined, + remainingAccounts, + } + ) + + return { + optionMarketKey, + optionMintKey, + quoteAssetPoolKey, + tx, + underlyingAssetPoolKey, + writerMintKey, + } +} + +/* TODO refactor to gov ui utility function */ +const getOrAddAssociatedTokenAccountTx = async ( + associatedAddress: PublicKey, + mintKey: PublicKey, + provider: Provider, + owner: PublicKey = FEE_OWNER_KEY +): Promise => { + const accountInfo = await provider.connection.getAccountInfo( + associatedAddress + ) + if (accountInfo) { + // accountInfo exists, so the associated token account has already + // been initialized + return null + } + + return Token.createAssociatedTokenAccountInstruction( + ASSOCIATED_TOKEN_PROGRAM_ID, + TOKEN_PROGRAM_ID, + mintKey, + associatedAddress, + owner, + // @ts-ignore + provider.wallet.publicKey + ) +} diff --git a/utils/instructions/PsyFinance/poseidon.ts b/utils/instructions/PsyFinance/poseidon.ts new file mode 100644 index 0000000000..5569a59708 --- /dev/null +++ b/utils/instructions/PsyFinance/poseidon.ts @@ -0,0 +1,60 @@ +import { BN, Program, web3 } from '@coral-xyz/anchor' +import { Poseidon } from './PoseidonIdl' + +type BoundedStrategyParamsV2 = { + boundPriceNumerator: BN + boundPriceDenominator: BN + reclaimDate: BN +} + +const deriveBoundedStrategyV2 = ( + program: Program, + mint: web3.PublicKey, + boundPriceNumerator: BN, + boundPriceDenominator: BN, + reclaimDate: BN +) => { + const textEncoder = new TextEncoder() + return web3.PublicKey.findProgramAddressSync( + [ + mint.toBuffer(), + boundPriceNumerator.toArrayLike(Buffer, 'le', 8), + boundPriceDenominator.toArrayLike(Buffer, 'le', 8), + reclaimDate.toArrayLike(Buffer, 'le', 8), + textEncoder.encode('boundedStrategy'), + ], + program.programId + ) +} + +const deriveCollateralAccount = ( + program: Program, + strategy: web3.PublicKey +) => { + const textEncoder = new TextEncoder() + return web3.PublicKey.findProgramAddressSync( + [strategy.toBuffer(), textEncoder.encode('orderPayer')], + program.programId + ) +} + +export const deriveAllBoundedStrategyKeysV2 = ( + program: Program, + mint: web3.PublicKey, + boundedStrategyParams: BoundedStrategyParamsV2 +) => { + const { + boundPriceNumerator, + boundPriceDenominator, + reclaimDate, + } = boundedStrategyParams + const [boundedStrategy] = deriveBoundedStrategyV2( + program, + mint, + boundPriceNumerator, + boundPriceDenominator, + reclaimDate + ) + const [collateralAccount] = deriveCollateralAccount(program, boundedStrategy) + return { collateralAccount, boundedStrategy } +} diff --git a/utils/instructions/PsyFinance/types.ts b/utils/instructions/PsyFinance/types.ts new file mode 100644 index 0000000000..d1b72e5441 --- /dev/null +++ b/utils/instructions/PsyFinance/types.ts @@ -0,0 +1,22 @@ +import * as anchor from '@coral-xyz/anchor' +import { PublicKey } from '@solana/web3.js' + +export type OptionMarket = { + optionMint: PublicKey + writerTokenMint: PublicKey + underlyingAssetMint: PublicKey + quoteAssetMint: PublicKey + underlyingAssetPool: PublicKey + quoteAssetPool: PublicKey + mintFeeAccount: PublicKey + exerciseFeeAccount: PublicKey + underlyingAmountPerContract: anchor.BN + quoteAmountPerContract: anchor.BN + expirationUnixTimestamp: anchor.BN + expired: boolean + bumpSeed: number +} + +export type OptionMarketWithKey = OptionMarket & { + key: PublicKey +} diff --git a/utils/lidoStake.ts b/utils/lidoStake.ts index cdf9e2d2ae..50aa19f507 100644 --- a/utils/lidoStake.ts +++ b/utils/lidoStake.ts @@ -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, diff --git a/utils/logs.ts b/utils/logs.ts new file mode 100644 index 0000000000..603152cb91 --- /dev/null +++ b/utils/logs.ts @@ -0,0 +1,17 @@ +import * as Sentry from '@sentry/react' + +export const trySentryLog = ({ + tag, + objToStringify, +}: { + tag: string + objToStringify: any +}) => { + try { + Sentry.captureMessage(JSON.stringify(objToStringify), { + tags: { tag: tag }, + }) + } catch (e) { + console.log(e, 'error in sentry log') + } +} diff --git a/utils/mangoV4Tools.ts b/utils/mangoV4Tools.ts new file mode 100644 index 0000000000..c2e932f3d3 --- /dev/null +++ b/utils/mangoV4Tools.ts @@ -0,0 +1,84 @@ +import { MANGO_V4_ID, MangoClient } from '@blockworks-foundation/mango-v4' +import { AnchorProvider } from '@coral-xyz/anchor' +import queryClient from '@hooks/queries/queryClient' +import { Connection, Keypair, PublicKey } from '@solana/web3.js' +import EmptyWallet from './Mango/listingTools' + +export function getChangedValues>( + originalValues: T, + newValues: T, + ignoredFields?: string[] +) { + const values: any = {} + for (const key of Object.keys(originalValues)) { + const typeOfValue = typeof originalValues[key] + if ( + (typeOfValue !== 'object' && originalValues[key] !== newValues[key]) || + (typeOfValue === 'object' && + JSON.stringify(originalValues[key]) !== JSON.stringify(newValues[key])) + ) { + values[key] = newValues[key] + } else { + values[key] = null + } + if (ignoredFields?.length && ignoredFields.find((x) => x === key)) { + values[key] = newValues[key] + } + } + return values as Partial +} + +export function getNullOrTransform( + val: any, + classTransformer: (new (val: any) => T) | null, + functionTransformer?: (val) => T +): T | null { + if (val === null) { + return null + } + if (typeof functionTransformer !== 'undefined') { + return functionTransformer(val) + } + if (classTransformer !== null) { + return new classTransformer(val) + } + return null +} + +export const getClient = async (connection: Connection) => { + const client = await queryClient.fetchQuery({ + queryKey: ['mangoClient', connection.rpcEndpoint], + queryFn: async () => { + const options = AnchorProvider.defaultOptions() + const adminProvider = new AnchorProvider( + connection, + new EmptyWallet(Keypair.generate()), + options + ) + const client = MangoClient.connect( + adminProvider, + 'mainnet-beta', + MANGO_V4_ID['mainnet-beta'], + { + idsSource: 'api', + } + ) + + return client + }, + }) + return client +} +export const getGroupForClient = async ( + client: MangoClient, + groupPk: PublicKey +) => { + const group = await queryClient.fetchQuery({ + queryKey: ['mangoGroup', groupPk.toBase58(), client.connection.rpcEndpoint], + queryFn: async () => { + const response = await client.getGroup(groupPk) + return response + }, + }) + return group +} diff --git a/utils/metaplex.ts b/utils/metaplex.ts new file mode 100644 index 0000000000..1cf3a484ad --- /dev/null +++ b/utils/metaplex.ts @@ -0,0 +1,47 @@ +import { fetchNFTbyMint } from '@hooks/queries/nft' +import { Metaplex } from '@metaplex-foundation/js' +import { Connection, PublicKey } from '@solana/web3.js' + +export const createIx_transferNft = async ( + connection: Connection, + fromOwner: PublicKey, + toOwner: PublicKey, + mint: PublicKey, + authority: PublicKey, + payer: PublicKey +) => { + const metaplex = new Metaplex( + connection + // surely this doesn't matter? who cares what the cluster is if you know the endpoint? + /* { + cluster: + connection.en === 'mainnet' ? 'mainnet-beta' : connection.cluster, + }*/ + ) //.use(walletAdapterIdentity(wallet)) // surely this doesnt matter either (IT DOES) + //metaplex.identity = () => ({ publicKey: fromOwner } as any) // you need to do this to set payer and authority. I love OOP!! + // except the payer might not be the same person. great! + + const nft = await fetchNFTbyMint(connection, mint) + if (!nft.result) throw 'failed to fetch nft' + + const tokenStandard = nft.result.tokenStandard + const ruleSet = nft.result.programmableConfig?.ruleSet + + const ix = metaplex + .nfts() + .builders() + .transfer({ + nftOrSft: { + address: mint, + tokenStandard, + }, + authorizationDetails: ruleSet ? { rules: ruleSet } : undefined, + toOwner, + fromOwner, + }) + .getInstructions()[0] + + ix.keys[9].pubkey = authority + ix.keys[10].pubkey = payer + return ix +} diff --git a/utils/modifiedMangolana.ts b/utils/modifiedMangolana.ts new file mode 100644 index 0000000000..87761fb884 --- /dev/null +++ b/utils/modifiedMangolana.ts @@ -0,0 +1,715 @@ +import { + AddressLookupTableAccount, + Commitment, + Connection, + Keypair, + RpcResponseAndContext, + SignatureStatus, + SimulatedTransactionResponse, + Transaction, + TransactionConfirmationStatus, + TransactionMessage, + TransactionSignature, + VersionedTransaction, +} from '@solana/web3.js' +import { + getUnixTs, + Logger, + MAXIMUM_NUMBER_OF_BLOCKS_FOR_TRANSACTION, + sleep, +} from '@blockworks-foundation/mangolana/lib/tools' +import { + BlockHeightStrategy, + BlockHeightStrategyClass, + getTimeoutConfig, + SequenceType, + TimeStrategy, + TransactionInstructionWithSigners, +} from '@blockworks-foundation/mangolana/lib/globalTypes' +import { WalletSigner } from '@solana/spl-governance' +import { getFeeEstimate } from '@tools/feeEstimate' +import { createComputeBudgetIx } from '@blockworks-foundation/mango-v4' + +interface TransactionInstructionWithType { + instructionsSet: TransactionInstructionWithSigners[] + sequenceType?: SequenceType +} + +interface TransactionsPlayingIndexes { + transactionsIdx: { [txIdx: number]: number }[] + sequenceType?: SequenceType +} + +type awaitTransactionSignatureConfirmationProps = { + txid: TransactionSignature + confirmLevel: TransactionConfirmationStatus + connection: Connection + timeoutStrategy: TimeStrategy | BlockHeightStrategy + config?: { + logFlowInfo?: boolean + } +} +/** + * waits for transaction confirmation + * @param timeoutStrategy TimeStrategy | BlockHeightStrategy + * + * TimeStrategy: pure timeout strategy + * + * timeout: optional, (secs) after how much secs not confirmed transaction will be considered timeout, default: 90 + * getSignatureStatusesPoolIntervalMs: optional, (ms) pool interval of getSignatureStatues, default: 2000 + * + * + * BlockHeightStrategy: blockheight pool satrategy + * + * startBlockCheckAfterSecs: optional, (secs) after that time we will start to pool current blockheight and check if transaction will reach blockchain, default: 90 + * block: BlockhashWithExpiryBlockHeight + * getSignatureStatusesPoolIntervalMs: optional, (ms) pool interval of getSignatureStatues and blockheight, default: 2000 + * @param config.logFlowInfo when true it will console log process of processing transactions + */ +const awaitTransactionSignatureConfirmation = async ({ + txid, + confirmLevel, + connection, + timeoutStrategy, + config, +}: awaitTransactionSignatureConfirmationProps) => { + const logger = new Logger({ ...config }) + const timeoutConfig = getTimeoutConfig(timeoutStrategy) + let timeoutBlockHeight = 0 + let timeout = 0 + if (timeoutConfig instanceof BlockHeightStrategyClass) { + timeoutBlockHeight = + timeoutConfig.block.lastValidBlockHeight + + MAXIMUM_NUMBER_OF_BLOCKS_FOR_TRANSACTION + timeout = timeoutConfig.startBlockCheckAfterSecs + } else { + timeout = timeoutConfig.timeout + } + + let startTimeoutCheck = false + let done = false + const confirmLevels: (TransactionConfirmationStatus | null | undefined)[] = [ + 'finalized', + ] + if (confirmLevel === 'confirmed') { + confirmLevels.push('confirmed') + } else if (confirmLevel === 'processed') { + confirmLevels.push('confirmed') + confirmLevels.push('processed') + } + let subscriptionId: number | undefined + + const result = await new Promise((resolve, reject) => { + ;(async () => { + setTimeout(() => { + if (done) { + return + } + if (timeoutBlockHeight !== 0) { + startTimeoutCheck = true + } else { + done = true + logger.log('Timed out for txid: ', txid) + reject({ timeout: true }) + } + }, timeout) + try { + subscriptionId = connection.onSignature( + txid, + (result, _context) => { + subscriptionId = undefined + done = true + if (result.err) { + reject(result.err) + } else { + resolve(result) + } + }, + confirmLevel + ) + } catch (e) { + done = true + logger.log('WS error in setup', txid, e) + } + const retrySleep = + timeoutConfig.getSignatureStatusesPoolIntervalMs || 5000 + while (!done) { + // eslint-disable-next-line no-loop-func + await sleep(retrySleep) + ;(async () => { + try { + const promises: [ + Promise>, + Promise? + ] = [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, currentBlockHeight] = await Promise.all( + promises + ) + if ( + typeof currentBlockHeight !== undefined && + timeoutBlockHeight <= currentBlockHeight! + ) { + logger.log('Timed out for txid: ', txid) + done = true + reject({ timeout: true }) + } + + const result = signatureStatuses && signatureStatuses.value[0] + if (!done) { + if (!result) return + if (result.err) { + logger.log('REST error for', txid, result) + done = true + reject(result.err) + } else if ( + !( + result.confirmations || + confirmLevels.includes(result.confirmationStatus) + ) + ) { + logger.log('REST not confirmed', txid, result) + } else { + logger.log('REST confirmed', txid, result) + done = true + resolve(result) + } + } + } catch (e) { + if (!done) { + logger.log('REST connection error: txid', txid, e) + } + } + })() + } + })() + }) + + if (subscriptionId) { + connection.removeSignatureListener(subscriptionId).catch((e) => { + logger.log('WS error in cleanup', e) + }) + } + + done = true + return result +} + +/** + * send and waits for transaction to confirm + * @param callbacks sets of callbacks. + * @param callbacks.postSendTxCallback post send transaction callback + * @param callbacks.afterTxConfirmation runs after tx confirmation + * @param timeoutStrategy TimeStrategy | BlockHeightStrategy + * + * TimeStrategy: pure timeout strategy + * + * timeout: optional, (secs) after how much secs not confirmed transaction will be considered timeout, default: 90 + * getSignatureStatusesPoolIntervalMs: optional, (ms) pool interval of getSignatureStatues, default: 5000 + * + * + * BlockHeightStrategy: blockheight pool satrategy + * + * startBlockCheckAfterSecs: optional, (secs) after that time we will start to pool current blockheight and check if transaction will reach blockchain, default: 90 + * block: BlockhashWithExpiryBlockHeight + * getSignatureStatusesPoolIntervalMs: optional, (ms) pool interval of getSignatureStatues and blockheight, default: 2000 + * + * @param config.resendTxUntilConfirmed force resend transaction in the mean time of waiting for confirmation, default false + * @param config.resendPoolTimeMs when resendTxUntilConfirmed is true it will resend transaction every value of ms until there is timeout, default 2000 + * @param config.logFlowInfo when true it will console log process of processing transactions + * @param config.skipPreflight + */ +export const sendAndConfirmSignedTransaction = async ({ + signedTransaction, + confirmLevel = 'processed', + connection, + callbacks, + timeoutStrategy, + config, +}: { + signedTransaction: VersionedTransaction + connection: Connection + confirmLevel?: TransactionConfirmationStatus + timeoutStrategy: TimeStrategy | BlockHeightStrategy + callbacks?: { + postSendTxCallback?: ({ txid }: { txid: string }) => void + afterTxConfirmation?: () => void + } + config?: { + resendTxUntilConfirmed?: boolean + resendPoolTimeMs?: number + logFlowInfo?: boolean + skipPreflight?: boolean + } +}) => { + const logger = new Logger({ ...config }) + const timeoutConfig = getTimeoutConfig(timeoutStrategy) + let resendTimeout = 0 + if (timeoutConfig instanceof BlockHeightStrategyClass) { + resendTimeout = timeoutConfig.startBlockCheckAfterSecs + } else { + resendTimeout = timeoutConfig.timeout + } + if (config?.resendTxUntilConfirmed) { + config.resendPoolTimeMs ||= 2000 + } + const rawTransaction = signedTransaction.serialize() + const startTime = getUnixTs() + const txid = await connection.sendRawTransaction(rawTransaction, { + skipPreflight: + config?.skipPreflight === undefined ? true : config.skipPreflight, + }) + console.log('sent transaction:', txid) + if (callbacks?.postSendTxCallback) { + try { + callbacks.postSendTxCallback({ txid }) + } catch (e) { + logger.log(`postSendTxCallback error ${e}`) + } + } + + let done = false + if (config?.resendTxUntilConfirmed) { + ;(async () => { + while (!done && getUnixTs() - startTime < resendTimeout!) { + await sleep(config?.resendPoolTimeMs || 2000) + connection.sendRawTransaction(rawTransaction, { + skipPreflight: + config?.skipPreflight === undefined ? true : config.skipPreflight, + }) + } + })() + } + + try { + await awaitTransactionSignatureConfirmation({ + txid, + timeoutStrategy: timeoutStrategy, + confirmLevel, + connection, + config, + }) + if (callbacks?.afterTxConfirmation) { + callbacks.afterTxConfirmation() + } + } catch (err: any) { + logger.log(err) + if (err.timeout) { + throw { txid } + } + let simulateResult: SimulatedTransactionResponse | null = null + try { + simulateResult = ( + await simulateTransaction( + connection, + signedTransaction, + 'single', + config?.logFlowInfo + ) + ).value + } catch (e) { + logger.log('Simulate tx failed', e) + } + logger.log(simulateResult) + 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: ')) { + throw { + message: + 'Transaction failed: ' + line.slice('Program log: '.length), + txid, + } + } + } + } + throw { + message: JSON.stringify(simulateResult.err), + txid, + } + } + throw { message: 'Transaction failed', txid } + } finally { + done = true + } + return txid +} + +export type sendSignAndConfirmTransactionsProps = { + connection: Connection + wallet: WalletSigner + transactionInstructions: TransactionInstructionWithType[] + timeoutStrategy?: BlockHeightStrategy + confirmLevel?: TransactionConfirmationStatus + callbacks?: { + afterFirstBatchSign?: (signedTxnsCount: number) => void + afterBatchSign?: (signedTxnsCount: number) => void + afterAllTxConfirmed?: () => void + afterEveryTxConfirmation?: () => void + onError?: ( + e: any, + notProcessedTransactions: TransactionInstructionWithType[], + originalProps: sendSignAndConfirmTransactionsProps + ) => void + } + config?: { + maxTxesInBatch: number + autoRetry: boolean + maxRetries?: number + retried?: number + logFlowInfo?: boolean + } + lookupTableAccounts?: AddressLookupTableAccount[] +} +/** + * sign and send array of transactions in desired batches with different styles of send for each array + * @param timeoutStrategy + * + * BlockHeightStrategy: blockheight pool satrategy + * + * startBlockCheckAfterSecs: optional, (secs) after that time we will start to pool current blockheight and check if transaction will reach blockchain, default: 90 + * block: BlockhashWithExpiryBlockHeight + * getSignatureStatusesPoolIntervalMs: optional, (ms) pool interval of getSignatureStatues and blockheight, default: 2000 + * + * + * @param callbacks sets of callbacks + * @param callbacks.afterFirstBatchSign callback will run only on first batch approval + * @param callbacks.afterBatchSign callback will run on any batch approval + * @param callbacks.afterAllTxConfirmed callback will run after all transaction batches are confirmed + * @param callbacks.afterEveryTxConfirmation callback will run on every single transaction confirmation + * @param callbacks.onError callback will run on error + * + * @param config.maxTxesInBatch max transactions in one batch of transactions, there is limitation on how much wallet can sign in one go depending on used wallet. default 40 + * @param config.autoRetry auto retry on any error approve and send of transaction after error + * @param config.maxRetries if auto retry is true, it will try this amount of times before actual error, default 5 + * @param config.retired argument passed by recursive function best not to change it, default 0 + * @param config.logFlowInfo when true it will console log process of processing transactions + */ +export const sendSignAndConfirmTransactions = async ({ + connection, + wallet, + transactionInstructions, + confirmLevel = 'processed', + timeoutStrategy, + callbacks, + config = { + maxTxesInBatch: 40, + autoRetry: false, + maxRetries: 5, + retried: 0, + logFlowInfo: false, + }, + lookupTableAccounts, +}: sendSignAndConfirmTransactionsProps) => { + const logger = new Logger({ ...config }) + const block = + timeoutStrategy?.block ?? (await connection.getLatestBlockhash('confirmed')) + const fee = await getFeeEstimate(connection) + const walletPk = wallet.publicKey + if (!walletPk) throw new Error('Wallet not connected!') + + if (typeof config?.retried === 'undefined') { + config.retried = 0 + } + if (typeof config?.maxRetries === 'undefined') { + config.maxRetries = 5 + } + //block will be used for timeout calculation + //max usable transactions per one sign is 40 + const maxTransactionsInBath = config.maxTxesInBatch + const currentTransactions = transactionInstructions.slice( + 0, + maxTransactionsInBath + ) + + // see NOTE 1 for explanation of how these transactions are used (they aren't signed) + const oldTransactionsThatShouldGetRefactored: 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: Keypair[] = [] + if (transactionInstruction.instructionsSet.length === 0) { + continue + } + + const transaction = new Transaction() + transaction.add(createComputeBudgetIx(fee)) + transactionInstruction.instructionsSet.forEach((instruction) => { + transaction.add(instruction.transactionInstruction) + if (instruction.signers?.length) { + signers.push(...instruction.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 = oldTransactionsThatShouldGetRefactored.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, + }) + } + oldTransactionsThatShouldGetRefactored.push(transaction) + } + + // @asktree: NOTE 1: I needed to make this fn use the new VersionedTransactions, + // but I have no idea what the above code is doing with this transactionCallOrchestrator stuff. + // So I'm just taking the outputs and converting them to the new object + + const versionedTxs = oldTransactionsThatShouldGetRefactored.map( + (tx) => + new VersionedTransaction( + new TransactionMessage({ + payerKey: walletPk, + instructions: tx.instructions, + recentBlockhash: block.blockhash, + }).compileToV0Message(lookupTableAccounts) + ) + ) + + const signers = currentTransactions.map((x) => + x.instructionsSet.flatMap((y) => y.signers ?? []) + ) + + versionedTxs.forEach((tx, i) => tx.sign(signers[i])) + + logger.log(transactionCallOrchestrator) + const signedTxns = ((await wallet.signAllTransactions( + //@ts-ignore + versionedTxs + )) as unknown) as VersionedTransaction[] + if (callbacks?.afterFirstBatchSign) { + callbacks.afterFirstBatchSign(signedTxns.length) + } else if (callbacks?.afterBatchSign) { + callbacks.afterBatchSign(signedTxns.length) + } + + logger.log( + 'Transactions play type order', + transactionCallOrchestrator.map((x) => { + return { + ...x, + sequenceType: + typeof x.sequenceType !== 'undefined' + ? SequenceType[Number(x.sequenceType)] + : 'Parallel', + } + }) + ) + logger.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 = Number(Object.keys(idx)[0]) + const transactionInstructionIdx = idx[transactionIdx] + // eslint-disable-next-line + return new Promise(async (resolve, reject) => { + try { + const resp = await sendAndConfirmSignedTransaction({ + connection, + signedTransaction: signedTxns[transactionIdx], + confirmLevel, + timeoutStrategy: { + block: block!, + }, + callbacks: { + afterTxConfirmation: callbacks?.afterEveryTxConfirmation, + }, + config, + }) + resolve(resp) + } catch (e) { + logger.log(e) + if (typeof e === 'object') { + reject({ + ...e, + transactionInstructionIdx, + }) + } else { + reject(e) + } + } + }) + }) + ) + } + if (fcn.sequenceType === SequenceType.Sequential) { + //wait for all Sequential + for (const idx of fcn.transactionsIdx) { + const transactionIdx = Number(Object.keys(idx)[0]) + const transactionInstructionIdx = idx[transactionIdx] + try { + await sendAndConfirmSignedTransaction({ + connection, + signedTransaction: signedTxns[transactionIdx], + confirmLevel, + timeoutStrategy: { + block, + }, + callbacks: { + afterTxConfirmation: callbacks?.afterEveryTxConfirmation, + }, + config, + }) + } catch (e) { + logger.log(e) + if (typeof e === 'object') { + throw { + ...e, + transactionInstructionIdx, + } + } else { + throw e + } + } + } + } + } + //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 + ) + await sendSignAndConfirmTransactions({ + connection, + wallet, + confirmLevel, + transactionInstructions: forwardedTransactions, + timeoutStrategy: timeoutStrategy, + callbacks: { + afterBatchSign: callbacks?.afterBatchSign, + afterAllTxConfirmed: callbacks?.afterAllTxConfirmed, + afterEveryTxConfirmation: callbacks?.afterEveryTxConfirmation, + onError: callbacks?.onError, + }, + config, + }) + } + if (callbacks?.afterAllTxConfirmed) { + callbacks.afterAllTxConfirmed() + } + } catch (e) { + logger.log(e) + if (callbacks?.onError) { + console.log('error object', JSON.stringify(e)) + if (typeof e === 'object') { + const idx = (e as any).txInstructionIdx + const txInstructionForRetry = transactionInstructions.slice( + idx, + transactionInstructions.length + ) + callbacks.onError(e, txInstructionForRetry, { + connection, + wallet, + confirmLevel, + transactionInstructions, + timeoutStrategy, + callbacks, + config, + }) + } else { + callbacks.onError(e, [], { + connection, + wallet, + confirmLevel, + transactionInstructions, + timeoutStrategy, + callbacks, + config, + }) + } + } + if (config.autoRetry && config.maxRetries < config.retried) { + const idx = (e as any)?.txInstructionIdx + if (typeof idx !== 'undefined') { + config.retried++ + const txInstructionForRetry = transactionInstructions.slice( + idx, + transactionInstructions.length + ) + await sendSignAndConfirmTransactions({ + connection, + wallet, + confirmLevel, + transactionInstructions: txInstructionForRetry, + callbacks, + config, + }) + } else { + throw e + } + } else { + throw e + } + } +} + +/** Copy of Connection.simulateTransaction that takes a commitment parameter. */ +async function simulateTransaction( + connection: Connection, + transaction: VersionedTransaction, + commitment: Commitment, + logInfo?: boolean +): Promise> { + const logger = new Logger({ logFlowInfo: !!logInfo }) + /* + const latestBlockhash = await connection.getLatestBlockhash() + transaction.lastValidBlockHeight = latestBlockhash.lastValidBlockHeight + transaction.recentBlockhash = latestBlockhash.blockhash + + logger.log('simulating transaction', transaction) + + const signData = transaction.serialize() + // @ts-ignore + const wireTransaction = transaction._serialize(signData) + const encodedTransaction = wireTransaction.toString('base64') + + logger.log('encoding') + const config: any = { encoding: 'base64', commitment } + const args = [encodedTransaction, config] + logger.log('simulating data', args) + + // @ts-ignore + const res = await connection._rpcRequest('simulateTransaction', args) + */ + const res = await connection.simulateTransaction(transaction, { commitment }) + + logger.log('res simulating transaction', res) + if (res.value.err) { + throw new Error( + 'failed to simulate transaction: ' + JSON.stringify(res.value.err) + ) + } + return res +} diff --git a/utils/parseTokenAccountData.tsx b/utils/parseTokenAccountData.tsx new file mode 100644 index 0000000000..61e57d3e6a --- /dev/null +++ b/utils/parseTokenAccountData.tsx @@ -0,0 +1,42 @@ +import { PublicKey } from '@solana/web3.js' +import { AccountInfo, AccountLayout, u64 } from '@solana/spl-token' + +/** @asktree its very unclear why this must exist, like... why doesn't spl-token do this? */ + +export function parseTokenAccountData( + account: PublicKey, + data: Buffer +): AccountInfo { + const accountInfo = AccountLayout.decode(data) + accountInfo.address = account + accountInfo.mint = new PublicKey(accountInfo.mint) + accountInfo.owner = new PublicKey(accountInfo.owner) + accountInfo.amount = u64.fromBuffer(accountInfo.amount) + + if (accountInfo.delegateOption === 0) { + accountInfo.delegate = null + accountInfo.delegatedAmount = new u64(0) + } else { + accountInfo.delegate = new PublicKey(accountInfo.delegate) + accountInfo.delegatedAmount = u64.fromBuffer(accountInfo.delegatedAmount) + } + + accountInfo.isInitialized = accountInfo.state !== 0 + accountInfo.isFrozen = accountInfo.state === 2 + + if (accountInfo.isNativeOption === 1) { + accountInfo.rentExemptReserve = u64.fromBuffer(accountInfo.isNative) + accountInfo.isNative = true + } else { + accountInfo.rentExemptReserve = null + accountInfo.isNative = false + } + + if (accountInfo.closeAuthorityOption === 0) { + accountInfo.closeAuthority = null + } else { + accountInfo.closeAuthority = new PublicKey(accountInfo.closeAuthority) + } + + return accountInfo +} diff --git a/utils/pause.ts b/utils/pause.ts new file mode 100644 index 0000000000..ed71209928 --- /dev/null +++ b/utils/pause.ts @@ -0,0 +1,5 @@ +export function pause(ms: number) { + return new Promise((resolve) => { + setTimeout(() => resolve(true), ms) + }) +} diff --git a/utils/plugin/accounts.ts b/utils/plugin/accounts.ts index 787bdd5636..a52e89c49b 100644 --- a/utils/plugin/accounts.ts +++ b/utils/plugin/accounts.ts @@ -1,12 +1,22 @@ +import { PluginName } from '@constants/plugins' import { PublicKey } from '@solana/web3.js' -export const getRegistrarPDA = async ( +export const getRegistrarPDA = ( realmPk: PublicKey, mint: PublicKey, - clientProgramId: PublicKey + clientProgramId: PublicKey, + pluginName?: PluginName ) => { - const [registrar, registrarBump] = await PublicKey.findProgramAddress( - [Buffer.from('registrar'), realmPk.toBuffer(), mint.toBuffer()], + const PLUGIN_NAME_SEEDS = { + VSR: [realmPk.toBuffer(), Buffer.from('registrar'), mint.toBuffer()], + } + const seed = (pluginName && PLUGIN_NAME_SEEDS[pluginName]) ?? [ + Buffer.from('registrar'), + realmPk.toBuffer(), + mint.toBuffer(), + ] + const [registrar, registrarBump] = PublicKey.findProgramAddressSync( + seed, clientProgramId ) return { diff --git a/utils/proposals.ts b/utils/proposals.ts new file mode 100644 index 0000000000..d3c4607d6c --- /dev/null +++ b/utils/proposals.ts @@ -0,0 +1,229 @@ +import { Filters } from '@components/ProposalFilter' +import { Sorting, SORTING_OPTIONS } from '@components/ProposalSorting' +import { hasInstructions } from '@components/ProposalStateBadge' +import { BN } from '@coral-xyz/anchor' +import { + Governance, + ProgramAccount, + Proposal, + ProposalState, + Realm, +} from '@solana/spl-governance' +import { MintInfo } from '@solana/spl-token' +import { fmtTokenAmount } from './formatting' + +export const compareProposals = ( + p1: Proposal, + p2: Proposal, + governances: { + [governance: string]: ProgramAccount + } +) => { + const p1Rank = p1.getStateSortRank() + const p2Rank = p2.getStateSortRank() + + if (p1Rank > p2Rank) { + return 1 + } else if (p1Rank < p2Rank) { + return -1 + } + + if (p1.state === ProposalState.Voting && p2.state === ProposalState.Voting) { + const p1VotingRank = getVotingStateRank(p1, governances) + const p2VotingRank = getVotingStateRank(p2, governances) + + if (p1VotingRank > p2VotingRank) { + return 1 + } else if (p1VotingRank < p2VotingRank) { + return -1 + } + + // Show the proposals in voting state expiring earlier at the top + return p2.getStateTimestamp() - p1.getStateTimestamp() + } + + return p1.getStateTimestamp() - p2.getStateTimestamp() +} + +function getVotingStateRank( + proposal: Proposal, + governances: { + [governance: string]: ProgramAccount + } +) { + // Show proposals in Voting state before proposals in Finalizing state + const governance = governances[proposal.governance.toBase58()].account + return proposal.hasVoteTimeEnded(governance) ? 0 : 1 +} + +export const filterProposals = ( + proposals: [string, ProgramAccount][], + filters: Filters, + sorting: Sorting, + realm: ProgramAccount | undefined, + governances: Record>, + councilMint: MintInfo | undefined, + communityMint: MintInfo | undefined +) => { + return proposals + .sort(([, proposalA], [, proposalB]) => { + if (sorting.completed_at === SORTING_OPTIONS.ASC) { + return ( + proposalA.account.votingCompletedAt || + proposalA.account.signingOffAt || + proposalA.account.draftAt || + new BN(0) + ) + .sub( + proposalB.account.votingCompletedAt || + proposalB.account.signingOffAt || + proposalB.account.draftAt || + new BN(0) + ) + .toNumber() + } + if (sorting.completed_at === SORTING_OPTIONS.DESC) { + return ( + proposalB.account.votingCompletedAt || + proposalB.account.signingOffAt || + proposalB.account.draftAt || + new BN(0) + ) + .sub( + proposalA.account.votingCompletedAt || + proposalA.account.signingOffAt || + proposalA.account.draftAt || + new BN(0) + ) + .toNumber() + } + if (sorting.signedOffAt === SORTING_OPTIONS.ASC) { + return ( + proposalA.account.signingOffAt || + proposalA.account.draftAt || + new BN(0) + ) + .sub( + proposalB.account.signingOffAt || + proposalB.account.draftAt || + new BN(0) + ) + .toNumber() + } + if (sorting.signedOffAt === SORTING_OPTIONS.DESC) { + return ( + proposalB.account.signingOffAt || + proposalB.account.draftAt || + new BN(0) + ) + .sub( + proposalA.account.signingOffAt || + proposalA.account.draftAt || + new BN(0) + ) + .toNumber() + } + return 0 + }) + .filter(([, proposal]) => { + if ( + !filters.Cancelled && + proposal.account.state === ProposalState.Cancelled + ) { + return false + } + + if (!filters.Completed) { + if (proposal.account.state === ProposalState.Completed) { + return false + } + + if ( + proposal.account.state === ProposalState.Succeeded && + !hasInstructions(proposal.account) + ) { + return false + } + } + + if (!filters.Vetoed && proposal.account.state === ProposalState.Vetoed) { + return false + } + + if ( + !filters.Defeated && + proposal.account.state === ProposalState.Defeated + ) { + return false + } + + if (!filters.Draft && proposal.account.state === ProposalState.Draft) { + return false + } + + if (!filters.Executable) { + if (proposal.account.state === ProposalState.Executing) { + return false + } + + if ( + proposal.account.state === ProposalState.Succeeded && + hasInstructions(proposal.account) + ) { + return false + } + } + + if ( + !filters.ExecutingWithErrors && + proposal.account.state === ProposalState.ExecutingWithErrors + ) { + return false + } + + if ( + !filters.SigningOff && + proposal.account.state === ProposalState.SigningOff + ) { + return false + } + + if ( + !filters.Voting && + proposal.account.state === ProposalState.Voting && + !filters.withoutQuorum + ) { + return false + } + if ( + filters.withoutQuorum && + proposal.account.state === ProposalState.Voting + ) { + const proposalMint = + proposal?.account.governingTokenMint.toBase58() === + realm?.account.communityMint.toBase58() + ? communityMint + : councilMint + const isCommunityVote = + proposal.account?.governingTokenMint.toBase58() === + realm?.account.communityMint.toBase58() + const governance = + governances[proposal.account.governance.toBase58()].account + const voteThresholdPct = isCommunityVote + ? governance.config.communityVoteThreshold.value + : governance.config.councilVoteThreshold.value + + const minimumYesVotes = + fmtTokenAmount(proposalMint!.supply, proposalMint!.decimals) * + (voteThresholdPct! / 100) + return ( + fmtTokenAmount( + proposal.account.getYesVoteCount(), + proposalMint!.decimals + ) < minimumYesVotes && !proposal.account.hasVoteTimeEnded(governance) + ) + } + + return true + }) +} diff --git a/utils/queries/asFindable.ts b/utils/queries/asFindable.ts new file mode 100644 index 0000000000..d01217995a --- /dev/null +++ b/utils/queries/asFindable.ts @@ -0,0 +1,32 @@ +/** + * @param {any} thisContext - second param if you want to call function that is part of + * an object eg. connection.getAccountInfo + * getAccountInfo will loss this binding so you need to + * pass connection as context. Depends on lib/function implementation + */ +const asFindable =

( + f: (...p: P) => Promise, + thisContext?: any +) => async (...p: P) => { + try { + const result = thisContext ? await f.call(thisContext, ...p) : await f(...p) + if (result === null || result === undefined) { + return { + found: false, + result: undefined, + } as const + } + return { + found: true, + result: result as NonNullable, + } as const + } catch (e) { + if ((e.message as string).includes('not found')) { + return { found: false, result: undefined, err: e.message } as const + } + + return Promise.reject(e) + } +} + +export default asFindable diff --git a/utils/send.tsx b/utils/send.tsx index aca836d0f4..7eca40b04a 100644 --- a/utils/send.tsx +++ b/utils/send.tsx @@ -1,9 +1,7 @@ import { notify } from './notifications' import { - Commitment, Connection, Keypair, - RpcResponseAndContext, SimulatedTransactionResponse, Transaction, TransactionSignature, @@ -11,6 +9,9 @@ import { import Wallet from '@project-serum/sol-wallet-adapter' import { sleep } from '@project-serum/common' import { WalletSigner } from '@solana/spl-governance' +import { invalidateInstructionAccounts } from '@hooks/queries/queryClient' +import { createComputeBudgetIx } from '@blockworks-foundation/mango-v4' +import { getFeeEstimate } from '@tools/feeEstimate' class TransactionError extends Error { public txid: string @@ -20,12 +21,13 @@ class TransactionError extends Error { } } -export function getUnixTs() { +function getUnixTs() { return new Date().getTime() / 1000 } const DEFAULT_TIMEOUT = 31000 +/** @deprecated use sendTransactionsV3 */ export async function sendTransaction({ transaction, wallet, @@ -69,9 +71,12 @@ export async function signTransaction({ signers?: Array connection: Connection }) { - transaction.recentBlockhash = ( - await connection.getLatestBlockhash('max') - ).blockhash + const [{ blockhash: recentBlockhash }, fee] = await Promise.all([ + connection.getLatestBlockhash('max'), + getFeeEstimate(connection), + ]) + transaction.add(createComputeBudgetIx(fee)) + transaction.recentBlockhash = recentBlockhash transaction.setSigners(wallet!.publicKey!, ...signers.map((s) => s.publicKey)) if (signers.length > 0) { transaction.partialSign(...signers) @@ -91,9 +96,14 @@ export async function signTransactions({ wallet: Wallet connection: Connection }) { - const blockhash = (await connection.getLatestBlockhash('max')).blockhash + const [{ blockhash: recentBlockhash }, fee] = await Promise.all([ + connection.getLatestBlockhash('max'), + getFeeEstimate(connection), + ]) + transactionsAndSigners.forEach(({ transaction, signers = [] }) => { - transaction.recentBlockhash = blockhash + transaction.add(createComputeBudgetIx(fee)) + transaction.recentBlockhash = recentBlockhash transaction.setSigners( wallet!.publicKey!, ...signers.map((s) => s.publicKey) @@ -179,9 +189,8 @@ export async function sendSignedTransaction({ // Simulate failed transaction to parse out an error reason try { console.log('start simulate') - simulateResult = ( - await simulateTransaction(connection, signedTransaction, 'single') - ).value + simulateResult = (await connection.simulateTransaction(signedTransaction)) + .value } catch (error) { console.log('Error simulating: ', error) } @@ -215,7 +224,7 @@ export async function sendSignedTransaction({ } notify({ message: successMessage, type: 'success', txid }) - + signedTransaction.instructions.forEach(invalidateInstructionAccounts) console.log('Latency', txid, getUnixTs() - startTime) return txid } @@ -293,9 +302,8 @@ export async function sendSignedAndAdjacentTransactions({ // Simulate failed transaction to parse out an error reason try { console.log('start simulate') - simulateResult = ( - await simulateTransaction(connection, signedTransaction, 'single') - ).value + simulateResult = (await connection.simulateTransaction(signedTransaction)) + .value } catch (error) { console.log('Error simulating: ', error) } @@ -423,37 +431,3 @@ async function awaitTransactionSignatureConfirmation( done = true return result } - -/** Copy of Connection.simulateTransaction that takes a commitment parameter. */ -export async function simulateTransaction( - connection: Connection, - transaction: Transaction, - commitment: Commitment -): Promise> { - // @ts-ignore - transaction.recentBlockhash = await connection._recentBlockhash( - // @ts-ignore - connection._disableBlockhashCaching - ) - - console.log('simulating transaction', transaction) - - const signData = transaction.serializeMessage() - // @ts-ignore - const wireTransaction = transaction._serialize(signData) - const encodedTransaction = wireTransaction.toString('base64') - - console.log('encoding') - const config: any = { encoding: 'base64', commitment } - const args = [encodedTransaction, config] - console.log('simulating data', args) - - // @ts-ignore - const res = await connection._rpcRequest('simulateTransaction', args) - - console.log('res simulating transaction', res) - if (res.error) { - throw new Error('failed to simulate transaction: ' + res.error.message) - } - return res.result -} diff --git a/utils/sendTransactions.tsx b/utils/sendTransactions.tsx index d0e63e35e0..6f632bf2dc 100644 --- a/utils/sendTransactions.tsx +++ b/utils/sendTransactions.tsx @@ -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, @@ -18,26 +7,16 @@ import { showTransactionsProcessUi, } from './transactionsLoader' -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)) +import { invalidateInstructionAccounts } from '@hooks/queries/queryClient' +import { + sendSignAndConfirmTransactionsProps, + sendSignAndConfirmTransactions, + TransactionInstructionWithType, +} from '@blockworks-foundation/mangolana/lib/transactions' +import { getFeeEstimate } from '@tools/feeEstimate' +import { TransactionInstructionWithSigners } from '@blockworks-foundation/mangolana/lib/globalTypes' +import { createComputeBudgetIx } from '@blockworks-foundation/mango-v4' +import { BACKUP_CONNECTIONS } from './connection' export type WalletSigner = Pick< SignerWalletAdapter, @@ -52,576 +31,155 @@ 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 can’t 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>, - Promise? - ] = [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 async function simulateTransaction( - connection: Connection, - transaction: Transaction, - commitment: Commitment -): Promise> { - // @ts-ignore - transaction.recentBlockhash = await connection._recentBlockhash( - // @ts-ignore - connection._disableBlockhashCaching - ) - - const signData = transaction.serializeMessage() - // @ts-ignore - const wireTransaction = transaction._serialize(signData) - const encodedTransaction = wireTransaction.toString('base64') - const config: any = { encoding: 'base64', commitment } - const args = [encodedTransaction, config] - - // @ts-ignore - const res = await connection._rpcRequest('simulateTransaction', args) - if (res.error) { - throw new Error('failed to simulate transaction: ' + res.error.message) - } - return res.result -} -/////////////////////////////////////// -export const getUnixTs = () => { - return new Date().getTime() / 1000 +export enum SequenceType { + Sequential, + Parallel, + StopOnFailure, } -const DEFAULT_TIMEOUT = 60000 -///////////////////////////////////////////////// -export async function sendSignedTransaction({ - signedTransaction, +export const sendTransactionsV3 = async ({ 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, + wallet, + transactionInstructions, + timeoutStrategy, + callbacks, + config, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + lookupTableAccounts, + autoFee = true, +}: sendSignAndConfirmTransactionsProps & { + lookupTableAccounts?: any + autoFee?: boolean +}) => { + const transactionInstructionsWithFee: TransactionInstructionWithType[] = [] + const fee = await getFeeEstimate(connection) + for (const tx of transactionInstructions) { + if (tx.instructionsSet.length) { + const txObjWithFee = { + ...tx, + instructionsSet: autoFee + ? [ + new TransactionInstructionWithSigners(createComputeBudgetIx(fee)), + ...tx.instructionsSet, + ] + : [...tx.instructionsSet], + } + transactionInstructionsWithFee.push(txObjWithFee) } - ) + } - 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 simulateTransaction(connection, signedTransaction, 'single') - ).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, - } - } - } + const callbacksWithUiComponent = { + afterBatchSign: (signedTxnsCount) => { + if (callbacks?.afterBatchSign) { + callbacks?.afterBatchSign(signedTxnsCount) + } + showTransactionsProcessUi(signedTxnsCount) + }, + afterAllTxConfirmed: () => { + if (callbacks?.afterAllTxConfirmed) { + callbacks?.afterAllTxConfirmed() } - Sentry.captureException( - `sendSignedTransaction line 314: ${simulateResult.err}`, - { tags: { tag: 'sendTransactionsErrors' } } + closeTransactionProcessUi() + transactionInstructionsWithFee.forEach((x) => + x.instructionsSet.forEach((x) => + invalidateInstructionAccounts(x.transactionInstruction) + ) ) - throw { - txInstructionIdx: transactionInstructionIdx, - error: JSON.stringify(simulateResult.err), - txid: txid, + }, + afterEveryTxConfirmation: () => { + if (callbacks?.afterEveryTxConfirmation) { + callbacks?.afterEveryTxConfirmation() } - } - // 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, + incrementProcessedTransactions() + }, + onError: (e, notProcessedTransactions, originalProps) => { + if (callbacks?.onError) { + callbacks?.onError(e, notProcessedTransactions, originalProps) + } + showTransactionError( + () => + sendTransactionsV3({ + ...originalProps, + transactionInstructions: notProcessedTransactions, + autoFee: false, + }), + getErrorMsg(e), + e.txid + ) + transactionInstructionsWithFee.forEach((x) => + x.instructionsSet.forEach((x) => + invalidateInstructionAccounts(x.transactionInstruction) + ) + ) + }, + } + + const cfg = { + maxTxesInBatch: + transactionInstructionsWithFee.filter( + (x) => x.sequenceType === SequenceType.Sequential + ).length > 0 + ? 20 + : 30, + autoRetry: false, + maxRetries: 5, + retried: 0, + logFlowInfo: true, + ...config, + } + return sendSignAndConfirmTransactions({ + connection, + wallet, + transactionInstructions: transactionInstructionsWithFee, + timeoutStrategy, + callbacks: callbacksWithUiComponent, + config: cfg, + confirmLevel: 'confirmed', + backupConnections: BACKUP_CONNECTIONS, //TODO base this on connection confirmation level + //lookupTableAccounts, + }) } -///////////////////////////////////////// -export const sendTransactions = async ( - connection: Connection, - wallet: WalletSigner, - instructionSet: TransactionInstruction[][], - signersSet: Keypair[][], - sequenceType: SequenceType = SequenceType.Parallel, - commitment: Commitment = 'singleGossip', - successCallback: (txid: string, ind: number) => void = (_txid, _ind) => null, - failCallback: (reason: string, ind: number) => boolean = (_txid, _ind) => - false, - block?: Block -): Promise => { - if (!wallet.publicKey) throw new Error('Wallet not connected!') - const unsignedTxns: Transaction[] = [] - - if (!block) { - block = await connection.getLatestBlockhash(commitment) +const getErrorMsg = (e) => { + if (e.error) { + return e.error } - for (let i = 0; i < instructionSet.length; i++) { - const instructions = instructionSet[i] - const signers = signersSet[i] - - if (instructions.length === 0) { - continue - } - - const transaction = new Transaction() - instructions.forEach((instruction) => transaction.add(instruction)) - transaction.recentBlockhash = block.blockhash - transaction.setSigners( - // fee payed by the wallet owner - wallet.publicKey, - ...signers.map((s) => s.publicKey) - ) - - if (signers.length > 0) { - transaction.partialSign(...signers) - } - - unsignedTxns.push(transaction) + if (e.message) { + return e.message } - const signedTxns = await wallet.signAllTransactions(unsignedTxns) - const pendingTxns: Promise<{ txid: string; slot: number }>[] = [] - - const breakEarlyObject = { breakEarly: false } - for (let i = 0; i < signedTxns.length; i++) { - const signedTxnPromise = sendSignedTransaction({ - connection, - signedTransaction: signedTxns[i], - block: block, - }) - - signedTxnPromise - .then(({ txid }) => { - successCallback(txid, i) - }) - .catch((_reason) => { - // @ts-ignore - failCallback(signedTxns[i], i) - if (sequenceType == SequenceType.StopOnFailure) { - breakEarlyObject.breakEarly = true - } - }) - - if (sequenceType != SequenceType.Parallel) { - await signedTxnPromise - if (breakEarlyObject.breakEarly) { - return i // REturn the txn we failed on by index - } - } else { - pendingTxns.push(signedTxnPromise) - } - } - - if (sequenceType != SequenceType.Parallel) { - await Promise.all(pendingTxns) + if (typeof e === 'object') { + return tryStringify(e) } - - return signedTxns.length + return `${e}` } -///////////////////////////////////////// -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 tryStringify = (obj) => { + try { + return JSON.stringify(obj) + } catch { + return null } +} - 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 +export const txBatchesToInstructionSetWithSigners = ( + txBatch: TransactionInstruction[], + signerBatches: Keypair[][], + batchIdx?: number +): { transactionInstruction: TransactionInstruction; signers: Keypair[] }[] => { + return txBatch.map((tx, txIdx) => { + let signers: Keypair[] = [] - 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 + typeof batchIdx !== 'undefined' && + signerBatches?.length && + signerBatches?.[batchIdx]?.[txIdx] ) { - //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, - }) + signers = [signerBatches[batchIdx][txIdx]] } - 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, - } + return { + transactionInstruction: tx, + signers, + } + }) } diff --git a/utils/services/token.tsx b/utils/services/token.tsx deleted file mode 100644 index c389d675c1..0000000000 --- a/utils/services/token.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import axios from 'axios' -import { TokenListProvider, TokenInfo } from '@solana/spl-token-registry' -import { notify } from '@utils/notifications' -import { WSOL_MINT } from '@components/instructions/tools' -import { MANGO_MINT } from 'Strategies/protocols/mango/tools' -const coingeckoPriceEndpoint = 'https://api.coingecko.com/api/v3/simple/price' - -class TokenService { - _tokenList: TokenInfo[] - _tokenPriceToUSDlist: any - constructor() { - this._tokenList = [] - this._tokenPriceToUSDlist = {} - } - async fetchSolanaTokenList() { - try { - const tokens = await new TokenListProvider().resolve() - const tokenList = tokens.filterByClusterSlug('mainnet-beta').getList() - if (tokenList && tokenList.length) { - this._tokenList = tokenList - } - } catch (e) { - console.log(e) - notify({ - type: 'error', - message: 'unable to fetch token list', - }) - } - } - async fetchTokenPrices(mintAddresses: string[]) { - if (mintAddresses.length) { - const mintAddressesWithSol = [...mintAddresses, WSOL_MINT, MANGO_MINT] - const tokenListRecords = this._tokenList?.filter((x) => - mintAddressesWithSol.includes(x.address) - ) - const coingeckoIds = tokenListRecords - .map((x) => x.extensions?.coingeckoId) - .join(',') - try { - const priceToUsdResponse = await axios.get( - `${coingeckoPriceEndpoint}?ids=${coingeckoIds}&vs_currencies=usd` - ) - const priceToUsd = priceToUsdResponse.data - this._tokenPriceToUSDlist = { - ...this._tokenPriceToUSDlist, - ...priceToUsd, - } - return priceToUsd - } catch (e) { - notify({ - type: 'error', - message: 'unable to fetch token prices', - }) - return {} - } - } - return {} - } - getUSDTokenPrice(mintAddress: string): number { - if (mintAddress) { - const tokenListRecord = this._tokenList?.find( - (x) => x.address === mintAddress - ) - const coingeckoId = tokenListRecord?.extensions?.coingeckoId - if (tokenListRecord && coingeckoId) { - return this._tokenPriceToUSDlist[coingeckoId]?.usd || 0 - } - return 0 - } - - return 0 - } - getTokenInfo(mintAddress: string) { - const tokenListRecord = this._tokenList?.find( - (x) => x.address === mintAddress - ) - return tokenListRecord - } - getTokenInfoFromCoingeckoId(coingeckoId: string) { - const tokenListRecord = this._tokenList?.find( - (x) => x.extensions?.coingeckoId === coingeckoId - ) - return tokenListRecord - } -} - -const tokenService = new TokenService() - -export default tokenService diff --git a/utils/services/tokenPrice.tsx b/utils/services/tokenPrice.tsx new file mode 100644 index 0000000000..1cc3bf6f09 --- /dev/null +++ b/utils/services/tokenPrice.tsx @@ -0,0 +1,132 @@ +import axios from 'axios' +import { mergeDeepRight } from 'ramda' + +import { notify } from '@utils/notifications' +import { WSOL_MINT } from '@components/instructions/tools' +import overrides from 'public/realms/token-overrides.json' +import { Price, TokenInfo } from './types' +import { chunks } from '@utils/helpers' +import { USDC_MINT } from '@blockworks-foundation/mango-v4' + +//this service provide prices it is not recommended to get anything more from here besides token name or price. +//decimals from metadata can be different from the realm on chain one +const priceEndpoint = 'https://price.jup.ag/v4/price' +const tokenListUrl = 'https://token.jup.ag/strict' + +export type TokenInfoWithoutDecimals = Omit + +/** @deprecated */ +class TokenPriceService { + _tokenList: TokenInfo[] + _tokenPriceToUSDlist: { + [mintAddress: string]: Price + } + constructor() { + this._tokenList = [] + this._tokenPriceToUSDlist = {} + } + async fetchSolanaTokenList() { + try { + const tokens = await axios.get(tokenListUrl) + const tokenList = tokens.data as TokenInfo[] + if (tokenList && tokenList.length) { + this._tokenList = tokenList.map((token) => { + const override = overrides[token.address] + + if (override) { + return mergeDeepRight(token, override) + } + + return token + }) + } + } catch (e) { + console.log(e) + notify({ + type: 'error', + message: 'unable to fetch token list', + }) + } + } + async fetchTokenPrices(mintAddresses: string[]) { + if (mintAddresses.length) { + //can query only 100 at once + const mintAddressesWithSol = chunks([...mintAddresses, WSOL_MINT], 100) + for (const mintChunk of mintAddressesWithSol) { + const symbols = mintChunk.join(',') + try { + const response = await axios.get(`${priceEndpoint}?ids=${symbols}`) + const priceToUsd: Price[] = response?.data?.data + ? Object.values(response.data.data) + : [] + const keyValue = Object.fromEntries( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + Object.entries(priceToUsd).map(([key, val]) => [val.id, val]) + ) + + this._tokenPriceToUSDlist = { + ...this._tokenPriceToUSDlist, + ...keyValue, + } + } catch (e) { + notify({ + type: 'error', + message: 'unable to fetch token prices', + }) + } + } + const USDC_MINT_BASE = USDC_MINT.toBase58() + if (!this._tokenPriceToUSDlist[USDC_MINT_BASE]) { + this._tokenPriceToUSDlist[USDC_MINT_BASE] = { + id: USDC_MINT_BASE, + mintSymbol: 'USDC', + price: 1, + vsToken: USDC_MINT_BASE, + vsTokenSymbol: 'USDC', + } + } + + //override chai price if its broken + const chaiMint = '3jsFX1tx2Z8ewmamiwSU851GzyzM2DJMq7KWW5DM8Py3' + const chaiData = this._tokenPriceToUSDlist[chaiMint] + + if (chaiData?.price && (chaiData.price > 1.3 || chaiData.price < 0.9)) { + this._tokenPriceToUSDlist[chaiMint] = { + ...chaiData, + price: 1, + } + } + } + } + /** + * @deprecated + * seriously do not use this. use fetchJupiterPrice + */ + getUSDTokenPrice(mintAddress: string): number { + return mintAddress ? this._tokenPriceToUSDlist[mintAddress]?.price || 0 : 0 + } + /** + * For decimals use on chain tryGetMint + */ + getTokenInfo(mintAddress: string): TokenInfoWithoutDecimals | undefined { + const tokenListRecord = this._tokenList?.find( + (x) => x.address === mintAddress + ) + return tokenListRecord + } + /** + * For decimals use on chain tryGetMint + */ + getTokenInfoFromCoingeckoId( + coingeckoId: string + ): TokenInfoWithoutDecimals | undefined { + const tokenListRecord = this._tokenList?.find( + (x) => x.extensions?.coingeckoId === coingeckoId + ) + return tokenListRecord + } +} + +const tokenPriceService = new TokenPriceService() + +export default tokenPriceService diff --git a/utils/services/types.tsx b/utils/services/types.tsx new file mode 100644 index 0000000000..c1c241fbf2 --- /dev/null +++ b/utils/services/types.tsx @@ -0,0 +1,37 @@ +export type Price = { + id: string + mintSymbol: string + price: number + vsToken: string + vsTokenSymbol: string +} + +export type TokenInfo = { + readonly chainId: number + readonly address: string + readonly name: string + readonly decimals: number + readonly symbol: string + readonly logoURI?: string + readonly tags?: string[] + readonly extensions?: TokenExtensions +} + +interface TokenExtensions { + readonly website?: string + readonly bridgeContract?: string + readonly assetContract?: string + readonly address?: string + readonly explorer?: string + readonly twitter?: string + readonly github?: string + readonly medium?: string + readonly tgann?: string + readonly tggroup?: string + readonly discord?: string + readonly serumV3Usdt?: string + readonly serumV3Usdc?: string + readonly coingeckoId?: string + readonly imageUrl?: string + readonly description?: string +} diff --git a/utils/splTokens.ts b/utils/splTokens.ts index 9d6176cd3b..f930873cbb 100644 --- a/utils/splTokens.ts +++ b/utils/splTokens.ts @@ -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 -} diff --git a/utils/textToAddressList.ts b/utils/textToAddressList.ts index d9b9c3f4db..0c28bac96f 100644 --- a/utils/textToAddressList.ts +++ b/utils/textToAddressList.ts @@ -1,6 +1,6 @@ -import { validateSolAddress } from '@utils/formValidation' +import { validatePubkey } from '@utils/formValidation' -export interface Addresses { +interface Addresses { valid: string[] invalid: string[] } @@ -10,7 +10,7 @@ export const textToAddressList = (textBlock: string): Addresses => { const invalid: string[] = [] textBlock.split(/[\s|,]/).forEach((address) => { - if (validateSolAddress(address)) { + if (validatePubkey(address)) { valid.push(address) } else if (address.trim() /* ignore empty strings */) { invalid.push(address.trim()) diff --git a/utils/tokens.tsx b/utils/tokens.tsx index 93bf12baf1..4faf2b21b7 100644 --- a/utils/tokens.tsx +++ b/utils/tokens.tsx @@ -7,29 +7,24 @@ import { } from '@solana/web3.js' import { AccountInfo, - AccountLayout, - ASSOCIATED_TOKEN_PROGRAM_ID, MintInfo, MintLayout, Token, u64, } from '@solana/spl-token' -import { MintMaxVoteWeightSource } from '@solana/spl-governance' +import { + MintMaxVoteWeightSource, + MintMaxVoteWeightSourceType, +} from '@solana/spl-governance' import { chunks } from './helpers' import { getAccountName, WSOL_MINT } from '@components/instructions/tools' import { formatMintNaturalAmountAsDecimal } from '@tools/sdk/units' -import tokenService from './services/token' -import { notify } from './notifications' -import { BN } from '@project-serum/anchor' +import tokenPriceService from './services/tokenPrice' +import { BN } from '@coral-xyz/anchor' import { abbreviateAddress } from './formatting' import BigNumber from 'bignumber.js' import { AssetAccount } from '@utils/uiTypes/assets' -import { I80F48 } from '@blockworks-foundation/mango-client' -import { NFTWithMeta } from './uiTypes/VotePlugin' -import { getParsedNftAccountsByOwner } from '@nfteyez/sol-rayz' -import axios from 'axios' -import { deprecated } from '@metaplex-foundation/mpl-token-metadata' -import { ConnectionContext } from './connection' +import { parseTokenAccountData } from './parseTokenAccountData' export type TokenAccount = AccountInfo export type MintAccount = MintInfo @@ -43,10 +38,11 @@ export async function getOwnedTokenAccounts( connection: Connection, publicKey: PublicKey ): Promise[]> { - const results = await connection.getTokenAccountsByOwner(publicKey, { + const result = await connection.getTokenAccountsByOwner(publicKey, { programId: TOKEN_PROGRAM_ID, }) - return results.value.map((r) => { + + return result.value.map((r) => { const publicKey = r.pubkey const data = Buffer.from(r.account.data) const account = parseTokenAccountData(publicKey, data) @@ -54,6 +50,7 @@ export async function getOwnedTokenAccounts( }) } +/** @deprecated -- use react-query by pubkey */ export const getTokenAccountsByMint = async ( connection: Connection, mint: string @@ -79,6 +76,7 @@ export const getTokenAccountsByMint = async ( }) } +/** @deprecated, probably */ export async function tryGetMint( connection: Connection, publicKey: PublicKey @@ -92,14 +90,15 @@ export async function tryGetMint( account, } } catch (ex) { - console.error(`Can't fetch mint ${publicKey?.toBase58()}`, ex) + console.error( + `Can't fetch mint ${publicKey?.toBase58()} @ ${connection.rpcEndpoint}`, + ex + ) + return undefined } } -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, publicKey: PublicKey @@ -123,6 +122,7 @@ export async function tryGetTokenAccount( } } +/** @deprecated -- use react-query by pubkey */ export async function tryGetTokenMint( connection: Connection, publicKey: PublicKey @@ -132,51 +132,16 @@ export async function tryGetTokenMint( } // copied from @solana/spl-token +/** @deprecated -- why? just import from spl-token? */ export const TOKEN_PROGRAM_ID = new PublicKey( 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' ) export const BPF_UPGRADE_LOADER_ID = new PublicKey( 'BPFLoaderUpgradeab1e11111111111111111111111' ) -export function parseTokenAccountData( - account: PublicKey, - data: Buffer -): TokenAccount { - const accountInfo = AccountLayout.decode(data) - accountInfo.address = account - accountInfo.mint = new PublicKey(accountInfo.mint) - accountInfo.owner = new PublicKey(accountInfo.owner) - accountInfo.amount = u64.fromBuffer(accountInfo.amount) - - if (accountInfo.delegateOption === 0) { - accountInfo.delegate = null - accountInfo.delegatedAmount = new u64(0) - } else { - accountInfo.delegate = new PublicKey(accountInfo.delegate) - accountInfo.delegatedAmount = u64.fromBuffer(accountInfo.delegatedAmount) - } - accountInfo.isInitialized = accountInfo.state !== 0 - accountInfo.isFrozen = accountInfo.state === 2 - - if (accountInfo.isNativeOption === 1) { - accountInfo.rentExemptReserve = u64.fromBuffer(accountInfo.isNative) - accountInfo.isNative = true - } else { - accountInfo.rentExemptReserve = null - accountInfo.isNative = false - } - - if (accountInfo.closeAuthorityOption === 0) { - accountInfo.closeAuthority = null - } else { - accountInfo.closeAuthority = new PublicKey(accountInfo.closeAuthority) - } - - return accountInfo -} - -export function parseMintAccountData(data: Buffer) { +/** @deprecated -- why not just use the normal mint layout? */ +export function parseMintAccountData(data: Buffer): MintAccount { const mintInfo = MintLayout.decode(data) if (mintInfo.mintAuthorityOption === 0) { mintInfo.mintAuthority = null @@ -251,6 +216,7 @@ export async function getMultipleAccountInfoChunked( } //TODO refactor both methods (getMintAccountLabelInfo, getTokenAccountLabelInfo) make it more common +/** @deprecated */ export function getTokenAccountLabelInfo(acc: AssetAccount | undefined) { let tokenAccount = '' let tokenName = '' @@ -259,7 +225,7 @@ export function getTokenAccountLabelInfo(acc: AssetAccount | undefined) { let imgUrl = '' if (acc?.extensions.token && acc.extensions.mint) { - const info = tokenService.getTokenInfo( + const info = tokenPriceService.getTokenInfo( acc.extensions!.mint!.publicKey.toBase58() ) imgUrl = info?.logoURI ? info.logoURI : '' @@ -282,6 +248,7 @@ export function getTokenAccountLabelInfo(acc: AssetAccount | undefined) { } } +/** @deprecated because i dont think i like the AssetAccount abstraction */ export function getSolAccountLabel(acc: AssetAccount | undefined) { let tokenAccount = '' let tokenName = '' @@ -290,7 +257,7 @@ export function getSolAccountLabel(acc: AssetAccount | undefined) { let imgUrl = '' if (acc?.extensions.mint) { - const info = tokenService.getTokenInfo(WSOL_MINT) + const info = tokenPriceService.getTokenInfo(WSOL_MINT) imgUrl = info?.logoURI ? info.logoURI : '' tokenAccount = acc.extensions.transferAddress!.toBase58() tokenName = 'SOL' @@ -312,6 +279,7 @@ export function getSolAccountLabel(acc: AssetAccount | undefined) { } } +/** @deprecated because i dont think i like the AssetAccount abstraction */ export function getMintAccountLabelInfo(acc: AssetAccount | undefined) { let account = '' let tokenName = '' @@ -319,13 +287,11 @@ export function getMintAccountLabelInfo(acc: AssetAccount | undefined) { let amount = '' let imgUrl = '' if (acc?.extensions.mint && acc.governance) { - const info = tokenService.getTokenInfo( - acc.governance.account.governedAccount.toBase58() - ) + const info = tokenPriceService.getTokenInfo(acc.pubkey.toBase58()) imgUrl = info?.logoURI ? info.logoURI : '' - account = acc.governance?.account.governedAccount.toBase58() + account = acc.pubkey.toBase58() tokenName = info?.name ? info.name : '' - mintAccountName = getAccountName(acc.governance.account.governedAccount) + mintAccountName = getAccountName(acc.pubkey) amount = formatMintNaturalAmountAsDecimal( acc.extensions.mint.account, acc?.extensions.mint.account.supply @@ -340,6 +306,7 @@ export function getMintAccountLabelInfo(acc: AssetAccount | undefined) { } } +/** @deprecated why? */ export type AccountInfoGen = { executable: boolean owner: PublicKey @@ -348,175 +315,6 @@ export type AccountInfoGen = { 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 -} - -const fetchNftsFromHolaplexIndexer = async (owner: PublicKey) => { - const result = await fetch('https://graph.holaplex.com/v1', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - query: ` - query nfts($owners: [PublicKey!]) { - nfts( - owners: $owners, - limit: 10000, offset: 0) { - name - mintAddress - address - image - tokenAccountAddress - updateAuthorityAddress - collection { - creators { - verified - address - } - mintAddress - } - - } - - } - `, - variables: { - owners: [owner.toBase58()], - }, - }), - }) - - const body = await result.json() - return body.data -} - -export const getNfts = async ( - ownerPk: PublicKey, - connection: ConnectionContext -): Promise => { - if (connection.cluster === 'devnet') { - return await getDevnetNfts(ownerPk, connection.current) - } else { - return await getMainnetNfts(ownerPk, connection.current) - } -} - -const getDevnetNfts = async ( - ownerPk: PublicKey, - connection: Connection -): Promise => { - const [nfts, tokenAccounts] = await Promise.all([ - getParsedNftAccountsByOwner({ - publicAddress: ownerPk.toBase58(), - connection: connection, - }), - getOwnedTokenAccounts(connection, ownerPk), - ]) - const data = Object.keys(nfts).map((key) => nfts[key]) - const arr: NFTWithMeta[] = [] - const vals = await Promise.all(data.map((x) => axios.get(x.data.uri))) - const metadataAccounts = await Promise.all( - data.map((x) => deprecated.Metadata.getPDA(x.mint)) - ) - for (let i = 0; i < data.length; i++) { - try { - const nft = data[i] - const val = vals[i].data - const tokenAccount = tokenAccounts.find((x) => { - return ( - x.account.mint.toBase58() === data[i].mint && - x.account.amount.cmpn(0) === 1 - ) - }) - const metadataAccount = metadataAccounts[i] - const metadata = await deprecated.Metadata.load( - connection, - metadataAccount - ) - if (tokenAccount) { - arr.push({ - image: val.image, - name: val.name, - description: val.description, - properties: { - category: val.properties?.category, - files: val.properties?.files, - }, - collection: { - mintAddress: metadata?.data?.collection?.key || '', - creators: nft.data.creators, - verified: metadata?.data?.collection?.verified, - }, - mintAddress: nft.mint, - address: metadata.pubkey.toBase58(), - tokenAccountAddress: tokenAccount.publicKey.toBase58(), - getAssociatedTokenAccount: async () => { - const ata = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID - TOKEN_PROGRAM_ID, // always TOKEN_PROGRAM_ID - new PublicKey(nft.mint), // mint - ownerPk, // owner - true - ) - - return ata.toBase58() - }, - }) - } - } catch (e) { - console.log(e) - } - } - return arr -} - -const getMainnetNfts = async ( - ownerPk: PublicKey, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - connection: Connection -): Promise => { - try { - const data = await fetchNftsFromHolaplexIndexer(ownerPk) - return data.nfts.map((nft) => { - return { - ...nft, - getAssociatedTokenAccount: async () => { - return nft.tokenAccountAddress - }, - } - }) - } catch (error) { - notify({ - type: 'error', - message: 'Unable to fetch nfts', - }) - } - return [] -} - export const parseMintSupplyFraction = (fraction: string) => { if (!fraction) { return MintMaxVoteWeightSource.FULL_SUPPLY_FRACTION @@ -527,14 +325,21 @@ export const parseMintSupplyFraction = (fraction: string) => { .toNumber() return new MintMaxVoteWeightSource({ + type: MintMaxVoteWeightSourceType.SupplyFraction, value: new BN(fractionValue), }) } -export const SCALED_FACTOR_SHIFT = 9 +const SCALED_FACTOR_SHIFT = 9 export function getScaledFactor(amount: number) { return new BN( new BigNumber(amount.toString()).shiftedBy(SCALED_FACTOR_SHIFT).toString() ) } + +export function getInverseScaledFactor(amount: BN) { + return new BigNumber(amount.toNumber()) + .shiftedBy(-SCALED_FACTOR_SHIFT) + .toNumber() +} diff --git a/utils/treasuryTools.tsx b/utils/treasuryTools.tsx index 93e7fd7590..dcb18f659f 100644 --- a/utils/treasuryTools.tsx +++ b/utils/treasuryTools.tsx @@ -1,10 +1,10 @@ import { getAccountName, WSOL_MINT } from '@components/instructions/tools' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { PublicKey } from '@solana/web3.js' import { getMintDecimalAmountFromNatural } from '@tools/sdk/units' import BigNumber from 'bignumber.js' import { abbreviateAddress } from './formatting' -import tokenService from './services/token' +import tokenPriceService from './services/tokenPrice' import { AccountType, AssetAccount } from './uiTypes/assets' export const getTreasuryAccountItemInfoV2 = (account: AssetAccount) => { @@ -24,12 +24,12 @@ export const getTreasuryAccountItemInfoV2 = (account: AssetAccount) => { ) ).toNumber() : 0 - const price = tokenService.getUSDTokenPrice(mintAddress!) + const price = tokenPriceService.getUSDTokenPrice(mintAddress!) const totalPrice = amount * price const totalPriceFormatted = amount ? new BigNumber(totalPrice).toFormat(0) : '' - const info = tokenService.getTokenInfo(mintAddress!) + const info = tokenPriceService.getTokenInfo(mintAddress!) const symbol = account.type === AccountType.NFT diff --git a/utils/typescript/assertUnreachable.ts b/utils/typescript/assertUnreachable.ts new file mode 100644 index 0000000000..1ffb322adf --- /dev/null +++ b/utils/typescript/assertUnreachable.ts @@ -0,0 +1,3 @@ +export default function assertUnreachable(_: never): never { + throw new Error('An unreachability assertion was reached') +} diff --git a/utils/uiTypes/NftVoterClient.ts b/utils/uiTypes/NftVoterClient.ts new file mode 100644 index 0000000000..1d0577d47f --- /dev/null +++ b/utils/uiTypes/NftVoterClient.ts @@ -0,0 +1,215 @@ +import {IdlAccounts, Program, Provider} from '@coral-xyz/anchor' +import {PublicKey, TransactionInstruction} from '@solana/web3.js' +import {IDL, NftVoter} from '../../idls/nft_voter' +import {IDLV2, NftVoterV2} from '../../idls/nft_voter_v2' +import {DEFAULT_NFT_VOTER_PLUGIN, DEFAULT_NFT_VOTER_PLUGIN_V2,} from '@tools/constants' +import {ON_NFT_VOTER_V2} from '@constants/flags' +import {Client, DEFAULT_GOVERNANCE_PROGRAM_ID} from "@solana/governance-program-library"; +import {SYSTEM_PROGRAM_ID, VoterWeightAction} from "@solana/spl-governance"; +import {getVotingNfts} from "@hooks/queries/plugins/nftVoter"; +import { + getUpdateVoterWeightRecordInstruction, + getUpdateVoterWeightRecordInstructionV2 +} from "@utils/instructions/NftVoter/updateVoterWeight"; +import {convertVoterWeightActionToType} from "../../VoterWeightPlugins/lib/utils"; +import BN from "bn.js"; +import { getNftGovpowerForOwnerAndRegistrar} from "@hooks/queries/governancePower"; + +// const programVersion = (ON_NFT_VOTER_V2 ? Program : Program) +// const idl = ON_NFT_VOTER_V2 ? IDLV2 : IDL +const DEFAULT_NFT_VOTER_PLUGIN_VERSION = ON_NFT_VOTER_V2 + ? DEFAULT_NFT_VOTER_PLUGIN_V2 + : DEFAULT_NFT_VOTER_PLUGIN + +export abstract class NftVoterClient extends Client { + readonly requiresInputVoterWeight = false; + + async getMaxVoterWeightRecordPDA(realm: PublicKey, mint: PublicKey) { + const [ + maxVoterWeightPk, + maxVoterWeightRecordBump, + ] = PublicKey.findProgramAddressSync( + [ + Buffer.from('max-voter-weight-record'), + realm.toBuffer(), + mint.toBuffer(), + ], + this.program.programId + ) + return { + maxVoterWeightPk, + maxVoterWeightRecordBump, + } + } + + async createVoterWeightRecord(voter: PublicKey, realm: PublicKey, mint: PublicKey): Promise { + const { voterWeightPk } = await this.getVoterWeightRecordPDA(realm, mint, voter) + return this.program.methods + .createVoterWeightRecord(voter) + .accounts({ + voterWeightRecord: voterWeightPk, + governanceProgramId: this.governanceProgramId, + realm, + realmGoverningTokenMint: mint, + payer: voter, + systemProgram: SYSTEM_PROGRAM_ID, + }) + .instruction(); + } + + // NO-OP + async createMaxVoterWeightRecord(): Promise { + return null; + } + + // NO-OP + async updateMaxVoterWeightRecord(): Promise { + return null; + } + async calculateVoterWeight(voter: PublicKey, realm: PublicKey, mint:PublicKey): Promise { + const registrar = await this.getRegistrarAccount(realm, mint); + return getNftGovpowerForOwnerAndRegistrar(this.program.provider.connection, voter, registrar as any); + } + + async calculateMaxVoterWeight(realm: PublicKey, mint: PublicKey): Promise { + const registrar = (await this.getRegistrarAccount(realm, mint)) as unknown as IdlAccounts['registrar'] | undefined; + const nftVoterPluginTotalWeight = registrar?.collectionConfigs.reduce( + (prev, curr) => { + const size = curr.size + const weight = curr.weight.toNumber() + if (typeof size === 'undefined' || typeof weight === 'undefined') + return prev + return prev + size * weight + }, + 0 + ) + + return nftVoterPluginTotalWeight !== undefined ? new BN(nftVoterPluginTotalWeight) : null; + } + + constructor( + public program: Program | Program, + public devnet: boolean, + readonly governanceProgramId: PublicKey + ) { + super(program, devnet) + } + + static async connect( + provider: Provider, + programId = new PublicKey(DEFAULT_NFT_VOTER_PLUGIN_VERSION), + devnet = false, + governanceProgramId = DEFAULT_GOVERNANCE_PROGRAM_ID + ): Promise { + if (ON_NFT_VOTER_V2) { + return NftVoterClientV2.connect( + provider, + programId, + devnet, + governanceProgramId + ) + } else { + return NftVoterClientV1.connect( + provider, + programId, + devnet, + governanceProgramId + ) + } + } +} + +export class NftVoterClientV1 extends NftVoterClient { + constructor(public program: Program, public devnet: boolean, readonly governanceProgramId) { + super(program, devnet, governanceProgramId) + } + + async updateVoterWeightRecord(voter: PublicKey, realm: PublicKey, mint: PublicKey, action: VoterWeightAction) { + // Not clear why, but it seems like updateVoterWeightRecord is not called during cast vote + // for the nft plugin + if (action === VoterWeightAction.CastVote) { + return {pre: []} + } + + const {registrar} = this.getRegistrarPDA(realm, mint); + const {voterWeightPk} = await this.getVoterWeightRecordPDA(realm, mint, voter); + const votingNfts = await getVotingNfts( + this.program.provider.connection, + realm, + voter + ) + + console.log('on nft voter v1') + const ix = await getUpdateVoterWeightRecordInstruction( + this.program, + voter, + registrar, + voterWeightPk, + votingNfts, + convertVoterWeightActionToType(action) + ) + return {pre: [ix]} + } + + static async connect( + provider: Provider, + programId = new PublicKey(DEFAULT_NFT_VOTER_PLUGIN_VERSION), + devnet = false, + governanceProgramId = DEFAULT_GOVERNANCE_PROGRAM_ID + ): Promise { + return new NftVoterClientV1( + new Program(IDL, programId, provider), + devnet, + governanceProgramId + ) + } +} + +export class NftVoterClientV2 extends NftVoterClient { + constructor(public program: Program, public devnet: boolean, readonly governanceProgramId) { + super(program, devnet, governanceProgramId) + } + + async updateVoterWeightRecord(voter: PublicKey, realm: PublicKey, mint: PublicKey, action: VoterWeightAction) { + // Not clear why, but it seems like updateVoterWeightRecord is not called during cast vote + // for the nft plugin + if (action === VoterWeightAction.CastVote) { + return {pre: []} + } + + const {registrar} = this.getRegistrarPDA(realm, mint); + const { voterWeightPk } = await this.getVoterWeightRecordPDA(realm, mint, voter); + const votingNfts = await getVotingNfts( + this.program.provider.connection, + realm, + voter + ) + + console.log('on nft voter v2') + const { + createNftTicketIxs, + updateVoterWeightRecordIx, + } = await getUpdateVoterWeightRecordInstructionV2( + this.program, + voter, + registrar, + voterWeightPk, + votingNfts, + convertVoterWeightActionToType(action) + ) + return { pre: [updateVoterWeightRecordIx] , post: createNftTicketIxs } + } + + static async connect( + provider: Provider, + programId = new PublicKey(DEFAULT_NFT_VOTER_PLUGIN_VERSION), + devnet = false, + governanceProgramId = DEFAULT_GOVERNANCE_PROGRAM_ID + ): Promise { + return new NftVoterClientV2( + new Program(IDLV2, programId, provider), + devnet, + governanceProgramId + ) + } +} diff --git a/utils/uiTypes/Result.ts b/utils/uiTypes/Result.ts index 84827a3af8..fd3471b971 100644 --- a/utils/uiTypes/Result.ts +++ b/utils/uiTypes/Result.ts @@ -1,72 +1 @@ -export enum Status { - /** - * The Result has completed, but an error has occured - */ - Failed, - /** - * The Result has completed, and the data is available - */ - Ok, - /** - * The Result is currently waiting to complete - */ - Pending, - /** - * The Result is currently waiting to complete, but stale data is available - */ - Stale, -} - -/** - * The Result has completed, but an error has occured - */ -export interface Failed { - status: Status.Failed - /** - * The error that has occured - */ - error: E -} - -export interface Ok { - status: Status.Ok - /** - * The data that was fetched - */ - data: D -} - -export interface Pending { - status: Status.Pending -} - -export interface Stale { - status: Status.Stale - /** - * The stale data that is being replaced - */ - data: D -} - -/** - * Data in various asynchronous states. - */ -export type Result = - | Failed - | Ok - | Pending - | Stale - -export function map( - result: Result, - fn: (data: D) => R -): Result { - if (result.status === Status.Ok || result.status === Status.Stale) { - return { - status: result.status, - data: fn(result.data), - } - } - - return result -} +export * from '@hub/types/Result' diff --git a/utils/uiTypes/VotePlugin.ts b/utils/uiTypes/VotePlugin.ts index a9b7d35eed..0282084276 100644 --- a/utils/uiTypes/VotePlugin.ts +++ b/utils/uiTypes/VotePlugin.ts @@ -1,43 +1,33 @@ +import {ProgramAccount, Proposal, Realm, VoterWeightAction,} from '@solana/spl-governance' +import {PublicKey, TransactionInstruction} from '@solana/web3.js' +import {chunks} from '@utils/helpers' import { - NftVoterClient, - GatewayClient, -} from '@solana/governance-program-library' -import { - SwitchboardQueueVoterClient, - SWITCHBOARD_ADDIN_ID, -} from '../../SwitchboardVotePlugin/SwitchboardQueueVoterClient' -import { - ProgramAccount, - Realm, - SYSTEM_PROGRAM_ID, - Proposal, - TokenOwnerRecord, -} from '@solana/spl-governance' -import { PublicKey, TransactionInstruction } from '@solana/web3.js' -import { chunks } from '@utils/helpers' -import { PythClient } from 'pyth-staking-api' -import { - getRegistrarPDA, - getVoterPDA, - getVoterWeightPDA, -} from 'VoteStakeRegistry/sdk/accounts' -import { NFTWithMint } from './nfts' -import { - getPreviousVotingWeightRecord, - getVoteInstruction, -} from '../../GatewayPlugin/sdk/accounts' -import { - getVoterWeightRecord as getPluginVoterWeightRecord, getRegistrarPDA as getPluginRegistrarPDA, - getMaxVoterWeightRecord as getPluginMaxVoterWeightRecord, } from '@utils/plugin/accounts' -import { VsrClient } from 'VoteStakeRegistry/sdk/client' +import {getUsedNftsForProposal} from 'NftVotePlugin/accounts' +import {PositionWithMeta} from 'HeliumVotePlugin/sdk/types' import { - getNftVoteRecordProgramAddress, - getUsedNftsForProposal, -} from 'NftVotePlugin/accounts' + nftVoteRecordKey, + registrarKey, +} from '@helium/voter-stake-registry-sdk' +import {getUnusedPositionsForProposal} from 'HeliumVotePlugin/utils/getUnusedPositionsForProposal' +import {getUsedPositionsForProposal} from 'HeliumVotePlugin/utils/getUsedPositionsForProposal' +import {getAssociatedTokenAddress} from '@blockworks-foundation/mango-v4' +import queryClient from '@hooks/queries/queryClient' +import asFindable from '@utils/queries/asFindable' +import {convertTypeToVoterWeightAction} from "../../VoterWeightPlugins"; +import {Client} from "@solana/governance-program-library"; +import {NftVoterClient} from "@utils/uiTypes/NftVoterClient"; +import {HeliumVsrClient} from "../../HeliumVotePlugin/sdk/client"; +import {getVotingNfts} from "@hooks/queries/plugins/nftVoter"; +import {ON_NFT_VOTER_V2} from "@constants/flags"; +import {getCastNftVoteInstruction, getCastNftVoteInstructionV2} from "@utils/instructions/NftVoter/castNftVote"; +import {Program} from "@coral-xyz/anchor"; +import {NftVoter} from "../../idls/nft_voter"; +import {NftVoterV2} from "../../idls/nft_voter_v2"; +import {UseRealmVoterWeightPluginsReturnType} from "@hooks/useRealmVoterWeightPlugins"; -type UpdateVoterWeightRecordTypes = +export type UpdateVoterWeightRecordTypes = | 'castVote' | 'commentProposal' | 'createGovernance' @@ -45,25 +35,20 @@ type UpdateVoterWeightRecordTypes = | 'signOffProposal' export interface VotingClientProps { - client: Client | undefined + client: Client | undefined realm: ProgramAccount | undefined walletPk: PublicKey | null | undefined -} - -export interface NFTWithMeta extends NFTWithMint { - getAssociatedTokenAccount(): Promise + voterWeightPluginDetails: UseRealmVoterWeightPluginsReturnType } export enum VotingClientType { NoClient, VsrClient, + HeliumVsrClient, NftVoterClient, - SwitchboardVoterClient, - PythClient, - GatewayClient, } -class AccountData { +export class AccountData { pubkey: PublicKey isSigner: boolean isWritable: boolean @@ -83,369 +68,297 @@ interface ProgramAddresses { maxVoterWeightRecord: PublicKey | undefined } -export type Client = - | VsrClient - | NftVoterClient - | SwitchboardQueueVoterClient - | PythClient - | GatewayClient - //Abstract for common functions that plugins will implement export class VotingClient { - client: Client | undefined + client: Client | undefined realm: ProgramAccount | undefined walletPk: PublicKey | null | undefined - votingNfts: NFTWithMeta[] - gatewayToken: PublicKey + heliumVsrVotingPositions: PositionWithMeta[] oracles: PublicKey[] instructions: TransactionInstruction[] clientType: VotingClientType noClient: boolean - constructor({ client, realm, walletPk }: VotingClientProps) { + voterWeightPluginDetails: UseRealmVoterWeightPluginsReturnType + constructor({ client, realm, walletPk, voterWeightPluginDetails }: VotingClientProps) { this.client = client this.realm = realm this.walletPk = walletPk - this.votingNfts = [] + this.heliumVsrVotingPositions = [] this.oracles = [] this.instructions = [] this.noClient = true this.clientType = VotingClientType.NoClient - if (this.client instanceof VsrClient) { - this.clientType = VotingClientType.VsrClient + this.voterWeightPluginDetails = voterWeightPluginDetails + if (this.client instanceof HeliumVsrClient) { + this.clientType = VotingClientType.HeliumVsrClient this.noClient = false } if (this.client instanceof NftVoterClient) { this.clientType = VotingClientType.NftVoterClient this.noClient = false } - if (this.client instanceof SwitchboardQueueVoterClient) { - this.clientType = VotingClientType.SwitchboardVoterClient - this.noClient = false - } - if (this.client instanceof GatewayClient) { - this.clientType = VotingClientType.GatewayClient - this.noClient = false - } - if (this.client instanceof GatewayClient) { - this.clientType = VotingClientType.GatewayClient - this.noClient = false - } - if (this.client instanceof PythClient) { - this.clientType = VotingClientType.PythClient - this.noClient = false - } } + + // Take this exact voting client, but set a different voter wallet - useful for combining delegate and delegator votes + public for(wallet: PublicKey): VotingClient { + return new VotingClient({ + client: this.client, + realm: this.realm, + walletPk: wallet, + voterWeightPluginDetails: this.voterWeightPluginDetails, + }) + } + + private get voterWeightPk() { + return this.walletPk ? this.voterWeightPluginDetails.voterWeightPkForWallet(this.walletPk) : undefined + } + + private get maxVoterWeightPk() { + return this.voterWeightPluginDetails.maxVoterWeightPk + } + withUpdateVoterWeightRecord = async ( instructions: TransactionInstruction[], - tokenOwnerRecord: ProgramAccount, type: UpdateVoterWeightRecordTypes, - voterWeightTarget?: PublicKey + createNftActionTicketIxs?: TransactionInstruction[], + target? : PublicKey ): Promise => { - if (this.noClient) { - return - } - const clientProgramId = this.client!.program.programId - const realm = this.realm! - const walletPk = this.walletPk! + // nothing to do if no wallet is connected, or no plugins are attached to this realm + if ( + !this.walletPk || + !this.voterWeightPluginDetails.plugins || + (this.voterWeightPluginDetails.plugins.voterWeight.length === 0 + && this.voterWeightPluginDetails.plugins.maxVoterWeight.length === 0) + ) return undefined; + + const {pre: preIxes, post: postIxes} = await this.voterWeightPluginDetails.updateVoterWeightRecords(this.walletPk, convertTypeToVoterWeightAction(type), target) + instructions.push(...preIxes); + createNftActionTicketIxs?.push(...postIxes); + + return { voterWeightPk: this.voterWeightPk, maxVoterWeightRecord: this.maxVoterWeightPk } + } + + withCastPluginVote = async ( + instructions: TransactionInstruction[], + proposal: ProgramAccount, + tokenOwnerRecord: PublicKey, + createNftActionTicketIxs?: TransactionInstruction[] + ): Promise => { + const clientProgramId = this.client?.program.programId + const realm = this.realm + const walletPk = this.walletPk + if ( + !realm || !walletPk || realm.account.communityMint.toBase58() !== - tokenOwnerRecord.account.governingTokenMint.toBase58() + proposal.account.governingTokenMint.toBase58() ) { return } - if (this.client instanceof VsrClient) { - const { registrar } = await getRegistrarPDA( - realm.pubkey, - realm.account.communityMint, - clientProgramId - ) - const { voter } = await getVoterPDA(registrar, walletPk, clientProgramId) - const { voterWeightPk } = await getVoterWeightPDA( - registrar, - walletPk, - clientProgramId - ) - const updateVoterWeightRecordIx = await this.client!.program.methods.updateVoterWeightRecord() - .accounts({ - registrar, - voter, - voterWeightRecord: voterWeightPk, - systemProgram: SYSTEM_PROGRAM_ID, - }) - .instruction() - instructions.push(updateVoterWeightRecordIx) - return { voterWeightPk, maxVoterWeightRecord: undefined } - } + const updateVoterWeightRecordIxes = await this.voterWeightPluginDetails.updateVoterWeightRecords(walletPk, VoterWeightAction.CastVote, proposal.pubkey); + const updateMaxVoterWeightRecordIxes = await this.voterWeightPluginDetails.updateMaxVoterWeightRecords(); + instructions.push(...updateMaxVoterWeightRecordIxes, ...updateVoterWeightRecordIxes.pre); + createNftActionTicketIxs?.push(...updateVoterWeightRecordIxes.post || []); - if (this.client instanceof NftVoterClient) { - const { registrar } = await getPluginRegistrarPDA( - realm.pubkey, - realm.account.communityMint, - this.client!.program.programId - ) - const { - voterWeightPk, - maxVoterWeightRecord, - } = await this._withHandleNftVoterWeight( - realm, - walletPk, - clientProgramId, - instructions - ) + // the helium client needs to add some additional accounts to the transaction + if (this.client instanceof HeliumVsrClient) { const remainingAccounts: AccountData[] = [] - for (let i = 0; i < this.votingNfts.length; i++) { - const nft = this.votingNfts[i] - const tokenAccount = await nft.getAssociatedTokenAccount() + + const [registrar] = registrarKey( + realm.pubkey, + realm.account.communityMint, + clientProgramId + ) + + const unusedPositions = await getUnusedPositionsForProposal({ + connection: this.client.program.provider.connection, + client: this.client, + positions: this.heliumVsrVotingPositions, + proposalPk: proposal.pubkey, + }) + + for (let i = 0; i < unusedPositions.length; i++) { + const pos = unusedPositions[i] + const tokenAccount = await getAssociatedTokenAddress( + pos.mint, + walletPk, + true + ) + const [nftVoteRecord] = nftVoteRecordKey( + proposal.pubkey, + pos.mint, + clientProgramId + ) remainingAccounts.push( - new AccountData(tokenAccount), - new AccountData(nft.address) + new AccountData(tokenAccount), + new AccountData(pos.pubkey, false, true), + new AccountData(nftVoteRecord, false, true) ) } - const updateVoterWeightRecordIx = await this.client.program.methods - .updateVoterWeightRecord({ [type]: {} }) - .accounts({ - registrar: registrar, - voterWeightRecord: voterWeightPk, - }) - .remainingAccounts(remainingAccounts.slice(0, 10)) - .instruction() - instructions.push(updateVoterWeightRecordIx) - return { voterWeightPk, maxVoterWeightRecord } - } - if (this.client instanceof GatewayClient) { - const { voterWeightPk } = await this._withHandleGatewayVoterWeight( - realm, - walletPk, - clientProgramId, - instructions - ) - if (!this.gatewayToken) - throw new Error(`Unable to execute transaction: No Civic Pass found`) + //1 nft is 3 accounts + const positionChunks = chunks(remainingAccounts, 9) + for (const chunk of positionChunks) { + instructions.push( + await this.client.program.methods + .castVoteV0({ + proposal: proposal.pubkey, + owner: walletPk, + }) + .accounts({ + registrar, + voterTokenOwnerRecord: tokenOwnerRecord, + }) + .remainingAccounts(chunk) + .instruction() + ) + } + } - const updateVoterWeightRecordIx = await getVoteInstruction( - this.client, - this.gatewayToken, - realm, - walletPk + if (this.client instanceof NftVoterClient && this.voterWeightPk) { + const {registrar} = await getPluginRegistrarPDA( + realm.pubkey, + realm.account.communityMint, + this.client.program.programId ) - instructions.push(updateVoterWeightRecordIx) - return { voterWeightPk, maxVoterWeightRecord: undefined } - } - if (this.client instanceof PythClient) { - const stakeAccount = await this.client!.stakeConnection.getMainAccount( - walletPk + + const nftVoteRecordsFiltered = await getUsedNftsForProposal( + this.client, + proposal.pubkey ) - const { - voterWeightAccount, - maxVoterWeightRecord, - } = await this.client.stakeConnection.withUpdateVoterWeight( - instructions, - stakeAccount!, - { [type]: {} }, - voterWeightTarget + const votingNfts = await getVotingNfts( + this.client.program.provider.connection, + realm.pubkey, + walletPk ) - return { - voterWeightPk: voterWeightAccount, - maxVoterWeightRecord, + if (!ON_NFT_VOTER_V2) { + const castNftVoteIxs = await getCastNftVoteInstruction( + this.client.program as Program, + walletPk, + registrar, + proposal.pubkey, + tokenOwnerRecord, + this.voterWeightPk, + votingNfts, + nftVoteRecordsFiltered + ) + instructions.push(...castNftVoteIxs) + } else { + const { + castNftVoteTicketIxs, + castNftVoteIxs, + } = await getCastNftVoteInstructionV2( + this.client.program as Program, + walletPk, + registrar, + proposal.pubkey, + tokenOwnerRecord, + this.voterWeightPk, + votingNfts, + nftVoteRecordsFiltered + ) + createNftActionTicketIxs?.push(...castNftVoteTicketIxs) + instructions.push(...castNftVoteIxs) } } - if (this.client instanceof SwitchboardQueueVoterClient) { - instructions.push(this.instructions[0]) - const [vwr] = await PublicKey.findProgramAddress( - [Buffer.from('VoterWeightRecord'), this.oracles[0].toBytes()], - SWITCHBOARD_ADDIN_ID - ) - return { voterWeightPk: vwr, maxVoterWeightRecord: undefined } + + return { + voterWeightPk: this.voterWeightPk, + maxVoterWeightRecord: this.maxVoterWeightPk, } } - withCastPluginVote = async ( + withRelinquishVote = async ( instructions: TransactionInstruction[], proposal: ProgramAccount, - tokeOwnerRecord: ProgramAccount + voteRecordPk: PublicKey, + tokenOwnerRecord: PublicKey ): Promise => { if (this.noClient) { return } - const clientProgramId = this.client!.program.programId - const realm = this.realm! - const walletPk = this.walletPk! + const clientProgramId = this.client?.program.programId + const realm = this.realm + const walletPk = this.walletPk + if ( + !realm || !walletPk || !this.voterWeightPk || !clientProgramId || realm.account.communityMint.toBase58() !== proposal.account.governingTokenMint.toBase58() ) { return } - if (this.client instanceof NftVoterClient) { - const { registrar } = await getPluginRegistrarPDA( + if (this.client instanceof HeliumVsrClient) { + const remainingAccounts: AccountData[] = [] + const [registrar] = registrarKey( realm.pubkey, realm.account.communityMint, - this.client!.program.programId - ) - const { - voterWeightPk, - maxVoterWeightRecord, - } = await this._withHandleNftVoterWeight( - realm!, - walletPk, - clientProgramId, - instructions - ) - const remainingAccounts: { - pubkey: PublicKey - isSigner: boolean - isWritable: boolean - }[] = [] - const nftVoteRecordsFiltered = await getUsedNftsForProposal( - this.client, - proposal.pubkey + clientProgramId ) - for (let i = 0; i < this.votingNfts.length; i++) { - const nft = this.votingNfts[i] - const tokenAccount = await nft.getAssociatedTokenAccount() - const { nftVoteRecord } = await getNftVoteRecordProgramAddress( + + const usedPositions = await getUsedPositionsForProposal({ + connection: this.client.program.provider.connection, + client: this.client, + positions: this.heliumVsrVotingPositions, + proposalPk: proposal.pubkey, + }) + + for (let i = 0; i < usedPositions.length; i++) { + const pos = usedPositions[i] + const [nftVoteRecord] = nftVoteRecordKey( proposal.pubkey, - nft.mintAddress, + pos.mint, clientProgramId ) - if ( - !nftVoteRecordsFiltered.find( - (x) => x.publicKey.toBase58() === nftVoteRecord.toBase58() - ) + + remainingAccounts.push( + new AccountData(nftVoteRecord, false, true), + new AccountData(pos.pubkey, false, true) ) - remainingAccounts.push( - new AccountData(tokenAccount), - new AccountData(nft.address), - new AccountData(nftVoteRecord, false, true) - ) - } - //1 nft is 3 accounts - const firstFiveNfts = remainingAccounts.slice(0, 15) - const remainingNftsToChunk = remainingAccounts.slice( - 15, - remainingAccounts.length - ) - const nftsChunk = chunks(remainingNftsToChunk, 12) - for (const i of nftsChunk) { - const castNftVoteIx = await this.client.program.methods - .castNftVote(proposal.pubkey) - .accounts({ - registrar, - voterWeightRecord: voterWeightPk, - governingTokenOwner: walletPk, - payer: walletPk, - systemProgram: SYSTEM_PROGRAM_ID, - }) - .remainingAccounts(i) - .instruction() - - instructions.push(castNftVoteIx) } - const castNftVoteIx2 = await this.client.program.methods - .castNftVote(proposal.pubkey) - .accounts({ - registrar, - voterWeightRecord: voterWeightPk, - governingTokenOwner: walletPk, - payer: walletPk, - systemProgram: SYSTEM_PROGRAM_ID, - }) - .remainingAccounts(firstFiveNfts) - .instruction() - instructions.push(castNftVoteIx2) - return { voterWeightPk, maxVoterWeightRecord } - } - - if (this.client instanceof VsrClient) { - const props = await this.withUpdateVoterWeightRecord( - instructions, - tokeOwnerRecord, - 'castVote' - ) - return props - } - if (this.client instanceof SwitchboardQueueVoterClient) { - const props = await this.withUpdateVoterWeightRecord( - instructions, - tokeOwnerRecord, - 'castVote' - ) - return props - } - if (this.client instanceof PythClient) { - const props = await this.withUpdateVoterWeightRecord( - instructions, - tokeOwnerRecord, - 'castVote', - proposal.pubkey - ) - return props - } - if (this.client instanceof GatewayClient) { - // get the gateway plugin vote instruction - const instruction = await getVoteInstruction( - this.client, - this.gatewayToken, - realm, - walletPk + const firstFivePositions = remainingAccounts.slice(0, 10) + const remainingPositionsChunk = chunks( + remainingAccounts.slice(10, remainingAccounts.length), + 12 ) - instructions.push(instruction) - - const { voterWeightPk } = await this._withHandleGatewayVoterWeight( - realm!, - walletPk, - clientProgramId, - instructions - ) + for (const chunk of [firstFivePositions, ...remainingPositionsChunk]) { + instructions.push( + await this.client.program.methods + .relinquishVoteV0() + .accounts({ + registrar, + voterTokenOwnerRecord: tokenOwnerRecord, + proposal: proposal.pubkey, + governance: proposal.account.governance, + voterWeightRecord: this.voterWeightPk, + voteRecord: voteRecordPk, + beneficiary: walletPk, + }) + .remainingAccounts(chunk) + .instruction() + ) + } - return { voterWeightPk, maxVoterWeightRecord: undefined } - } - } - withRelinquishVote = async ( - instructions, - proposal: ProgramAccount, - voteRecordPk: PublicKey - ): Promise => { - if (this.noClient) { - return - } - const clientProgramId = this.client!.program.programId - const realm = this.realm! - const walletPk = this.walletPk! - if ( - realm.account.communityMint.toBase58() !== - proposal.account.governingTokenMint.toBase58() - ) { - return + return { + voterWeightPk: this.voterWeightPk, + maxVoterWeightRecord: this.maxVoterWeightPk, + } } if (this.client instanceof NftVoterClient) { - const { registrar } = await getPluginRegistrarPDA( + const remainingAccounts: AccountData[] = [] + const { registrar } = getPluginRegistrarPDA( realm.pubkey, realm.account.communityMint, - this.client!.program.programId - ) - const { - voterWeightPk, - maxVoterWeightRecord, - } = await this._withHandleNftVoterWeight( - realm!, - walletPk, - clientProgramId, - instructions + this.client.program.programId ) - const remainingAccounts: { - pubkey: PublicKey - isSigner: boolean - isWritable: boolean - }[] = [] + const nftVoteRecordsFiltered = ( await getUsedNftsForProposal(this.client, proposal.pubkey) ).filter( @@ -456,124 +369,54 @@ export class VotingClient { new AccountData(voteRecord.publicKey, false, true) ) } + const connection = this.client.program.provider.connection - const firstFiveNfts = remainingAccounts.slice(0, 5) - const remainingNftsToChunk = remainingAccounts.slice( - 5, - remainingAccounts.length - ) - const nftsChunk = chunks(remainingNftsToChunk, 12) - const relinquishNftVoteIx = await this.client.program.methods - .relinquishNftVote() - .accounts({ - registrar, - voterWeightRecord: voterWeightPk, - governance: proposal.account.governance, - proposal: proposal.pubkey, - governingTokenOwner: walletPk, - voteRecord: voteRecordPk, - beneficiary: walletPk, - }) - .remainingAccounts(firstFiveNfts) - .instruction() - instructions.push(relinquishNftVoteIx) - for (const i of nftsChunk) { - const relinquishNftVote2Ix = await this.client.program.methods - .relinquishNftVote() - .accounts({ - registrar, - voterWeightRecord: voterWeightPk, - governance: proposal.account.governance, - proposal: proposal.pubkey, - governingTokenOwner: walletPk, - voteRecord: voteRecordPk, - beneficiary: walletPk, - }) - .remainingAccounts(i) - .instruction() - instructions.push(relinquishNftVote2Ix) + // if this was good code, this would appear outside of this fn. + // But we're not writing good code, there's no good place for it, I'm not bothering. + const voterWeightRecord = await queryClient.fetchQuery({ + queryKey: [this.voterWeightPk], + queryFn: () => { + if (!this.voterWeightPk) throw new Error("No voter weight pk for the current wallet") + return asFindable(connection.getAccountInfo, connection)(this.voterWeightPk); + }, + }) + + if (voterWeightRecord.result) { + const firstFiveNfts = remainingAccounts.slice(0, 5) + const remainingNftsChunk = chunks( + remainingAccounts.slice(5, remainingAccounts.length), + 12 + ) + + for (const chunk of [firstFiveNfts, ...remainingNftsChunk]) { + instructions.push( + await this.client.program.methods + .relinquishNftVote() + .accounts({ + registrar, + voterWeightRecord: this.voterWeightPk, + governance: proposal.account.governance, + proposal: proposal.pubkey, + voterTokenOwnerRecord: tokenOwnerRecord, + voterAuthority: walletPk, + voteRecord: voteRecordPk, + beneficiary: walletPk, + }) + .remainingAccounts(chunk) + .instruction() + ) + } } - return { voterWeightPk, maxVoterWeightRecord } - } - } - _withHandleNftVoterWeight = async ( - realm: ProgramAccount, - walletPk: PublicKey, - clientProgramId: PublicKey, - _instructions - ) => { - if (this.client instanceof NftVoterClient === false) { - throw 'Method only allowed for nft voter client' - } - const { - voterWeightPk, - voterWeightRecordBump, - } = await getPluginVoterWeightRecord( - realm!.pubkey, - realm!.account.communityMint, - walletPk!, - clientProgramId - ) - - const { - maxVoterWeightRecord, - maxVoterWeightRecordBump, - } = await getPluginMaxVoterWeightRecord( - realm!.pubkey, - realm!.account.communityMint, - clientProgramId - ) - return { - voterWeightPk, - voterWeightRecordBump, - maxVoterWeightRecord, - maxVoterWeightRecordBump, + return { + voterWeightPk: this.voterWeightPk, + maxVoterWeightRecord: this.maxVoterWeightPk + } } } - // TODO: this can probably be merged with the nft voter plugin implementation - _withHandleGatewayVoterWeight = async ( - realm: ProgramAccount, - walletPk: PublicKey, - clientProgramId: PublicKey, - _instructions - ) => { - if (!(this.client instanceof GatewayClient)) { - throw 'Method only allowed for gateway client' - } - const { - voterWeightPk, - voterWeightRecordBump, - } = await getPluginVoterWeightRecord( - realm.pubkey, - realm.account.communityMint, - walletPk, - clientProgramId - ) - - const previousVoterWeightPk = await getPreviousVotingWeightRecord( - this.client, - realm, - walletPk - ) - return { - previousVoterWeightPk, - voterWeightPk, - voterWeightRecordBump, - } - } - _setCurrentVoterNfts = (nfts: NFTWithMeta[]) => { - this.votingNfts = nfts - } - _setCurrentVoterGatewayToken = (gatewayToken: PublicKey) => { - this.gatewayToken = gatewayToken - } - _setOracles = (oracles: PublicKey[]) => { - this.oracles = oracles - } - _setInstructions = (instructions: TransactionInstruction[]) => { - this.instructions = instructions + _setCurrentHeliumVsrPositions = (positions: PositionWithMeta[]) => { + this.heliumVsrVotingPositions = positions } } diff --git a/utils/uiTypes/assets.ts b/utils/uiTypes/assets.ts index 755a403301..5305d424ec 100644 --- a/utils/uiTypes/assets.ts +++ b/utils/uiTypes/assets.ts @@ -1,4 +1,4 @@ -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { Governance, ProgramAccount } from '@solana/spl-governance' import { AccountInfo, MintInfo, u64 } from '@solana/spl-token' import { ParsedAccountData, PublicKey } from '@solana/web3.js' @@ -10,10 +10,17 @@ interface AccountExtension { amount?: u64 solAccount?: AccountInfoGen token?: TokenProgramAccount + program?: { + authority: PublicKey + } + stake?: StakeAccount } +export type GovernanceProgramAccountWithNativeTreasuryAddress = ProgramAccount & { + nativeTreasuryAddress: PublicKey +} export interface AssetAccount { - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress pubkey: PublicKey type: AccountType extensions: AccountExtension @@ -29,11 +36,12 @@ export enum AccountType { PROGRAM, NFT, GENERIC, - AuxiliaryToken, + AUXILIARY_TOKEN, + STAKE, } export class AccountTypeToken implements AssetAccount { - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress type: AccountType extensions: AccountExtension pubkey: PublicKey @@ -41,7 +49,7 @@ export class AccountTypeToken implements AssetAccount { constructor( tokenAccount: TokenProgramAccount, mint: TokenProgramAccount, - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress ) { this.governance = governance this.pubkey = tokenAccount.publicKey @@ -57,7 +65,7 @@ export class AccountTypeToken implements AssetAccount { } export class AccountTypeAuxiliaryToken implements AssetAccount { - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress type: AccountType extensions: AccountExtension pubkey: PublicKey @@ -67,7 +75,7 @@ export class AccountTypeAuxiliaryToken implements AssetAccount { ) { this.governance = {} as any this.pubkey = tokenAccount.publicKey - this.type = AccountType.AuxiliaryToken + this.type = AccountType.AUXILIARY_TOKEN this.extensions = { token: tokenAccount, mint: mint, @@ -78,30 +86,67 @@ export class AccountTypeAuxiliaryToken implements AssetAccount { } export class AccountTypeProgram implements AssetAccount { - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress type: AccountType extensions: AccountExtension pubkey: PublicKey - constructor(governance: ProgramAccount) { + constructor( + governance: GovernanceProgramAccountWithNativeTreasuryAddress, + programId: PublicKey, + owner: PublicKey + ) { this.governance = governance - this.pubkey = governance.account.governedAccount + this.pubkey = programId this.type = AccountType.PROGRAM - this.extensions = {} + this.extensions = { + program: { + authority: owner, + }, + } + } +} + +export class AccountTypeStake implements AssetAccount { + governance: GovernanceProgramAccountWithNativeTreasuryAddress + type: AccountType + extensions: AccountExtension + pubkey: PublicKey + constructor( + governance: GovernanceProgramAccountWithNativeTreasuryAddress, + stakePk: PublicKey, + state: StakeState, + delegatedValidator: PublicKey | null, + amount: number + ) { + this.governance = governance + this.pubkey = stakePk + this.type = AccountType.STAKE + this.extensions = { + stake: { + stakeAccount: stakePk, + state: state, + delegatedValidator: delegatedValidator, + amount: amount, + }, + } } } export class AccountTypeMint implements AssetAccount { - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress type: AccountType extensions: AccountExtension pubkey: PublicKey - constructor(governance: ProgramAccount, account: MintInfo) { + constructor( + governance: GovernanceProgramAccountWithNativeTreasuryAddress, + account: MintInfo & { publicKey: PublicKey } + ) { this.governance = governance - this.pubkey = governance.account.governedAccount + this.pubkey = account.publicKey this.type = AccountType.MINT this.extensions = { mint: { - publicKey: governance.account.governedAccount, + publicKey: account.publicKey, account: account, }, } @@ -109,7 +154,7 @@ export class AccountTypeMint implements AssetAccount { } export class AccountTypeNFT implements AssetAccount { - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress type: AccountType extensions: AccountExtension pubkey: PublicKey @@ -117,7 +162,7 @@ export class AccountTypeNFT implements AssetAccount { constructor( tokenAccount: TokenProgramAccount, mint: TokenProgramAccount, - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress ) { this.governance = governance this.pubkey = tokenAccount.publicKey @@ -133,7 +178,7 @@ export class AccountTypeNFT implements AssetAccount { } export class AccountTypeSol implements AssetAccount { - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress type: AccountType extensions: AccountExtension pubkey: PublicKey @@ -142,7 +187,7 @@ export class AccountTypeSol implements AssetAccount { mint: TokenProgramAccount, solAddress: PublicKey, solAccount: AccountInfoGen, - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress ) { this.governance = governance this.type = AccountType.SOL @@ -159,11 +204,11 @@ export class AccountTypeSol implements AssetAccount { } export class AccountTypeGeneric implements AssetAccount { - governance: ProgramAccount + governance: GovernanceProgramAccountWithNativeTreasuryAddress type: AccountType extensions: AccountExtension pubkey: PublicKey - constructor(governance: ProgramAccount) { + constructor(governance: GovernanceProgramAccountWithNativeTreasuryAddress) { this.governance = governance this.pubkey = governance.account.governedAccount this.type = AccountType.GENERIC diff --git a/utils/uiTypes/members.ts b/utils/uiTypes/members.ts index ec5f62e774..f360749106 100644 --- a/utils/uiTypes/members.ts +++ b/utils/uiTypes/members.ts @@ -1,9 +1,8 @@ -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { PublicKey } from '@solana/web3.js' export interface Member { walletAddress: string - votesCasted: number councilVotes: BN communityVotes: BN hasCouncilTokenOutsideRealm?: boolean @@ -11,14 +10,3 @@ export interface Member { delegateWalletCouncil?: PublicKey delegateWalletCommunity?: PublicKey } - -export interface Delegate { - communityMembers?: Array - councilMembers?: Array - communityTokenCount?: number - councilTokenCount?: number -} - -export interface Delegates { - [key: string]: Delegate -} diff --git a/utils/uiTypes/proposalCreationTypes.ts b/utils/uiTypes/proposalCreationTypes.ts index fcd420f21d..d0aaa9eaa9 100644 --- a/utils/uiTypes/proposalCreationTypes.ts +++ b/utils/uiTypes/proposalCreationTypes.ts @@ -1,14 +1,34 @@ -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' import { SupportedMintName } from '@tools/sdk/solend/configuration' import { DepositWithMintAccount, Voter } from 'VoteStakeRegistry/sdk/accounts' import { LockupKind } from 'VoteStakeRegistry/tools/types' -import { consts as foresightConsts } from '@foresight-tmp/foresight-sdk' import { AssetAccount, StakeAccount } from '@utils/uiTypes/assets' +import { RealmInfo } from '@models/registry/api' +import * as PaymentStreaming from '@mean-dao/payment-streaming' + +// Alphabetical order +export enum PackageEnum { + Common, + Distribution, + Dual, + GatewayPlugin, + Identity, + MangoMarketV4, + MeanFinance, + NftPlugin, + PsyFinance, + Pyth, + Serum, + Solend, + Symmetry, + Squads, + Switchboard, + VsrPlugin, +} export interface UiInstruction { serializedInstruction: string @@ -17,11 +37,9 @@ export interface UiInstruction { governance: ProgramAccount | undefined customHoldUpTime?: number prerequisiteInstructions?: TransactionInstruction[] - chunkSplitByDefault?: boolean - prerequisiteInstructionsSigners?: Keypair[] + prerequisiteInstructionsSigners?: (Keypair | null)[] chunkBy?: number signers?: Keypair[] - shouldSplitIntoSeparateTxs?: boolean | undefined } export interface SplTokenTransferForm { @@ -32,72 +50,57 @@ export interface SplTokenTransferForm { mintInfo: MintInfo | undefined } +export interface BurnTokensForm { + amount: number | undefined + governedTokenAccount: AssetAccount | undefined + mintInfo: MintInfo | undefined +} + export interface DomainNameTransferForm { destinationAccount: string governedAccount: AssetAccount | undefined domainAddress: string | undefined } -export interface CastleDepositForm { - amount: number | undefined +export interface MeanCreateAccount { governedTokenAccount: AssetAccount | undefined - castleVaultId: string - programId: string | undefined + label: string | undefined mintInfo: MintInfo | undefined -} - -export interface CastleWithdrawForm { amount: number | undefined - governedTokenAccount: AssetAccount | undefined - castleVaultId: string - programId: string | undefined - mintInfo: MintInfo | undefined + type: PaymentStreaming.AccountType } -export interface FriktionDepositForm { - amount: number | undefined +export interface MeanFundAccount { governedTokenAccount: AssetAccount | undefined - voltVaultId: string - programId: string | undefined mintInfo: MintInfo | undefined -} - -export interface FriktionWithdrawForm { amount: number | undefined - governedTokenAccount: AssetAccount | undefined - voltVaultId: string - programId: string | undefined - mintInfo: MintInfo | undefined + paymentStreamingAccount: PaymentStreaming.PaymentStreamingAccount | undefined } -export interface FriktionClaimPendingDepositForm { +export interface MeanWithdrawFromAccount { governedTokenAccount: AssetAccount | undefined - voltVaultId: string - programId: string | undefined mintInfo: MintInfo | undefined + amount: number | undefined + paymentStreamingAccount: PaymentStreaming.PaymentStreamingAccount | undefined + destination: string | undefined } -export interface FriktionClaimPendingWithdrawForm { +export interface MeanCreateStream { governedTokenAccount: AssetAccount | undefined - voltVaultId: string - programId: string | undefined - mintInfo: MintInfo | undefined -} - -export interface GoblinGoldDepositForm { - amount: number | undefined - governedTokenAccount?: AssetAccount | undefined - goblinGoldVaultId: string - mintName?: SupportedMintName | undefined + paymentStreamingAccount: PaymentStreaming.PaymentStreamingAccount | undefined + streamName: string | undefined + destination: string | undefined mintInfo: MintInfo | undefined + allocationAssigned: number | undefined + rateAmount: number | undefined + rateInterval: 0 | 1 | 2 | 3 | 4 | 5 + startDate: string } -export interface GoblinGoldWithdrawForm { - amount: number | undefined - governedTokenAccount?: AssetAccount | undefined - goblinGoldVaultId?: string - mintName?: SupportedMintName - mintInfo: MintInfo | undefined +export interface MeanTransferStream { + governedTokenAccount: AssetAccount | undefined + stream: PaymentStreaming.Stream | undefined + destination: string | undefined } export interface GrantForm { @@ -115,9 +118,13 @@ export interface ClawbackForm { governedTokenAccount: AssetAccount | undefined voter: Voter | null deposit: DepositWithMintAccount | null + holdupTime: number } -export interface SendTokenCompactViewForm extends SplTokenTransferForm { +export interface SendTokenCompactViewForm extends Omit { + destinationAccount: string[] + amount: (number | undefined)[] + txDollarAmount: (string | undefined)[] description: string title: string } @@ -144,16 +151,6 @@ export interface ProgramUpgradeForm { bufferSpillAddress?: string | undefined } -export interface CreateStreamForm { - recipient: string - tokenAccount?: AssetAccount - start: string - depositedAmount: number - releaseAmount: number - amountAtCliff: number - cancelable: boolean -} - export const programUpgradeFormNameOf = getNameOf() export interface MangoMakeAddOracleForm { @@ -168,186 +165,39 @@ 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 +/* PsyOptions American options */ +export interface PsyFinanceMintAmericanOptionsForm { + contractSize: number + expirationUnixTimestamp: number + optionTokenDestinationAccount: string + quoteMint: string + size: number | undefined + strike: number + underlyingAccount: AssetAccount | undefined + underlyingMint: PublicKey | undefined + writerTokenDestinationAccount: string } -export interface MangoSwapSpotMarketForm { - governedAccount: AssetAccount | null - mangoGroup: NameValue | null - market: NameValue | null - adminPk: string - newSpotMarketPk: string +export interface PsyFinanceBurnWriterForQuote { + size: number + writerTokenAccount: AssetAccount | undefined + quoteDestination: string } -export interface MangoRemoveOracleForm { - governedAccount: AssetAccount | null - mangoGroup: NameValue | null - adminPk: string - oraclePk: NameValue | null +export interface PsyFinanceClaimUnderlyingPostExpiration { + size: number + writerTokenAccount: AssetAccount | undefined + underlyingDestination: string } -export interface SagaPhoneForm { - governedAccount: AssetAccount | null - quantity: number +export interface PsyFinanceExerciseOption { + size: number + optionTokenAccount: AssetAccount | undefined + quoteAssetAccount: AssetAccount | undefined } -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 -} +/* End PsyOptions American options */ -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 -} - -export interface ForesightHasGovernedAccount { - governedAccount: AssetAccount -} - -export interface ForesightHasMarketListId extends ForesightHasGovernedAccount { - marketListId: string -} - -export interface ForesightHasMarketId extends ForesightHasMarketListId { - marketId: number -} - -export interface ForesightHasCategoryId extends ForesightHasGovernedAccount { - categoryId: string -} - -export interface ForesightMakeAddMarketListToCategoryParams - extends ForesightHasCategoryId, - ForesightHasMarketListId {} - -export interface ForesightMakeResolveMarketParams extends ForesightHasMarketId { - winner: number -} - -export interface ForesightMakeSetMarketMetadataParams - extends ForesightHasMarketId { - content: string - field: foresightConsts.MarketMetadataFieldName -} export interface Base64InstructionForm { governedAccount: AssetAccount | undefined base64: string @@ -358,16 +208,6 @@ export interface EmptyInstructionForm { governedAccount: AssetAccount | undefined } -export interface SwitchboardAdmitOracleForm { - oraclePubkey: PublicKey | undefined - queuePubkey: PublicKey | undefined -} - -export interface SwitchboardRevokeOracleForm { - oraclePubkey: PublicKey | undefined - queuePubkey: PublicKey | undefined -} - export interface CreateAssociatedTokenAccountForm { governedAccount?: AssetAccount splTokenMint?: string @@ -420,96 +260,145 @@ export interface UpdateTokenMetadataForm { programId: string | undefined } +export interface SerumInitUserForm { + governedAccount?: AssetAccount + owner: string + programId: string +} + +export interface SerumGrantLockedForm { + governedAccount?: AssetAccount + owner: string + mintInfo: MintInfo | undefined + amount: number | undefined + programId: string +} + +export interface SerumUpdateConfigParam { + governedAccount?: AssetAccount // Config Authority + claimDelay?: number + redeemDelay?: number + cliffPeriod?: number + linearVestingPeriod?: number +} + +export interface SerumUpdateConfigAuthority { + governedAccount?: AssetAccount // Config Authority + newAuthority?: string +} + +export interface JoinDAOForm { + governedAccount?: AssetAccount + mintInfo: MintInfo | undefined + realm: RealmInfo | null + amount?: number +} + export enum Instructions { - Transfer, - ProgramUpgrade, - Mint, Base64, - None, - MangoAddOracle, - MangoAddSpotMarket, - MangoChangeMaxAccounts, - MangoChangePerpMarket, - MangoChangeReferralFeeParams, - MangoChangeReferralFeeParams2, - MangoChangeSpotMarket, - MangoCreatePerpMarket, - MangoSetMarketMode, - MangoChangeQuoteParams, - MangoRemoveSpotMarket, - MangoRemovePerpMarket, - MangoSwapSpotMarket, - MangoRemoveOracle, - MangoV4TokenRegister, - MangoV4TokenEdit, - MangoV4PerpEdit, - MangoV4Serum3RegisterMarket, - MangoV4PerpCreate, - MangoV4TokenRegisterTrustless, - CreateStream, - CancelStream, - Grant, + Burn, + ChangeMakeDonation, Clawback, + CloseTokenAccount, + CloseMultipleTokenAccounts, + ConfigureGatewayPlugin, + ConfigureNftPluginCollection, CreateAssociatedTokenAccount, - DepositIntoVolt, - WithdrawFromVolt, - ClaimPendingDeposit, - ClaimPendingWithdraw, - DepositIntoCastle, - WithrawFromCastle, - DepositIntoGoblinGold, - WithdrawFromGoblinGold, + CreateGatewayPluginRegistrar, + CreateNftPluginMaxVoterWeight, + CreateNftPluginRegistrar, CreateSolendObligationAccount, - InitSolendObligationAccount, + CreateTokenMetadata, + CreateVsrRegistrar, + DeactivateValidatorStake, DepositReserveLiquidityAndObligationCollateral, - WithdrawObligationCollateralAndRedeemReserveLiquidity, - SwitchboardAdmitOracle, - SwitchboardRevokeOracle, + DifferValidatorStake, + DualFinanceAirdrop, + DualFinanceExerciseStakingOption, + DualFinanceLiquidityStakingOption, + DualFinanceInitStrike, + DualFinanceStakingOption, + DualFinanceGso, + DualFinanceGsoWithdraw, + DualFinanceStakingOptionWithdraw, + DualFinanceDelegate, + DualFinanceDelegateWithdraw, + DualFinanceVoteDeposit, + DaoVote, + DistributionCloseVaults, + DistributionFillVaults, + DelegateStake, + RemoveStakeLock, + Grant, + InitSolendObligationAccount, + JoinDAO, + MangoV4PerpCreate, + MangoV4PerpEdit, + MangoV4OpenBookRegisterMarket, + MangoV4OpenBookEditMarket, + MangoV4TokenEdit, + MangoV4TokenRegister, + MangoV4TokenRegisterTrustless, + MangoV4GroupEdit, + IdlSetBuffer, + MangoV4IxGateSet, + MangoV4AltSet, + MangoV4AltExtend, + MangoV4StubOracleCreate, + MangoV4StubOracleSet, + MangoV4TokenAddBank, + MangoV4AdminWithdrawTokenFees, + MangoV4WithdrawPerpFees, + MeanCreateAccount, + MeanCreateStream, + MeanFundAccount, + MeanTransferStream, + MeanWithdrawFromAccount, + Mint, + None, + ProgramUpgrade, + PsyFinanceBurnWriterForQuote, + PsyFinanceClaimUnderlyingPostExpiration, + PsyFinanceExerciseOption, + PsyFinanceMintAmericanOptions, + RealmConfig, RefreshSolendObligation, RefreshSolendReserve, - ForesightInitMarket, - ForesightInitMarketList, - ForesightInitCategory, - ForesightResolveMarket, - ForesightAddMarketListToCategory, - ForesightSetMarketMetadata, - RealmConfig, - CreateNftPluginRegistrar, - CreateNftPluginMaxVoterWeight, - ConfigureNftPluginCollection, - CloseTokenAccount, - VotingMintConfig, - CreateVsrRegistrar, - CreateGatewayPluginRegistrar, - ConfigureGatewayPlugin, - ChangeMakeDonation, - CreateTokenMetadata, - UpdateTokenMetadata, - SagaPreOrder, - DepositToMangoAccount, - DepositToMangoAccountCsv, + SerumGrantLockedMSRM, + SerumGrantLockedSRM, + SerumGrantVestMSRM, + SerumGrantVestSRM, + SerumInitUser, + SerumUpdateGovConfigAuthority, + SerumUpdateGovConfigParams, + SquadsMeshAddMember, + SquadsMeshChangeThresholdMember, + SquadsMeshRemoveMember, + PythRecoverAccount, + PythUpdatePoolAuthority, StakeValidator, - DeactivateValidatorStake, - WithdrawValidatorStake, - DifferValidatorStake, + SwitchboardFundOracle, + WithdrawFromOracle, + Transfer, TransferDomainName, - EverlendDeposit, - EverlendWithdraw, -} - -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 -] + UpdateTokenMetadata, + VotingMintConfig, + WithdrawObligationCollateralAndRedeemReserveLiquidity, + WithdrawValidatorStake, + SplitStake, + AddKeyToDID, + RemoveKeyFromDID, + AddServiceToDID, + RemoveServiceFromDID, + RevokeGoverningTokens, + SetMintAuthority, + SanctumDepositStake, + SanctumWithdrawStake, + SymmetryCreateBasket, + SymmetryEditBasket, + SymmetryDeposit, + SymmetryWithdraw +} export interface ComponentInstructionData { governedAccount?: ProgramAccount | undefined @@ -518,6 +407,7 @@ export interface ComponentInstructionData { } export interface InstructionsContext { instructionsData: ComponentInstructionData[] + voteByCouncil?: boolean | null handleSetInstructions: (val, index) => void governance: ProgramAccount | null | undefined setGovernance: (val) => void @@ -566,3 +456,157 @@ export interface ValidatorWithdrawStakeForm { stakingAccount: StakeAccount | undefined amount: number } + +export interface ValidatorRemoveLockup { + governedTokenAccount: AssetAccount | undefined + stakeAccount: string +} + +export interface DelegateStakeForm { + governedTokenAccount: AssetAccount | undefined + stakingAccount: StakeAccount | undefined + votePubkey: string +} + +export interface DualFinanceAirdropForm { + root: string + amount: number + eligibilityStart: number + eligibilityEnd: number + amountPerVoter: number + treasury: AssetAccount | undefined +} + +export interface DualFinanceStakingOptionForm { + strike: number + soName: string | undefined + optionExpirationUnixSeconds: number + numTokens: string + lotSize: number + baseTreasury: AssetAccount | undefined + quoteTreasury: AssetAccount | undefined + payer: AssetAccount | undefined + userPk: string | undefined +} + +export interface DualFinanceGsoForm { + strike: number + soName: string | undefined + optionExpirationUnixSeconds: number + numTokens: number + lotSize: number + subscriptionPeriodEnd: number + lockupRatio: number + lockupMint: string + baseTreasury: AssetAccount | undefined + quoteTreasury: AssetAccount | undefined + payer: AssetAccount | undefined +} + +export interface DualFinanceLiquidityStakingOptionForm { + optionExpirationUnixSeconds: number + numTokens: number + lotSize: number + baseTreasury: AssetAccount | undefined + quoteTreasury: AssetAccount | undefined + payer: AssetAccount | undefined +} + +export interface DualFinanceInitStrikeForm { + strikes: string + soName: string + payer: AssetAccount | undefined + baseTreasury: AssetAccount | undefined +} + +export interface DualFinanceExerciseForm { + numTokens: number + soName: string | undefined + baseTreasury: AssetAccount | undefined + quoteTreasury: AssetAccount | undefined + optionAccount: AssetAccount | undefined +} + +export interface DualFinanceWithdrawForm { + soName: string | undefined + baseTreasury: AssetAccount | undefined + mintPk: string | undefined +} + +export interface DualFinanceGsoWithdrawForm { + soName: string | undefined + baseTreasury: AssetAccount | undefined +} + +export interface DualFinanceDelegateForm { + delegateAccount: string | undefined + realm: string | undefined + delegateToken: AssetAccount | undefined +} + +export interface DualFinanceDelegateWithdrawForm { + realm: string | undefined + delegateToken: AssetAccount | undefined +} + +export interface DualFinanceVoteDepositForm { + numTokens: number + realm: string | undefined + delegateToken: AssetAccount | undefined +} + +export interface SymmetryCreateBasketForm { + governedAccount?: AssetAccount, + basketType: number, + basketName: string, + basketSymbol: string, + basketMetadataUrl: string, + basketComposition: { + name: string, + symbol: string, + token: PublicKey; + weight: number; + }[], + rebalanceThreshold: number, + rebalanceSlippageTolerance: number, + depositFee: number, + feeCollectorAddress:string, + liquidityProvision: boolean, + liquidityProvisionRange: number, +} + + +export interface SymmetryEditBasketForm { + governedAccount?: AssetAccount, + basketAddress?: PublicKey, + basketType: number, + basketName: string, + basketSymbol: string, + basketMetadataUrl: string, + basketComposition: { + name: string, + symbol: string, + token: PublicKey; + weight: number; + }[], + rebalanceThreshold: number, + rebalanceSlippageTolerance: number, + depositFee: number, + feeCollectorAddress:string, + liquidityProvision: boolean, + liquidityProvisionRange: number, +} + +export interface SymmetryDepositForm { + governedAccount?: AssetAccount, + basketAddress?: PublicKey, + depositToken?: PublicKey, + depositAmount: number, +} + +export interface SymmetryWithdrawForm { + governedAccount?: AssetAccount, + basketAddress?: PublicKey, + withdrawAmount: number, + withdrawType: number +} diff --git a/utils/validations.tsx b/utils/validations.tsx index f1e5a04004..7f9c818178 100644 --- a/utils/validations.tsx +++ b/utils/validations.tsx @@ -15,24 +15,30 @@ import { ASSOCIATED_TOKEN_PROGRAM_ID, Token, TOKEN_PROGRAM_ID, + MintInfo, } from '@solana/spl-token' import { Connection } from '@solana/web3.js' -import { BN } from '@project-serum/anchor' +import { BN } from '@coral-xyz/anchor' import { - nftPluginsPks, - vsrPluginsPks, - gatewayPluginsPks, -} from '@hooks/useVotingPlugins' + NFT_PLUGINS_PKS, + VSR_PLUGIN_PKS, + HELIUM_VSR_PLUGINS_PKS, + GATEWAY_PLUGINS_PKS, + QV_PLUGINS_PKS, +} from '@constants/plugins' import { AssetAccount } from '@utils/uiTypes/assets' +import { validatePubkey } from './formValidation' // Plugins supported by Realms const supportedPlugins = [ - ...nftPluginsPks, - ...vsrPluginsPks, - ...gatewayPluginsPks, + ...NFT_PLUGINS_PKS, + ...VSR_PLUGIN_PKS, + ...HELIUM_VSR_PLUGINS_PKS, + ...GATEWAY_PLUGINS_PKS, + ...QV_PLUGINS_PKS ] -export const getValidateAccount = async ( +const getValidateAccount = async ( connection: Connection, pubKey: PublicKey ) => { @@ -53,7 +59,7 @@ export const getValidatedPublickKey = (val: string) => { } } -export const validateDoseTokenAccountMatchMint = ( +const validateDoseTokenAccountMatchMint = ( tokenAccount: AccountInfo, mint: PublicKey ) => { @@ -90,7 +96,7 @@ export const isExistingTokenAccount = async ( return isExistingTokenAccount } -export const validateDestinationAccAddress = async ( +const validateDestinationAccAddress = async ( connection: ConnectionContext, val: any, governedAccount?: PublicKey @@ -118,7 +124,7 @@ export const validateDestinationAccAddress = async ( return true } -export const validateDestinationAccAddressWithMint = async ( +const validateDestinationAccAddressWithMint = async ( connection: ConnectionContext, val: any, mintPubKey: PublicKey @@ -187,35 +193,40 @@ export const validateBuffer = async ( let buffer: ProgramBufferAccount try { + // eslint-disable-next-line @typescript-eslint/no-unused-vars buffer = create(info.data.parsed, ProgramBufferAccount) } catch { throw 'Invalid program buffer account' } - + /* if (buffer.info.authority?.toBase58() !== governedAccount.toBase58()) { throw `Buffer authority must be set to governance account ${governedAccount.toBase58()}` - } + } */ }) } else { throw 'Provided value is not a valid account address' } } -export const getFriktionDepositSchema = ({ form }) => { - const governedTokenAccount = form.governedTokenAccount as AssetAccount +export const getMeanCreateAccountSchema = ({ form }) => { + const governedTokenAccount = form.governedTokenAccount as + | AssetAccount + | undefined + return yup.object().shape({ - governedTokenAccount: yup.object().required('Source account is required'), + governedTokenAccount: yup.object().required('Source of funds is required'), + label: yup.string().required('Name is required'), amount: yup .number() .typeError('Amount is required') .test( 'amount', - 'Transfer amount must be less than the source account available amount', + 'Transfer amount must be less than the source of funds available amount', async function (val: number) { if (val && !form.governedTokenAccount) { return this.createError({ - message: `Please select source account to validate the amount`, + message: `Please select source of funds to validate the amount`, }) } if ( @@ -244,7 +255,647 @@ export const getFriktionDepositSchema = ({ form }) => { }) } -export const getCastleDepositSchema = ({ form }) => { +export const getMeanFundAccountSchema = ({ form }) => { + const governedTokenAccount = form.governedTokenAccount as + | AssetAccount + | undefined + + return yup.object().shape({ + governedTokenAccount: yup.object().required('Source of funds is required'), + paymentStreamingAccount: yup + .object() + .required('Streaming account destination is required'), + amount: yup + .number() + .typeError('Amount is required') + .test( + 'amount', + 'Transfer amount must be less than the source of funds available amount', + async function (val: number) { + if (val && !form.governedTokenAccount) { + return this.createError({ + message: `Please select source of funds to validate the amount`, + }) + } + if ( + val && + governedTokenAccount && + governedTokenAccount.extensions.mint + ) { + const mintValue = getMintNaturalAmountFromDecimalAsBN( + val, + governedTokenAccount?.extensions.mint.account.decimals + ) + return !!(governedTokenAccount?.extensions.token?.publicKey && + !governedTokenAccount.isSol + ? governedTokenAccount.extensions.token.account.amount.gte( + mintValue + ) + : new BN( + governedTokenAccount.extensions.solAccount!.lamports + ).gte(mintValue)) + } + return this.createError({ + message: `Amount is required`, + }) + } + ), + }) +} +export const getMeanWithdrawFromAccountSchema = ({ + form, + connection, + mintInfo, +}: { + form: any + connection: ConnectionContext + mintInfo?: MintInfo +}) => { + return yup.object().shape({ + governedTokenAccount: yup.object().required('Governance is required'), + paymentStreamingAccount: yup + .object() + .required('Streaming account source is required'), + + destination: yup + .string() + .test( + 'destination', + 'Account validation error', + async function (val: string) { + if (val) { + try { + if (form.paymentStreamingAccount?.id.toString() == val) { + return this.createError({ + message: `Destination account address can't be same as source account`, + }) + } + await validateDestinationAccAddress( + connection, + val, + new PublicKey(form.paymentStreamingAccount?.id) + ) + return true + } catch (e) { + console.log(e) + return this.createError({ + message: `${e}`, + }) + } + } else { + return this.createError({ + message: `Destination account is required`, + }) + } + } + ), + amount: yup + .number() + .typeError('Amount is required') + .test( + 'amount', + 'Transfer amount must be less than the source of funds available amount', + async function (val: number) { + if (val && !form.paymentStreamingAccount) { + return this.createError({ + message: `Please select source of funds to validate the amount`, + }) + } + if (val && form.paymentStreamingAccount && mintInfo) { + const mintValue = getMintNaturalAmountFromDecimalAsBN( + val, + mintInfo.decimals + ) + return new BN(form.paymentStreamingAccount.balance).gte(mintValue) + } + return this.createError({ + message: `Amount is required`, + }) + } + ), + }) +} + +export const getMeanCreateStreamSchema = ({ + form, + connection, + mintInfo, +}: { + form: any + connection: ConnectionContext + mintInfo?: MintInfo +}) => { + return yup.object().shape({ + governedTokenAccount: yup.object().required('Governance is required'), + paymentStreamingAccount: yup + .object() + .required('Streaming account source is required'), + streamName: yup.string().required('Stream name is required'), + destination: yup + .string() + .test( + 'destination', + 'Account validation error', + async function (val: string) { + if (val) { + try { + if (form.paymentStreamingAccount?.id.toString() == val) { + return this.createError({ + message: `Destination account address can't be same as source account`, + }) + } + await validateDestinationAccAddress( + connection, + val, + new PublicKey(form.paymentStreamingAccount?.id) + ) + return true + } catch (e) { + console.log(e) + return this.createError({ + message: `${e}`, + }) + } + } else { + return this.createError({ + message: `Destination account is required`, + }) + } + } + ), + allocationAssigned: yup + .number() + .typeError('Amount is required') + .test( + 'amount', + 'Transfer amount must be less than the source of funds available amount', + async function (val: number) { + if (val && !form.paymentStreamingAccount) { + return this.createError({ + message: `Please select source of funds to validate the amount`, + }) + } + if (val && form.paymentStreamingAccount && mintInfo) { + const mintValue = getMintNaturalAmountFromDecimalAsBN( + val, + mintInfo.decimals + ) + return new BN(form.paymentStreamingAccount.balance).gte(mintValue) + } + return this.createError({ + message: `Amount is required`, + }) + } + ), + rateAmount: yup.number().required('Rate amount is required'), + }) +} + +export const getMeanTransferStreamSchema = () => { + return yup.object().shape({ + governedTokenAccount: yup.object().required('Governance is required'), + stream: yup.object().required('Stream source is required'), + destination: yup.string().required('New stream owner is required'), + }) +} + +export const getDualFinanceGovernanceAirdropSchema = ({ + form, +}: { + form: any +}) => { + return yup.object().shape({ + amountPerVoter: yup + .number() + .typeError('Amount per voter is required') + .test('amountPerVoter', 'amountPerVoter', async function (val: number) { + if (val > form.amount) { + return this.createError({ + message: `Amount per voter cannot be more than total`, + }) + } + return true + }), + eligibilityStart: yup + .number() + .typeError('Eligibility start is required') + .test( + 'eligibilityStart', + 'EligibilityStart must be a reasonable unix seconds timestamp', + function (val: number) { + // 01/01/2020 + // Primary goal is to catch users inputting ms instead of sec. + if (val < 1577854800 || val > 1577854800 * 10) { + return this.createError({ + message: `Please select a valid unix seconds timestamp`, + }) + } + return true + } + ), + eligibilityEnd: yup + .number() + .typeError('Eligibility end is required') + .test( + 'eligibilityEnd', + 'EligibilityEnd must be a reasonable unix seconds timestamp', + function (val: number) { + // 01/01/2020 + // Primary goal is to catch users inputting ms instead of sec. + if (val < 1577854800 || val > 1577854800 * 10) { + return this.createError({ + message: `Please select a valid unix seconds timestamp`, + }) + } + return true + } + ), + treasury: yup.object().typeError('Treasury is required'), + amount: yup + .string() + .typeError('Amount is required') + .test('amount', 'amount', async function (val: string) { + if (!form.treasury) { + return this.createError({ + message: `Please select a treasury`, + }) + } + const numAtomsInTreasury = new BN( + form.treasury.extensions.token.account.amount + ) + if (numAtomsInTreasury.lt(new BN(val))) { + return this.createError({ + message: `Not enough tokens`, + }) + } + return true + }), + }) +} + +export const getDualFinanceMerkleAirdropSchema = ({ form }: { form: any }) => { + return yup.object().shape({ + root: yup + .string() + .required('Root is required') + .test( + 'destination', + 'Account validation error', + async function (val: string) { + if (val) { + try { + const arr = Uint8Array.from(Buffer.from(val, 'hex')) + if (arr.length !== 32) { + return this.createError({ + message: 'Expected 32 bytes', + }) + } + return true + } catch (e) { + console.log(e) + } + try { + const root = val.split(',').map(function (item) { + return parseInt(item, 10) + }) + if (root.length !== 32) { + return this.createError({ + message: 'Expected 32 bytes', + }) + } + for (const byte of root) { + if (byte < 0 || byte >= 256) { + return this.createError({ + message: 'Invalid byte', + }) + } + } + return true + } catch (e) { + console.log(e) + } + return this.createError({ + message: `Could not parse`, + }) + } else { + return this.createError({ + message: `Root is required`, + }) + } + } + ), + treasury: yup.object().typeError('Treasury is required'), + amount: yup + .string() + .typeError('Amount is required') + .test('amount', 'amount', async function (val: string) { + if (!form.treasury) { + return this.createError({ + message: `Please select a treasury`, + }) + } + const numAtomsInTreasury = new BN( + form.treasury.extensions.token.account.amount + ) + if (numAtomsInTreasury.lt(new BN(val))) { + return this.createError({ + message: `Not enough tokens`, + }) + } + return true + }), + }) +} + +export const getDualFinanceLiquidityStakingOptionSchema = ({ + form, +}: { + form: any +}) => { + return yup.object().shape({ + optionExpirationUnixSeconds: yup + .number() + .typeError('Expiration is required') + .test( + 'expiration', + 'Expiration must be a future unix seconds timestamp', + function (val: number) { + const nowUnixMs = Date.now() / 1_000 + // Primary goal is to catch users inputting ms instead of sec. + if (val > nowUnixMs * 10) { + return this.createError({ + message: `Please select a valid unix seconds timestamp`, + }) + } + if (val < nowUnixMs) { + return this.createError({ + message: `Please select a time in the future`, + }) + } + return true + } + ), + numTokens: yup + .string() + .typeError('Num tokens is required') + .test('amount', 'amount', async function (val: string) { + if (!form.baseTreasury) { + return this.createError({ + message: `Please select a treasury`, + }) + } + const numAtomsInTreasury = new BN( + form.baseTreasury.extensions.token.account.amount + ) + if (numAtomsInTreasury.lt(new BN(val))) { + return this.createError({ + message: `Not enough tokens`, + }) + } + return true + }), + lotSize: yup.number().typeError('lotSize is required'), + baseTreasury: yup.object().typeError('baseTreasury is required'), + quoteTreasury: yup.object().typeError('quoteTreasury is required'), + payer: yup.object().typeError('payer is required'), + }) +} + +export const getDualFinanceStakingOptionSchema = ({ + form, + connection, +}: { + form: any + connection: any +}) => { + return yup.object().shape({ + soName: yup + .string() + .required('Staking option name is required') + .test( + 'is-not-too-long', + 'soName too long', + (value) => value !== undefined && value.length < 32 + ), + userPk: yup + .string() + .test( + 'is-valid-address1', + 'Please enter a valid PublicKey', + async function (userPk: string) { + if (!userPk || !validatePubkey(userPk)) { + return false + } + + const pubKey = getValidatedPublickKey(userPk) + const account = await getValidateAccount(connection.current, pubKey) + if (!account) { + return false + } + return true + } + ), + optionExpirationUnixSeconds: yup + .number() + .typeError('Expiration is required') + .test( + 'expiration', + 'Expiration must be a future unix seconds timestamp', + function (val: number) { + const nowUnixMs = Date.now() / 1_000 + // Primary goal is to catch users inputting ms instead of sec. + if (val > nowUnixMs * 10) { + return this.createError({ + message: `Please select a valid unix seconds timestamp`, + }) + } + if (val < nowUnixMs) { + return this.createError({ + message: `Please select a time in the future`, + }) + } + return true + } + ), + numTokens: yup + .string() + .typeError('Num tokens is required') + .test('amount', 'amount', async function (val: string) { + if (!form.baseTreasury) { + return this.createError({ + message: `Please select a treasury`, + }) + } + const numAtomsInTreasury = new BN( + form.baseTreasury.extensions.token.account.amount + ) + if (numAtomsInTreasury.lt(new BN(val))) { + return this.createError({ + message: `Not enough tokens`, + }) + } + return true + }), + strike: yup.number().typeError('Strike is required'), + lotSize: yup.number().typeError('lotSize is required'), + baseTreasury: yup.object().typeError('baseTreasury is required'), + quoteTreasury: yup.object().typeError('quoteTreasury is required'), + payer: yup.object().typeError('payer is required'), + }) +} + +export const getDualFinanceGsoSchema = ({ form }: { form: any }) => { + return yup.object().shape({ + soName: yup + .string() + .required('Staking option name is required') + .test( + 'is-not-too-long', + 'soName too long', + (value) => value !== undefined && value.length < 32 + ), + optionExpirationUnixSeconds: yup + .number() + .typeError('Expiration is required') + .test( + 'expiration', + 'Expiration must be a future unix seconds timestamp', + function (val: number) { + const nowUnixMs = Date.now() / 1_000 + // Primary goal is to catch users inputting ms instead of sec. + if (val > nowUnixMs * 10) { + return this.createError({ + message: `Please select a valid unix seconds timestamp`, + }) + } + if (val < nowUnixMs) { + return this.createError({ + message: `Please select a time in the future`, + }) + } + return true + } + ), + numTokens: yup + .string() + .typeError('Num tokens is required') + .test('amount', 'amount', async function (val: string) { + if (!form.baseTreasury) { + return this.createError({ + message: `Please select a treasury`, + }) + } + const numAtomsInTreasury = new BN( + form.baseTreasury.extensions.token.account.amount + ) + if (numAtomsInTreasury.lt(new BN(val))) { + return this.createError({ + message: `Not enough tokens`, + }) + } + return true + }), + strike: yup.number().typeError('strike is required'), + lotSize: yup.number().typeError('lotSize is required'), + baseTreasury: yup.object().typeError('baseTreasury is required'), + quoteTreasury: yup.object().typeError('quoteTreasury is required'), + payer: yup.object().typeError('payer is required'), + subscriptionPeriodEnd: yup + .number() + .typeError('subscriptionPeriodEnd is required'), + lockupRatio: yup.number().typeError('lockupRatio is required'), + }) +} + +export const getDualFinanceInitStrikeSchema = () => { + return yup.object().shape({ + soName: yup.string().required('Staking option name is required'), + // TODO: Verify it is comma separated ints + strikes: yup.string().typeError('Strike is required'), + payer: yup.object().typeError('payer is required'), + baseTreasury: yup.object().typeError('baseTreasury is required'), + }) +} + +export const getDualFinanceExerciseSchema = () => { + return yup.object().shape({ + soName: yup.string().required('Staking option name is required'), + optionAccount: yup.object().required('Option account is required'), + numTokens: yup.number().typeError('Num tokens is required'), + baseTreasury: yup.object().typeError('baseTreasury is required'), + quoteTreasury: yup.object().typeError('quoteTreasury is required'), + }) +} + +export const getDualFinanceWithdrawSchema = () => { + return yup.object().shape({ + soName: yup.string().required('Staking option name is required'), + baseTreasury: yup.object().typeError('baseTreasury is required'), + mintPk: yup + .string() + .test('is-valid-address1', 'Please enter a valid PublicKey', (value) => + value ? validatePubkey(value) : true + ), + }) +} + +export const getDualFinanceGsoWithdrawSchema = () => { + return yup.object().shape({ + soName: yup.string().required('Staking option name is required'), + baseTreasury: yup.object().typeError('baseTreasury is required'), + }) +} + +export const getDualFinanceDelegateSchema = () => { + return yup.object().shape({ + delegateAccount: yup + .string() + .test('is-valid-address1', 'Please enter a valid PublicKey', (value) => + value ? validatePubkey(value) : true + ), + realm: yup + .string() + .test('is-valid-address1', 'Please enter a valid PublicKey', (value) => + value ? validatePubkey(value) : true + ), + token: yup.object().typeError('Delegate Token is required'), + }) +} + +export const getDualFinanceDelegateWithdrawSchema = () => { + return yup.object().shape({ + realm: yup + .string() + .test('is-valid-address1', 'Please enter a valid PublicKey', (value) => + value ? validatePubkey(value) : true + ), + token: yup.object().typeError('Delegate Token is required'), + }) +} + +export const getDualFinanceVoteDepositSchema = () => { + return yup.object().shape({ + numTokens: yup.number().typeError('Num tokens is required'), + realm: yup.string(), + token: yup.object().typeError('Delegate Token is required'), + }) +} + +export const getTokenTransferSchema = ({ + form, + connection, + tokenAmount, + mintDecimals, + nftMode, + ignoreAmount, +}: { + form: any + connection: ConnectionContext + tokenAmount?: BN + mintDecimals?: number + nftMode?: boolean + ignoreAmount?: boolean +}) => { const governedTokenAccount = form.governedTokenAccount as AssetAccount return yup.object().shape({ governedTokenAccount: yup.object().required('Source account is required'), @@ -255,8 +906,8 @@ export const getCastleDepositSchema = ({ form }) => { 'amount', 'Transfer amount must be less than the source account available amount', async function (val: number) { - const isNft = governedTokenAccount?.isNft - if (isNft) { + const isNft = nftMode || governedTokenAccount?.isNft + if (isNft || ignoreAmount) { return true } if (val && !form.governedTokenAccount) { @@ -271,8 +922,13 @@ export const getCastleDepositSchema = ({ form }) => { ) { const mintValue = getMintNaturalAmountFromDecimalAsBN( val, - governedTokenAccount?.extensions.mint.account.decimals + typeof mintDecimals !== 'undefined' + ? mintDecimals + : governedTokenAccount?.extensions.mint.account.decimals ) + if (tokenAmount) { + return tokenAmount.gte(mintValue) + } return !!(governedTokenAccount?.extensions.token?.publicKey && !governedTokenAccount.isSol ? governedTokenAccount.extensions.token.account.amount.gte( @@ -287,35 +943,73 @@ export const getCastleDepositSchema = ({ form }) => { }) } ), + destinationAccount: yup + .string() + .test( + 'accountTests', + 'Account validation error', + async function (val: string) { + if (val) { + try { + if ( + governedTokenAccount?.extensions?.transferAddress?.toBase58() == + val + ) { + return this.createError({ + message: `Destination account address can't be same as source account`, + }) + } + await validateDestinationAccAddress( + connection, + val, + governedTokenAccount?.extensions.transferAddress + ) + return true + } catch (e) { + console.log(e) + return this.createError({ + message: `${e}`, + }) + } + } else { + return this.createError({ + message: `Destination account is required`, + }) + } + } + ), }) } -export const getCastleWithdrawSchema = () => { - return yup.object().shape({ - governedTokenAccount: yup.object().required('Source account is required'), - amount: yup.number().typeError('Amount is required'), - }) -} - -export const getFriktionWithdrawSchema = () => { - return yup.object().shape({ - governedTokenAccount: yup.object().required('Source account is required'), - amount: yup.number().typeError('Amount is required'), - }) -} - -export const getGoblinGoldDepositSchema = ({ form }) => { +export const getBatchTokenTransferSchema = ({ + form, + connection, + tokenAmount, + mintDecimals, + nftMode, + ignoreAmount, +}: { + form: any + connection: ConnectionContext + tokenAmount?: BN + mintDecimals?: number + nftMode?: boolean + ignoreAmount?: boolean +}) => { const governedTokenAccount = form.governedTokenAccount as AssetAccount return yup.object().shape({ governedTokenAccount: yup.object().required('Source account is required'), - goblinGoldVaultId: yup.string().required('Vault ID is required'), - amount: yup - .number() + amount: yup.array().of( + yup.number() .typeError('Amount is required') .test( 'amount', 'Transfer amount must be less than the source account available amount', async function (val: number) { + const isNft = nftMode || governedTokenAccount?.isNft + if (isNft || ignoreAmount) { + return true + } if (val && !form.governedTokenAccount) { return this.createError({ message: `Please select source account to validate the amount`, @@ -324,12 +1018,17 @@ export const getGoblinGoldDepositSchema = ({ form }) => { if ( val && governedTokenAccount && - governedTokenAccount.extensions.mint + governedTokenAccount?.extensions.mint ) { const mintValue = getMintNaturalAmountFromDecimalAsBN( val, - governedTokenAccount?.extensions.mint.account.decimals + typeof mintDecimals !== 'undefined' + ? mintDecimals + : governedTokenAccount?.extensions.mint.account.decimals ) + if (tokenAmount) { + return tokenAmount.gte(mintValue) + } return !!(governedTokenAccount?.extensions.token?.publicKey && !governedTokenAccount.isSol ? governedTokenAccount.extensions.token.account.amount.gte( @@ -343,46 +1042,64 @@ export const getGoblinGoldDepositSchema = ({ form }) => { message: `Amount is required`, }) } + )), + destinationAccount: yup + .array().of( + yup + .string() + .test( + 'accountTests', + 'Account validation error', + async function (val: string) { + if (val) { + try { + if ( + governedTokenAccount?.extensions?.transferAddress?.toBase58() == + val + ) { + return this.createError({ + message: `Destination account address can't be same as source account`, + }) + } + await validateDestinationAccAddress( + connection, + val, + governedTokenAccount?.extensions.transferAddress + ) + return true + } catch (e) { + console.log(e) + return this.createError({ + message: `${e}`, + }) + } + } else { + return this.createError({ + message: `Destination account is required`, + }) + } + } + ) ), }) } -export const getGoblinGoldWithdrawSchema = () => { - return yup.object().shape({ - governedTokenAccount: yup.object().required('Source account is required'), - goblinGoldVaultId: yup.string().required('Vault ID is required'), - amount: yup.number().typeError('Amount is required'), - }) -} - -export const getFriktionClaimPendingDepositSchema = () => { - return yup.object().shape({ - governedTokenAccount: yup.object().required('Source account is required'), - }) -} - -export const getFriktionClaimPendingWithdrawSchema = () => { - return yup.object().shape({ - governedTokenAccount: yup.object().required('Source account is required'), - }) -} - -export const getTokenTransferSchema = ({ +export const getBurnTokensSchema = ({ form, - connection, tokenAmount, mintDecimals, nftMode, + ignoreAmount, }: { form: any - connection: ConnectionContext tokenAmount?: BN mintDecimals?: number nftMode?: boolean + ignoreAmount?: boolean }) => { const governedTokenAccount = form.governedTokenAccount as AssetAccount return yup.object().shape({ - governedTokenAccount: yup.object().required('Source account is required'), + governedTokenAccount: yup.object().required('Token account is required'), amount: yup .number() .typeError('Amount is required') @@ -391,7 +1108,7 @@ export const getTokenTransferSchema = ({ 'Transfer amount must be less than the source account available amount', async function (val: number) { const isNft = nftMode || governedTokenAccount?.isNft - if (isNft) { + if (isNft || ignoreAmount) { return true } if (val && !form.governedTokenAccount) { @@ -427,41 +1144,6 @@ export const getTokenTransferSchema = ({ }) } ), - destinationAccount: yup - .string() - .test( - 'accountTests', - 'Account validation error', - async function (val: string) { - if (val) { - try { - if ( - governedTokenAccount?.extensions?.transferAddress?.toBase58() == - val - ) { - return this.createError({ - message: `Destination account address can't be same as source account`, - }) - } - await validateDestinationAccAddress( - connection, - val, - governedTokenAccount?.extensions.transferAddress - ) - return true - } catch (e) { - console.log(e) - return this.createError({ - message: `${e}`, - }) - } - } else { - return this.createError({ - message: `Destination account is required`, - }) - } - } - ), }) } @@ -481,9 +1163,7 @@ export const getMintSchema = ({ form, connection }) => { val, form.mintAccount?.extensions.mint.account.decimals ) - return !!( - form.mintAccount.governance?.account.governedAccount && mintValue - ) + return !!(form.mintAccount.extensions.mint.publicKey && mintValue) } return this.createError({ message: `Amount is required`, @@ -501,7 +1181,7 @@ export const getMintSchema = ({ form, connection }) => { await validateDestinationAccAddressWithMint( connection, val, - form.mintAccount.governance.account.governedAccount + form.mintAccount.extensions.mint.publicKey ) } else { return this.createError({ @@ -517,7 +1197,7 @@ export const getMintSchema = ({ form, connection }) => { } } else { return this.createError({ - message: `Destination account is required`, + message: `Invalid destination account`, }) } } @@ -568,80 +1248,233 @@ export const getStakeSchema = ({ form }) => { }) } -export const getRealmCfgSchema = ({ form }) => { - return yup.object().shape({ - governedAccount: yup - .object() - .nullable() - .required('Governed account is required'), - minCommunityTokensToCreateGovernance: yup - .number() - .required('Min community tokens to create governance is required'), - communityVoterWeightAddin: yup - .string() - .test( - 'communityVoterWeightAddinTest', - 'communityVoterWeightAddin validation error', - function (val: string) { - if (!form?.communityVoterWeightAddin) { - return true - } - if (val) { - try { - getValidatedPublickKey(val) - if (supportedPlugins.includes(val)) { +// @asktree: It's odd that `form` would be an input both to the schema factory and the schema itself. +export const getRealmCfgSchema = ({ + form, + programVersion, +}: { + form: any + programVersion: number +}) => { + return programVersion >= 3 + ? yup.object().shape({ + governedAccount: yup + .object() + .nullable() + .required('Governed account is required'), + minCommunityTokensToCreateGovernance: yup + .number() + .required('Min community tokens to create governance is required'), + communityVoterWeightAddin: yup + .string() + .test( + 'communityVoterWeightAddinTest', + 'communityVoterWeightAddin validation error', + function (val: string) { + if (!form?.communityVoterWeightAddin) { return true + } + if (val) { + try { + getValidatedPublickKey(val) + if (supportedPlugins.includes(val)) { + return true + } else { + return this.createError({ + message: `Provided pubkey is not a known plugin pubkey`, + }) + } + } catch (e) { + console.log(e) + return this.createError({ + message: `${e}`, + }) + } } else { return this.createError({ - message: `Provided pubkey is not a known plugin pubkey`, + message: `communityVoterWeightAddin is required`, }) } - } catch (e) { - console.log(e) - return this.createError({ - message: `${e}`, - }) } - } else { - return this.createError({ - message: `communityVoterWeightAddin is required`, - }) - } - } - ), - maxCommunityVoterWeightAddin: yup - .string() - .test( - 'maxCommunityVoterWeightAddin', - 'maxCommunityVoterWeightAddin validation error', - function (val: string) { - if (!form?.maxCommunityVoterWeightAddin) { - return true - } - if (val) { - try { - getValidatedPublickKey(val) - if ([...nftPluginsPks].includes(val)) { + ), + maxCommunityVoterWeightAddin: yup + .string() + .test( + 'maxCommunityVoterWeightAddin', + 'maxCommunityVoterWeightAddin validation error', + function (val: string) { + if (!form?.maxCommunityVoterWeightAddin) { return true + } + if (val) { + try { + getValidatedPublickKey(val) + if ( + [...NFT_PLUGINS_PKS, ...HELIUM_VSR_PLUGINS_PKS].includes( + val + ) + ) { + return true + } else { + return this.createError({ + message: `Provided pubkey is not a known plugin pubkey`, + }) + } + } catch (e) { + console.log(e) + return this.createError({ + message: `${e}`, + }) + } } else { return this.createError({ - message: `Provided pubkey is not a known plugin pubkey`, + message: `maxCommunityVoterWeightAddin is required`, }) } - } catch (e) { - console.log(e) - return this.createError({ - message: `${e}`, - }) } - } else { - return this.createError({ - message: `maxCommunityVoterWeightAddin is required`, - }) - } - } - ), - }) + ), + councilVoterWeightAddin: yup + .string() + .test( + 'councilVoterWeightAddinTest', + 'councilVoterWeightAddin validation error', + function (val: string) { + if (!form?.councilVoterWeightAddin) { + return true + } + if (val) { + try { + getValidatedPublickKey(val) + if (supportedPlugins.includes(val)) { + return true + } else { + return this.createError({ + message: `Provided pubkey is not a known plugin pubkey`, + }) + } + } catch (e) { + console.log(e) + return this.createError({ + message: `${e}`, + }) + } + } else { + return this.createError({ + message: `councilVoterWeightAddin is required`, + }) + } + } + ), + maxCouncilVoterWeightAddin: yup + .string() + .test( + 'maxCouncilVoterWeightAddin', + 'maxCouncilVoterWeightAddin validation error', + function (val: string) { + if (!form?.maxCouncilVoterWeightAddin) { + return true + } + if (val) { + try { + getValidatedPublickKey(val) + if ([...NFT_PLUGINS_PKS].includes(val)) { + return true + } else { + return this.createError({ + message: `Provided pubkey is not a known plugin pubkey`, + }) + } + } catch (e) { + console.log(e) + return this.createError({ + message: `${e}`, + }) + } + } else { + return this.createError({ + message: `maxCouncilVoterWeightAddin is required`, + }) + } + } + ), + }) + : yup.object().shape({ + governedAccount: yup + .object() + .nullable() + .required('Governed account is required'), + minCommunityTokensToCreateGovernance: yup + .number() + .required('Min community tokens to create governance is required'), + communityVoterWeightAddin: yup + .string() + .test( + 'communityVoterWeightAddinTest', + 'communityVoterWeightAddin validation error', + function (val: string) { + if (!form?.communityVoterWeightAddin) { + return true + } + if (val) { + try { + getValidatedPublickKey(val) + if (supportedPlugins.includes(val)) { + return true + } else { + return this.createError({ + message: `Provided pubkey is not a known plugin pubkey`, + }) + } + } catch (e) { + console.log(e) + return this.createError({ + message: `${e}`, + }) + } + } else { + return this.createError({ + message: `communityVoterWeightAddin is required`, + }) + } + } + ), + maxCommunityVoterWeightAddin: yup + .string() + .test( + 'maxCommunityVoterWeightAddin', + 'maxCommunityVoterWeightAddin validation error', + function (val: string) { + if (!form?.maxCommunityVoterWeightAddin) { + return true + } + if (val) { + try { + getValidatedPublickKey(val) + if ( + [...NFT_PLUGINS_PKS, ...HELIUM_VSR_PLUGINS_PKS].includes( + val + ) + ) { + return true + } else { + return this.createError({ + message: `Provided pubkey is not a known plugin pubkey`, + }) + } + } catch (e) { + console.log(e) + return this.createError({ + message: `${e}`, + }) + } + } else { + return this.createError({ + message: `maxCommunityVoterWeightAddin is required`, + }) + } + } + ), + }) } export const getCreateTokenMetadataSchema = () => { diff --git a/utils/wallet-adapters/index.ts b/utils/wallet-adapters/index.ts index a7a3cdd864..c14f05d94a 100644 --- a/utils/wallet-adapters/index.ts +++ b/utils/wallet-adapters/index.ts @@ -5,46 +5,109 @@ import { TorusWalletAdapter } from '@solana/wallet-adapter-torus' import { GlowWalletAdapter } from '@solana/wallet-adapter-glow' import { BackpackWalletAdapter } from '@solana/wallet-adapter-backpack' import { ExodusWalletAdapter } from '@solana/wallet-adapter-exodus' +import { WalletConnectWalletAdapter } from '@solana/wallet-adapter-walletconnect' +import { + createDefaultAddressSelector, + createDefaultAuthorizationResultCache, + createDefaultWalletNotFoundHandler, + SolanaMobileWalletAdapter, +} from '@solana-mobile/wallet-adapter-mobile' +import { + WalletAdapterNetwork, + WalletReadyState, +} from '@solana/wallet-adapter-base' + +const BACKPACK_PROVIDER = { + name: 'Backpack', + url: 'https://www.backpack.app/', + adapter: new BackpackWalletAdapter(), +} + +const EXODUS_PROVIDER = { + name: 'Exodus', + url: 'https://www.exodus.com/', + adapter: new ExodusWalletAdapter(), +} + +const GLOW_PROVIDER = { + name: 'Glow', + url: 'https://glow.app', + adapter: new GlowWalletAdapter(), +} + +const MOBILE_WALLET_PROVIDER = { + name: 'Mobile Wallet Adapter', + url: 'https://solanamobile.com/wallets', + adapter: new SolanaMobileWalletAdapter({ + addressSelector: createDefaultAddressSelector(), + appIdentity: { + icon: '/img/logo-realms.png', + name: 'Realms', + uri: 'https://app.realms.today', + }, + authorizationResultCache: createDefaultAuthorizationResultCache(), + // FIXME: Find a way to toggle this when the application is set to devnet. + cluster: 'mainnet-beta', + onWalletNotFound: createDefaultWalletNotFoundHandler(), + }), +} + +const PHANTOM_PROVIDER = { + name: 'Phantom', + url: 'https://phantom.app', + adapter: new PhantomWalletAdapter(), +} + +const SOLFLARE_PROVIDER = { + name: 'Solflare', + url: 'https://solflare.com', + adapter: new SolflareWalletAdapter(), +} + +const SOLLET_PROVIDER = { + name: 'Sollet.io', + url: 'https://www.sollet.io', + adapter: new SolletWalletAdapter({ provider: 'https://www.sollet.io' }), +} + +const TORUS_PROVIDER = { + name: 'Torus', + url: 'https://tor.us', + adapter: new TorusWalletAdapter(), +} + +const WALLET_CONNECT = { + name: 'Wallet Connect', + url: 'https://walletconnect.com/', + adapter: new WalletConnectWalletAdapter({ + // TODO make network dynamic + network: WalletAdapterNetwork.Mainnet, + options: { + projectId: '59618f8645f135f20f975e83f4ef0743', + metadata: { + name: 'Realms', + description: + 'Powered by Solana, Realms is a hub for communities to share ideas, make decisions, and collectively manage treasuries.', + url: 'https://app.realms.today/img/logo-realms.png', + icons: ['https://app.realms.today'], + }, + }, + }), +} export const WALLET_PROVIDERS = [ - { - name: 'Phantom', - url: 'https://phantom.app', - adapter: new PhantomWalletAdapter(), - }, - { - name: 'Backpack', - url: 'https://www.backpack.app/', - adapter: new BackpackWalletAdapter(), - }, - { - name: 'Torus', - url: 'https://tor.us', - adapter: new TorusWalletAdapter(), - }, - { - name: 'Glow', - url: 'https://glow.app', - adapter: new GlowWalletAdapter(), - }, - { - name: 'Solflare', - url: 'https://solflare.com', - adapter: new SolflareWalletAdapter(), - }, - { - name: 'Sollet.io', - url: 'https://www.sollet.io', - adapter: new SolletWalletAdapter({ provider: 'https://www.sollet.io' }), - }, - { - name: 'Exodus', - url: 'https://www.exodus.com/', - adapter: new ExodusWalletAdapter(), - }, + MOBILE_WALLET_PROVIDER, + PHANTOM_PROVIDER, + BACKPACK_PROVIDER, + TORUS_PROVIDER, + GLOW_PROVIDER, + SOLFLARE_PROVIDER, + SOLLET_PROVIDER, + EXODUS_PROVIDER, + WALLET_CONNECT, ] -export const DEFAULT_PROVIDER = WALLET_PROVIDERS[0] - -export const getWalletProviderByUrl = (urlOrNull) => - WALLET_PROVIDERS.find(({ url }) => url === urlOrNull) || DEFAULT_PROVIDER +export const DEFAULT_PROVIDER = + MOBILE_WALLET_PROVIDER.adapter.readyState !== WalletReadyState.Unsupported + ? MOBILE_WALLET_PROVIDER + : PHANTOM_PROVIDER diff --git a/verify-wallet/.eslintrc.json b/verify-wallet/.eslintrc.json new file mode 100644 index 0000000000..6683913c25 --- /dev/null +++ b/verify-wallet/.eslintrc.json @@ -0,0 +1,44 @@ +{ + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "tsconfig.json", + "tsconfigRootDir": ".", + "sourceType": "module" + }, + "plugins": ["@typescript-eslint/eslint-plugin", "import"], + "extends": [ + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended" + ], + "root": true, + "env": { + "node": true, + "jest": true + }, + "ignorePatterns": [".eslintrc.js", "migrations"], + "rules": { + "@typescript-eslint/interface-name-prefix": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-empty-interface": "off", + "import/order": [ + "error", + { + "newlines-between": "always-and-inside-groups", + "pathGroupsExcludedImportTypes": ["builtin"], + "pathGroups": [ + { + "pattern": "@hub/**/**", + "group": "parent" + } + ], + "alphabetize": { + "order": "asc", + "caseInsensitive": true + } + } + ] + } +} diff --git a/verify-wallet/.prettierrc b/verify-wallet/.prettierrc new file mode 100644 index 0000000000..c29a1e1f0e --- /dev/null +++ b/verify-wallet/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "quoteProps": "consistent" +} diff --git a/verify-wallet/components/footer.tsx b/verify-wallet/components/footer.tsx new file mode 100644 index 0000000000..19b89c6b26 --- /dev/null +++ b/verify-wallet/components/footer.tsx @@ -0,0 +1,52 @@ +import cx from '@hub/lib/cx'; + +interface Props { + className?: string; +} + +export function GlobalFooter(props: Props) { + const year = new Date().getFullYear(); + return ( +

+ ); +} diff --git a/verify-wallet/components/gql.ts b/verify-wallet/components/gql.ts new file mode 100644 index 0000000000..e6016d773d --- /dev/null +++ b/verify-wallet/components/gql.ts @@ -0,0 +1,18 @@ +import * as IT from 'io-ts'; +import { gql } from 'urql'; + +const VerifyWalletResponse = IT.type({ + publicKey: IT.string, +}); + +export const verifyWallet = gql` + mutation($code: String!, $application: DiscordApplication = SOLANA) { + verifyWallet(code: $code, application: $application) { + publicKey + } + } +`; + +export const verifyWalletResp = IT.type({ + verifyWallet: VerifyWalletResponse, +}); diff --git a/verify-wallet/components/index.tsx b/verify-wallet/components/index.tsx new file mode 100644 index 0000000000..3c4f972714 --- /dev/null +++ b/verify-wallet/components/index.tsx @@ -0,0 +1,61 @@ +import { GlobalFooter } from '@verify-wallet/components/footer'; +import { StepOne } from '@verify-wallet/components/step-one'; +import { StepThree } from '@verify-wallet/components/step-three'; +import { StepTwo } from '@verify-wallet/components/step-two'; +import { Application } from '@verify-wallet/constants'; + +import { useJWT } from '@hub/hooks/useJWT'; +import cx from '@hub/lib/cx'; + +enum VerifyWalletSteps { + SIGN_IN_WITH_SOLANA, // Step one + AUTHORIZE_DISCORD_OAUTH, // Step two + UPDATE_DISCORD_METADATA, // Step three +} + +const getCurrentStep = (jwt: string | null, oauthCode: string | null) => { + if (jwt) { + if (oauthCode) { + return VerifyWalletSteps.UPDATE_DISCORD_METADATA; + } else { + return VerifyWalletSteps.AUTHORIZE_DISCORD_OAUTH; + } + } + return VerifyWalletSteps.SIGN_IN_WITH_SOLANA; +}; + +interface Props { + application: Application; + discordCode: string | null; +} + +const VerifyWallet = (props: Props) => { + const [jwt] = useJWT(); + + const currentStep = getCurrentStep(jwt, props.discordCode); + + return ( + <> +
+
+
+ {currentStep === VerifyWalletSteps.SIGN_IN_WITH_SOLANA && ( + + )} + {currentStep === VerifyWalletSteps.AUTHORIZE_DISCORD_OAUTH && ( + + )} + {currentStep === VerifyWalletSteps.UPDATE_DISCORD_METADATA && ( + + )} +
+
+
+ + + ); +}; + +export default VerifyWallet; diff --git a/verify-wallet/components/sign-in-with-solana.tsx b/verify-wallet/components/sign-in-with-solana.tsx new file mode 100644 index 0000000000..e120f136b6 --- /dev/null +++ b/verify-wallet/components/sign-in-with-solana.tsx @@ -0,0 +1,108 @@ +import * as IT from 'io-ts'; +import { gql } from 'urql'; + +import { SolanaLogo } from '@hub/components/branding/SolanaLogo'; +import { useJWT } from '@hub/hooks/useJWT'; +import { useMutation } from '@hub/hooks/useMutation'; +import { ToastType, useToast } from '@hub/hooks/useToast'; +import { useWallet } from '@hub/hooks/useWallet'; +import cx from '@hub/lib/cx'; + +import * as sig from '@hub/lib/signature'; +import * as RE from '@hub/types/Result'; + +const getClaim = gql` + mutation getClaim($publicKey: PublicKey!) { + createAuthenticationClaim(publicKey: $publicKey) { + claim + } + } +`; + +const getClaimResp = IT.type({ + createAuthenticationClaim: IT.type({ + claim: IT.string, + }), +}); + +const getToken = gql` + mutation getToken($claim: String!, $signature: Signature!) { + createAuthenticationToken(claim: $claim, signature: $signature) + } +`; + +const getTokenResp = IT.type({ + createAuthenticationToken: IT.string, +}); + +interface Props { + className?: string; +} + +export const SignInWithSolana = (props: Props) => { + const { connect, signMessage } = useWallet(); + const [, createClaim] = useMutation(getClaimResp, getClaim); + const [, createToken] = useMutation(getTokenResp, getToken); + const [, setJwt] = useJWT(); + const { publish } = useToast(); + + return ( + + ); +}; diff --git a/verify-wallet/components/step-one.tsx b/verify-wallet/components/step-one.tsx new file mode 100644 index 0000000000..575ad80e60 --- /dev/null +++ b/verify-wallet/components/step-one.tsx @@ -0,0 +1,60 @@ +import { SignInWithSolana as SignInWithSolanaButton } from '@verify-wallet/components/sign-in-with-solana'; + +import { Application } from '@verify-wallet/constants'; + +import { SolanaLogo } from '@hub/components/branding/SolanaLogo'; + +const DirectionRightIcon = () => ( + Right arrow +); + +const DiscordLogo = () => ( + Discord +); + +const MatchdayLogo = () => ( + Matchday +); + +interface Props { + application: Application; +} + +export const StepOne = (props: Props) => ( + <> +
+ {props.application === Application.SOLANA ? ( + + ) : ( + + )} + + +
+

+ Sign in with Solana to get your role in Discord. +

+

+ In order to add this role, follow the steps below to connect a Solana + wallet to your Discord account. +

+
+ +
+ +); diff --git a/verify-wallet/components/step-three.tsx b/verify-wallet/components/step-three.tsx new file mode 100644 index 0000000000..c8f465bc30 --- /dev/null +++ b/verify-wallet/components/step-three.tsx @@ -0,0 +1,131 @@ +import { XIcon } from '@heroicons/react/solid'; +import { Application } from '@verify-wallet/constants'; +import { useRouter } from 'next/router'; +import { useEffect, useState } from 'react'; + +import { SolanaLogo } from '@hub/components/branding/SolanaLogo'; +import { LoadingDots } from '@hub/components/LoadingDots'; +import { useMutation } from '@hub/hooks/useMutation'; +import * as RE from '@hub/types/Result'; + +import * as gqlWallet from './gql'; + +const ConnectedDiscordIcon = () => ( + Discord +); + +const ConnectedIcon = () => ( + Connected +); + +const MatchdayLogo = () => ( + Matchday +); + +enum VerifyWalletState { + FAILED, + VERIFYING, + VERIFIED, +} + +interface Props { + application: Application; +} + +export const StepThree = (props: Props) => { + const [, verifyWallet] = useMutation( + gqlWallet.verifyWalletResp, + gqlWallet.verifyWallet, + ); + const [status, setStatus] = useState(VerifyWalletState.VERIFYING); + const parsedLocationHash = new URLSearchParams( + window.location.search.substring(1), + ); + + const router = useRouter(); + + useEffect(() => { + const updateDiscordMetadata = async () => { + try { + const verifyWalletResult = await verifyWallet({ + code: parsedLocationHash.get('code'), + application: + props.application == Application.MATCHDAY ? 'MATCHDAY' : 'SOLANA', + }); + + if (RE.isFailed(verifyWalletResult)) { + // Likely an issue like the Discord code has already been used + setStatus(VerifyWalletState.FAILED); + console.error(verifyWalletResult.error); + setTimeout(() => { + router.push(window.location.pathname); + }, 5000); + throw verifyWalletResult.error; + } + + setStatus(VerifyWalletState.VERIFIED); + } catch (e) { + console.error(e); + } + }; + if (parsedLocationHash.get('code')) { + updateDiscordMetadata(); + } + }, [window.location.search]); + + if (status === VerifyWalletState.FAILED) { + return ( + <> + +

Something went wrong!

+

+ Retrying the connection to Discord... +

+ + ); + } else if (status === VerifyWalletState.VERIFYING) { + return ( + <> + +

+ Linking this wallet to your Discord account... +

+ + ); + } else { + return ( + <> +
+ {props.application === Application.MATCHDAY ? ( + + ) : ( + + )} + + +
+

+ Your new role awaits in Discord! +

+

+ You can safely close this tab and go back to Discord +

+ + ); + } +}; diff --git a/verify-wallet/components/step-two.tsx b/verify-wallet/components/step-two.tsx new file mode 100644 index 0000000000..d0c9eb7c9e --- /dev/null +++ b/verify-wallet/components/step-two.tsx @@ -0,0 +1,69 @@ +import { Application } from '@verify-wallet/constants'; + +const SolanaConnectedIcon = () => ( + Connected +); + +interface Props { + application: Application; +} + +export const StepTwo = (props: Props) => { + const DISCORD_CLIENT_ID = + props.application === Application.SOLANA + ? process.env.NEXT_PUBLIC_DISCORD_APPLICATION_CLIENT_ID! + : process.env.NEXT_PUBLIC_DISCORD_MATCHDAY_CLIENT_ID!; + + const discordRedirectURI = encodeURI( + `${window.location.protocol}//${window.location.host}${window.location.pathname}`, + ); + + const scopes = ['role_connections.write']; + if (props.application === Application.MATCHDAY) { + scopes.push('identify'); + } + + const DISCORD_AUTHORIZE_URL = `https://discord.com/api/oauth2/authorize?${new URLSearchParams( + { + client_id: DISCORD_CLIENT_ID, + redirect_uri: discordRedirectURI, + response_type: 'code', + scope: scopes.join(' '), + }, + )}`; + + return ( + <> + +

One more step...

+

+ Your Solana wallet has been verified, but you must link it with Discord + to finish. +

+ +

+ (This will open a new window) +

+ + ); +}; diff --git a/verify-wallet/constants.ts b/verify-wallet/constants.ts new file mode 100644 index 0000000000..3a055e844d --- /dev/null +++ b/verify-wallet/constants.ts @@ -0,0 +1,4 @@ +export enum Application { + SOLANA, + MATCHDAY, +} diff --git a/verify-wallet/tsconfig.json b/verify-wallet/tsconfig.json new file mode 100644 index 0000000000..20d5e2e03c --- /dev/null +++ b/verify-wallet/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "strict": true + } +} diff --git a/yarn.lock b/yarn.lock index 1ca16082e7..100510001d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,1549 +2,405 @@ # yarn lockfile v1 -"@aws-crypto/crc32@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-2.0.0.tgz#4ad432a3c03ec3087c5540ff6e41e6565d2dc153" - integrity sha512-TvE1r2CUueyXOuHdEigYjIZVesInd9KN+K/TFFNfkkxRThiNxO6i4ZqqAVMoEjAamZZ1AA8WXJkjCz7YShHPQA== - dependencies: - "@aws-crypto/util" "^2.0.0" - "@aws-sdk/types" "^3.1.0" - tslib "^1.11.1" - -"@aws-crypto/crc32c@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-2.0.0.tgz#4235336ef78f169f6a05248906703b9b78da676e" - integrity sha512-vF0eMdMHx3O3MoOXUfBZry8Y4ZDtcuskjjKgJz8YfIDjLStxTZrYXk+kZqtl6A0uCmmiN/Eb/JbC/CndTV1MHg== - dependencies: - "@aws-crypto/util" "^2.0.0" - "@aws-sdk/types" "^3.1.0" - tslib "^1.11.1" - -"@aws-crypto/ie11-detection@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-2.0.0.tgz#bb6c2facf8f03457e949dcf0921477397ffa4c6e" - integrity sha512-pkVXf/dq6PITJ0jzYZ69VhL8VFOFoPZLZqtU/12SGnzYuJOOGNfF41q9GxdI1yqC8R13Rq3jOLKDFpUJFT5eTA== - dependencies: - tslib "^1.11.1" - -"@aws-crypto/sha1-browser@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-2.0.0.tgz#71e735df20ea1d38f59259c4b1a2e00ca74a0eea" - integrity sha512-3fIVRjPFY8EG5HWXR+ZJZMdWNRpwbxGzJ9IH9q93FpbgCH8u8GHRi46mZXp3cYD7gealmyqpm3ThZwLKJjWJhA== - dependencies: - "@aws-crypto/ie11-detection" "^2.0.0" - "@aws-crypto/supports-web-crypto" "^2.0.0" - "@aws-sdk/types" "^3.1.0" - "@aws-sdk/util-locate-window" "^3.0.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-crypto/sha256-browser@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-2.0.0.tgz#741c9024df55ec59b51e5b1f5d806a4852699fb5" - integrity sha512-rYXOQ8BFOaqMEHJrLHul/25ckWH6GTJtdLSajhlqGMx0PmSueAuvboCuZCTqEKlxR8CQOwRarxYMZZSYlhRA1A== - dependencies: - "@aws-crypto/ie11-detection" "^2.0.0" - "@aws-crypto/sha256-js" "^2.0.0" - "@aws-crypto/supports-web-crypto" "^2.0.0" - "@aws-crypto/util" "^2.0.0" - "@aws-sdk/types" "^3.1.0" - "@aws-sdk/util-locate-window" "^3.0.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-crypto/sha256-js@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-2.0.0.tgz#f1f936039bdebd0b9e2dd834d65afdc2aac4efcb" - integrity sha512-VZY+mCY4Nmrs5WGfitmNqXzaE873fcIZDu54cbaDaaamsaTOP1DBImV9F4pICc3EHjQXujyE8jig+PFCaew9ig== - dependencies: - "@aws-crypto/util" "^2.0.0" - "@aws-sdk/types" "^3.1.0" - tslib "^1.11.1" - -"@aws-crypto/sha256-js@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-2.0.1.tgz#79e1e6cf61f652ef2089c08d471c722ecf1626a9" - integrity sha512-mbHTBSPBvg6o/mN/c18Z/zifM05eJrapj5ggoOIeHIWckvkv5VgGi7r/wYpt+QAO2ySKXLNvH2d8L7bne4xrMQ== - dependencies: - "@aws-crypto/util" "^2.0.1" - "@aws-sdk/types" "^3.1.0" - tslib "^1.11.1" - -"@aws-crypto/supports-web-crypto@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-2.0.0.tgz#fd6cde30b88f77d5a4f57b2c37c560d918014f9e" - integrity sha512-Ge7WQ3E0OC7FHYprsZV3h0QIcpdyJLvIeg+uTuHqRYm8D6qCFJoiC+edSzSyFiHtZf+NOQDJ1q46qxjtzIY2nA== - dependencies: - tslib "^1.11.1" - -"@aws-crypto/util@^2.0.0", "@aws-crypto/util@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-2.0.1.tgz#976cf619cf85084ca85ec5eb947a6ac6b8b5c98c" - integrity sha512-JJmFFwvbm08lULw4Nm5QOLg8+lAQeC8aCXK5xrtxntYzYXCGfHwUJ4Is3770Q7HmICsXthGQ+ZsDL7C2uH3yBQ== - dependencies: - "@aws-sdk/types" "^3.1.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-sdk/abort-controller@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.127.0.tgz#60c98bffdb185d8eb5d3e43f30f57a32cc8687d6" - integrity sha512-G77FLYcl9egUoD3ZmR6TX94NMqBMeT53hBGrEE3uVUJV1CwfGKfaF007mPpRZnIB3avnJBQGEK6MrwlCfv2qAw== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/chunked-blob-reader-native@3.109.0": - version "3.109.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/chunked-blob-reader-native/-/chunked-blob-reader-native-3.109.0.tgz#4db2ec81faf38fe33cf9dd6f75641afe0826dcfd" - integrity sha512-Ybn3vDZ3CqGyprL2qdF6QZqoqlx8lA3qOJepobjuKKDRw+KgGxjUY4NvWe0R2MdRoduyaDj6uvhIay0S1MOSJQ== - dependencies: - "@aws-sdk/util-base64-browser" "3.109.0" - tslib "^2.3.1" - -"@aws-sdk/chunked-blob-reader@3.55.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/chunked-blob-reader/-/chunked-blob-reader-3.55.0.tgz#db240c78e7c4c826e707f0ca32a4d221c41cf6a0" - integrity sha512-o/xjMCq81opAjSBjt7YdHJwIJcGVG5XIV9+C2KXcY5QwVimkOKPybWTv0mXPvSwSilSx+EhpLNhkcJuXdzhw4w== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/client-s3@^3.54.1": - version "3.131.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.131.0.tgz#6a193cfef008877028de0018f7b218191997bf5e" - integrity sha512-ue6uzk04pRJCJIaU1xKAW7Fx4TJx5n5Dwtycm0H94msj5HpJOfDKPoO9+kbywZywWP7n+eNnzNl/6lMjCSfO4g== - dependencies: - "@aws-crypto/sha1-browser" "2.0.0" - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/client-sts" "3.131.0" - "@aws-sdk/config-resolver" "3.130.0" - "@aws-sdk/credential-provider-node" "3.131.0" - "@aws-sdk/eventstream-serde-browser" "3.127.0" - "@aws-sdk/eventstream-serde-config-resolver" "3.127.0" - "@aws-sdk/eventstream-serde-node" "3.127.0" - "@aws-sdk/fetch-http-handler" "3.131.0" - "@aws-sdk/hash-blob-browser" "3.127.0" - "@aws-sdk/hash-node" "3.127.0" - "@aws-sdk/hash-stream-node" "3.127.0" - "@aws-sdk/invalid-dependency" "3.127.0" - "@aws-sdk/md5-js" "3.127.0" - "@aws-sdk/middleware-bucket-endpoint" "3.127.0" - "@aws-sdk/middleware-content-length" "3.127.0" - "@aws-sdk/middleware-expect-continue" "3.127.0" - "@aws-sdk/middleware-flexible-checksums" "3.127.0" - "@aws-sdk/middleware-host-header" "3.127.0" - "@aws-sdk/middleware-location-constraint" "3.127.0" - "@aws-sdk/middleware-logger" "3.127.0" - "@aws-sdk/middleware-recursion-detection" "3.127.0" - "@aws-sdk/middleware-retry" "3.127.0" - "@aws-sdk/middleware-sdk-s3" "3.127.0" - "@aws-sdk/middleware-serde" "3.127.0" - "@aws-sdk/middleware-signing" "3.130.0" - "@aws-sdk/middleware-ssec" "3.127.0" - "@aws-sdk/middleware-stack" "3.127.0" - "@aws-sdk/middleware-user-agent" "3.127.0" - "@aws-sdk/node-config-provider" "3.127.0" - "@aws-sdk/node-http-handler" "3.127.0" - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/signature-v4-multi-region" "3.130.0" - "@aws-sdk/smithy-client" "3.127.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/url-parser" "3.127.0" - "@aws-sdk/util-base64-browser" "3.109.0" - "@aws-sdk/util-base64-node" "3.55.0" - "@aws-sdk/util-body-length-browser" "3.55.0" - "@aws-sdk/util-body-length-node" "3.55.0" - "@aws-sdk/util-defaults-mode-browser" "3.127.0" - "@aws-sdk/util-defaults-mode-node" "3.130.0" - "@aws-sdk/util-stream-browser" "3.131.0" - "@aws-sdk/util-stream-node" "3.129.0" - "@aws-sdk/util-user-agent-browser" "3.127.0" - "@aws-sdk/util-user-agent-node" "3.127.0" - "@aws-sdk/util-utf8-browser" "3.109.0" - "@aws-sdk/util-utf8-node" "3.109.0" - "@aws-sdk/util-waiter" "3.127.0" - "@aws-sdk/xml-builder" "3.109.0" - entities "2.2.0" - fast-xml-parser "3.19.0" - tslib "^2.3.1" - -"@aws-sdk/client-sso@3.131.0": - version "3.131.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.131.0.tgz#2a1177854092a64e976720a7e69bbab0d72e0855" - integrity sha512-6fbjqLdVZF7mvGpHjWX5YsqBE/99MilNtGUFlwuf4/KnmYy49V16A6Dltnd43Hu6HVGxJ8caH9nCkIdNp3YZcQ== - dependencies: - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/config-resolver" "3.130.0" - "@aws-sdk/fetch-http-handler" "3.131.0" - "@aws-sdk/hash-node" "3.127.0" - "@aws-sdk/invalid-dependency" "3.127.0" - "@aws-sdk/middleware-content-length" "3.127.0" - "@aws-sdk/middleware-host-header" "3.127.0" - "@aws-sdk/middleware-logger" "3.127.0" - "@aws-sdk/middleware-recursion-detection" "3.127.0" - "@aws-sdk/middleware-retry" "3.127.0" - "@aws-sdk/middleware-serde" "3.127.0" - "@aws-sdk/middleware-stack" "3.127.0" - "@aws-sdk/middleware-user-agent" "3.127.0" - "@aws-sdk/node-config-provider" "3.127.0" - "@aws-sdk/node-http-handler" "3.127.0" - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/smithy-client" "3.127.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/url-parser" "3.127.0" - "@aws-sdk/util-base64-browser" "3.109.0" - "@aws-sdk/util-base64-node" "3.55.0" - "@aws-sdk/util-body-length-browser" "3.55.0" - "@aws-sdk/util-body-length-node" "3.55.0" - "@aws-sdk/util-defaults-mode-browser" "3.127.0" - "@aws-sdk/util-defaults-mode-node" "3.130.0" - "@aws-sdk/util-user-agent-browser" "3.127.0" - "@aws-sdk/util-user-agent-node" "3.127.0" - "@aws-sdk/util-utf8-browser" "3.109.0" - "@aws-sdk/util-utf8-node" "3.109.0" - tslib "^2.3.1" - -"@aws-sdk/client-sts@3.131.0": - version "3.131.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.131.0.tgz#5867be8c1e9cf71c9abad90e3a67c8d10a5aa89b" - integrity sha512-D9GAnF8n3VwFhaE+jxXH035ZZ24WxpY36DUxszCRwXbA7qFazY1BTs1WoKFr8tDH4/iUUqCXd8NuA1l4RiwnqQ== - dependencies: - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/config-resolver" "3.130.0" - "@aws-sdk/credential-provider-node" "3.131.0" - "@aws-sdk/fetch-http-handler" "3.131.0" - "@aws-sdk/hash-node" "3.127.0" - "@aws-sdk/invalid-dependency" "3.127.0" - "@aws-sdk/middleware-content-length" "3.127.0" - "@aws-sdk/middleware-host-header" "3.127.0" - "@aws-sdk/middleware-logger" "3.127.0" - "@aws-sdk/middleware-recursion-detection" "3.127.0" - "@aws-sdk/middleware-retry" "3.127.0" - "@aws-sdk/middleware-sdk-sts" "3.130.0" - "@aws-sdk/middleware-serde" "3.127.0" - "@aws-sdk/middleware-signing" "3.130.0" - "@aws-sdk/middleware-stack" "3.127.0" - "@aws-sdk/middleware-user-agent" "3.127.0" - "@aws-sdk/node-config-provider" "3.127.0" - "@aws-sdk/node-http-handler" "3.127.0" - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/smithy-client" "3.127.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/url-parser" "3.127.0" - "@aws-sdk/util-base64-browser" "3.109.0" - "@aws-sdk/util-base64-node" "3.55.0" - "@aws-sdk/util-body-length-browser" "3.55.0" - "@aws-sdk/util-body-length-node" "3.55.0" - "@aws-sdk/util-defaults-mode-browser" "3.127.0" - "@aws-sdk/util-defaults-mode-node" "3.130.0" - "@aws-sdk/util-user-agent-browser" "3.127.0" - "@aws-sdk/util-user-agent-node" "3.127.0" - "@aws-sdk/util-utf8-browser" "3.109.0" - "@aws-sdk/util-utf8-node" "3.109.0" - entities "2.2.0" - fast-xml-parser "3.19.0" - tslib "^2.3.1" - -"@aws-sdk/config-resolver@3.130.0": - version "3.130.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.130.0.tgz#ba0fa915fa5613e87051a9826531e59cab4387b1" - integrity sha512-7dkCHHI9kRcHW6YNr9/2Ub6XkvU9Fu6H/BnlKbaKlDR8jq7QpaFhPhctOVi5D/NDpxJgALifexFne0dvo3piTw== - dependencies: - "@aws-sdk/signature-v4" "3.130.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-config-provider" "3.109.0" - "@aws-sdk/util-middleware" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-env@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.127.0.tgz#06eb67461f7df8feb14abd3b459f682544d78e43" - integrity sha512-Ig7XhUikRBlnRTYT5JBGzWfYZp68X5vkFVIFCmsHHt/qVy0Nz9raZpmDHicdS1u67yxDkWgCPn/bNevWnM0GFg== - dependencies: - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-imds@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.127.0.tgz#1fc7b40bf21adcc2a897e47b72796bd8ebcc7d86" - integrity sha512-I6KlIBBzmJn/U1KikiC50PK3SspT9G5lkVLBaW5a6YfOcijqVTXfAN3kYzqhfeS0j4IgfJEwKVsjsZfmprJO5A== - dependencies: - "@aws-sdk/node-config-provider" "3.127.0" - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/url-parser" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-ini@3.131.0": - version "3.131.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.131.0.tgz#fa22aebeb65804b8ec1c4a7167292a80ea7d8131" - integrity sha512-0hA2ZwRUDmG5Wp/1t5BLvju2kZft1T3b3KC068ZY3t1+t/O46R6R9vINKEodohKTbfmGddu+aGY58Ai+N7O5Xw== - dependencies: - "@aws-sdk/credential-provider-env" "3.127.0" - "@aws-sdk/credential-provider-imds" "3.127.0" - "@aws-sdk/credential-provider-sso" "3.131.0" - "@aws-sdk/credential-provider-web-identity" "3.127.0" - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/shared-ini-file-loader" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-node@3.131.0": - version "3.131.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.131.0.tgz#df76ef73c90320121a9d63d3c85e1579d58b9125" - integrity sha512-nVQ6P91nd7i/G+iEnKWVwRRsQZIdY0qfza2+v70fOphjv0vzgDN7Xbn1GiYQVbxBiuxMSjQqg1r/p9PdRmt6QA== - dependencies: - "@aws-sdk/credential-provider-env" "3.127.0" - "@aws-sdk/credential-provider-imds" "3.127.0" - "@aws-sdk/credential-provider-ini" "3.131.0" - "@aws-sdk/credential-provider-process" "3.127.0" - "@aws-sdk/credential-provider-sso" "3.131.0" - "@aws-sdk/credential-provider-web-identity" "3.127.0" - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/shared-ini-file-loader" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-process@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.127.0.tgz#6046a20013a3edd58b631668ed1d73dfd63a931c" - integrity sha512-6v0m2lqkO9J5fNlTl+HjriQNIdfg8mjVST544+5y9EnC/FVmTnIz64vfHveWdNkP/fehFx7wTimNENtoSqCn3A== - dependencies: - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/shared-ini-file-loader" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-sso@3.131.0": - version "3.131.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.131.0.tgz#263694373bb9ee87d622d32a3e79d4e0ff4e9787" - integrity sha512-3LVan87e6NqnwUrpmjM5dbx8LbZyGG7Gdzf68YL0tZFptCFh1mR/kTJCToGX/hm7Jf3SRU3wtUWJ6G72yP72Sw== - dependencies: - "@aws-sdk/client-sso" "3.131.0" - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/shared-ini-file-loader" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-web-identity@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.127.0.tgz#a56c390bf0148f20573abd022930b28df345043a" - integrity sha512-85ahDZnLYB3dqkW+cQ0bWt+NVqOoxomTrJoq3IC2q6muebeFrJ0pyf0JEW/RNRzBiUvvsZujzGdWifzWyQKfVg== - dependencies: - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/eventstream-codec@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-codec/-/eventstream-codec-3.127.0.tgz#a51497e5dbd39edbfc68839bb6d2906654e716cd" - integrity sha512-+Tlujx3VkB4DK8tYzG0rwxIE0ee6hWItQgSEREEmi5CwHQFw7VpRLYAShYabEx9wIJmRFObWzhlKxWNRi+TfaA== - dependencies: - "@aws-crypto/crc32" "2.0.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-hex-encoding" "3.109.0" - tslib "^2.3.1" - -"@aws-sdk/eventstream-serde-browser@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-browser/-/eventstream-serde-browser-3.127.0.tgz#128f8822acaec7ec1b43a6aeab247a518f01e018" - integrity sha512-d1rTK4ljEp3Y/BQ78/AJ7eqgGyI6TE0bxNosCmXWcUBv00Tr5cerPqPe7Zvw8XwIMPX5y8cjtd1/cOtB2ePaBw== - dependencies: - "@aws-sdk/eventstream-serde-universal" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/eventstream-serde-config-resolver@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.127.0.tgz#2184d7441db1cf5909a7dd6720a224f7c2084740" - integrity sha512-dYvLfQYcKLOFtZVgwLwKDCykAxNkDyDLQRWytJK9DHCyjRig66IKi1codts9vOy4j0CeYwnXWs5WDavrUaE05g== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/eventstream-serde-node@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-node/-/eventstream-serde-node-3.127.0.tgz#cad3b376a4dd1634dfaa99b49519b0f2ccf09b46" - integrity sha512-Ie59jZYAIw3Kt6GePvEilp1k3JoYEQpY3WIyVZltm3dkVf0GmzhCZrPROH9vgF3qApzu1aGOWDV2wX91poXF8A== - dependencies: - "@aws-sdk/eventstream-serde-universal" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/eventstream-serde-universal@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/eventstream-serde-universal/-/eventstream-serde-universal-3.127.0.tgz#f0335cddbf55b8a3d5c5364cecac3f3c8bfbb212" - integrity sha512-cJLSTtYDGTevknMTykzHpcDNRbD6yGve8FBUKSAczuNVjXZOedj0GbHJqkASuLj0ZnojbKBdCx4uu1XGyvubng== - dependencies: - "@aws-sdk/eventstream-codec" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/fetch-http-handler@3.131.0": - version "3.131.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.131.0.tgz#426721ba3c4e7687a6c12ce10bdc661900325815" - integrity sha512-eNxmPZQX2IUeBGWHNC7eNTekWn9VIPLYEMKJbKYUBJryxuTJ7TtLeyEK5oakUjMwP1AUvWT+CV7C+8L7uG1omQ== - dependencies: - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/querystring-builder" "3.127.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-base64-browser" "3.109.0" - tslib "^2.3.1" - -"@aws-sdk/hash-blob-browser@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/hash-blob-browser/-/hash-blob-browser-3.127.0.tgz#5dc55800ecce69aed727d37bfd3241a6c12afec2" - integrity sha512-XH9s2w6GXCtDI+3/y+sDAzMWJRTvhRXJJtI1fVDsCiyq96SYUTNKLLaUSuR01uawEBiRDBqGDDPMT8qJPDXc/w== - dependencies: - "@aws-sdk/chunked-blob-reader" "3.55.0" - "@aws-sdk/chunked-blob-reader-native" "3.109.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/hash-node@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.127.0.tgz#2fbbeb509a515e6a5cfd6846c02cc1967961a40b" - integrity sha512-wx7DKlXdKebH4JcMsOevdsm2oDNMVm36kuMm0XWRIrFWQ/oq7OquDpEMJzWvGqWF/IfFUpb7FhAWZZpALwlcwA== - dependencies: - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-buffer-from" "3.55.0" - tslib "^2.3.1" - -"@aws-sdk/hash-stream-node@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/hash-stream-node/-/hash-stream-node-3.127.0.tgz#75ee97b86978de6227c4e24ae2563b5fcea97667" - integrity sha512-ZCNqi+FJViYFCo8JfSx+YK0Hd/SC555gHqBe24GVBMCDqJ8UFIled7tF+GOQ8wTcKjxuwp/0EXDTXoaAb0K89g== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/invalid-dependency@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.127.0.tgz#3a99603e1969f67278495b827243e9a391b8cfc4" - integrity sha512-bxvmtmJ6gIRfOHvh1jAPZBH2mzppEblPjEOFo4mOzXz4U3qPIxeuukCjboMnGK9QEpV2wObWcYYld0vxoRrfiA== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/is-array-buffer@3.55.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/is-array-buffer/-/is-array-buffer-3.55.0.tgz#c46122c5636f01d5895e5256a587768c3425ea7a" - integrity sha512-NbiPHVYuPxdqdFd6FxzzN3H1BQn/iWA3ri3Ry7AyLeP/tGs1yzEWMwf8BN8TSMALI0GXT6Sh0GDWy3Ok5xB6DA== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/md5-js@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/md5-js/-/md5-js-3.127.0.tgz#0fe0e8d86f734a0f2c9431e8305a4b7b8085c6a1" - integrity sha512-9FzD++p2bvfZ56hbDxvGcLlA9JIMt9uZB/m4NEvbuvrpx1qnUpFv6HqthhGaVuhctkK25hONT5ZpOYHSisATrA== - dependencies: - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-utf8-browser" "3.109.0" - "@aws-sdk/util-utf8-node" "3.109.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-bucket-endpoint@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.127.0.tgz#789ba99cc4f4100241406fdbb5c6a89226b4d6cf" - integrity sha512-wJpXxWceBDhWktoxrRb4s6tMx0dWsEGYIaV0KkQPGhTPk2KMUgwa4xApfCXXVfYcE3THk486OKwHhPrR5jpe+g== - dependencies: - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-arn-parser" "3.55.0" - "@aws-sdk/util-config-provider" "3.109.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-content-length@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.127.0.tgz#662c1971fdb2dd7d34a9945ebd8da52578900434" - integrity sha512-AFmMaIEW3Rzg0TaKB9l/RENLowd7ZEEOpm0trYw1CgUUORWW/ydCsDT7pekPlC25CPbhUmWXCSA4xPFSYOVnDw== - dependencies: - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-expect-continue@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.127.0.tgz#f67b3b9de34ac319958a8b3ae9f93026dc1a9f06" - integrity sha512-+X7mdgFqt9UqUDeGuMt+afR8CBX9nMecTxEIilAKdVOLx+fuXzHnC2mpddKMtiE9IGKMU4BI1Ahf7t32Odhs1Q== - dependencies: - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-flexible-checksums@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.127.0.tgz#8477b784b5db5b159427819c8411d406ad98a7ba" - integrity sha512-sXkAwhE9dikO72sEJ7DrUCo5mawauAxICCqipCCSGp0geSkptvtZHhySgJNMVSbUJQmu5bcS+zsFpFVwuJvGxg== - dependencies: - "@aws-crypto/crc32" "2.0.0" - "@aws-crypto/crc32c" "2.0.0" - "@aws-sdk/is-array-buffer" "3.55.0" - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-host-header@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.127.0.tgz#679f685bd8b4f221ed2c11e90b381d6904034ef9" - integrity sha512-e2gTLJb5lYP9lRV7hN3rKY2l4jv8OygOoHElZJ3Z8KPZskjHelYPcQ8XbdfhSXXxC3vc/0QqN0ResFt3W3Pplg== - dependencies: - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-location-constraint@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.127.0.tgz#8a1c6dd438b8cd80ffc86f3c393e5e0fbaba1ae8" - integrity sha512-UtPmbOKEVu+Ue7CwICFSOOOSePV8Piydco/v2IpdRkMO0e4bqQ3Tn0XprBlWWfSW4QCtAPzydrArLsUdk636GA== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-logger@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.127.0.tgz#b62fd148888f418bd74b0c9d76b80588224ee98f" - integrity sha512-jMNLcZB/ECA7OfkNBLNeAlrLRehyfnUeNQJHW3kcxs9h1+6VxaF6wY+WKozszLI7/3OBzQrFHBQCfRZV7ykSLg== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-recursion-detection@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.127.0.tgz#84949efd4a05a4d00da3e9242825e3c9d715f800" - integrity sha512-tB6WX+Z1kUKTnn5h38XFrTCzoqPKjUZLUjN4Wb27/cbeSiTSKGAZcCXHOJm36Ukorl5arlybQTqGe689EU00Hw== - dependencies: - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-retry@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.127.0.tgz#bcd0741ed676588101739083c6bd141d5c1911e1" - integrity sha512-ZSvg/AyGUacWnf3i8ZbyImtiCH+NyafF8uV7bITP7JkwPrG+VdNocJZOr88GRM0c1A0jfkOf7+oq+fInPwwiNA== - dependencies: - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/service-error-classification" "3.127.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-middleware" "3.127.0" - tslib "^2.3.1" - uuid "^8.3.2" - -"@aws-sdk/middleware-sdk-s3@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.127.0.tgz#3f6e5049480320ce121a8615dfe1b314c7f9a2ee" - integrity sha512-q1mkEN7kYYdQ3LOHIhaT56omYe8DCubyiCKOXuEo5ZiIkE5iq06K/BxWxj3f8bFZxSX80Ma1m8XA5jcOEMphSA== - dependencies: - "@aws-sdk/middleware-bucket-endpoint" "3.127.0" - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-arn-parser" "3.55.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-sdk-sts@3.130.0": - version "3.130.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.130.0.tgz#b8dc87c25db048ae8b91962459dfaec5d5b48a8f" - integrity sha512-FDfs7+ohbhEK3eH3Dshr6JDiL8P72bp3ffeNpPBXuURFqwt4pCmjHuX3SqQR0JIJ2cl3aIdxc17rKaZJfOjtPw== - dependencies: - "@aws-sdk/middleware-signing" "3.130.0" - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/signature-v4" "3.130.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-serde@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.127.0.tgz#8732d71ed0d28c43e609fcc156b1a1ac307c0d5f" - integrity sha512-xmWMYV/t9M+b9yHjqaD1noDNJJViI2QwOH7TQZ9VbbrvdVtDrFuS9Sf9He80TBCJqeHShwQN9783W1I3Pu/8kw== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-signing@3.130.0": - version "3.130.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.130.0.tgz#10c5606cf6cd32cf9afa857b0ff32659460902a7" - integrity sha512-JePq5XLR9TfRN3RQ0d7Za/bEW5D3xgtD1FNAwHeenWALeozMuQgRPjM5RroCnL/5jY3wuvCZI7cSXeqhawWqmA== - dependencies: - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/signature-v4" "3.130.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-ssec@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.127.0.tgz#e9dc757aee4ff301200845d5494154037519cc57" - integrity sha512-R5A13EvdYPdYD2Tq9eW5jqIdscyZlQykQXFEolBD2oi4pew7TZpc/5aazZC0zo9YKJ29qiUR1P4NvjcFJ7zFBg== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-stack@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.127.0.tgz#d569d964256cdd4a5afd149de325296cf19762f6" - integrity sha512-S1IoUE5o1vCmjsF5nIE8zlItNOM1UE+lhmZeigF7knXJ9+a6ewMB6POAj/s4eoi0wcn0eSnAGsqJCWMSUjOPLA== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/middleware-user-agent@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.127.0.tgz#f676aac4ddaba64bb12b6d69b0ed7328479cf798" - integrity sha512-CHxgswoOzdkOEoIq7Oyob3Sx/4FYUv6BhUesAX7MNshaDDsTQPbSWjw5bqZDiL/gO+X/34fvqCVVpVD2GvxW/g== - dependencies: - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/node-config-provider@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.127.0.tgz#43a460526f0c24a661264189712e0ff5475e9b45" - integrity sha512-bAHkASMhLZHT1yv2TX6OJGFV9Lc3t1gKfTMEKdXM2O2YhGfSx9A/qLeJm79oDfnILWQtSS2NicxlRDI2lYGf4g== - dependencies: - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/shared-ini-file-loader" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/node-http-handler@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.127.0.tgz#81c0a34061b233027bc673f3359c36555c0688d7" - integrity sha512-pyMKvheK8eDwWLgYIRsWy8wiyhsbYYcqkZQs3Eh6upI4E8iCY7eMmhWvHYCibvsO+UjsOwa4cAMOfwnv/Z9s8A== - dependencies: - "@aws-sdk/abort-controller" "3.127.0" - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/querystring-builder" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/property-provider@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.127.0.tgz#3b70d23354c35ea04c29c97f05cc4108c2e194ba" - integrity sha512-JxenxlTEkWfLrtJqIjaXaJzAVQbbscoCb5bNjmdud07ESLVfWRKJx2nAJdecHKYp2M5NQyqBuFhQ1ELSFYQKCA== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/protocol-http@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.127.0.tgz#c1d7bb20f09f9e86fd885d3effb33850b618e549" - integrity sha512-UG83PVuKX40wilG2uRU0Fvz4OY8Bt+bSPOG776DFjwIXYzK7BwpJm9H2XI2HLhS5WxrJHhwrLBRgW6UiykMnFw== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/querystring-builder@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.127.0.tgz#50a100d13bd13bb06ee92dcd9568e21a37fb9c49" - integrity sha512-tsoyp4lLPsASPDYWsezGAHD8VJsZbjUNATNAzTCFdH6p+4SKBK83Q5kfXCzxt13M+l3oKbxxIWLvS0kVQFyltQ== - dependencies: - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-uri-escape" "3.55.0" - tslib "^2.3.1" - -"@aws-sdk/querystring-parser@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.127.0.tgz#d485db0d24005e95bb4c9c478691cd805e5fc0f4" - integrity sha512-Vn/Dv+PqUSepp/DzLqq0LJJD8HdPefJCnLbO5WcHCARHSGlyGlZUFEM45k/oEHpTvgMXj/ORaP3A+tLwLu0AmA== - dependencies: - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/service-error-classification@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.127.0.tgz#64b69215b2525e3b6806856187ef54b00c0f85d1" - integrity sha512-wjZY9rnlA8SPrICUumTYicEKtK4/yKB62iadUk66hxe8MrH8JhuHH2NqIad0Pt/bK/YtNVhd3yb4pRapOeY5qQ== - -"@aws-sdk/shared-ini-file-loader@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.127.0.tgz#019c5512bf92f954f6aca6f6811e38fe048aadf6" - integrity sha512-S3Nn4KRTqoJsB/TbRZSWBBUrkckNMR0Juqz7bOB+wupVvddKP6IcpspSC/GX9zgJjVMV8iGisZ6AUsYsC5r+cA== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/signature-v4-multi-region@3.130.0": - version "3.130.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.130.0.tgz#bf56fd5235222377e3931961a21c86bfac74cb74" - integrity sha512-ZRRoPRoCVdkGDtjuog81pqHsSLfnXK6ELrWm4Dq8xdcHQGbEDNdYmeXARXG9yPAO42x9yIJXHNutMz5Y/P64cw== - dependencies: - "@aws-sdk/protocol-http" "3.127.0" - "@aws-sdk/signature-v4" "3.130.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-arn-parser" "3.55.0" - tslib "^2.3.1" - -"@aws-sdk/signature-v4@3.130.0": - version "3.130.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.130.0.tgz#152085234311610a350fdcd9a7f877a83aa44cf1" - integrity sha512-g5G1a1NHL2uOoFfC2zQdZcj+wbjgBQPkx6xGdtqNKf9v2kS0n6ap5JUGEaqWE02lUlmWHsoMsS73hXtzwXaBRQ== - dependencies: - "@aws-sdk/is-array-buffer" "3.55.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-hex-encoding" "3.109.0" - "@aws-sdk/util-middleware" "3.127.0" - "@aws-sdk/util-uri-escape" "3.55.0" - tslib "^2.3.1" - -"@aws-sdk/smithy-client@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.127.0.tgz#64bbdedc3f8ef8a9b908b109833c458f24f58a13" - integrity sha512-sfcAJ+7a41CJMtsv6HRIjA91155Yk013RvMUdG2EMSo3cpLq/QmTJ1EGw4ByDZs5HLpXAaRoLI+bA2ovriGQnQ== - dependencies: - "@aws-sdk/middleware-stack" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/types@3.127.0", "@aws-sdk/types@^3.1.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.127.0.tgz#a7bafc47ee2328eee2453087521e6c3a39e7278d" - integrity sha512-e0wtx2IkOl7rwfKfLH5pPTzQ+d45V7b1WrjeL0WDI8kOu6w+sXmhNxI6uM2kf0k4NiTLN84lW290AEWupey9Og== - -"@aws-sdk/url-parser@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.127.0.tgz#7a5c6186e83dc6f823c989c0575aebe384e676b0" - integrity sha512-njZ7zn41JHRpNfr3BCesVXCLZE0zcWSfEdtRV0ICw0cU1FgYcKELSuY9+gLUB4ci6uc7gq7mPE8+w30FcM4QeA== - dependencies: - "@aws-sdk/querystring-parser" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/util-arn-parser@3.55.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.55.0.tgz#6672eb2975e798a460bedfaf6b5618d4e4b262e1" - integrity sha512-76KJxp4MRWufHYWys7DFl64znr5yeJ3AIQNAPCKKw1sP0hzO7p6Kx0PaJnw9x+CPSzOrT4NbuApL6/srYhKDGg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-base64-browser@3.109.0": - version "3.109.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-base64-browser/-/util-base64-browser-3.109.0.tgz#e7faf5c4cbb88bc39b9c1c5a1a79e4c869e9f645" - integrity sha512-lAZ6fyDGiRLaIsKT9qh7P9FGuNyZ4gAbr1YOSQk/5mHtaTuUvxlPptZuInNM/0MPQm6lpcot00D8IWTucn4PbA== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-base64-node@3.55.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-base64-node/-/util-base64-node-3.55.0.tgz#da9a3fd6752be49163572144793e6b23d0186ff4" - integrity sha512-UQ/ZuNoAc8CFMpSiRYmevaTsuRKzLwulZTnM8LNlIt9Wx1tpNvqp80cfvVj7yySKROtEi20wq29h31dZf1eYNQ== - dependencies: - "@aws-sdk/util-buffer-from" "3.55.0" - tslib "^2.3.1" - -"@aws-sdk/util-body-length-browser@3.55.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.55.0.tgz#9c2637097501032f6a1afddb76687415fe9b44b6" - integrity sha512-Ei2OCzXQw5N6ZkTMZbamUzc1z+z1R1Ja5tMEagz5BxuX4vWdBObT+uGlSzL8yvTbjoPjnxWA2aXyEqaUP3JS8Q== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-body-length-node@3.55.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-node/-/util-body-length-node-3.55.0.tgz#67049bbb6c62d794a1bb5a13b9a678988c925489" - integrity sha512-lU1d4I+9wJwydduXs0SxSfd+mHKjxeyd39VwOv6i2KSwWkPbji9UQqpflKLKw+r45jL7+xU/zfeTUg5Tt/3Gew== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-buffer-from@3.55.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-buffer-from/-/util-buffer-from-3.55.0.tgz#e7c927974b07a29502aa1ad58509b91d0d7cf0f7" - integrity sha512-uVzKG1UgvnV7XX2FPTylBujYMKBPBaq/qFBxfl0LVNfrty7YjpfieQxAe6yRLD+T0Kir/WDQwGvYC+tOYG3IGA== - dependencies: - "@aws-sdk/is-array-buffer" "3.55.0" - tslib "^2.3.1" - -"@aws-sdk/util-config-provider@3.109.0": - version "3.109.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-config-provider/-/util-config-provider-3.109.0.tgz#7828b8894b2b23c289ffc5c106cbced7a5d6ee86" - integrity sha512-GrAZl/aBv0A28LkyNyq8SPJ5fmViCwz80fWLMeWx/6q5AbivuILogjlWwEZSvZ9zrlHOcFC0+AnCa5pQrjaslw== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-defaults-mode-browser@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.127.0.tgz#4fa9fe802e4296c0ab2e63a6a3c7c787ac5286df" - integrity sha512-e/vBm+EYSJ0R79591EPiCPE3aR5RKk5CjOkQjNxZIX8UPnIlo7xohTcebfR/iugSTxNrpfrFv+o4H5GjzAuhLA== - dependencies: - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/types" "3.127.0" - bowser "^2.11.0" - tslib "^2.3.1" - -"@aws-sdk/util-defaults-mode-node@3.130.0": - version "3.130.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.130.0.tgz#4347aeabccf7b3d04aecd7545e904781ac9c0be1" - integrity sha512-0BWx7C6GhHBrjPUuSgMnRA4InxYisX6MIGs5yIHk2OArYkQLJMdeORYXXz1y40ahMihmtjD/Ap5xQGBm2vyffA== - dependencies: - "@aws-sdk/config-resolver" "3.130.0" - "@aws-sdk/credential-provider-imds" "3.127.0" - "@aws-sdk/node-config-provider" "3.127.0" - "@aws-sdk/property-provider" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/util-hex-encoding@3.109.0": - version "3.109.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.109.0.tgz#93b20acc27c0a1d7d80f653bf19d3dd01c2ccc65" - integrity sha512-s8CgTNrn3cLkrdiohfxLuOYPCanzvHn/aH5RW6DaMoeQiG5Hl9QUiP/WtdQ9QQx3xvpQFpmvxIaSBwSgFNLQxA== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-locate-window@^3.0.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.55.0.tgz#a4136a20ee1bfcb73967a6614caf769ef79db070" - integrity sha512-0sPmK2JaJE2BbTcnvybzob/VrFKCXKfN4CUKcvn0yGg/me7Bz+vtzQRB3Xp+YSx+7OtWxzv63wsvHoAnXvgxgg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-middleware@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.127.0.tgz#266d6160886f272cb3e3c3eb5266abbac0c033bc" - integrity sha512-EwAPPed9TNqh+Wov2VStLn2NuJ/Wyt7IkZCbCsBuSNp3BFZ1V4gfwTjqtKCtB2LQgQ48MTgWgNCvrH0zjCSPGg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-stream-browser@3.131.0": - version "3.131.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-stream-browser/-/util-stream-browser-3.131.0.tgz#96c5e2c64ca3802e31760f47994a1b796a88cbed" - integrity sha512-1YFbBPDu+elIgp8z1woUfT7zM+2PAvgJiw6ljDBuAlJzsP5xMhwk0X9e+8aQ+Qe4XftA0e7y/PH0gqvjNgCx2A== - dependencies: - "@aws-sdk/fetch-http-handler" "3.131.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-base64-browser" "3.109.0" - "@aws-sdk/util-hex-encoding" "3.109.0" - "@aws-sdk/util-utf8-browser" "3.109.0" - tslib "^2.3.1" - -"@aws-sdk/util-stream-node@3.129.0": - version "3.129.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-stream-node/-/util-stream-node-3.129.0.tgz#e4c11674aeab5aa37a83748f4045944fdd736be0" - integrity sha512-1iWqsWvVXyP4JLPPPs8tBZKyzs7D5e7KctXuCtIjI+cnGOCeVLL+X4L/7KDZfV7sI2D6vONtIoTnUjMl5V/kEg== - dependencies: - "@aws-sdk/node-http-handler" "3.127.0" - "@aws-sdk/types" "3.127.0" - "@aws-sdk/util-buffer-from" "3.55.0" - tslib "^2.3.1" - -"@aws-sdk/util-uri-escape@3.55.0": - version "3.55.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-uri-escape/-/util-uri-escape-3.55.0.tgz#ee57743c628a1c9f942dfe73205ce890ec011916" - integrity sha512-mmdDLUpFCN2nkfwlLdOM54lTD528GiGSPN1qb8XtGLgZsJUmg3uJSFIN2lPeSbEwJB3NFjVas/rnQC48i7mV8w== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-user-agent-browser@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.127.0.tgz#dc6c4c9049ebf238c321883593b2cd3d82b5e755" - integrity sha512-uO2oHmJswuYKJS+GiMdYI8izhpC9M7/jFFvnAmLlTEVwpEi1VX9KePAOF+u5AaBC2kzITo/7dg141XfRHZloIQ== - dependencies: - "@aws-sdk/types" "3.127.0" - bowser "^2.11.0" - tslib "^2.3.1" - -"@aws-sdk/util-user-agent-node@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.127.0.tgz#368dc0c0e1160e8ca9e5ca21f3857004509aa06e" - integrity sha512-3P/M4ZDD2qMeeoCk7TE/Mw7cG5IjB87F6BP8nI8/oHuaz7j6fsI7D49SNpyjl8JApRynZ122Ad6hwQwRj3isYw== - dependencies: - "@aws-sdk/node-config-provider" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/util-utf8-browser@3.109.0", "@aws-sdk/util-utf8-browser@^3.0.0": - version "3.109.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.109.0.tgz#d013272e1981b23a4c84ac06f154db686c0cf84e" - integrity sha512-FmcGSz0v7Bqpl1SE8G1Gc0CtDpug+rvqNCG/szn86JApD/f5x8oByjbEiAyTU2ZH2VevUntx6EW68ulHyH+x+w== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-utf8-node@3.109.0": - version "3.109.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-node/-/util-utf8-node-3.109.0.tgz#89e06d916f5b246c7265f59bac742973ac0767ac" - integrity sha512-Ti/ZBdvz2eSTElsucjzNmzpyg2MwfD1rXmxD0hZuIF8bPON/0+sZYnWd5CbDw9kgmhy28dmKue086tbZ1G0iLQ== - dependencies: - "@aws-sdk/util-buffer-from" "3.55.0" - tslib "^2.3.1" - -"@aws-sdk/util-waiter@3.127.0": - version "3.127.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.127.0.tgz#3485ebb614cc417fee397daf61ba4ca3aa5bbedb" - integrity sha512-E5qrRpBJS8dmClqSDW1pWVMKzCG/mxabG6jVUtlW/WLHnl/znxGaOQc6tnnwKik0nEq/4DpT9fEfPUz9JiLrkw== - dependencies: - "@aws-sdk/abort-controller" "3.127.0" - "@aws-sdk/types" "3.127.0" - tslib "^2.3.1" - -"@aws-sdk/xml-builder@3.109.0": - version "3.109.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.109.0.tgz#dd2d3bf59d29a1c2968f477ec16680d47d81d921" - integrity sha512-+aAXynnrqya1Eukz4Gxch4xIXCZolIMWGD4Ll/Q5yXT5uAjGh2HQWd9J0LWE+gYChpWetZbAVYZ3cEJ6F+SpZA== - dependencies: - tslib "^2.3.1" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz" - dependencies: - "@babel/highlight" "^7.12.13" +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== -"@babel/code-frame@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz" - integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== dependencies: - "@babel/highlight" "^7.16.0" - -"@babel/compat-data@^7.13.15": - version "7.13.15" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.15.tgz" - -"@babel/compat-data@^7.16.0": - version "7.16.4" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz" - integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q== + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" -"@babel/core@^7.1.0", "@babel/core@^7.7.5": - version "7.13.16" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.13.16.tgz" - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.13.16" - "@babel/helper-compilation-targets" "^7.13.16" - "@babel/helper-module-transforms" "^7.13.14" - "@babel/helpers" "^7.13.16" - "@babel/parser" "^7.13.16" - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.13.15" - "@babel/types" "^7.13.16" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - source-map "^0.5.0" - -"@babel/core@^7.7.2": - version "7.16.5" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.16.5.tgz" - integrity sha512-wUcenlLzuWMZ9Zt8S0KmFwGlH6QKRh3vsm/dhDA3CHkiTA45YuG1XkHRcNRl73EFPXDp/d5kVOU0/y7x2w6OaQ== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/generator" "^7.16.5" - "@babel/helper-compilation-targets" "^7.16.3" - "@babel/helper-module-transforms" "^7.16.5" - "@babel/helpers" "^7.16.5" - "@babel/parser" "^7.16.5" - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.5" - "@babel/types" "^7.16.0" +"@apocentre/alias-sampling@^0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@apocentre/alias-sampling/-/alias-sampling-0.5.3.tgz#897ff181b48ad7b2bcb4ecf29400214888244f08" + integrity sha512-7UDWIIF9hIeJqfKXkNIzkVandlwLf1FWTSdrb9iXvOP8oF544JRXQjCbiTmCv2c9n44n/FIWtehhBfNuAx2CZA== + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + +"@babel/compat-data@^7.20.0": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.5.tgz#86f172690b093373a933223b4745deeb6049e733" + integrity sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.5.tgz#45e2114dc6cd4ab167f81daf7820e8fa1250d113" + integrity sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-module-transforms" "^7.20.2" + "@babel/helpers" "^7.20.5" + "@babel/parser" "^7.20.5" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.1.2" + json5 "^2.2.1" semver "^6.3.0" - source-map "^0.5.0" - -"@babel/generator@^7.13.16": - version "7.13.16" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.13.16.tgz" - dependencies: - "@babel/types" "^7.13.16" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.16.5", "@babel/generator@^7.7.2": - version "7.16.5" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.16.5.tgz" - integrity sha512-kIvCdjZqcdKqoDbVVdt5R99icaRtrtYhYK/xux5qiWCBmfdvEYMFZ68QCrpE5cbFM1JsuArUNs1ZkuKtTtUcZA== - dependencies: - "@babel/types" "^7.16.0" - jsesc "^2.5.1" - source-map "^0.5.0" -"@babel/generator@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d" - integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw== +"@babel/generator@^7.20.5", "@babel/generator@^7.23.0", "@babel/generator@^7.7.2": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" + integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== dependencies: - "@babel/types" "^7.18.2" - "@jridgewell/gen-mapping" "^0.3.0" + "@babel/types" "^7.23.0" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" - integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-compilation-targets@^7.13.16": - version "7.13.16" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz" - dependencies: - "@babel/compat-data" "^7.13.15" - "@babel/helper-validator-option" "^7.12.17" - browserslist "^4.14.5" - semver "^6.3.0" + "@babel/types" "^7.22.5" -"@babel/helper-compilation-targets@^7.16.3": - version "7.16.3" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz" - integrity sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA== +"@babel/helper-compilation-targets@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" + integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== dependencies: - "@babel/compat-data" "^7.16.0" - "@babel/helper-validator-option" "^7.14.5" - browserslist "^4.17.5" + "@babel/compat-data" "^7.20.0" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" semver "^6.3.0" -"@babel/helper-environment-visitor@^7.16.5": - version "7.16.5" - resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.5.tgz" - integrity sha512-ODQyc5AnxmZWm/R2W7fzhamOk1ey8gSguo5SGvF0zcB3uUzRpTRmM/jmLSm9bDMyPlvbyJ+PwPEK0BWIoZ9wjg== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-environment-visitor@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd" - integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ== - -"@babel/helper-function-name@^7.12.13": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz" - dependencies: - "@babel/helper-get-function-arity" "^7.12.13" - "@babel/template" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/helper-function-name@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz" - integrity sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog== - dependencies: - "@babel/helper-get-function-arity" "^7.16.0" - "@babel/template" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/helper-function-name@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12" - integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg== - dependencies: - "@babel/template" "^7.16.7" - "@babel/types" "^7.17.0" - -"@babel/helper-get-function-arity@^7.12.13": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz" - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-get-function-arity@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz" - integrity sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-hoist-variables@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz" - integrity sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-member-expression-to-functions@^7.13.12": - version "7.13.12" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz" - dependencies: - "@babel/types" "^7.13.12" - -"@babel/helper-module-imports@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.13.12": - version "7.13.12" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz" - dependencies: - "@babel/types" "^7.13.12" - -"@babel/helper-module-imports@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz" - integrity sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-module-transforms@^7.13.14": - version "7.13.14" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz" - dependencies: - "@babel/helper-module-imports" "^7.13.12" - "@babel/helper-replace-supers" "^7.13.12" - "@babel/helper-simple-access" "^7.13.12" - "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/helper-validator-identifier" "^7.12.11" - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.13.13" - "@babel/types" "^7.13.14" - -"@babel/helper-module-transforms@^7.16.5": - version "7.16.5" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.5.tgz" - integrity sha512-CkvMxgV4ZyyioElFwcuWnDCcNIeyqTkCm9BxXZi73RR1ozqlpboqsbGUNvRTflgZtFbbJ1v5Emvm+lkjMYY/LQ== - dependencies: - "@babel/helper-environment-visitor" "^7.16.5" - "@babel/helper-module-imports" "^7.16.0" - "@babel/helper-simple-access" "^7.16.0" - "@babel/helper-split-export-declaration" "^7.16.0" - "@babel/helper-validator-identifier" "^7.15.7" - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.5" - "@babel/types" "^7.16.0" - -"@babel/helper-optimise-call-expression@^7.12.13": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz" - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.8.0": - version "7.13.0" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz" - -"@babel/helper-plugin-utils@^7.16.5": - version "7.16.5" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.5.tgz" - integrity sha512-59KHWHXxVA9K4HNF4sbHCf+eJeFe0Te/ZFGqBT4OjXhrwvA04sGfaEGsVTdsjoszq0YTP49RC9UKe5g8uN2RwQ== - -"@babel/helper-replace-supers@^7.13.12": - version "7.13.12" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz" - dependencies: - "@babel/helper-member-expression-to-functions" "^7.13.12" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/traverse" "^7.13.0" - "@babel/types" "^7.13.12" - -"@babel/helper-simple-access@^7.13.12": - version "7.13.12" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz" - dependencies: - "@babel/types" "^7.13.12" - -"@babel/helper-simple-access@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz" - integrity sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-split-export-declaration@^7.12.13": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz" - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-split-export-declaration@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz" - integrity sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-identifier@^7.15.7": - version "7.15.7" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== - -"@babel/helper-validator-option@^7.12.17": - version "7.12.17" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz" - -"@babel/helper-validator-option@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz" - integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== - -"@babel/helpers@^7.13.16": - version "7.13.17" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.17.tgz" - dependencies: - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.13.17" - "@babel/types" "^7.13.17" - -"@babel/helpers@^7.16.5": - version "7.16.5" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.5.tgz" - integrity sha512-TLgi6Lh71vvMZGEkFuIxzaPsyeYCHQ5jJOOX1f0xXn0uciFuE8cEk0wyBquMcCxBXZ5BJhE2aUB7pnWTD150Tw== - dependencies: - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.5" - "@babel/types" "^7.16.0" +"@babel/helper-environment-visitor@^7.18.9", "@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6", "@babel/helper-module-imports@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" + integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-module-transforms@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" + integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.2" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-simple-access@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" + integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== + dependencies: + "@babel/types" "^7.20.2" + +"@babel/helper-split-export-declaration@^7.18.6", "@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + +"@babel/helper-validator-identifier@^7.19.1", "@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== -"@babel/highlight@^7.12.13", "@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== +"@babel/helpers@^7.20.5": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.6.tgz#e64778046b70e04779dfbdf924e7ebb45992c763" + integrity sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w== dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.5" + "@babel/types" "^7.20.5" -"@babel/highlight@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz" - integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== dependencies: - "@babel/helper-validator-identifier" "^7.15.7" - chalk "^2.0.0" + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.12.5", "@babel/parser@^7.13.16": - version "7.13.16" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.13.16.tgz" - -"@babel/parser@^7.16.0", "@babel/parser@^7.16.5", "@babel/parser@^7.7.2": - version "7.16.6" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.16.6.tgz" - integrity sha512-Gr86ujcNuPDnNOY8mi383Hvi8IYrJVJYuf3XcuBM/Dgd+bINn/7tHqsj+tKkoreMbmGsFLsltI/JJd8fOFWGDQ== - -"@babel/parser@^7.16.7": - version "7.16.12" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz" - integrity sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A== - -"@babel/parser@^7.18.5": - version "7.18.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.5.tgz#337062363436a893a2d22faa60be5bb37091c83c" - integrity sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.5", "@babel/parser@^7.14.7", "@babel/parser@^7.20.5", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-bigint@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.12.13": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz" +"@babel/plugin-syntax-jsx@^7.17.12", "@babel/plugin-syntax-jsx@^7.22.5", "@babel/plugin-syntax-jsx@^7.7.2": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918" + integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz" + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: - "@babel/helper-plugin-utils" "^7.12.13" + "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.16.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.5.tgz" - integrity sha512-/d4//lZ1Vqb4mZ5xTep3dDK888j7BGM/iKqBmndBaoYAFPlPKrGU608VVBz5JeyAb6YQDjRu1UKqj86UhwWVgw== + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/runtime-corejs3@^7.10.2": - version "7.13.17" - resolved "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.13.17.tgz" - dependencies: - core-js-pure "^3.0.0" - regenerator-runtime "^0.13.4" - -"@babel/runtime@7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.0.tgz#49dcbcd637099a55d3a61e590a00d6861393b1b5" - integrity sha512-2xsuyZ0R0RBFwjgae5NpXk8FcfH4qovj5cEM5VEeB7KXnKqzaisIu2HSV/mCEISolJJuR4wkViUGYujA8MH9tw== - dependencies: - regenerator-runtime "^0.13.2" - -"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.7", "@babel/runtime@^7.7.2", "@babel/runtime@^7.9.2": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" - integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.17.2": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580" - integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.17.9", "@babel/runtime@^7.6.2": - version "7.18.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4" - integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a" - integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.12.13", "@babel/template@^7.3.3": - version "7.12.13" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz" - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/parser" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/template@^7.14.5", "@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/template@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz" - integrity sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/parser" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.13", "@babel/traverse@^7.13.15", "@babel/traverse@^7.13.17": - version "7.13.17" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.17.tgz" - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.13.16" - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.13.16" - "@babel/types" "^7.13.17" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.16.5", "@babel/traverse@^7.7.2": - version "7.16.5" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.5.tgz" - integrity sha512-FOCODAzqUMROikDYLYxl4nmwiLlu85rNqBML/A5hKRVXG2LV8d0iMqgPzdYTcIpjZEBB7D6UDU9vxRZiriASdQ== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/generator" "^7.16.5" - "@babel/helper-environment-visitor" "^7.16.5" - "@babel/helper-function-name" "^7.16.0" - "@babel/helper-hoist-variables" "^7.16.0" - "@babel/helper-split-export-declaration" "^7.16.0" - "@babel/parser" "^7.16.5" - "@babel/types" "^7.16.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.4.5": - version "7.18.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.5.tgz#94a8195ad9642801837988ab77f36e992d9a20cd" - integrity sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.18.2" - "@babel/helper-environment-visitor" "^7.18.2" - "@babel/helper-function-name" "^7.17.9" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.18.5" - "@babel/types" "^7.18.4" + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.20.6.tgz#63dae945963539ab0ad578efbf3eff271e7067ae" + integrity sha512-tqeujPiuEfcH067mx+7otTQWROVMKHXEaOQcAeNV5dDdbPWvPcFA8/W9LXw2NfjNmOetqLl03dfnG2WALPlsRQ== + dependencies: + core-js-pure "^3.25.1" + regenerator-runtime "^0.13.11" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.2", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.4", "@babel/runtime@^7.22.6", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.9.2": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.6.tgz#c05e610dc228855dc92ef1b53d07389ed8ab521d" + integrity sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.14.5", "@babel/template@^7.18.10", "@babel/template@^7.22.15", "@babel/template@^7.3.3": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/traverse@>=7.23.2", "@babel/traverse@^7.20.1", "@babel/traverse@^7.20.5", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.13", "@babel/types@^7.13.12", "@babel/types@^7.13.14", "@babel/types@^7.13.16", "@babel/types@^7.13.17", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.13.17" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.13.17.tgz" - dependencies: - "@babel/helper-validator-identifier" "^7.12.11" - to-fast-properties "^2.0.0" - -"@babel/types@^7.16.0": - version "7.16.0" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz" - integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== - dependencies: - "@babel/helper-validator-identifier" "^7.15.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.16.7": - version "7.16.8" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz" - integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.17.0", "@babel/types@^7.18.2", "@babel/types@^7.18.4": - version "7.18.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.4.tgz#27eae9b9fd18e9dccc3f9d6ad051336f307be354" - integrity sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw== +"@babel/types@^7.0.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" + integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== dependencies: - "@babel/helper-validator-identifier" "^7.16.7" + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" - resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@blockworks-foundation/mango-client@3.4.5": - version "3.4.5" - resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-client/-/mango-client-3.4.5.tgz#9ba8e8450e7a834c4067885eef2c21dc1a7d4fb7" - integrity sha512-RQ8WAcUMKtV72TGZ3qLFqcZW17WbDyDMcnCZrzSHp0rWpuThXcKb17/YBJY7TugVRvc6JnV1aJtlibI/oF15Gw== +"@blockworks-foundation/mango-mints-redemption@0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-mints-redemption/-/mango-mints-redemption-0.0.11.tgz#5b33ec316007c34993a9be8f739af9cb94ebe322" + integrity sha512-kMY0e26xK5LxuLbdnCxexo2oHYT46nv+jNRMMzCDJn3z6JjiQpqYS2EpgvkSSSHa4MjJzonp377GxvYyIfeYxg== dependencies: - "@project-serum/anchor" "^0.21.0" - "@project-serum/serum" "0.13.55" - "@project-serum/sol-wallet-adapter" "^0.2.0" - "@solana/spl-token" "^0.1.6" - "@solana/web3.js" "^1.31.0" - big.js "^6.1.1" - bn.js "^5.1.0" - buffer-layout "^1.2.1" - cross-fetch "^3.1.5" - dotenv "^10.0.0" - toformat "^2.0.0" - yargs "^17.0.1" + "@coral-xyz/anchor" "^0.28.0" + "@solana/spl-token" "^0.3.8" + axios "^1.4.0" + keccak256 "^1.0.6" + merkletreejs "^0.3.11" -"@blockworks-foundation/mango-client@^3.6.14": - version "3.6.14" - resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-client/-/mango-client-3.6.14.tgz#00c46c815d78b20ffe0e9ef78ad3240c87bd49a4" - integrity sha512-uYjLXftjyfyOc6JYoRojTu7ZkbeboZqZhlpFm/7xl/dgg98KxQjRKyuHbdTdeAJCE9YtEUhKX2Cz5rVWDnWRlQ== +"@blockworks-foundation/mango-v4-settings@0.14.24": + version "0.14.24" + resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.14.24.tgz#646b0802fb6222654e247bea7966106af9b7a970" + integrity sha512-X3mY2x6XSZTySfB65b5DWuE7v/tffMlFGXQsgv+Zl+cgHdJn77vqdXvQFlR+544xsTjK+kWpWiHTHiSWRzG/4Q== dependencies: - "@project-serum/anchor" "^0.21.0" - "@project-serum/serum" "^0.13.65" - "@project-serum/sol-wallet-adapter" "^0.2.0" - "@solana/spl-token" "^0.1.6" - "@solana/web3.js" "^1.43.5" + bn.js "^5.2.1" + eslint-config-prettier "^9.0.0" + +"@blockworks-foundation/mango-v4@0.33.6": + version "0.33.6" + resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.33.6.tgz#d7aac0f1d0d2a647364188840261a78dd0e785dd" + integrity sha512-QC2mTprJ7/zrl+C61BPTZXdnvZD9HhhAQpadBxQ3BMtj8seoKTSC9RqKr+rq8GpxWVgALJcwXuxzOngu/Lr5LA== + dependencies: + "@blockworks-foundation/mango-v4-settings" "0.14.24" + "@blockworks-foundation/mangolana" "0.1.2" + "@coral-xyz/anchor" "^0.29.0" + "@eslint/eslintrc" "^3.1.0" + "@eslint/js" "^9.8.0" + "@iarna/toml" "2.2.5" + "@project-serum/serum" "0.13.65" + "@pythnetwork/client" "~2.21.1" + "@raydium-io/raydium-sdk" "^1.3.1-beta.57" + "@solana/spl-token" "0.4.8" + "@solana/web3.js" "^1.95.2" + "@switchboard-xyz/common" "^2.4.4" + "@switchboard-xyz/on-demand" "^1.2.38" + "@switchboard-xyz/sbv2-lite" "^0.1.6" + "@switchboard-xyz/solana.js" "^3.2.5" big.js "^6.1.1" - bn.js "^5.1.0" - buffer-layout "^1.2.1" + binance-api-node "^0.12.7" + bs58 "^5.0.0" cross-fetch "^3.1.5" - dotenv "^10.0.0" - toformat "^2.0.0" - yargs "^17.0.1" + dotenv "^16.0.3" + fast-copy "^3.0.1" + lodash "^4.17.21" + node-kraken-api "^2.2.2" + switchboard-anchor "npm:@coral-xyz/anchor@0.30.1" -"@blockworks-foundation/mango-v4@^0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.0.2.tgz#b1d812f9e7bc3d61fffcb722132343e9c700bd9b" - integrity sha512-xNyU5Ne/pz6H2u2VOCXGEj4opC2rdK2SrA4MsohfKbiubHtgXcpTDtRqGYrYy/kAw3PbV6w+Yc32mSgWTbNnPA== +"@blockworks-foundation/mangolana@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@blockworks-foundation/mangolana/-/mangolana-0.1.2.tgz#3b7ec1cd8a21c2fedd559dabb1e2212278a08ad4" + integrity sha512-eU+z1K29M6zzpAqwHcHCoZA+O4g+QPNM4PXsDygueZarqgsG6FehLoqWBV43w3uSFCl8Cb5op+fE/HufQ9xKww== dependencies: - "@project-serum/anchor" "^0.25.0" - "@project-serum/serum" "^0.13.65" - "@pythnetwork/client" "^2.7.0" - "@solana/spl-token" "^0.1.8" - big.js "^6.1.1" + "@solana/promises" "2.0.0-canary-20240812091942" + "@solana/web3.js" "^1.95.2" bs58 "^5.0.0" + isomorphic-ws "^5.0.0" + node-fetch "3.3.2" + ws "^8.18.0" -"@bonfida/aaob@^0.0.4": - version "0.0.4" - resolved "https://registry.yarnpkg.com/@bonfida/aaob/-/aaob-0.0.4.tgz#a79dbae9c182e38ccc1b0ef80f10755980e2e8ce" - integrity sha512-pjsFjzKCfydGFcCuLMR7kCYGtY9GJTpZNTN4RMC+gB7GJXjyb4D6xwOvkHO7qZ26P9Ug/bGBQIg4YW/VaVlrAQ== +"@blocto/sdk@^0.2.22": + version "0.2.22" + resolved "https://registry.yarnpkg.com/@blocto/sdk/-/sdk-0.2.22.tgz#c7fe62809de0640a0a3f7a043c5bbceb8be17e38" + integrity sha512-Ro1AiISSlOiri/It932NEFxnDuF83Ide+z0p3KHs5+CdYYLYgCMmyroQnfRtoh3mbXdrTvI+EAuSkr+meWNqrg== dependencies: - "@solana/spl-token" "0.1.5" - "@solana/web3.js" "^1.15.0" - bn.js "^5.1.3" - borsh "^0.6.0" - bs58 "4.0.1" + bs58 "^4.0.1" + buffer "^6.0.3" + eip1193-provider "^1.0.1" + js-sha3 "^0.8.0" "@bonfida/name-offers@^0.0.1": version "0.0.1" @@ -1558,23 +414,22 @@ borsh "^0.6.0" bs58 "4.0.1" -"@bonfida/spl-name-service@^0.1.24", "@bonfida/spl-name-service@^0.1.31": - version "0.1.44" - resolved "https://registry.yarnpkg.com/@bonfida/spl-name-service/-/spl-name-service-0.1.44.tgz#b4020a49c1826232aec3505e09dfa4c49b10198e" - integrity sha512-XYE6wOkQUMdA2Dz0b+HkOLlfviK2FQTLuALe3A8Ux12AMLxZIu9UTuo/WLGw4nh/SpJh08/S9Oie715055Mung== +"@bonfida/spl-name-service@0.1.47", "@bonfida/spl-name-service@^0.1.24", "@bonfida/spl-name-service@^1.0.6": + version "0.1.47" + resolved "https://registry.yarnpkg.com/@bonfida/spl-name-service/-/spl-name-service-0.1.47.tgz#bb5b22ccbbb3135d70f2fa3e7bbfaee0c2c7f3dc" + integrity sha512-BQrdvWm27KJowPvCuWmDWNC4vtYOnBNK9i+PFzfhKAMxa0X58DYpmk7ZSQDr4/EklAK8aR2noUMfvBInlsIfgg== dependencies: "@bonfida/name-offers" "^0.0.1" "@ethersproject/sha2" "^5.5.0" -"@bonfida/spl-name-service@^0.1.47", "@bonfida/spl-name-service@^0.1.50": - version "0.1.50" - resolved "https://registry.yarnpkg.com/@bonfida/spl-name-service/-/spl-name-service-0.1.50.tgz#462560199f6869fd97c8a19a8a09851ac15191db" - integrity sha512-StwKh4DPuLm/zSpf2Dk6pFr7gYrV7T+XTSafgoGI+2STXrzipPDtUtwXeF56HGKZ/IkUtZh4SRUd42q6U/MyrA== +"@brokerloop/ttlcache@^3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@brokerloop/ttlcache/-/ttlcache-3.2.3.tgz#bc3c79bb381f7b43f83745eb96e86673f75d3d11" + integrity sha512-kZWoyJGBYTv1cL5oHBYEixlJysJBf2RVnub3gbclD+dwaW9aKubbHzbZ9q1q6bONosxaOqMsoBorOrZKzBDiqg== dependencies: - "@bonfida/name-offers" "^0.0.1" - "@ethersproject/sha2" "^5.5.0" + "@soncodi/signal" "~2.0.7" -"@bundlr-network/client@^0.7.14", "@bundlr-network/client@^0.7.15": +"@bundlr-network/client@0.7.15", "@bundlr-network/client@^0.8.8": version "0.7.15" resolved "https://registry.yarnpkg.com/@bundlr-network/client/-/client-0.7.15.tgz#099c5edf287878465686bd01e29638958badabb1" integrity sha512-PzKH6VVyK/Ii5+rRwG7/5kcXZK0WeZGIng7xVtYaA8eb/SvIfaufTfJQl6ff3xnCA0QO0Fr6wkIWoXU5lHuEXA== @@ -1599,48 +454,87 @@ near-api-js "^0.44.2" near-seed-phrase "^0.2.0" -"@cardinal/certificates@^1.2.3", "@cardinal/certificates@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@cardinal/certificates/-/certificates-1.3.0.tgz#32961546de819d0491b6fce633b63c55002d51ea" - integrity sha512-UmCxerq++uzcts4TJlh2Dtrq5wuZvM16pISmjrC4N24IYKle/9GIKc4+rwKwJjeAcaBsM0CDGUITQjH/JnanwA== +"@carbon/icon-helpers@^10.32.0": + version "10.36.0" + resolved "https://registry.yarnpkg.com/@carbon/icon-helpers/-/icon-helpers-10.36.0.tgz#2052af78d320a1a9b69010a19a56eaf7dd5115b1" + integrity sha512-omrDngPr3HnwecIDzCNYrpPPdLX0kilyHxHpnztKlT7ePTbn5fb+ndmnWaqxjVDFqQgSvfJhTqTUQnwPpGHpAA== + +"@carbon/icons-react@11.7.0": + version "11.7.0" + resolved "https://registry.yarnpkg.com/@carbon/icons-react/-/icons-react-11.7.0.tgz#02063d4bf5ebccef7994a94297ed5a070463e19e" + integrity sha512-bSYatbW+xEx5e2QZ0WFgbVXrVgfRQpiYk3p/X+c007zcboxsG/3eq/GU6GEliFlQWZ02z0f0tUOG3sdD5jHurQ== + dependencies: + "@carbon/icon-helpers" "^10.32.0" + "@carbon/telemetry" "0.1.0" + prop-types "^15.7.2" + +"@carbon/telemetry@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@carbon/telemetry/-/telemetry-0.1.0.tgz#57b331cd5a855b4abbf55457456da8211624d879" + integrity sha512-kNWt0bkgPwGW0i5h7HFuljbKRXPvIhsKbB+1tEURAYLXoJg9iJLF1eGvWN5iVoFCS2zje4GR3OGOsvvKVe7Hlg== + +"@cardinal/certificates@^1.2.3", "@cardinal/certificates@^1.3.0", "@cardinal/certificates@^1.3.4": + version "1.3.4" + resolved "https://registry.yarnpkg.com/@cardinal/certificates/-/certificates-1.3.4.tgz#151e9d80624cb7f90185c15cbca5bbafcdb8fd00" + integrity sha512-IVr8CGS3OP3fe7L/W1Y4FIaCGf6223vPx5wVeQ/ug9NO6uOI9aRgayFP4j2ZOGrPKMz8SdRj12xgPX6LGc+JFg== dependencies: "@project-serum/anchor" "0.20.1" "@saberhq/solana-contrib" "^1.12.23" "@solana/spl-token" "^0.1.8" - typescript "^4.5.4" + mocha "^9.2.0" + ts-mocha "^9.0.2" + typescript "^4.5.5" -"@cardinal/namespaces-components@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@cardinal/namespaces-components/-/namespaces-components-3.1.0.tgz#654d20f5feb68612f550be2ee441a71cac1683c1" - integrity sha512-1aBdg2ihtf/omTDwZZo6VIiDzgxwjawlpVEXRlkptRJRCKkRIjZBsajpKQeMfndEOCiQEcIHmMOV86TJ9Y1hcg== +"@cardinal/common@^1.0.10": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@cardinal/common/-/common-1.0.10.tgz#e40a84c7f253db9154f3022f2e1ef6b8a2ff40c7" + integrity sha512-FCgatr08oyimIDkOk6Fi8gQLtWACnS3MTaMSjZfkXgQa1Wd+58s0k1DBG6IxWthmlSpl6w1/+kN0JfeWoVKO0w== dependencies: - "@cardinal/certificates" "^1.3.0" - "@cardinal/namespaces" "^3.1.0" - "@emotion/react" "^11.7.1" - "@emotion/styled" "^11.6.0" - "@headlessui/react" "^1.6.1" - "@metaplex/js" "^4.2.1" - "@popperjs/core" "^2.11.5" - "@project-serum/anchor" "^0.20.1" - "@reach/dialog" "^0.16.2" - "@react-spring/web" "^9.4.2" - "@saberhq/solana-contrib" "^1.12.26" - "@saberhq/use-solana" "^1.12.26" + "@cardinal/stake-pool" "^1.1.1" + "@metaplex-foundation/mpl-token-metadata" "^1.2.5" + "@project-serum/anchor" "^0.22.1" + "@saberhq/anchor-contrib" "^1.12.48" + "@saberhq/solana-contrib" "^1.12.48" + "@saberhq/token-utils" "^1.12.48" "@solana/buffer-layout" "^4.0.0" "@solana/spl-token" "^0.1.8" - "@solana/web3.js" "^1.31.0" - polished "^4.1.3" - react-content-loader "^6.1.0" - react-device-detect "^2.1.2" - react-icons "^4.3.1" - react-popper "^2.3.0" - react-use-gesture "^9.1.3" - tailwindcss "^3.0.15" - twin.macro "^2.8.2" - typescript "^4.1.2" - webpack-merge "^5.8.0" + "@ubeswap/token-math" "^4.4.4" + tiny-invariant "^1.2.0" + tslib "^2.3.1" + +"@cardinal/common@^2.0.12": + version "2.0.14" + resolved "https://registry.yarnpkg.com/@cardinal/common/-/common-2.0.14.tgz#bdbe2f923df048f37ce80de39216d838dc24c1e6" + integrity sha512-/mZPDrD41JFPl83Potv9b3HklYIKF4ZpFHZV7pFZRXAZc+QDBbjvNDdx5EVW8gFYkfHkfH8M62LbBK8ZDtbm0g== + dependencies: + "@metaplex-foundation/mpl-token-metadata" "^1.2.5" + "@project-serum/anchor" "^0.24.2" + "@saberhq/anchor-contrib" "^1.14.1" + "@saberhq/solana-contrib" "^1.14.1" + "@saberhq/token-utils" "^1.14.1" + "@solana/buffer-layout" "^4.0.0" + "@solana/spl-token" "^0.1.8" + "@ubeswap/token-math" "^4.4.4" + bignumber.js "^9.1.0" + bn.js "^5.2.1" + polished "^4.2.2" + tiny-invariant "^1.2.0" + tslib "^2.3.1" + +"@cardinal/common@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@cardinal/common/-/common-3.0.1.tgz#7e5c00d6493a1457f487eb7dfc09b8a8894fa7ed" + integrity sha512-ldJbG9WYTA+fwwu/AkiW0iqTV7Z5h0VycSStcXpikPbqRtZMDWZOz0br2QZWMJCnzec6UWWYqIOae4hEh+2ADQ== + dependencies: + "@project-serum/anchor" "^0.24.2" + "@solana/buffer-layout" "^4.0.0" + "@solana/spl-token" "^0.3.5" + bignumber.js "^9.1.0" + bn.js "^5.2.1" + polished "^4.2.2" + tslib "^2.4.0" -"@cardinal/namespaces-components@^2.5.5": +"@cardinal/namespaces-components@2.5.5": version "2.5.5" resolved "https://registry.yarnpkg.com/@cardinal/namespaces-components/-/namespaces-components-2.5.5.tgz#40a4417ea751af91d1ce21163e3a26c4ca554abb" integrity sha512-rMckp4Rravsp1AH3lc7Ub+O3PLjIBKvbx7JPlMIpAerMggZ2PzenB2DYJrpRMjdtNFTpWdtHririNvvIXGUrnA== @@ -1666,119 +560,198 @@ twin.macro "^2.8.2" typescript "^4.1.2" -"@cardinal/namespaces@3.1.0", "@cardinal/namespaces@^3.1.0": - version "3.1.0" - resolved "https://registry.npmjs.org/@cardinal/namespaces/-/namespaces-3.1.0.tgz" - integrity sha512-eX44mI0EFZrzvIHKGS/j0iUJPmCrl1av89jfSqWf6ldYYwLyENQysyOQv2az718pbJd9H5IQb+kJX0JLlQCo/w== +"@cardinal/namespaces@^3.1.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@cardinal/namespaces/-/namespaces-3.2.0.tgz#7727356eae59c8d8ee0014ff3a4fa99d08b4c23d" + integrity sha512-DT/iUopuGlZS62qvsrhRHlda1iYRU1+sJfYedhxOOQIMgeestWeSLyw7UFWjI1l8QfwvaegFrwXFal9auJst/w== dependencies: "@cardinal/certificates" "^1.2.3" - "@cardinal/namespaces" "^2.0.42" - "@metaplex-foundation/mpl-token-metadata" "^0.0.2" - "@project-serum/anchor" "^0.20.1" - "@saberhq/solana-contrib" "^1.12.23" - "@solana/spl-token" "^0.1.8" - typescript "^4.5.4" + "@cardinal/common" "^1.0.10" + "@cardinal/token-manager" "^1.1.0" + "@metaplex-foundation/mpl-token-metadata" "^1.2.5" + "@project-serum/anchor" "^0.24.2" -"@cardinal/namespaces@^2.0.42": - version "2.0.59" - resolved "https://registry.npmjs.org/@cardinal/namespaces/-/namespaces-2.0.59.tgz" - integrity sha512-2waZMfLyzAKi5y7bWBPzuqP/FDSjLS5u9VhsBLfEQbNOR3BHmHrSwrYPpAfV+IrULNBSSg8jobxoD5b94C3GEQ== +"@cardinal/payment-manager@^1.7.9": + version "1.7.9" + resolved "https://registry.yarnpkg.com/@cardinal/payment-manager/-/payment-manager-1.7.9.tgz#47d894ccfbce5a40d90006e243d7b31e33524a89" + integrity sha512-saI8EOLwDeF41uVimBIRnDmR2RtWUWatWbYR1exAOjqrQn1D6WfrUPmmz5AoVsXmsIqQQfjydyuAYwQllIA8cw== dependencies: - "@cardinal/certificates" "^1.2.3" - "@cardinal/namespaces" "^2.0.42" - "@metaplex-foundation/mpl-token-metadata" "^0.0.2" - "@project-serum/anchor" "^0.20.1" - "@saberhq/solana-contrib" "^1.12.23" + "@cardinal/common" "^3.0.1" + "@metaplex-foundation/mpl-token-metadata" "^1.2.5" + "@project-serum/anchor" "^0.25.0" + "@saberhq/anchor-contrib" "^1.14.9" + "@saberhq/chai-solana" "^1.14.9" + "@saberhq/solana-contrib" "^1.14.9" "@solana/spl-token" "^0.1.8" - typescript "^4.5.4" - -"@castlefinance/vault-core@^0.1.0", "@castlefinance/vault-core@^0.1.3": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@castlefinance/vault-core/-/vault-core-0.1.5.tgz#984da02fc4ca1270359c9c3283243658905eb562" - integrity sha512-Evq4CslcF5wsnMpd0oTGq4iNfjqprut25GQTQFI6mCTITFtrCa7G7cprw9jaBSXlyX/fpa3LI799VtPhrCoViA== + "@solana/web3.js" "^1.66.2" + +"@cardinal/stake-pool@^1.1.1": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@cardinal/stake-pool/-/stake-pool-1.1.9.tgz#aa148066779dfec17bef58d5f612b5225ae85739" + integrity sha512-1b6jyiMt4N1xjA1bC3dbETpIq3GoHYyGc5RPSXjAKyWWWBU001Ti+/wipI5bKx7yl6Q5UDP68Rbu93CGLagqiA== + dependencies: + "@cardinal/certificates" "^1.3.4" + "@cardinal/common" "^1.0.10" + "@metaplex-foundation/mpl-token-metadata" "^1.2.4" + "@project-serum/anchor" "0.21.0" + "@saberhq/anchor-contrib" "^1.12.47" + "@saberhq/solana-contrib" "^1.12.47" + "@solana/spl-token" "^0.1.8" + "@types/mocha" "^9.1.0" + mocha "^9.1.4" + ts-mocha "^8.0.0" + typescript "^4.5.5" -"@castlefinance/vault-sdk@^2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@castlefinance/vault-sdk/-/vault-sdk-2.1.2.tgz#7006fb3c1807be2ef3db0599cf154da0513f15f2" - integrity sha512-EIKsJm8jUJqcflE2la1jvh/rkOfD3vVI07uMW9yEJ0PmzKUX7QX6PGXnENmnfqzy5NjZ5a6gTw7gOrhRuK4Ofg== +"@cardinal/token-manager@^1.1.0": + version "1.7.12" + resolved "https://registry.yarnpkg.com/@cardinal/token-manager/-/token-manager-1.7.12.tgz#c0427507767de7f4c468111369b30dd17b2d709b" + integrity sha512-cUAzEBcow9tJwE42vQ1o7XwDotc5yaZGmDaCyDHbppPHbar5Y5jGIHlx7EquR/5wOPTFlUVKQ9mmmvqe/Q/bKQ== dependencies: - "@castlefinance/vault-core" "^0.1.0" - "@jet-lab/jet-engine" "^0.2.15" - "@port.finance/port-sdk" "^0.2.33" - "@project-serum/anchor" "0.18.2" + "@cardinal/common" "^2.0.12" + "@cardinal/payment-manager" "^1.7.9" + "@metaplex-foundation/mpl-token-metadata" "^1.2.5" + "@solana/buffer-layout" "^4.0.0" + "@solana/buffer-layout-utils" "^0.2.0" "@solana/spl-token" "^0.1.8" - "@solana/web3.js" "^1.31.0" - "@solendprotocol/solend-sdk" "^0.4.4" - big.js "^6.1.1" - bigint-buffer "^1.1.5" - buffer-layout "^1.2.2" + borsh "^0.7.0" + bs58 "^4.0.1" + superstruct "^0.15.4" + tiny-invariant "^1.2.0" + tslib "^2.3.1" -"@civic/common-gateway-react@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@civic/common-gateway-react/-/common-gateway-react-0.4.1.tgz#fe03923abe76c1ec5634f8c6212d842ccb6a5a10" - integrity sha512-RI7gihmJivuF/HpLf7PLdTKIPDaN6yANPY9afvIHI9Lrs/+H1Fz5Z9C/BA/fetkrBTBSH9tC14w+wKpAC8povA== +"@censo-custody/solana-wallet-adapter@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@censo-custody/solana-wallet-adapter/-/solana-wallet-adapter-0.1.0.tgz#064adae9f216dc4b726c1cc45b6b24cf0c734f07" + integrity sha512-iM1jFVzBMfk7iokgUVfA2xvGUegixklUISgMARa/VA2mFIjoi32t4xmD8PtWHht81fmg107aYhLnTV1cM7NkAg== + dependencies: + "@solana/web3.js" "^1.44.3" + bs58 "^4.0.1" + eventemitter3 "^4.0.7" + uuid "^8.3.2" + +"@civic/common-gateway-react@0.11.10": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@civic/common-gateway-react/-/common-gateway-react-0.11.10.tgz#90421d6c02077eadd495ddd24c0304acb86f5086" + integrity sha512-gwS2XfiEGdqqEyG6XHM1rG1Fi5lX4dNjm2Whg56sFDrQwwSJWhaio8LxMXYFOeE6NCqAgVNDtcbX8gV58//33w== dependencies: - fetch-retry-ts "^1.1.24" + fetch-retry "^5.0.6" iframe-resizer-react "^1.1.0" - ramda "^0.27.1" + ramda "^0.28.0" styled-components "^5.3.1" + uuid "^9.0.1" -"@civic/lexi@0.0.10": - version "0.0.10" - resolved "https://registry.yarnpkg.com/@civic/lexi/-/lexi-0.0.10.tgz#77066df36e8c78cf88a9ee50fc8cb1bbec9d987e" - integrity sha512-TxscOBzV29s+onZTrKbcZZErYgpXCH2syFVJzSWl/WYmE9LNNCU/p4dvTAlaQdSH7cDYEFu7d7zqyyVUMY1Vtw== +"@civic/did-registry@0.0.6-alpha.2": + version "0.0.6-alpha.2" + resolved "https://registry.yarnpkg.com/@civic/did-registry/-/did-registry-0.0.6-alpha.2.tgz#6d2ee70a8d784194978c99c3387072f63503be4d" + integrity sha512-5s60RIElhcOSjhJxmAs5Squ5aCdMN1XqphT9xs8TTMXgz83E06eEKgm03yTF01Trrq/3P4opUFMdhKJLq/8Wzg== dependencies: - "@stablelib/base64" "^1.0.1" - "@stablelib/utf8" "^1.0.1" - axios "^0.26.1" - bs58 "^5.0.0" - did-jwt "git+https://github.com/civicteam/did-jwt" + "@identity.com/sol-did-client" "^3.1.4" + "@project-serum/anchor" "^0.25.0" + +"@civic/identity-store-client@*": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@civic/identity-store-client/-/identity-store-client-0.1.1.tgz#7d42e170c45e18fa6188f6ddb3940a6417c64e13" + integrity sha512-2F3v4/BYngAZmAW06QjPyFFk5eM4Nr0rcF+3h6ODCLgM3WileeHZqdGNkqjOoA97zeO6nDHOaClgYHSVg3xxgA== + dependencies: + isomorphic-fetch "^3.0.0" + querystring "^0.2.1" + +"@civic/pkh-did-resolver@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@civic/pkh-did-resolver/-/pkh-did-resolver-1.2.0.tgz#c3b396913ed19446c248c847ee42b0e3e4607f0b" + integrity sha512-UVZHrEDeVg4c/fVNGtvHZhty6ab24WzaCFwfuFXvsg94jN9qDKFrAyuKudfc2Ner12CVbpbOXAKscbcHvEJVMg== + dependencies: + caip "~1.1.0" + +"@civic/profile@^0.5.0-beta.1": + version "0.5.0-beta.1" + resolved "https://registry.yarnpkg.com/@civic/profile/-/profile-0.5.0-beta.1.tgz#8caf4e575a682c4dcc47237310642ee8896463ea" + integrity sha512-NdWUcxu0/ecdVJoHVbVP2sSY+1nqV4uuEAYyfrIFfp9x6EiJZoXnxl73cNa22NKThCumSURTkAoiW3cs2q7bMg== + dependencies: + "@bonfida/spl-name-service" "^1.0.6" + "@civic/did-registry" "0.0.6-alpha.2" + "@civic/identity-store-client" "*" + "@civic/pkh-did-resolver" "^1.2.0" + "@civic/storage-adapter" "*" + "@ethersproject/address" "^5.7.0" + "@ethersproject/providers" "^5.7.2" + "@solana/web3.js" "^1.87.6" + axios "^1.3.6" did-resolver "^3.2.0" - ed2curve-esm "^0.3.0-alpha-1" - tweetnacl "^1.0.3" + ramda "^0.29.0" -"@civic/profile@0.0.3-alpha.1": - version "0.0.3-alpha.1" - resolved "https://registry.yarnpkg.com/@civic/profile/-/profile-0.0.3-alpha.1.tgz#b6c62d98c3214d4e9ca0366ac4cff98556f2ff03" - integrity sha512-vyoZdqQT4wLpZf9KfQETlNG/SAUozQmG5hnPrmcITrSWtZR7AkYZBMLBb7cgGVYIaK0j1G3dzHyLa3jwb/KVjA== +"@civic/solana-gateway-react@^0.16.10": + version "0.16.11" + resolved "https://registry.yarnpkg.com/@civic/solana-gateway-react/-/solana-gateway-react-0.16.11.tgz#1524fd87caa359c5d78c9fb84f85be4c08179b2c" + integrity sha512-N/5n1ozpLdWPTgzjC95AiCBJsiGpNqVwoXeDYNXAtJTXnxKpoIXtfMFjrGlWmSIVovRFDSaBu6d2UYcCKR1v/A== dependencies: - "@bonfida/spl-name-service" "^0.1.50" - "@civic/storage" "^0.1.12-alpha.1" - "@identity.com/sol-did-client" "^2.0.0" - "@solana/web3.js" "^1.48.0" + "@civic/common-gateway-react" "0.11.10" + "@identity.com/prove-solana-wallet" "0.4.2" + "@identity.com/solana-gateway-ts" "^0.12.0" + "@solana/web3.js" "^1.73.0" + prop-types "^15.8.1" ramda "^0.28.0" -"@civic/solana-gateway-react@0.9.2": - version "0.9.2" - resolved "https://registry.yarnpkg.com/@civic/solana-gateway-react/-/solana-gateway-react-0.9.2.tgz#b88a5a2033878bff274355dcf363546a178e2432" - integrity sha512-sAaFkGeo3tgzZwTG3Nw1yyt8MnONQWcskJBEFoPTbcwwTvnUl/i8bXI1SnAGON+D/LuQbssllOD8zPm86UHuLA== +"@civic/storage-adapter@*": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@civic/storage-adapter/-/storage-adapter-0.1.0.tgz#92a966958a3745aac79832928f51cc08cf2d7448" + integrity sha512-wP2uYnSvs6rvfbzqpDvIF12XyEuMqXfCMlt8iDnPa2FQ791K9uz/F1xnUE/bPTM1DtK8R1KTjQgpF6Ihyq1jxQ== dependencies: - "@civic/common-gateway-react" "^0.4.1" - "@identity.com/prove-solana-wallet" "0.2.9" - "@identity.com/solana-gateway-ts" "^0.7.0" - "@solana/web3.js" "1.39.0" + ajv "^8.12.0" -"@civic/storage@^0.1.12-alpha.1": - version "0.1.12-alpha.1" - resolved "https://registry.yarnpkg.com/@civic/storage/-/storage-0.1.12-alpha.1.tgz#02393d4d020686ae5b0aa4124c4cd63b0a7666d7" - integrity sha512-5KA/AvuhFCLKKhKSKqMjO3/qszqfY9tPzQEmzHlyQojXCSc6tBJE8xVz1Qv6ZHvhpUf0TYcomGTcU7nUMOarcw== +"@coral-xyz/anchor-30@npm:@coral-xyz/anchor@0.30.1", "@coral-xyz/anchor@0.30.1", "@coral-xyz/anchor@^0.30.1", "switchboard-anchor@npm:@coral-xyz/anchor@0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.30.1.tgz#17f3e9134c28cd0ea83574c6bab4e410bcecec5d" + integrity sha512-gDXFoF5oHgpriXAaLpxyWBHdCs8Awgf/gLHIo6crv7Aqm937CNdY+x+6hoj7QR5vaJV7MxWSQ0NGFzL3kPbWEQ== dependencies: - "@civic/lexi" "0.0.10" - "@identity.com/sol-did-client" "^2.0.1" - "@solana/web3.js" "^1.30.2" - axios "^0.26.1" - graceful-fs "^4.2.10" - jsonpath "^1.1.1" - jsonschema "^1.4.0" - multiformats "^9.7.1" - node-localstorage "^2.2.1" - ramda "^0.28.0" - tweetnacl "^1.0.3" + "@coral-xyz/anchor-errors" "^0.30.1" + "@coral-xyz/borsh" "^0.30.1" + "@noble/hashes" "^1.3.1" + "@solana/web3.js" "^1.68.0" + bn.js "^5.1.2" + bs58 "^4.0.1" + buffer-layout "^1.2.2" + camelcase "^6.3.0" + cross-fetch "^3.1.5" + crypto-hash "^1.3.0" + eventemitter3 "^4.0.7" + pako "^2.0.3" + snake-case "^3.0.4" + superstruct "^0.15.4" + toml "^3.0.0" -"@colors/colors@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" - integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== +"@coral-xyz/anchor-errors@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@coral-xyz/anchor-errors/-/anchor-errors-0.30.1.tgz#bdfd3a353131345244546876eb4afc0e125bec30" + integrity sha512-9Mkradf5yS5xiLWrl9WrpjqOrAV+/W2RQHDlbnAZBivoGpOs1ECjoDCkVk4aRG8ZdiFiB8zQEVlxf+8fKkmSfQ== + +"@coral-xyz/anchor@0.26.0", "@coral-xyz/anchor@0.28.1-beta.2", "@coral-xyz/anchor@0.29.0", "@coral-xyz/anchor@^0.26.0", "@coral-xyz/anchor@^0.28.0", "@coral-xyz/anchor@^0.29.0": + version "0.29.0" + resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.29.0.tgz#bd0be95bedfb30a381c3e676e5926124c310ff12" + integrity sha512-eny6QNG0WOwqV0zQ7cs/b1tIuzZGmP7U7EcH+ogt4Gdbl8HDmIYVMh/9aTmYZPaFWjtUaI8qSn73uYEXWfATdA== + dependencies: + "@coral-xyz/borsh" "^0.29.0" + "@noble/hashes" "^1.3.1" + "@solana/web3.js" "^1.68.0" + bn.js "^5.1.2" + bs58 "^4.0.1" + buffer-layout "^1.2.2" + camelcase "^6.3.0" + cross-fetch "^3.1.5" + crypto-hash "^1.3.0" + eventemitter3 "^4.0.7" + pako "^2.0.3" + snake-case "^3.0.4" + superstruct "^0.15.4" + toml "^3.0.0" + +"@coral-xyz/borsh@0.27.0", "@coral-xyz/borsh@^0.26.0", "@coral-xyz/borsh@^0.28.0", "@coral-xyz/borsh@^0.29.0", "@coral-xyz/borsh@^0.30.1": + version "0.27.0" + resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.27.0.tgz#700c647ea5262b1488957ac7fb4e8acf72c72b63" + integrity sha512-tJKzhLukghTWPLy+n8K8iJKgBq1yLT/AxaNd10yJrX8mI56ao5+OFAKAqW/h0i79KCvb4BK0VGO5ECmmolFz9A== + dependencies: + bn.js "^5.1.2" + buffer-layout "^1.2.0" "@cspotcode/source-map-support@^0.8.0": version "0.8.1" @@ -1789,120 +762,151 @@ "@csstools/convert-colors@^1.4.0": version "1.4.0" - resolved "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" + integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== + +"@dialectlabs/blockchain-sdk-solana@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@dialectlabs/blockchain-sdk-solana/-/blockchain-sdk-solana-1.2.0.tgz#9bc73519d0ba326b6e5dda90972e617f8d8e5265" + integrity sha512-gluOP6+xEWmL59BCvZBQhisn91+lrGRE8NJ5oRRjgbRjgsLOR0xYGzNe4LSfB6CYG26Yv1kLPIRGsqHZQf+pNg== -"@dialectlabs/react-sdk@^1.0.0-beta.23": - version "1.0.0-beta.23" - resolved "https://registry.yarnpkg.com/@dialectlabs/react-sdk/-/react-sdk-1.0.0-beta.23.tgz#350bd98b48b4a649b2e329f5b8beda0e27ec66c6" - integrity sha512-WE/KzqFqJaeLyUywmbXaejdGF3AYOTVH8o+A6AiyexJsCfS3rxVdnbho4KfkwvVno6fTrTJ2yX1gM7KC1by7dA== +"@dialectlabs/react-sdk-blockchain-solana@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@dialectlabs/react-sdk-blockchain-solana/-/react-sdk-blockchain-solana-2.0.3.tgz#65da74f5f9004f504532fadc7181b8ae20dcb44f" + integrity sha512-yMPs3cMA0NkA9Gx91Gx2XspiaXs4TrP23XTuJj0mhlrW7srs0OyryzRdc+ZBtTqD/TGjICxAASBpZBXlljBA9Q== dependencies: - "@dialectlabs/sdk" "^0.6.4" - nanoid "^4.0.0" - swr "^1.3.0" + "@dialectlabs/blockchain-sdk-solana" "^1.2.0" + "@dialectlabs/react-sdk" "^2.0.2" -"@dialectlabs/react-ui@^1.0.0-beta.43": - version "1.0.0-beta.43" - resolved "https://registry.yarnpkg.com/@dialectlabs/react-ui/-/react-ui-1.0.0-beta.43.tgz#9de23ee4228f8a2ed61c1d38ccdcd5a82438900f" - integrity sha512-5qX3bcqPAUDUe/SJeo0NtGwQOykBEVMwcsxtUE89kQIk3v+5nGoxKIEadtcb/tZRYJtKmj3tgKlJWUw0uYD8dA== +"@dialectlabs/react-sdk@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@dialectlabs/react-sdk/-/react-sdk-2.0.2.tgz#84990b7776496f121c87f804295630d670fa78c1" + integrity sha512-01Jc1IqrdKSS9xxAVKqhT6lKr5KCMjXjonh36fh/F0ga+Zr+J2X0IsLiMgJ6NKPbnSkRX2HqwaPbZtnV2xknTA== dependencies: - "@bonfida/name-offers" "^0.0.1" - "@bonfida/spl-name-service" "^0.1.31" - "@cardinal/namespaces" "3.1.0" - "@cardinal/namespaces-components" "3.1.0" - "@dialectlabs/react-sdk" "^1.0.0-beta.23" - "@dialectlabs/web3" "^0.3.2" - "@headlessui/react" "^1.2.0" - "@project-serum/anchor" "^0.23.0" - clsx "^1.1.1" - focus-visible "^5.2.0" - immer "^9.0.14" - react-linkify "^1.0.0-alpha" - react-media-hook "^0.4.9" - react-transition-group "^4.4.2" - swr "^1.3.0" + "@dialectlabs/sdk" "^1.8.0" + swr "^2.2.5" -"@dialectlabs/sdk@^0.6.4": - version "0.6.4" - resolved "https://registry.yarnpkg.com/@dialectlabs/sdk/-/sdk-0.6.4.tgz#d1fc39e9c53f1efb8e2b1de00cbcc13aeeedbc10" - integrity sha512-VwZIQA+Xp7qciJhtvhuVF/MFFI2OSAeItzmDvH5TeCo/pB9L/KDFs7oenYi6GkkZHvlLOuiNRsInG05JhiouXg== +"@dialectlabs/react-ui@^2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@dialectlabs/react-ui/-/react-ui-2.0.7.tgz#b1f6a01f5bb731341bdd2f89d79018f53b835a2f" + integrity sha512-t2nuoG6+Ig1vETsyPI6rSN7xxObNy+lsSyFbqyaVODKhmcnxsGehqkFyGqWgzPDUVrpcxkgepe2SFwHHpDuDtA== + dependencies: + "@dialectlabs/react-sdk" "^2.0.2" + clsx "^2.1.0" + react-tiny-linkify "^1.2.0" + +"@dialectlabs/sdk@^1.8.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@dialectlabs/sdk/-/sdk-1.9.0.tgz#13bdccf187767d1584ce74b3cd065cd25c06e047" + integrity sha512-vXAFRL6L/+vzJVFUR0JbOghzEabM1CMKKWcYZ28UHCBwedLloY6fBD02xtKXHlUq2bTJikblWHtBFtIcOIMoqQ== dependencies: - "@dialectlabs/web3" "^0.3.2" - "@project-serum/anchor" "0.23.0" - "@solana/wallet-adapter-base" "^0.9.5" - "@solana/web3.js" "^1.22.0" "@stablelib/base64" "^1.0.1" axios "^0.27.2" + bs58 "^5.0.0" ed2curve "^0.3.0" - luxon "^2.4.0" + js-sha3 "^0.8.0" nanoid "^3.3.4" tweetnacl "^1.0.3" -"@dialectlabs/web3@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@dialectlabs/web3/-/web3-0.3.2.tgz#465409691053cfe98054e1113b47285993ca2ccf" - integrity sha512-pBay/M6aaMNyHvZgwjDZsta+aqTrmhJ0b+8qeVqkOzCrAgO/H5kCcz2tAoRypCnWi9U0BJaguwr4dHP8jFperA== +"@dual-finance/airdrop@0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@dual-finance/airdrop/-/airdrop-0.3.1.tgz#64b697ee0e82da69d50ab5be517929a11fc2f138" + integrity sha512-V+6wcyyWZfLB6Yj1gUMlTO+DptsG21kumh+TF38e6Z/Z8Fu9I3c8mNY1Dh8KZNCZwlw2cF+PB2fO2kWUqvd/ZA== dependencies: - "@project-serum/anchor" "0.23.0" - "@solana/spl-token" "^0.1.8" - "@solana/web3.js" "^1.22.0" - bytebuffer "^5.0.1" - copy-to-clipboard "^3.3.1" - ed2curve "0.3.0" - js-sha256 "^0.9.0" - tweetnacl "1.0.3" + "@coral-xyz/anchor" "^0.26.0" + "@solana/spl-token" "^0.3.6" + "@solana/web3.js" "^1.73.2" + bs58 "^5.0.0" + js-sha3 "^0.8.0" -"@emotion/babel-plugin@^11.7.1": - version "11.7.2" - resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.7.2.tgz#fec75f38a6ab5b304b0601c74e2a5e77c95e5fa0" - integrity sha512-6mGSCWi9UzXut/ZAN6lGFu33wGR3SJisNl3c0tvlmb8XChH1b2SUvxvnOh7hvLpqyRdHHU9AiazV3Cwbk5SXKQ== +"@dual-finance/gso@0.0.17": + version "0.0.17" + resolved "https://registry.yarnpkg.com/@dual-finance/gso/-/gso-0.0.17.tgz#b547bc722c7e924be20dd424acb048739ccb3bdb" + integrity sha512-SatlyKfQq185FVWfzOu62IDorCiS/5+JMbnNybgZuI9f2/Sz/WU7ybY4Z7MZz4u8fK6ZWkLQEU3Mfmki/opBzA== dependencies: - "@babel/helper-module-imports" "^7.12.13" - "@babel/plugin-syntax-jsx" "^7.12.13" - "@babel/runtime" "^7.13.10" - "@emotion/hash" "^0.8.0" - "@emotion/memoize" "^0.7.5" - "@emotion/serialize" "^1.0.2" - babel-plugin-macros "^2.6.1" + "@dual-finance/staking-options" "^0.0.17" + "@project-serum/anchor" "^0.25.0" + "@project-serum/associated-token" "^0.1.1" + "@solana/spl-token" "^0.3.6" + "@solana/web3.js" "^1.66.2" + dotenv "^16.0.3" + +"@dual-finance/staking-options@0.0.26": + version "0.0.26" + resolved "https://registry.yarnpkg.com/@dual-finance/staking-options/-/staking-options-0.0.26.tgz#37bce685e1b8a2c8a3dca00606899249d897ab62" + integrity sha512-jwtMpoQzIliKlp+Nlu2Js/UaXL7/0tk+NqtMZLdKf997OdfHgxoDJrUC/sha1oZgBEuPjAwThWtwlY+Ku/tc8w== + dependencies: + "@coral-xyz/anchor" "^0.28.0" + "@dual-finance/staking-options" "^0.0.21" + "@project-serum/anchor" "^0.25.0" + "@solana/spl-token" "^0.3.6" + "@solana/web3.js" "^1.66.2" + +"@dual-finance/staking-options@^0.0.17": + version "0.0.17" + resolved "https://registry.yarnpkg.com/@dual-finance/staking-options/-/staking-options-0.0.17.tgz#e56f7eb8be7d1364ac7fac6e0d0e8b79cab833cf" + integrity sha512-ecpHUGjENVUUZJfAtclec5MQU0KwLc6y/1taMxIkk36dAcsV2431kOLayHYRfRFaBph6lVGDzj+OfJHYhsFKEQ== + dependencies: + "@project-serum/anchor" "^0.25.0" + "@solana/spl-token" "^0.3.6" + "@solana/web3.js" "^1.66.2" + +"@dual-finance/staking-options@^0.0.21": + version "0.0.21" + resolved "https://registry.yarnpkg.com/@dual-finance/staking-options/-/staking-options-0.0.21.tgz#618a5633e22ab6078808abbe669eaf65e899d463" + integrity sha512-6XmpavPwalguOx1mDXB5XeJY1o+QyDFrdqJOlkXktpAeIzml/esm1sDrLQU8tb8RiwV6jUDV0pFUrZyrI5cQtw== + dependencies: + "@project-serum/anchor" "^0.25.0" + "@solana/spl-token" "^0.3.6" + "@solana/web3.js" "^1.66.2" + +"@emotion/babel-plugin@^11.10.5", "@emotion/babel-plugin@^11.7.1": + version "11.10.5" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.5.tgz#65fa6e1790ddc9e23cc22658a4c5dea423c55c3c" + integrity sha512-xE7/hyLHJac7D2Ve9dKroBBZqBT7WuPQmWcq7HSGb84sUuP4mlOWoB8dvVfD9yk5DHkU1m6RW7xSoDtnQHNQeA== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/plugin-syntax-jsx" "^7.17.12" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.0" + "@emotion/memoize" "^0.8.0" + "@emotion/serialize" "^1.1.1" + babel-plugin-macros "^3.1.0" convert-source-map "^1.5.0" escape-string-regexp "^4.0.0" find-root "^1.1.0" source-map "^0.5.7" - stylis "4.0.13" + stylis "4.1.3" -"@emotion/cache@^11.7.1": - version "11.7.1" - resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz" - integrity sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A== +"@emotion/cache@^11.10.5", "@emotion/cache@^11.7.1": + version "11.10.5" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.5.tgz#c142da9351f94e47527ed458f7bbbbe40bb13c12" + integrity sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA== dependencies: - "@emotion/memoize" "^0.7.4" - "@emotion/sheet" "^1.1.0" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" - stylis "4.0.13" - -"@emotion/hash@^0.8.0": - version "0.8.0" - resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz" + "@emotion/memoize" "^0.8.0" + "@emotion/sheet" "^1.2.1" + "@emotion/utils" "^1.2.0" + "@emotion/weak-memoize" "^0.3.0" + stylis "4.1.3" -"@emotion/is-prop-valid@^1.1.0": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.1.3.tgz#f0907a416368cf8df9e410117068e20fe87c0a3a" - integrity sha512-RFg04p6C+1uO19uG8N+vqanzKqiM9eeV1LDOG3bmkYmuOj7NbKNlFC/4EZq5gnwAIlcC/jOT24f8Td0iax2SXA== - dependencies: - "@emotion/memoize" "^0.7.4" +"@emotion/hash@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7" + integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ== -"@emotion/is-prop-valid@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.1.2.tgz#34ad6e98e871aa6f7a20469b602911b8b11b3a95" - integrity sha512-3QnhqeL+WW88YjYbQL5gUIkthuMw7a0NGbZ7wfFVk2kg/CK5w8w5FFa0RzWjyY1+sujN0NWbtSHH6OJmWHtJpQ== +"@emotion/is-prop-valid@^1.1.0", "@emotion/is-prop-valid@^1.1.2", "@emotion/is-prop-valid@^1.2.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc" + integrity sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw== dependencies: - "@emotion/memoize" "^0.7.4" + "@emotion/memoize" "^0.8.1" -"@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5": - version "0.7.5" - resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz" +"@emotion/memoize@^0.8.0", "@emotion/memoize@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== -"@emotion/react@^11.7.1", "@emotion/react@^11.9.0": +"@emotion/react@11.9.0": version "11.9.0" resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.9.0.tgz#b6d42b1db3bd7511e7a7c4151dc8bc82e14593b8" integrity sha512-lBVSF5d0ceKtfKCDQJveNAtkC7ayxpVlgOohLgXqRwqWr9bOf4TZAFFyIcNngnV6xK6X4x2ZeXq7vliHkoVkxQ== @@ -1915,23 +919,37 @@ "@emotion/weak-memoize" "^0.2.5" hoist-non-react-statics "^3.3.1" -"@emotion/serialize@^1.0.2", "@emotion/serialize@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.3.tgz#99e2060c26c6292469fb30db41f4690e1c8fea63" - integrity sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA== +"@emotion/react@^11.7.1": + version "11.10.5" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.5.tgz#95fff612a5de1efa9c0d535384d3cfa115fe175d" + integrity sha512-TZs6235tCJ/7iF6/rvTaOH4oxQg2gMAcdHemjwLKIjKz4rRuYe1HJ2TQJKnAcRAfOUDdU8XoDadCe1rl72iv8A== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.10.5" + "@emotion/cache" "^11.10.5" + "@emotion/serialize" "^1.1.1" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" + "@emotion/utils" "^1.2.0" + "@emotion/weak-memoize" "^0.3.0" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.0.2", "@emotion/serialize@^1.0.3", "@emotion/serialize@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.1.tgz#0595701b1902feded8a96d293b26be3f5c1a5cf0" + integrity sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA== dependencies: - "@emotion/hash" "^0.8.0" - "@emotion/memoize" "^0.7.4" - "@emotion/unitless" "^0.7.5" - "@emotion/utils" "^1.0.0" + "@emotion/hash" "^0.9.0" + "@emotion/memoize" "^0.8.0" + "@emotion/unitless" "^0.8.0" + "@emotion/utils" "^1.2.0" csstype "^3.0.2" -"@emotion/sheet@^1.1.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.0.tgz" - integrity sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g== +"@emotion/sheet@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.1.tgz#0767e0305230e894897cadb6c8df2c51e61a6c2c" + integrity sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA== -"@emotion/styled@^11.6.0", "@emotion/styled@^11.8.1": +"@emotion/styled@11.8.1": version "11.8.1" resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.8.1.tgz#856f6f63aceef0eb783985fa2322e2bf66d04e17" integrity sha512-OghEVAYBZMpEquHZwuelXcRjRJQOVayvbmNR0zr174NHdmMgrNkLC6TljKC5h9lZLkN5WGrdUcrKlOJ4phhoTQ== @@ -1942,456 +960,560 @@ "@emotion/serialize" "^1.0.2" "@emotion/utils" "^1.1.0" +"@emotion/styled@^11.6.0": + version "11.10.5" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.10.5.tgz#1fe7bf941b0909802cb826457e362444e7e96a79" + integrity sha512-8EP6dD7dMkdku2foLoruPCNkRevzdcBaY6q0l0OsbyJK+x8D9HWjX27ARiSIKNF634hY9Zdoedh8bJCiva8yZw== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.10.5" + "@emotion/is-prop-valid" "^1.2.0" + "@emotion/serialize" "^1.1.1" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" + "@emotion/utils" "^1.2.0" + "@emotion/stylis@^0.8.4": version "0.8.5" resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== -"@emotion/unitless@^0.7.4", "@emotion/unitless@^0.7.5": +"@emotion/unitless@^0.7.4": version "0.7.5" - resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== -"@emotion/utils@^1.0.0", "@emotion/utils@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.1.0.tgz#86b0b297f3f1a0f2bdb08eeac9a2f49afd40d0cf" - integrity sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ== +"@emotion/unitless@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db" + integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw== + +"@emotion/use-insertion-effect-with-fallbacks@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz#ffadaec35dbb7885bd54de3fa267ab2f860294df" + integrity sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A== + +"@emotion/utils@^1.1.0", "@emotion/utils@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561" + integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw== "@emotion/weak-memoize@^0.2.5": version "0.2.5" - resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" + integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== -"@eslint/eslintrc@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f" - integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw== +"@emotion/weak-memoize@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb" + integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg== + +"@esbuild/aix-ppc64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz#145b74d5e4a5223489cabdc238d8dad902df5259" + integrity sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ== + +"@esbuild/android-arm64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz#453bbe079fc8d364d4c5545069e8260228559832" + integrity sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ== + +"@esbuild/android-arm@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.23.0.tgz#26c806853aa4a4f7e683e519cd9d68e201ebcf99" + integrity sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g== + +"@esbuild/android-x64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.23.0.tgz#1e51af9a6ac1f7143769f7ee58df5b274ed202e6" + integrity sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ== + +"@esbuild/darwin-arm64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz#d996187a606c9534173ebd78c58098a44dd7ef9e" + integrity sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow== + +"@esbuild/darwin-x64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz#30c8f28a7ef4e32fe46501434ebe6b0912e9e86c" + integrity sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ== + +"@esbuild/freebsd-arm64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz#30f4fcec8167c08a6e8af9fc14b66152232e7fb4" + integrity sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw== + +"@esbuild/freebsd-x64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz#1003a6668fe1f5d4439e6813e5b09a92981bc79d" + integrity sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ== + +"@esbuild/linux-arm64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz#3b9a56abfb1410bb6c9138790f062587df3e6e3a" + integrity sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw== + +"@esbuild/linux-arm@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz#237a8548e3da2c48cd79ae339a588f03d1889aad" + integrity sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw== + +"@esbuild/linux-ia32@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz#4269cd19cb2de5de03a7ccfc8855dde3d284a238" + integrity sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA== + +"@esbuild/linux-loong64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz#82b568f5658a52580827cc891cb69d2cb4f86280" + integrity sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A== + +"@esbuild/linux-mips64el@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz#9a57386c926262ae9861c929a6023ed9d43f73e5" + integrity sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w== + +"@esbuild/linux-ppc64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz#f3a79fd636ba0c82285d227eb20ed8e31b4444f6" + integrity sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw== + +"@esbuild/linux-riscv64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz#f9d2ef8356ce6ce140f76029680558126b74c780" + integrity sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw== + +"@esbuild/linux-s390x@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz#45390f12e802201f38a0229e216a6aed4351dfe8" + integrity sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg== + +"@esbuild/linux-x64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz#c8409761996e3f6db29abcf9b05bee8d7d80e910" + integrity sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ== + +"@esbuild/netbsd-x64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz#ba70db0114380d5f6cfb9003f1d378ce989cd65c" + integrity sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw== + +"@esbuild/openbsd-arm64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz#72fc55f0b189f7a882e3cf23f332370d69dfd5db" + integrity sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ== + +"@esbuild/openbsd-x64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz#b6ae7a0911c18fe30da3db1d6d17a497a550e5d8" + integrity sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg== + +"@esbuild/sunos-x64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz#58f0d5e55b9b21a086bfafaa29f62a3eb3470ad8" + integrity sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA== + +"@esbuild/win32-arm64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz#b858b2432edfad62e945d5c7c9e5ddd0f528ca6d" + integrity sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ== + +"@esbuild/win32-ia32@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz#167ef6ca22a476c6c0c014a58b4f43ae4b80dec7" + integrity sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA== + +"@esbuild/win32-x64@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz#db44a6a08520b5f25bbe409f34a59f2d4bcc7ced" + integrity sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g== + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" + integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== + +"@eslint/config-array@^0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.17.1.tgz#d9b8b8b6b946f47388f32bedfd3adf29ca8f8910" + integrity sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA== + dependencies: + "@eslint/object-schema" "^2.1.4" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/eslintrc@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6" + integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.3.2" - globals "^13.15.0" + espree "^10.0.1" + globals "^14.0.0" ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@ethersproject/abi@5.6.4", "@ethersproject/abi@^5.6.3": - version "5.6.4" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.4.tgz#f6e01b6ed391a505932698ecc0d9e7a99ee60362" - integrity sha512-TTeZUlCeIHG6527/2goZA6gW5F8Emoc7MrZDC7hhP84aRGvW3TEdTnZR08Ls88YXM1m2SuK42Osw/jSi3uO8gg== - dependencies: - "@ethersproject/address" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/hash" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.1" - -"@ethersproject/abstract-provider@5.6.1", "@ethersproject/abstract-provider@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.1.tgz#02ddce150785caf0c77fe036a0ebfcee61878c59" - integrity sha512-BxlIgogYJtp1FS8Muvj8YfdClk3unZH0vRMVX791Z9INBNT/kuACZ9GzaY1Y4yFq+YSy6/w4gzj3HCRKrK9hsQ== - dependencies: - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/networks" "^5.6.3" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/transactions" "^5.6.2" - "@ethersproject/web" "^5.6.1" - -"@ethersproject/abstract-signer@5.6.2", "@ethersproject/abstract-signer@^5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.2.tgz#491f07fc2cbd5da258f46ec539664713950b0b33" - integrity sha512-n1r6lttFBG0t2vNiI3HoWaS/KdOt8xyDjzlP2cuevlWLG6EX0OwcKLyG/Kp/cuwNxdy/ous+R/DEMdTUwWQIjQ== - dependencies: - "@ethersproject/abstract-provider" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - -"@ethersproject/address@5.6.1", "@ethersproject/address@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.1.tgz#ab57818d9aefee919c5721d28cd31fd95eff413d" - integrity sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q== - dependencies: - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/rlp" "^5.6.1" - -"@ethersproject/base64@5.6.1", "@ethersproject/base64@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.1.tgz#2c40d8a0310c9d1606c2c37ae3092634b41d87cb" - integrity sha512-qB76rjop6a0RIYYMiB4Eh/8n+Hxu2NIZm8S/Q7kNo5pmZfXhHGHmS4MinUainiBC54SCyRnwzL+KZjj8zbsSsw== - dependencies: - "@ethersproject/bytes" "^5.6.1" - -"@ethersproject/basex@5.6.1", "@ethersproject/basex@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.1.tgz#badbb2f1d4a6f52ce41c9064f01eab19cc4c5305" - integrity sha512-a52MkVz4vuBXR06nvflPMotld1FJWSj2QT0985v7P/emPZO00PucFAkbcmq2vpVU7Ts7umKiSI6SppiLykVWsA== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/properties" "^5.6.0" - -"@ethersproject/bignumber@5.6.2", "@ethersproject/bignumber@^5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.2.tgz#72a0717d6163fab44c47bcc82e0c550ac0315d66" - integrity sha512-v7+EEUbhGqT3XJ9LMPsKvXYHFc8eHxTowFCG/HgJErmq4XHJ2WR7aeyICg3uTOAQ7Icn0GFHAohXEhxQHq4Ubw== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - bn.js "^5.2.1" +"@eslint/js@9.9.0", "@eslint/js@^9.8.0": + version "9.9.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.9.0.tgz#d8437adda50b3ed4401964517b64b4f59b0e2638" + integrity sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug== -"@ethersproject/bytes@5.6.1", "@ethersproject/bytes@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" - integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== - dependencies: - "@ethersproject/logger" "^5.6.0" +"@eslint/object-schema@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.4.tgz#9e69f8bb4031e11df79e03db09f9dbbae1740843" + integrity sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ== + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" -"@ethersproject/bytes@^5.5.0": - version "5.5.0" - resolved "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.5.0.tgz" - integrity sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog== - dependencies: - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/constants@5.6.1", "@ethersproject/constants@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.1.tgz#e2e974cac160dd101cf79fdf879d7d18e8cb1370" - integrity sha512-QSq9WVnZbxXYFftrjSjZDUshp6/eKp6qrtdBtUCm0QxCV5z1fG/w3kdlcsjMCQuQHUnAclKoK7XpXMezhRDOLg== - dependencies: - "@ethersproject/bignumber" "^5.6.2" - -"@ethersproject/contracts@5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.6.2.tgz#20b52e69ebc1b74274ff8e3d4e508de971c287bc" - integrity sha512-hguUA57BIKi6WY0kHvZp6PwPlWF87MCeB4B7Z7AbUpTxfFXFdn/3b0GmjZPagIHS+3yhcBJDnuEfU4Xz+Ks/8g== - dependencies: - "@ethersproject/abi" "^5.6.3" - "@ethersproject/abstract-provider" "^5.6.1" - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/address" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/transactions" "^5.6.2" - -"@ethersproject/hash@5.6.1", "@ethersproject/hash@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.1.tgz#224572ea4de257f05b4abf8ae58b03a67e99b0f4" - integrity sha512-L1xAHurbaxG8VVul4ankNX5HgQ8PNCTrnVXEiFnE9xoRnaUcgfD12tZINtDinSllxPLCtGwguQxJ5E6keE84pA== - dependencies: - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/address" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.1" - -"@ethersproject/hdnode@5.6.2", "@ethersproject/hdnode@^5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.2.tgz#26f3c83a3e8f1b7985c15d1db50dc2903418b2d2" - integrity sha512-tERxW8Ccf9CxW2db3WsN01Qao3wFeRsfYY9TCuhmG0xNpl2IO8wgXU3HtWIZ49gUWPggRy4Yg5axU0ACaEKf1Q== - dependencies: - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/basex" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/pbkdf2" "^5.6.1" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/sha2" "^5.6.1" - "@ethersproject/signing-key" "^5.6.2" - "@ethersproject/strings" "^5.6.1" - "@ethersproject/transactions" "^5.6.2" - "@ethersproject/wordlists" "^5.6.1" - -"@ethersproject/json-wallets@5.6.1", "@ethersproject/json-wallets@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.1.tgz#3f06ba555c9c0d7da46756a12ac53483fe18dd91" - integrity sha512-KfyJ6Zwz3kGeX25nLihPwZYlDqamO6pfGKNnVMWWfEVVp42lTfCZVXXy5Ie8IZTN0HKwAngpIPi7gk4IJzgmqQ== - dependencies: - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/address" "^5.6.1" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/hdnode" "^5.6.2" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/pbkdf2" "^5.6.1" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/random" "^5.6.1" - "@ethersproject/strings" "^5.6.1" - "@ethersproject/transactions" "^5.6.2" +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.6.1", "@ethersproject/keccak256@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.1.tgz#b867167c9b50ba1b1a92bccdd4f2d6bd168a91cc" - integrity sha512-bB7DQHCTRDooZZdL3lk9wpL0+XuG3XLGHLh3cePnybsO3V0rdCAOQGpn/0R3aODmnTOOkCATJiD2hnL+5bwthA== +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== dependencies: - "@ethersproject/bytes" "^5.6.1" + "@ethersproject/bytes" "^5.7.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.6.0", "@ethersproject/logger@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" - integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== -"@ethersproject/logger@^5.5.0": - version "5.5.0" - resolved "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.5.0.tgz" - integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== - -"@ethersproject/networks@5.6.4", "@ethersproject/networks@^5.6.3": - version "5.6.4" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.4.tgz#51296d8fec59e9627554f5a8a9c7791248c8dc07" - integrity sha512-KShHeHPahHI2UlWdtDMn2lJETcbtaJge4k7XSjDR9h79QTd6yQJmv6Cp2ZA4JdqWnhszAOLSuJEd9C0PRw7hSQ== - dependencies: - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/pbkdf2@5.6.1", "@ethersproject/pbkdf2@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.1.tgz#f462fe320b22c0d6b1d72a9920a3963b09eb82d1" - integrity sha512-k4gRQ+D93zDRPNUfmduNKq065uadC2YjMP/CqwwX5qG6R05f47boq6pLZtV/RnC4NZAYOPH1Cyo54q0c9sshRQ== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/sha2" "^5.6.1" - -"@ethersproject/properties@5.6.0", "@ethersproject/properties@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.6.0.tgz#38904651713bc6bdd5bdd1b0a4287ecda920fa04" - integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg== - dependencies: - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/providers@5.6.8": - version "5.6.8" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.8.tgz#22e6c57be215ba5545d3a46cf759d265bb4e879d" - integrity sha512-Wf+CseT/iOJjrGtAOf3ck9zS7AgPmr2fZ3N97r4+YXN3mBePTG2/bJ8DApl9mVwYL+RpYbNxMEkEp4mPGdwG/w== - dependencies: - "@ethersproject/abstract-provider" "^5.6.1" - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/address" "^5.6.1" - "@ethersproject/base64" "^5.6.1" - "@ethersproject/basex" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/hash" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/networks" "^5.6.3" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/random" "^5.6.1" - "@ethersproject/rlp" "^5.6.1" - "@ethersproject/sha2" "^5.6.1" - "@ethersproject/strings" "^5.6.1" - "@ethersproject/transactions" "^5.6.2" - "@ethersproject/web" "^5.6.1" +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" bech32 "1.1.4" ws "7.4.6" -"@ethersproject/random@5.6.1", "@ethersproject/random@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.1.tgz#66915943981bcd3e11bbd43733f5c3ba5a790255" - integrity sha512-/wtPNHwbmng+5yi3fkipA8YBT59DdkGRoC2vWk09Dci/q5DlgnMkhIycjHlavrvrjJBkFjO/ueLyT+aUDfc4lA== +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" -"@ethersproject/rlp@5.6.1", "@ethersproject/rlp@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.1.tgz#df8311e6f9f24dcb03d59a2bac457a28a4fe2bd8" - integrity sha512-uYjmcZx+DKlFUk7a5/W9aQVaoEC7+1MOBgNtvNg13+RnuUwT4F0zTovC0tmay5SmRslb29V1B7Y5KCri46WhuQ== +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" -"@ethersproject/sha2@5.6.1", "@ethersproject/sha2@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.1.tgz#211f14d3f5da5301c8972a8827770b6fd3e51656" - integrity sha512-5K2GyqcW7G4Yo3uenHegbXRPDgARpWUiXc6RiF7b6i/HXUoWlb7uCARh7BAHg7/qT/Q5ydofNwiZcim9qpjB6g== +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.5.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" hash.js "1.1.7" -"@ethersproject/sha2@^5.5.0": - version "5.5.0" - resolved "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.5.0.tgz" - integrity sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - hash.js "1.1.7" - -"@ethersproject/signing-key@5.6.2", "@ethersproject/signing-key@^5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.2.tgz#8a51b111e4d62e5a62aee1da1e088d12de0614a3" - integrity sha512-jVbu0RuP7EFpw82vHcL+GP35+KaNruVAZM90GxgQnGqB6crhBqW/ozBfFvdeImtmb4qPko0uxXjn8l9jpn0cwQ== +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" bn.js "^5.2.1" elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/solidity@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.6.1.tgz#5845e71182c66d32e6ec5eefd041fca091a473e2" - integrity sha512-KWqVLkUUoLBfL1iwdzUVlkNqAUIFMpbbeH0rgCfKmJp0vFtY4AsaN91gHKo9ZZLkC4UOm3cI3BmMV4N53BOq4g== - dependencies: - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/sha2" "^5.6.1" - "@ethersproject/strings" "^5.6.1" - -"@ethersproject/strings@5.6.1", "@ethersproject/strings@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.1.tgz#dbc1b7f901db822b5cafd4ebf01ca93c373f8952" - integrity sha512-2X1Lgk6Jyfg26MUnsHiT456U9ijxKUybz8IM1Vih+NJxYtXhmvKBcHOmvGqpFSVJ0nQ4ZCoIViR8XlRw1v/+Cw== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/transactions@5.6.2", "@ethersproject/transactions@^5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.2.tgz#793a774c01ced9fe7073985bb95a4b4e57a6370b" - integrity sha512-BuV63IRPHmJvthNkkt9G70Ullx6AcM+SDc+a8Aw/8Yew6YwT51TcBKEp1P4oOQ/bP25I18JJr7rcFRgFtU9B2Q== - dependencies: - "@ethersproject/address" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/rlp" "^5.6.1" - "@ethersproject/signing-key" "^5.6.2" - -"@ethersproject/units@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.6.1.tgz#ecc590d16d37c8f9ef4e89e2005bda7ddc6a4e6f" - integrity sha512-rEfSEvMQ7obcx3KWD5EWWx77gqv54K6BKiZzKxkQJqtpriVsICrktIQmKl8ReNToPeIYPnFHpXvKpi068YFZXw== - dependencies: - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/wallet@5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.2.tgz#cd61429d1e934681e413f4bc847a5f2f87e3a03c" - integrity sha512-lrgh0FDQPuOnHcF80Q3gHYsSUODp6aJLAdDmDV0xKCN/T7D99ta1jGVhulg3PY8wiXEngD0DfM0I2XKXlrqJfg== - dependencies: - "@ethersproject/abstract-provider" "^5.6.1" - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/address" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/hash" "^5.6.1" - "@ethersproject/hdnode" "^5.6.2" - "@ethersproject/json-wallets" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/random" "^5.6.1" - "@ethersproject/signing-key" "^5.6.2" - "@ethersproject/transactions" "^5.6.2" - "@ethersproject/wordlists" "^5.6.1" - -"@ethersproject/web@5.6.1", "@ethersproject/web@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.1.tgz#6e2bd3ebadd033e6fe57d072db2b69ad2c9bdf5d" - integrity sha512-/vSyzaQlNXkO1WV+RneYKqCJwualcUdx/Z3gseVovZP0wIlOFcCE1hkRhKBH8ImKbGQbMl9EAAyJFrJu7V0aqA== - dependencies: - "@ethersproject/base64" "^5.6.1" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.1" - -"@ethersproject/wordlists@5.6.1", "@ethersproject/wordlists@^5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.1.tgz#1e78e2740a8a21e9e99947e47979d72e130aeda1" - integrity sha512-wiPRgBpNbNwCQFoCr8bcWO8o5I810cqO6mkdtKfLKFlLxeCWcnzDi4Alu8iyNzlhYuS9npCwivMbRWF19dyblw== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/hash" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.1" - -"@everlend/common@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@everlend/common/-/common-0.0.3.tgz#b18d7e025592a6f863dc84abf563ca2b25df0ac2" - integrity sha512-hj729mHUw250kJNKgdhfK/ZLiUJOSze2IquGyNs6qooMe856Au9E/vi3RlkuCzDMe3nkvvC8mpRzjzRmkwpJWw== - dependencies: - "@solana/spl-token" "^0.1.5" - "@solana/web3.js" "^1.16.1" - borsh "^0.6.0" - bs58 "^4.0.1" - buffer "^6.0.3" - -"@everlend/core@^0.0.6": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@everlend/core/-/core-0.0.6.tgz#2841f4195155d2e9931cdbc16930b05972b64a25" - integrity sha512-Af2BqHZr4xYcPdYkUZys53m1ZLbTKB+DHqZXSxP7ML/AE36QOWOitAGxymMgAUzpnvWifI12t0ayVfho6/TnrQ== - dependencies: - "@project-serum/anchor" "0.24.2" - "@solana/spl-token" "^0.2.0" - -"@everlend/general-pool@^0.0.23": - version "0.0.23" - resolved "https://registry.yarnpkg.com/@everlend/general-pool/-/general-pool-0.0.23.tgz#8f52bd28150f73bda021e4e6c286fe96f0f7061b" - integrity sha512-eIa/pGXHwJ72jJOiRFrHbQZ2y4wY0Z1ynmBpyC9FXY8O3YPHLtLPaRdXxGzO2uLEKJAxVLVmYHWlcKOL9DSGQQ== - dependencies: - "@everlend/common" "^0.0.3" - "@solana/spl-token" "^0.1.5" - "@solana/web3.js" "^1.16.1" - borsh "^0.6.0" - bs58 "^4.0.1" - buffer "^6.0.3" - -"@fast-csv/format@4.3.5": - version "4.3.5" - resolved "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz" - integrity sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A== - dependencies: - "@types/node" "^14.0.1" - lodash.escaperegexp "^4.1.2" - lodash.isboolean "^3.0.3" - lodash.isequal "^4.5.0" - lodash.isfunction "^3.0.9" - lodash.isnil "^4.0.0" - -"@fast-csv/parse@4.3.6": - version "4.3.6" - resolved "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz" - integrity sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA== - dependencies: - "@types/node" "^14.0.1" - lodash.escaperegexp "^4.1.2" - lodash.groupby "^4.6.0" - lodash.isfunction "^3.0.9" - lodash.isnil "^4.0.0" - lodash.isundefined "^3.0.1" - lodash.uniq "^4.5.0" +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" "@floating-ui/core@^0.7.3": version "0.7.3" @@ -2403,130 +1525,175 @@ resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.4.tgz#4eae73f78bcd4bd553ae2ade30e6f1f9c73fe3f1" integrity sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg== dependencies: - "@floating-ui/core" "^0.7.3" + "@floating-ui/core" "^0.7.3" + +"@floating-ui/react-dom@0.7.2": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864" + integrity sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg== + dependencies: + "@floating-ui/dom" "^0.5.3" + use-isomorphic-layout-effect "^1.1.1" + +"@fractalwagmi/popup-connection@^1.0.18": + version "1.0.21" + resolved "https://registry.yarnpkg.com/@fractalwagmi/popup-connection/-/popup-connection-1.0.21.tgz#a1d76c8e6f0efa2187795c7d9db648ffaffb25f2" + integrity sha512-LpEpRwn7Y4rn58NZ/i1MAnQENyYpill4rI4MNjmXWexxIlzdiloQqF8gXqef3sMQgi4EbHLfizyn02gGtxQhjg== + +"@fractalwagmi/solana-wallet-adapter@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@fractalwagmi/solana-wallet-adapter/-/solana-wallet-adapter-0.1.1.tgz#13d97bca657007a62b2118ea60f5d9e73f654a37" + integrity sha512-oTZLEuD+zLKXyhZC5tDRMPKPj8iaxKLxXiCjqRfOo4xmSbS2izGRWLJbKMYYsJysn/OI3UJ3P6CWP8WUWi0dZg== + dependencies: + "@fractalwagmi/popup-connection" "^1.0.18" + "@solana/wallet-adapter-base" "^0.9.17" + bs58 "^5.0.0" + +"@grpc/grpc-js@^1.8.13": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.11.1.tgz#a92f33e98f1959feffcd1b25a33b113d2c977b70" + integrity sha512-gyt/WayZrVPH2w/UTLansS7F9Nwld472JxxaETamrM8HNlsa+jSLNyKAZmhxI2Me4c3mQHFiS1wWHDY1g1Kthw== + dependencies: + "@grpc/proto-loader" "^0.7.13" + "@js-sdsl/ordered-map" "^4.4.2" -"@floating-ui/react-dom@0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864" - integrity sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg== +"@grpc/proto-loader@^0.7.13": + version "0.7.13" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" + integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== dependencies: - "@floating-ui/dom" "^0.5.3" - use-isomorphic-layout-effect "^1.1.1" + lodash.camelcase "^4.3.0" + long "^5.0.0" + protobufjs "^7.2.5" + yargs "^17.7.2" + +"@headlessui/react@1.6.6": + version "1.6.6" + resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.6.6.tgz#3073c066b85535c9d28783da0a4d9288b5354d0c" + integrity sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q== -"@foresight-tmp/foresight-sdk@^0.1.46": - version "0.1.46" - resolved "https://registry.yarnpkg.com/@foresight-tmp/foresight-sdk/-/foresight-sdk-0.1.46.tgz#f928dde22f424cfd438f8c9116d5ce84f5b56864" - integrity sha512-fqYnT+OrRDe84OWoDGow4KB5KYX/sRP+jg0Ylz0ExdNqoewK8gLmmAg6AvPc+B9ItAhcDhEBf0H/cGG6HpIQdw== +"@helium/address@^4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@helium/address/-/address-4.8.1.tgz#d8d7cefc6aa7791d79eb8759befb821aaccec3ff" + integrity sha512-OEqX9j8m4sIc6bmvGUWV3/AHeuJCBWIl9EvRpS9xOPy+mC17OkDiPwZI35DSbMlAM7cK7+UjKYZvIVQL/aCgSQ== dependencies: - "@project-serum/anchor" "^0.23.0" - "@project-serum/serum" "0.13.64" - "@solana/web3.js" "^1.37.1" - assert "^2.0.0" - axios "^0.24.0" - buffer-layout "^1.2.2" - lodash "^4.17.21" - process "^0.11.10" + bs58 "^5.0.0" + js-sha256 "^0.9.0" + multiformats "^9.6.4" -"@friktion-labs/entropy-client@^1.7.3": - version "1.7.3" - resolved "https://registry.yarnpkg.com/@friktion-labs/entropy-client/-/entropy-client-1.7.3.tgz#741dc326e646df126ac7752f93bccd7f29551f81" - integrity sha512-vpDhYmNG7f+n1u5NNYXhAUproy1X5l05YMPqSCzOx8INyEjyVmMgK45CHCnVJFnIPGxWmChzAmwP7Pd6adUvyQ== +"@helium/circuit-breaker-sdk@^0.0.44": + version "0.0.44" + resolved "https://registry.yarnpkg.com/@helium/circuit-breaker-sdk/-/circuit-breaker-sdk-0.0.44.tgz#7986c89a617f78c00641b36568c8112b84da5026" + integrity sha512-6oMnvX3KO3/dVa66IFxMPKk6mQ+DEAePsEr5NgrlB80SFqRg2JT6MFYEgy3nlY6li4oboZs4ia+vUXxScoZ6UQ== dependencies: - "@project-serum/anchor" "^0.16.2" - "@project-serum/borsh" "^0.2.3" - "@project-serum/serum" "0.13.55" - "@project-serum/sol-wallet-adapter" "^0.2.0" - "@solana/spl-token" "^0.1.6" - "@solana/web3.js" "^1.21.0" - axios "^0.25.0" - big.js "^6.1.1" + "@coral-xyz/anchor" "^0.26.0" + "@helium/idls" "^0.0.44" + "@helium/spl-utils" "^0.0.44" + "@solana/spl-token" "^0.3.6" bn.js "^5.2.0" - buffer-layout "^1.2.1" - dotenv "^10.0.0" - dotenv-expand "^6.0.1" - yargs "^17.0.1" - -"@friktion-labs/friktion-sdk@^1.1.118": - version "1.1.118" - resolved "https://registry.yarnpkg.com/@friktion-labs/friktion-sdk/-/friktion-sdk-1.1.118.tgz#8c7258f4317780e4c6bcffbf8a973ecf87a60cbf" - integrity sha512-fZTqpl6qKsWIQWp+QrHfYP4/f0IbqCuujhJBrH2JjUzXsVjzDKZDFuOv6jOFis4YNPqu5P6Ne2jRJr6OHtrQ8Q== - dependencies: - "@blockworks-foundation/mango-client" "3.4.5" - "@friktion-labs/entropy-client" "^1.7.3" - "@oclif/command" "^1.8.16" - "@project-serum/anchor" "^0.25.0-beta.1" - "@project-serum/common" "^0.0.1-beta.3" - "@project-serum/serum" "^0.13.61" - "@saberhq/anchor-contrib" "1.12.53" - "@saberhq/solana-contrib" "1.12.53" - "@saberhq/token-utils" "1.12.53" - "@solana/spl-token" "^0.1.8" - "@solana/web3.js" "^1.42.0" - "@switchboard-xyz/switchboard-v2" "^0.0.34" - bn.js "^5.2.1" - csv-parse "^5.0.4" - decimal.js "^10.3.1" - fast-csv "^4.3.6" - superagent "^7.1.3" + bs58 "^4.0.1" -"@gar/promisify@^1.0.1": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" - integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@helium/helium-sub-daos-sdk@0.0.44": + version "0.0.44" + resolved "https://registry.yarnpkg.com/@helium/helium-sub-daos-sdk/-/helium-sub-daos-sdk-0.0.44.tgz#57954fdea7cb5334ec1c1726749e4e36c34c1689" + integrity sha512-DqqssOYo+kIqadT0471Q+BoaxVjSmDWkNRJplrbJbTQ3/cHojFHNFWm8/WJwNJWpSkKuAdT94h8VnPZz/KiiBg== + dependencies: + "@coral-xyz/anchor" "0.26.0" + "@helium/circuit-breaker-sdk" "^0.0.44" + "@helium/spl-utils" "^0.0.44" + "@helium/treasury-management-sdk" "^0.0.44" + "@helium/voter-stake-registry-sdk" "^0.0.44" + bn.js "^5.2.0" + bs58 "^4.0.1" -"@hapi/hoek@^9.0.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" - integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== +"@helium/idls@0.0.44", "@helium/idls@^0.0.44": + version "0.0.44" + resolved "https://registry.yarnpkg.com/@helium/idls/-/idls-0.0.44.tgz#fc5870b6c2f39a4a9586702b02d05a32fe0138d6" + integrity sha512-h+QfQQHFqxrYKaGTedN89NvFKwuSIL6ksJBCcIkVRvAJJ8SD38tB9y52Phoh87O3TY0cF6/gpMYJr3pOUM4Cxw== + dependencies: + "@coral-xyz/anchor" "0.26.0" + "@solana/web3.js" "^1.43.4" + bn.js "^5.2.0" + borsh "^0.7.0" + bs58 "^4.0.1" -"@hapi/topo@^5.0.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" - integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== +"@helium/spl-utils@0.0.44", "@helium/spl-utils@^0.0.44": + version "0.0.44" + resolved "https://registry.yarnpkg.com/@helium/spl-utils/-/spl-utils-0.0.44.tgz#d5a71ef5615169d5964c58307018ae7cd3609ec9" + integrity sha512-Yh+8FChoI3Ol1cSHR7VfMos5ivT3RTwFkoxOrPpVMUynCmEh4JXdMjqUtoEeS0JPJoXcFWkrmc26Y6zoBMRUgQ== dependencies: - "@hapi/hoek" "^9.0.0" + "@coral-xyz/anchor" "0.26.0" + "@helium/address" "^4.8.1" + "@solana/spl-token" "^0.3.6" + "@solana/web3.js" "^1.43.4" + bn.js "^5.2.0" + borsh "^0.7.0" + bs58 "^5.0.0" -"@headlessui/react@^1.2.0", "@headlessui/react@^1.6.1", "@headlessui/react@^1.6.6": - version "1.6.6" - resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.6.6.tgz#3073c066b85535c9d28783da0a4d9288b5354d0c" - integrity sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q== +"@helium/treasury-management-sdk@^0.0.44": + version "0.0.44" + resolved "https://registry.yarnpkg.com/@helium/treasury-management-sdk/-/treasury-management-sdk-0.0.44.tgz#213f0aa1c1e54df89a2113d2b793cf44c97be91f" + integrity sha512-DbVYpEKK94zSP1UdYOyHtocroLRWCm9i32jpzkYnPPIqLu4u4c9ns//81iXN2254GFODXkgkRfgqHJTvEWCXtQ== + dependencies: + "@coral-xyz/anchor" "0.26.0" + "@helium/circuit-breaker-sdk" "^0.0.44" + "@helium/idls" "^0.0.44" + "@helium/spl-utils" "^0.0.44" + "@solana/spl-token" "^0.3.6" + bn.js "^5.2.0" + bs58 "^4.0.1" + +"@helium/voter-stake-registry-sdk@0.0.44", "@helium/voter-stake-registry-sdk@^0.0.44": + version "0.0.44" + resolved "https://registry.yarnpkg.com/@helium/voter-stake-registry-sdk/-/voter-stake-registry-sdk-0.0.44.tgz#54bdecc6d1ed1d9982f366c6d740b457ed738548" + integrity sha512-E649yrl8wIeR8IOkuDpuxlqV+3AA1f4uxeGAO4UjriZ33Q7+9cwnStDYDmIPUi/AUEs0e5Uxq5ueSp7sQbsZ+A== + dependencies: + "@coral-xyz/anchor" "0.26.0" + "@helium/idls" "^0.0.44" + "@helium/spl-utils" "^0.0.44" + "@metaplex-foundation/mpl-token-metadata" "^2.2.3" + "@solana/spl-token" "^0.3.6" + bn.js "^5.2.0" + bs58 "^4.0.1" -"@heroicons/react@^1.0.1": +"@heroicons/react@1.0.6": version "1.0.6" resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.6.tgz#35dd26987228b39ef2316db3b1245c42eb19e324" integrity sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ== -"@hookform/resolvers@^2.8.10": +"@hookform/resolvers@2.8.10": version "2.8.10" resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.8.10.tgz#b66d7a7848b1b1dd5b976a73fff36bb366666e7d" integrity sha512-DDFtNlugsbwAhCJHYp3NcN5LvJrwSsCLPi41Wo5O8UAIbUFnBfY/jW+zKnlX57BZ4jE0j/g6R9rB3JlO89ad0g== -"@humanwhocodes/config-array@^0.9.2": - version "0.9.2" - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz" - integrity sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.4" +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@humanwhocodes/retry@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.0.tgz#6d86b8cb322660f03d3f0aa94b99bdd8e172d570" + integrity sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew== -"@identity.com/prove-solana-wallet@0.2.9": - version "0.2.9" - resolved "https://registry.yarnpkg.com/@identity.com/prove-solana-wallet/-/prove-solana-wallet-0.2.9.tgz#b75419a1a7baaed25ac489055c13188c295fcfd4" - integrity sha512-BpDyNbMp1j+yGlGooTd/D8Qs+DtkblvPqBMRjK9pMI2dG6HcAYUaG5NFt+yB9mfl1sGu10LuTBGqL5KS4Ggu8Q== +"@iarna/toml@2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" + integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== + +"@identity.com/prove-solana-wallet@0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@identity.com/prove-solana-wallet/-/prove-solana-wallet-0.4.2.tgz#e4250dbf1e884cd890746c977061342618226bd4" + integrity sha512-pf80VWM+BdeO/H5AcXQ28PFh0YuHHVOjKTYPTvdYreci+F0KZTfMBYHjcA1BESzX8GfRTOb1v+dkSlGeeU39RQ== dependencies: - "@solana/web3.js" "1.39.0" + "@solana/web3.js" "^1.63.1" bs58 "^4.0.1" + tweetnacl "^1.0.3" -"@identity.com/sol-did-client@^2.0.0", "@identity.com/sol-did-client@^2.0.1": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@identity.com/sol-did-client/-/sol-did-client-2.0.2.tgz#001aa84f8975f149852da45b50c8f8b769ea6891" - integrity sha512-1JP5JGGCB2z18/gEMVUpkZKHv2RZ8DCktr2WAiUZ4gUMMyfuDzu1JOeL1XDZl9BE8BSzyKIY0PRvWxubykt7Mw== +"@identity.com/sol-did-client-legacy@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@identity.com/sol-did-client-legacy/-/sol-did-client-legacy-2.0.4.tgz#95b7be01f0022cd34abaee37cc11750f423f1b54" + integrity sha512-+LrYg0g3UriEMLpOrzFFZ17eeCA3Ynuyg5cbaAFnoV5bmMCOKr8Y03DERQWrtagfvVJBsWBtz6h6v/ZQSzxnlQ== dependencies: "@solana/web3.js" "^1.21.0" bn.js "^4.12.0" @@ -2535,25 +1702,58 @@ did-resolver "^3.0.1" ramda "^0.27.1" -"@identity.com/solana-gateway-ts@^0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@identity.com/solana-gateway-ts/-/solana-gateway-ts-0.7.0.tgz#61ece3f781148b040778bc936128039e52918ecc" - integrity sha512-hxOHbQDH3mQ6cBIvEsUZFICJAfgv0V8GB2QpnvXwHoAnPVRpYACHb98P2i93gwyC+jFUEJ5fOQo4eaa06bnAvw== +"@identity.com/sol-did-client@3.3.0", "@identity.com/sol-did-client@^3.1.4": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@identity.com/sol-did-client/-/sol-did-client-3.3.0.tgz#05df2f37d0d4c19b4eeeacde7842f552b0c5d0a2" + integrity sha512-v/hPHocEG0eaWyOUvLIMcl8+EDVXNFxX4EHInn/UsFpTrjg73ZIcPTEylWlRBF4mvBf1Qt7CuV60jK6H36GfNQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@identity.com/sol-did-client-legacy" "^2.0.4" + "@identity.com/sol-did-idl" "^3.1.0" + "@project-serum/anchor" "0.26.0" + "@solana/web3.js" "^1.59.1" + bs58 "^5.0.0" + did-resolver "^3.2.2" + +"@identity.com/sol-did-idl@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@identity.com/sol-did-idl/-/sol-did-idl-3.1.0.tgz#dfd00b0f80aeed25ff898a7bd95320df3abc337d" + integrity sha512-umy6Adt9d7v50iduN02L5hzxK9742va0yZxFDsTopXcYAgTW/jQ/xsR5Q4VTuqJXtn6szhIO1q0hbNHScq22Cg== + +"@identity.com/solana-gateway-ts@^0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@identity.com/solana-gateway-ts/-/solana-gateway-ts-0.12.0.tgz#8954dfacd0c4f3b02437541d6ab15a8069a6814b" + integrity sha512-VF3sjYLu9mD2fvSyTfR07HYRz3LnEhZPtqZ53Jmm3+CnlabsVLLShSvCvPSz+4TQtD/4gNKMG1VAJenxBr8W5Q== dependencies: - "@solana/web3.js" "^1.22.0" + "@solana/web3.js" "^1.63.0" async-retry "^1.3.3" bn.js "^5.2.0" borsh "^0.4.0" + bs58 "^5.0.0" ramda "^0.27.1" -"@isaacs/string-locale-compare@^1.0.1", "@isaacs/string-locale-compare@^1.1.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz" - integrity sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ== +"@ioredis/commands@^1.1.1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" + integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" - resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== dependencies: camelcase "^5.3.1" find-up "^4.1.0" @@ -2563,169 +1763,193 @@ "@istanbuljs/schema@^0.1.2": version "0.1.3" - resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^27.4.2": - version "27.4.2" - resolved "https://registry.npmjs.org/@jest/console/-/console-27.4.2.tgz" - integrity sha512-xknHThRsPB/To1FUbi6pCe43y58qFC03zfb6R7fDb/FfC7k2R3i1l+izRBJf8DI46KhYGRaF14Eo9A3qbBoixg== +"@jest/console@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.3.1.tgz#3e3f876e4e47616ea3b1464b9fbda981872e9583" + integrity sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^29.3.1" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^27.4.2" - jest-util "^27.4.2" + jest-message-util "^29.3.1" + jest-util "^29.3.1" slash "^3.0.0" -"@jest/core@^27.4.5": - version "27.4.5" - resolved "https://registry.npmjs.org/@jest/core/-/core-27.4.5.tgz" - integrity sha512-3tm/Pevmi8bDsgvo73nX8p/WPng6KWlCyScW10FPEoN1HU4pwI83tJ3TsFvi1FfzsjwUlMNEPowgb/rPau/LTQ== +"@jest/core@^29.2.0", "@jest/core@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.3.1.tgz#bff00f413ff0128f4debec1099ba7dcd649774a1" + integrity sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw== dependencies: - "@jest/console" "^27.4.2" - "@jest/reporters" "^27.4.5" - "@jest/test-result" "^27.4.2" - "@jest/transform" "^27.4.5" - "@jest/types" "^27.4.2" + "@jest/console" "^29.3.1" + "@jest/reporters" "^29.3.1" + "@jest/test-result" "^29.3.1" + "@jest/transform" "^29.3.1" + "@jest/types" "^29.3.1" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - emittery "^0.8.1" + ci-info "^3.2.0" exit "^0.1.2" - graceful-fs "^4.2.4" - jest-changed-files "^27.4.2" - jest-config "^27.4.5" - jest-haste-map "^27.4.5" - jest-message-util "^27.4.2" - jest-regex-util "^27.4.0" - jest-resolve "^27.4.5" - jest-resolve-dependencies "^27.4.5" - jest-runner "^27.4.5" - jest-runtime "^27.4.5" - jest-snapshot "^27.4.5" - jest-util "^27.4.2" - jest-validate "^27.4.2" - jest-watcher "^27.4.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.2.0" + jest-config "^29.3.1" + jest-haste-map "^29.3.1" + jest-message-util "^29.3.1" + jest-regex-util "^29.2.0" + jest-resolve "^29.3.1" + jest-resolve-dependencies "^29.3.1" + jest-runner "^29.3.1" + jest-runtime "^29.3.1" + jest-snapshot "^29.3.1" + jest-util "^29.3.1" + jest-validate "^29.3.1" + jest-watcher "^29.3.1" micromatch "^4.0.4" - rimraf "^3.0.0" + pretty-format "^29.3.1" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^27.4.4": - version "27.4.4" - resolved "https://registry.npmjs.org/@jest/environment/-/environment-27.4.4.tgz" - integrity sha512-q+niMx7cJgt/t/b6dzLOh4W8Ef/8VyKG7hxASK39jakijJzbFBGpptx3RXz13FFV7OishQ9lTbv+dQ5K3EhfDQ== +"@jest/environment@^29.2.2", "@jest/environment@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.3.1.tgz#eb039f726d5fcd14698acd072ac6576d41cfcaa6" + integrity sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag== dependencies: - "@jest/fake-timers" "^27.4.2" - "@jest/types" "^27.4.2" + "@jest/fake-timers" "^29.3.1" + "@jest/types" "^29.3.1" "@types/node" "*" - jest-mock "^27.4.2" + jest-mock "^29.3.1" + +"@jest/expect-utils@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.3.1.tgz#531f737039e9b9e27c42449798acb5bba01935b6" + integrity sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g== + dependencies: + jest-get-type "^29.2.0" + +"@jest/expect@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.3.1.tgz#456385b62894349c1d196f2d183e3716d4c6a6cd" + integrity sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg== + dependencies: + expect "^29.3.1" + jest-snapshot "^29.3.1" -"@jest/fake-timers@^27.4.2": - version "27.4.2" - resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.4.2.tgz" - integrity sha512-f/Xpzn5YQk5adtqBgvw1V6bF8Nx3hY0OIRRpCvWcfPl0EAjdqWPdhH3t/3XpiWZqtjIEHDyMKP9ajpva1l4Zmg== +"@jest/fake-timers@^29.2.2", "@jest/fake-timers@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.3.1.tgz#b140625095b60a44de820876d4c14da1aa963f67" + integrity sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A== dependencies: - "@jest/types" "^27.4.2" - "@sinonjs/fake-timers" "^8.0.1" + "@jest/types" "^29.3.1" + "@sinonjs/fake-timers" "^9.1.2" "@types/node" "*" - jest-message-util "^27.4.2" - jest-mock "^27.4.2" - jest-util "^27.4.2" + jest-message-util "^29.3.1" + jest-mock "^29.3.1" + jest-util "^29.3.1" -"@jest/globals@^27.4.4": - version "27.4.4" - resolved "https://registry.npmjs.org/@jest/globals/-/globals-27.4.4.tgz" - integrity sha512-bqpqQhW30BOreXM8bA8t8JbOQzsq/WnPTnBl+It3UxAD9J8yxEAaBEylHx1dtBapAr/UBk8GidXbzmqnee8tYQ== +"@jest/globals@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.3.1.tgz#92be078228e82d629df40c3656d45328f134a0c6" + integrity sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q== dependencies: - "@jest/environment" "^27.4.4" - "@jest/types" "^27.4.2" - expect "^27.4.2" + "@jest/environment" "^29.3.1" + "@jest/expect" "^29.3.1" + "@jest/types" "^29.3.1" + jest-mock "^29.3.1" -"@jest/reporters@^27.4.5": - version "27.4.5" - resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-27.4.5.tgz" - integrity sha512-3orsG4vi8zXuBqEoy2LbnC1kuvkg1KQUgqNxmxpQgIOQEPeV0onvZu+qDQnEoX8qTQErtqn/xzcnbpeTuOLSiA== +"@jest/reporters@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.3.1.tgz#9a6d78c109608e677c25ddb34f907b90e07b4310" + integrity sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^27.4.2" - "@jest/test-result" "^27.4.2" - "@jest/transform" "^27.4.5" - "@jest/types" "^27.4.2" + "@jest/console" "^29.3.1" + "@jest/test-result" "^29.3.1" + "@jest/transform" "^29.3.1" + "@jest/types" "^29.3.1" + "@jridgewell/trace-mapping" "^0.3.15" "@types/node" "*" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" - glob "^7.1.2" - graceful-fs "^4.2.4" + glob "^7.1.3" + graceful-fs "^4.2.9" istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^4.0.3" + istanbul-lib-instrument "^5.1.0" istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.0.2" - jest-haste-map "^27.4.5" - jest-resolve "^27.4.5" - jest-util "^27.4.2" - jest-worker "^27.4.5" + istanbul-reports "^3.1.3" + jest-message-util "^29.3.1" + jest-util "^29.3.1" + jest-worker "^29.3.1" slash "^3.0.0" - source-map "^0.6.0" string-length "^4.0.1" - terminal-link "^2.0.0" - v8-to-istanbul "^8.1.0" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.0.0": + version "29.0.0" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" + integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== + dependencies: + "@sinclair/typebox" "^0.24.1" -"@jest/source-map@^27.4.0": - version "27.4.0" - resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-27.4.0.tgz" - integrity sha512-Ntjx9jzP26Bvhbm93z/AKcPRj/9wrkI88/gK60glXDx1q+IeI0rf7Lw2c89Ch6ofonB0On/iRDreQuQ6te9pgQ== +"@jest/source-map@^29.2.0": + version "29.2.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.2.0.tgz#ab3420c46d42508dcc3dc1c6deee0b613c235744" + integrity sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ== dependencies: + "@jridgewell/trace-mapping" "^0.3.15" callsites "^3.0.0" - graceful-fs "^4.2.4" - source-map "^0.6.0" + graceful-fs "^4.2.9" -"@jest/test-result@^27.4.2": - version "27.4.2" - resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-27.4.2.tgz" - integrity sha512-kr+bCrra9jfTgxHXHa2UwoQjxvQk3Am6QbpAiJ5x/50LW8llOYrxILkqY0lZRW/hu8FXesnudbql263+EW9iNA== +"@jest/test-result@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.3.1.tgz#92cd5099aa94be947560a24610aa76606de78f50" + integrity sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw== dependencies: - "@jest/console" "^27.4.2" - "@jest/types" "^27.4.2" + "@jest/console" "^29.3.1" + "@jest/types" "^29.3.1" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^27.4.5": - version "27.4.5" - resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.4.5.tgz" - integrity sha512-n5woIn/1v+FT+9hniymHPARA9upYUmfi5Pw9ewVwXCDlK4F5/Gkees9v8vdjGdAIJ2MPHLHodiajLpZZanWzEQ== +"@jest/test-sequencer@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz#fa24b3b050f7a59d48f7ef9e0b782ab65123090d" + integrity sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA== dependencies: - "@jest/test-result" "^27.4.2" - graceful-fs "^4.2.4" - jest-haste-map "^27.4.5" - jest-runtime "^27.4.5" + "@jest/test-result" "^29.3.1" + graceful-fs "^4.2.9" + jest-haste-map "^29.3.1" + slash "^3.0.0" -"@jest/transform@^27.4.5": - version "27.4.5" - resolved "https://registry.npmjs.org/@jest/transform/-/transform-27.4.5.tgz" - integrity sha512-PuMet2UlZtlGzwc6L+aZmR3I7CEBpqadO03pU40l2RNY2fFJ191b9/ITB44LNOhVtsyykx0OZvj0PCyuLm7Eew== +"@jest/transform@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.3.1.tgz#1e6bd3da4af50b5c82a539b7b1f3770568d6e36d" + integrity sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug== dependencies: - "@babel/core" "^7.1.0" - "@jest/types" "^27.4.2" - babel-plugin-istanbul "^6.0.0" + "@babel/core" "^7.11.6" + "@jest/types" "^29.3.1" + "@jridgewell/trace-mapping" "^0.3.15" + babel-plugin-istanbul "^6.1.1" chalk "^4.0.0" - convert-source-map "^1.4.0" - fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.2.4" - jest-haste-map "^27.4.5" - jest-regex-util "^27.4.0" - jest-util "^27.4.2" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.3.1" + jest-regex-util "^29.2.0" + jest-util "^29.3.1" micromatch "^4.0.4" - pirates "^4.0.1" + pirates "^4.0.4" slash "^3.0.0" - source-map "^0.6.1" - write-file-atomic "^3.0.0" + write-file-atomic "^4.0.1" "@jest/types@^26.6.2": version "26.6.2" - resolved "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" @@ -2733,58 +1957,69 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@jest/types@^27.4.2": - version "27.4.2" - resolved "https://registry.npmjs.org/@jest/types/-/types-27.4.2.tgz" - integrity sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg== +"@jest/types@^29.2.0", "@jest/types@^29.2.1", "@jest/types@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.3.1.tgz#7c5a80777cb13e703aeec6788d044150341147e3" + integrity sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA== dependencies: + "@jest/schemas" "^29.0.0" "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" "@types/node" "*" - "@types/yargs" "^16.0.0" + "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jet-lab/jet-engine@^0.2.15": - version "0.2.50" - resolved "https://registry.yarnpkg.com/@jet-lab/jet-engine/-/jet-engine-0.2.50.tgz#55dc001018a0eb012940e21563a2c40582352eeb" - integrity sha512-N73kuVmJiPoQUTAVTHX88qRVQp2w3YBhHWj089AYCx/Ao8xxHea5LggZVP/NYM+dji/13BKeCeoUoUo2S9tUGA== +"@jnwng/walletconnect-solana@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@jnwng/walletconnect-solana/-/walletconnect-solana-0.2.0.tgz#aebea64beaa47273b9b9a71c62d88d543900ab96" + integrity sha512-nyRq0xLEj9i2J4UXQ0Mr4KzsooTMbLu0ewHOqdQV7iZE0PfbtKa8poTSF4ZBAQD8hoMHEx+I7zGFCNMI9BTrTA== dependencies: - "@project-serum/anchor" "^0.23.0" - "@project-serum/serum" "^0.13.60" - "@pythnetwork/client" "^2.5.1" - "@solana/buffer-layout" "^4.0.0" - "@solana/buffer-layout-utils" "^0.2.0" - "@solana/spl-governance" "^0.0.29" - "@solana/spl-token" "^0.2.0" - "@solana/web3.js" "^1.36.0" - eventemitter3 "^4.0.7" - lodash "^4.17.21" - react "^17.0.0" - react-dom "^17.0.0" + "@walletconnect/qrcode-modal" "^1.8.0" + "@walletconnect/sign-client" "^2.7.2" + "@walletconnect/utils" "^2.4.5" + bs58 "^5.0.0" -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9" - integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg== +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== dependencies: "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + "@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== -"@jridgewell/set-array@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" - integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" - integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -2794,102 +2029,251 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.13" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" - integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w== +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@js-sdsl/ordered-map@^4.4.2": + version "4.4.2" + resolved "https://registry.yarnpkg.com/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz#9299f82874bab9e4c7f9c48d865becbfe8d6907c" + integrity sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw== + +"@json-rpc-tools/provider@^1.5.5": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@json-rpc-tools/provider/-/provider-1.7.6.tgz#8a17c34c493fa892632e278fd9331104e8491ec6" + integrity sha512-z7D3xvJ33UfCGv77n40lbzOYjZKVM3k2+5cV7xS8G6SCvKTzMkhkUYuD/qzQUNT4cG/lv0e9mRToweEEVLVVmA== + dependencies: + "@json-rpc-tools/utils" "^1.7.6" + axios "^0.21.0" + safe-json-utils "^1.1.1" + ws "^7.4.0" -"@ledgerhq/devices@^6.20.0": - version "6.20.0" - resolved "https://registry.npmjs.org/@ledgerhq/devices/-/devices-6.20.0.tgz" - integrity sha512-WehM7HGdb+nSUzyUlz1t2qJ8Tg4I+rQkOJJsx0/Dpjkx6/+1hHcX6My/apPuwh39qahqwYhjszq0H1YzGDS0Yg== +"@json-rpc-tools/types@^1.7.6": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@json-rpc-tools/types/-/types-1.7.6.tgz#5abd5fde01364a130c46093b501715bcce5bdc0e" + integrity sha512-nDSqmyRNEqEK9TZHtM15uNnDljczhCUdBmRhpNZ95bIPKEDQ+nTDmGMFd2lLin3upc5h2VVVd9tkTDdbXUhDIQ== + dependencies: + keyvaluestorage-interface "^1.0.0" + +"@json-rpc-tools/utils@^1.7.6": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@json-rpc-tools/utils/-/utils-1.7.6.tgz#67f04987dbaa2e7adb6adff1575367b75a9a9ba1" + integrity sha512-HjA8x/U/Q78HRRe19yh8HVKoZ+Iaoo3YZjakJYxR+rw52NHo6jM+VE9b8+7ygkCFXl/EHID5wh/MkXaE/jGyYw== + dependencies: + "@json-rpc-tools/types" "^1.7.6" + "@pedrouid/environment" "^1.0.1" + +"@jup-ag/referral-sdk@0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@jup-ag/referral-sdk/-/referral-sdk-0.1.5.tgz#02a8bc901154659e75a5f31ae9a3e3edd28cd6cd" + integrity sha512-0R/NuBkIj2otpLnatacZqIwVAwL+OIheSlT+a2atAaNuf2WceL4lKZ/EZWm1AVTFhmFd/07HHN9PJ2fma9AMPA== + dependencies: + "@coral-xyz/anchor" "0.28.1-beta.2" + "@solana/spl-token" "0.3.8" + "@solana/web3.js" "^1.77.3" + lodash "^4.17.21" + +"@keystonehq/bc-ur-registry-sol@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@keystonehq/bc-ur-registry-sol/-/bc-ur-registry-sol-0.3.1.tgz#5319c7c4a22cc83bbacfa6fe09aaa6fb21363f24" + integrity sha512-Okr5hwPxBZxB4EKLK1GSC9vsrh/tFMQ5dvs3EQ9NCOmCn7CXdXIMSeafrpGCHk484Jf5c6X0Wq0yf0VqY2A/8Q== + dependencies: + "@keystonehq/bc-ur-registry" "^0.5.0" + bs58check "^2.1.2" + uuid "^8.3.2" + +"@keystonehq/bc-ur-registry@^0.5.0": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@keystonehq/bc-ur-registry/-/bc-ur-registry-0.5.3.tgz#c3861f18ccc402f006d417da2db5a8bb6a0bb5c5" + integrity sha512-HMFdfTeJB9C2gxvNf4FLmddRbBaLxouokj3QFg0/bMRwDU1w2usAo8VnXURrWsRV256RJLalbX52V6CerjW17w== + dependencies: + "@ngraveio/bc-ur" "^1.1.5" + bs58check "^2.1.2" + tslib "^2.3.0" + +"@keystonehq/sdk@^0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@keystonehq/sdk/-/sdk-0.13.1.tgz#782a1f71cfc38a7635a8bcb0cb99ae403a6316a8" + integrity sha512-545l83TE5t1cyUZUaNqZOAh15ibWOg9QbK/YeLwnrxt+GOod+ATk3j9SpN6yTSLO8DNl2/x6dKRIFVtTEkZDAg== + dependencies: + "@ngraveio/bc-ur" "^1.0.0" + qrcode.react "^1.0.1" + react "16.13.1" + react-dom "16.13.1" + react-modal "^3.12.1" + react-qr-reader "^2.2.1" + rxjs "^6.6.3" + typescript "^4.6.2" + +"@keystonehq/sol-keyring@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@keystonehq/sol-keyring/-/sol-keyring-0.3.1.tgz#9ed61269bab92601eedb7f1adb9ca3258634dbbc" + integrity sha512-RU6I3HQrQ9NpRDP9TwlBIy5DftVcNcyk0NWfhkPy/YanhMcCB0cRPw68iQl1rMnR6n1G2+YrBHMxm6swCW+B4Q== + dependencies: + "@keystonehq/bc-ur-registry" "^0.5.0" + "@keystonehq/bc-ur-registry-sol" "^0.3.1" + "@keystonehq/sdk" "^0.13.1" + "@solana/web3.js" "^1.36.0" + bs58 "^5.0.0" + uuid "^8.3.2" + +"@lavamoat/aa@^3.1.1": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@lavamoat/aa/-/aa-3.1.2.tgz#3e2c0bbff791204bb4dabe96c2486b0c910e1897" + integrity sha512-oHKUcSzCDxpICm247dH28no8k0VXURPVOS6jWx7GcoW9XowObqoiWSrX90folzEaaQq9HvO4X2OWvTubUm/0Qg== + dependencies: + resolve "^1.20.0" + +"@lavamoat/allow-scripts@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@lavamoat/allow-scripts/-/allow-scripts-2.3.0.tgz#f1bcf4b7c8866a87a17c1c4334f50fd168c9eb4f" + integrity sha512-Tp4qQsJ02RPPZwioI+SBrMo8HuUSWpDqGw7vjigioXnFo8k7UITQBwroZ7qUcp8avJSCOgnZDytMawgYbCFpOA== + dependencies: + "@lavamoat/aa" "^3.1.1" + "@npmcli/run-script" "^1.8.1" + bin-links "4.0.1" + npm-normalize-package-bin "^3.0.0" + yargs "^16.2.0" + +"@lavamoat/preinstall-always-fail@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@lavamoat/preinstall-always-fail/-/preinstall-always-fail-1.0.0.tgz#e78a6e3d9e212a4fef869ec37d4f5fb498dea373" + integrity sha512-vD2DcC0ffJj1w2y1Lu0OU39wHmlPEd2tCDW04Bm6Kf4LyRnCHCezTsS8yzeSJ+4so7XP+TITuR5FGJRWxPb+GA== + +"@ledgerhq/devices@6.27.1", "@ledgerhq/devices@^6.27.1": + version "6.27.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-6.27.1.tgz#3b13ab1d1ba8201e9e74a08f390560483978c962" + integrity sha512-jX++oy89jtv7Dp2X6gwt3MMkoajel80JFWcdc0HCouwDsV1mVJ3SQdwl/bQU0zd8HI6KebvUP95QTwbQLLK/RQ== dependencies: "@ledgerhq/errors" "^6.10.0" "@ledgerhq/logs" "^6.10.0" rxjs "6" semver "^7.3.5" -"@ledgerhq/errors@^6.10.0": - version "6.10.0" - resolved "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.10.0.tgz" - integrity sha512-fQFnl2VIXh9Yd41lGjReCeK+Q2hwxQJvLZfqHnKqWapTz68NHOv5QcI0OHuZVNEbv0xhgdLhi5b65kgYeQSUVg== +"@ledgerhq/devices@^7.0.5": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-7.0.5.tgz#2b3f69b84d4bccb2c4b1d34e534444da862f4880" + integrity sha512-2o2zD2Yv1Hgd3+R2aLCvlyT7NxBz2nltawTCPSXaf3+8MDIyZbiJlXi43hLEISRFBG3u3bYwAQuiOisimN9C6Q== + dependencies: + "@ledgerhq/errors" "^6.12.1" + "@ledgerhq/logs" "^6.10.1" + rxjs "6" + semver "^7.3.5" + +"@ledgerhq/errors@^6.10.0", "@ledgerhq/errors@^6.12.1": + version "6.12.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-6.12.1.tgz#99ad10bd528942bdfde0ef3d4d0dce658f6f4405" + integrity sha512-2qeUSUCpQbMhV9eLJDLI8wycFwTcWszP8g3cJycBt9Jf1VczC5MRERwAQv5AYhPa4rcy+jLKBOVZYxc35r5l7g== + +"@ledgerhq/hw-transport-webhid@6.27.1": + version "6.27.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-6.27.1.tgz#8fd1710d23b6bd7cbe2382dd02054dfabe788447" + integrity sha512-u74rBYlibpbyGblSn74fRs2pMM19gEAkYhfVibq0RE1GNFjxDMFC1n7Sb+93Jqmz8flyfB4UFJsxs8/l1tm2Kw== + dependencies: + "@ledgerhq/devices" "^6.27.1" + "@ledgerhq/errors" "^6.10.0" + "@ledgerhq/hw-transport" "^6.27.1" + "@ledgerhq/logs" "^6.10.0" -"@ledgerhq/hw-transport-webusb@^6.20.0": - version "6.20.0" - resolved "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.20.0.tgz" - integrity sha512-7rtgOEuEZ7/O5JofcglUVck7RXH5D8vS3zP5SjPURhvSFiJVGrtOVS+Qna7gXqGdkesDcNF0xBkwme+67n4Imw== +"@ledgerhq/hw-transport-webusb@6.27.1": + version "6.27.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.27.1.tgz#62be3b2e5f0d54ae06d066571e4408a807d0f01f" + integrity sha512-n0ygJSeRpznrUfwtbDCLQOM5mA23YT/ngYY8HU46dzsVJHrHQ4jwBNJU48iKB+a9GhHyPAUpPNlWGTogvoVUxg== dependencies: - "@ledgerhq/devices" "^6.20.0" + "@ledgerhq/devices" "^6.27.1" "@ledgerhq/errors" "^6.10.0" - "@ledgerhq/hw-transport" "^6.20.0" + "@ledgerhq/hw-transport" "^6.27.1" "@ledgerhq/logs" "^6.10.0" -"@ledgerhq/hw-transport@^6.20.0": - version "6.20.0" - resolved "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.20.0.tgz" - integrity sha512-5KS0Y6CbWRDOv3FgNIfk53ViQOIZqMxAw0RuOexreW5GMwuYfK7ddGi4142qcu7YrxkGo7cNe42wBbx1hdXl0Q== +"@ledgerhq/hw-transport@6.27.1": + version "6.27.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.27.1.tgz#88072278f69c279cb6569352acd4ae2fec33ace3" + integrity sha512-hnE4/Fq1YzQI4PA1W0H8tCkI99R3UWDb3pJeZd6/Xs4Qw/q1uiQO+vNLC6KIPPhK0IajUfuI/P2jk0qWcMsuAQ== dependencies: - "@ledgerhq/devices" "^6.20.0" + "@ledgerhq/devices" "^6.27.1" "@ledgerhq/errors" "^6.10.0" events "^3.3.0" -"@ledgerhq/logs@^6.10.0": - version "6.10.0" - resolved "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.10.0.tgz" - integrity sha512-lLseUPEhSFUXYTKj6q7s2O3s2vW2ebgA11vMAlKodXGf5AFw4zUoEbTz9CoFOC9jS6xY4Qr8BmRnxP/odT4Uuw== +"@ledgerhq/hw-transport@^6.27.1": + version "6.27.8" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.27.8.tgz#57ece7e2b726216df698767de6828478fbe461e1" + integrity sha512-WSUgF1W3tAikSnAfeNAT2e2dgTdEQd5Vi/095C2mR5Fr0/POCSl9X4T9rlBhK5NSVD+nGXI0rN2ISj08zai8HQ== + dependencies: + "@ledgerhq/devices" "^7.0.5" + "@ledgerhq/errors" "^6.12.1" + events "^3.3.0" + +"@ledgerhq/logs@^6.10.0", "@ledgerhq/logs@^6.10.1": + version "6.10.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-6.10.1.tgz#5bd16082261d7364eabb511c788f00937dac588d" + integrity sha512-z+ILK8Q3y+nfUl43ctCPuR4Y2bIxk/ooCQFwZxhtci1EhAtMDzMAx2W25qx8G1PPL9UUOdnUax19+F0OjXoj4w== -"@marinade.finance/marinade-ts-sdk@^2.0.9": +"@marinade.finance/marinade-ts-sdk@2.0.9": version "2.0.9" - resolved "https://registry.npmjs.org/@marinade.finance/marinade-ts-sdk/-/marinade-ts-sdk-2.0.9.tgz" + resolved "https://registry.yarnpkg.com/@marinade.finance/marinade-ts-sdk/-/marinade-ts-sdk-2.0.9.tgz#0268d8776480d613cab43dbec913749242454148" integrity sha512-teXINCXLTfspXzwNKDtfluZ/wvKBQmcQH2j7SNcFAbJzK6NYo3RdYALu4IHIXMwLs9hEs7XZU8AsKKh+HSLPLA== dependencies: "@project-serum/anchor" "^0.18.2" "@solana/spl-token" "^0.1.8" borsh "^0.6.0" -"@metaplex-foundation/beet-solana@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet-solana/-/beet-solana-0.1.1.tgz#85deec5d3354ee1da868bd6bb0de5ae1ea92d209" - integrity sha512-QV2DbxjaJWLkMvn12OC09g+r7a6R0uNwf8msYuOUSw4cG7amXzvFb7s0bh4IxY3Rk8/0ma0PfKi/FEdC7Hi4Pg== +"@mean-dao/payment-streaming@4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@mean-dao/payment-streaming/-/payment-streaming-4.0.3.tgz#6ad5ecc705eba86b204dade0910bf531095818ef" + integrity sha512-l/cZuUZ6OLEKCRcVe5T3jJL/99A0pvjTj35EH/M1EPBjrNA4phwqPCumylEVKOl84B5z9OsTMnAHXUrnxe9GNw== + dependencies: + "@project-serum/anchor" "^0.24.2" + "@solana/spl-token" "^0.1.8" + "@solana/web3.js" "1.56.0" + bignumber.js "^9.1.0" + bn.js "^5.2.0" + +"@metaplex-foundation/beet-solana@0.4.0", "@metaplex-foundation/beet-solana@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet-solana/-/beet-solana-0.4.0.tgz#52891e78674aaa54e0031f1bca5bfbc40de12e8d" + integrity sha512-B1L94N3ZGMo53b0uOSoznbuM5GBNJ8LwSeznxBxJ+OThvfHQ4B5oMUqb+0zdLRfkKGS7Q6tpHK9P+QK0j3w2cQ== dependencies: "@metaplex-foundation/beet" ">=0.1.0" - "@solana/web3.js" "^1.31.0" + "@solana/web3.js" "^1.56.2" + bs58 "^5.0.0" + debug "^4.3.4" -"@metaplex-foundation/beet-solana@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet-solana/-/beet-solana-0.3.0.tgz#28180e1f31a94fe0e926f3728c8a25d8f02ec562" - integrity sha512-7kl9E7PWKshYCKVAE/EB6s0wXPmqyubwMbfuRHlgECQoX7RM+4OlnC156WUThOsHBy8GeZxSwc6te6PkgqED4A== +"@metaplex-foundation/beet-solana@^0.3.0", "@metaplex-foundation/beet-solana@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet-solana/-/beet-solana-0.3.1.tgz#4b37cda5c7f32ffd2bdd8b3164edc05c6463ab35" + integrity sha512-tgyEl6dvtLln8XX81JyBvWjIiEcjTkUwZbrM5dIobTmoqMuGewSyk9CClno8qsMsFdB5T3jC91Rjeqmu/6xk2g== dependencies: "@metaplex-foundation/beet" ">=0.1.0" - "@solana/web3.js" "^1.44.0" + "@solana/web3.js" "^1.56.2" bs58 "^5.0.0" debug "^4.3.4" -"@metaplex-foundation/beet@>=0.1.0", "@metaplex-foundation/beet@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.4.0.tgz#eb2a0a6eb084bb25d67dd9bed2f7387ee7e63a55" - integrity sha512-2OAKJnLatCc3mBXNL0QmWVQKAWK2C7XDfepgL0p/9+8oSx4bmRAFHFqptl1A/C0U5O3dxGwKfmKluW161OVGcA== +"@metaplex-foundation/beet@0.7.1", "@metaplex-foundation/beet@>=0.1.0", "@metaplex-foundation/beet@^0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.7.1.tgz#0975314211643f87b5f6f3e584fa31abcf4c612c" + integrity sha512-hNCEnS2WyCiYyko82rwuISsBY3KYpe828ubsd2ckeqZr7tl0WVLivGkoyA/qdiaaHEBGdGl71OpfWa2rqL3DiA== dependencies: ansicolors "^0.3.2" bn.js "^5.2.0" debug "^4.3.3" -"@metaplex-foundation/beet@^0.1.0": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.1.4.tgz#888dfd68fbbb027c045a4b6649bfc85b04610e26" - integrity sha512-gUlgl4h9XzSvSx7lUDvYQuy1eMxu4UXbt5MSR9K/dYIHHd3gcCxm8/6vn0VnUXMvpwVHS8tezxlsaKu+TIu6zQ== +"@metaplex-foundation/beet@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.4.0.tgz#eb2a0a6eb084bb25d67dd9bed2f7387ee7e63a55" + integrity sha512-2OAKJnLatCc3mBXNL0QmWVQKAWK2C7XDfepgL0p/9+8oSx4bmRAFHFqptl1A/C0U5O3dxGwKfmKluW161OVGcA== dependencies: ansicolors "^0.3.2" bn.js "^5.2.0" debug "^4.3.3" -"@metaplex-foundation/beet@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.2.0.tgz#e543e17fd1c4dc1251e9aea481a7429bc73f70b8" - integrity sha512-H570hkJxmx/FxET1OggPPLkPL7psYQa71rNI9NJjYRM8WXdrEvmI/IRIEUW2KR6RqwWWN3FvlRHnKoQUV/lQtA== +"@metaplex-foundation/beet@^0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.6.1.tgz#6331bdde0648bf2cae6f9e482f8e3552db05d69f" + integrity sha512-OYgnijLFzw0cdUlRKH5POp0unQECPOW9muJ2X3QIVyak5G6I6l/rKo72sICgPLIFKdmsi2jmnkuLY7wp14iXdw== dependencies: ansicolors "^0.3.2" bn.js "^5.2.0" @@ -2900,92 +2284,116 @@ resolved "https://registry.yarnpkg.com/@metaplex-foundation/cusper/-/cusper-0.0.2.tgz#dc2032a452d6c269e25f016aa4dd63600e2af975" integrity sha512-S9RulC2fFCFOQraz61bij+5YCHhSO9llJegK8c8Y6731fSi6snUSQJdCUqYS8AIgR0TKbQvdvgSyIIdbDFZbBA== -"@metaplex-foundation/js@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/js/-/js-0.12.0.tgz#e16528ec306abe0fa194840b7f3d734cb28ebb15" - integrity sha512-qi4v0NcDz5VLL2GEOC9AU8GSywcuZAgyfvQ/V43EWZuYRfEEHuh+qcn7/EvP/pjC4HyCRIXIRct5R84vBaQipQ== - dependencies: - "@aws-sdk/client-s3" "^3.54.1" - "@bundlr-network/client" "^0.7.14" - "@metaplex-foundation/beet" "^0.2.0" - "@metaplex-foundation/beet-solana" "^0.1.1" - "@metaplex-foundation/mpl-auction-house" "^2.0.0" - "@metaplex-foundation/mpl-candy-machine" "^4.3.0" - "@metaplex-foundation/mpl-token-metadata" "^2.1.2" - "@solana/spl-token" "^0.2.0" - "@solana/web3.js" "^1.47.3" - abort-controller "^3.0.0" +"@metaplex-foundation/js@0.19.4": + version "0.19.4" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/js/-/js-0.19.4.tgz#992fe6b48e8dd0374d99028a07f75547cb6381d7" + integrity sha512-fiAaMl4p7v1tcU7ZoEr1lCzE6JR2gEWGeHOBarLTpiCjMe8ni3E+cukJQC6p0Ik+Z6IIFtEVNNy5OnMS3LLS4A== + dependencies: + "@bundlr-network/client" "^0.8.8" + "@metaplex-foundation/beet" "0.7.1" + "@metaplex-foundation/mpl-auction-house" "^2.3.0" + "@metaplex-foundation/mpl-bubblegum" "^0.6.2" + "@metaplex-foundation/mpl-candy-guard" "^0.3.0" + "@metaplex-foundation/mpl-candy-machine" "^5.0.0" + "@metaplex-foundation/mpl-candy-machine-core" "^0.1.2" + "@metaplex-foundation/mpl-token-metadata" "^2.11.0" + "@noble/ed25519" "^1.7.1" + "@noble/hashes" "^1.1.3" + "@solana/spl-account-compression" "^0.1.8" + "@solana/spl-token" "^0.3.5" + "@solana/web3.js" "^1.63.1" bignumber.js "^9.0.2" - bn.js "^5.2.0" + bn.js "^5.2.1" bs58 "^5.0.0" buffer "^6.0.3" - cross-fetch "^3.1.5" debug "^4.3.4" eventemitter3 "^4.0.7" lodash.clonedeep "^4.5.0" lodash.isequal "^4.5.0" + merkletreejs "^0.2.32" mime "^3.0.0" - tweetnacl "^1.0.3" + node-fetch "^2.6.7" -"@metaplex-foundation/mpl-auction-house@^2.0.0": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-auction-house/-/mpl-auction-house-2.1.1.tgz#137a35395f2b44b5c7e49ca9d62ef41e4c71336a" - integrity sha512-KBQAiN2/BYd1aVtun0ObbFF1xbIaAXnKU4dlS/ruK5FO1itw6KiaICbl+nUJOvc7F7oTBnrtzfDYXHWEy4G0VQ== +"@metaplex-foundation/mpl-auction-house@^2.3.0": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-auction-house/-/mpl-auction-house-2.5.1.tgz#ea0e21e594b0db5e73f88688eb2e7c9b748b378b" + integrity sha512-O+IAdYVaoOvgACB8pm+1lF5BNEjl0COkqny2Ho8KQZwka6aC/vHbZ239yRwAMtJhf5992BPFdT4oifjyE0O+Mw== dependencies: - "@metaplex-foundation/beet" "^0.1.0" - "@metaplex-foundation/beet-solana" "^0.1.1" + "@metaplex-foundation/beet" "^0.6.1" + "@metaplex-foundation/beet-solana" "^0.3.1" "@metaplex-foundation/cusper" "^0.0.2" - "@solana/web3.js" "^1.35.1" + "@solana/spl-token" "^0.3.5" + "@solana/web3.js" "^1.56.2" bn.js "^5.2.0" "@metaplex-foundation/mpl-auction@^0.0.2": version "0.0.2" - resolved "https://registry.npmjs.org/@metaplex-foundation/mpl-auction/-/mpl-auction-0.0.2.tgz" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-auction/-/mpl-auction-0.0.2.tgz#3de3c982e88d6a88f0ef05be73453cf3cfaccf26" integrity sha512-4UDDi8OiQr+D6KrCNTRrqf/iDD6vi5kzRtMRtuNpywTyhX9hnbr1Zkc6Ncncbh9GZhbhcn+/h5wHgzh+xA6TnQ== dependencies: "@metaplex-foundation/mpl-core" "^0.0.2" "@solana/spl-token" "^0.1.8" "@solana/web3.js" "^1.31.0" -"@metaplex-foundation/mpl-candy-machine@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-candy-machine/-/mpl-candy-machine-4.3.0.tgz#168e0de04548b0ba62abb78ddc90aafd07de804d" - integrity sha512-Vgx0Ly+JGosXFFz/mz5eWKovZgAQBLSFAwuat/c+yGmT7FGlnCEqV3lsBsg+P8iiuG39DxCvNfBQEH8fsiuOlQ== +"@metaplex-foundation/mpl-bubblegum@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-bubblegum/-/mpl-bubblegum-0.6.2.tgz#e1b098ccef10899b0d759a03e3d4b1ae7bdc9f0c" + integrity sha512-4tF7/FFSNtpozuIGD7gMKcqK2D49eVXZ144xiowC5H1iBeu009/oj2m8Tj6n4DpYFKWJ2JQhhhk0a2q7x0Begw== + dependencies: + "@metaplex-foundation/beet" "0.7.1" + "@metaplex-foundation/beet-solana" "0.4.0" + "@metaplex-foundation/cusper" "^0.0.2" + "@metaplex-foundation/mpl-token-metadata" "^2.5.2" + "@solana/spl-account-compression" "^0.1.4" + "@solana/spl-token" "^0.1.8" + "@solana/web3.js" "^1.50.1" + bn.js "^5.2.0" + js-sha3 "^0.8.0" + +"@metaplex-foundation/mpl-candy-guard@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-candy-guard/-/mpl-candy-guard-0.3.2.tgz#426e89793676b42e9bbb5e523303fba36ccd5281" + integrity sha512-QWXzPDz+6OR3957LtfW6/rcGvFWS/0AeHJa/BUO2VEVQxN769dupsKGtrsS8o5RzXCeap3wrCtDSNxN3dnWu4Q== dependencies: "@metaplex-foundation/beet" "^0.4.0" "@metaplex-foundation/beet-solana" "^0.3.0" "@metaplex-foundation/cusper" "^0.0.2" - "@metaplex-foundation/mpl-core" "^0.6.1" - "@solana/web3.js" "^1.35.1" + "@solana/web3.js" "^1.66.2" + bn.js "^5.2.0" -"@metaplex-foundation/mpl-core@^0.0.2": - version "0.0.2" - resolved "https://registry.npmjs.org/@metaplex-foundation/mpl-core/-/mpl-core-0.0.2.tgz" - integrity sha512-UUJ4BlYiWdDegAWmjsNQiNehwYU3QfSFWs3sv4VX0J6/ZrQ28zqosGhQ+I2ZCTEy216finJ82sZWNjuwSWCYyQ== +"@metaplex-foundation/mpl-candy-machine-core@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-candy-machine-core/-/mpl-candy-machine-core-0.1.2.tgz#07e19558d0ef120fac1d8612ae4de90d52cd4d1f" + integrity sha512-jjDkRvMR+iykt7guQ7qVnOHTZedql0lq3xqWDMaenAUCH3Xrf2zKATThhJppIVNX1/YtgBOO3lGqhaFbaI4pCw== dependencies: - "@solana/web3.js" "^1.31.0" - bs58 "^4.0.1" + "@metaplex-foundation/beet" "^0.4.0" + "@metaplex-foundation/beet-solana" "^0.3.0" + "@metaplex-foundation/cusper" "^0.0.2" + "@solana/web3.js" "^1.56.2" + bn.js "^5.2.0" -"@metaplex-foundation/mpl-core@^0.0.5": - version "0.0.5" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-core/-/mpl-core-0.0.5.tgz#0504ad49b6d2e6d2321700edf549804f343c86c6" - integrity sha512-3nVRxcwju/A9oU3VtBfrH9kLECUdp6Y+xmZ6ADOOLFSQ2FDxeESTrlcBJNPi582vEROEUyE4efXD6EvO4EZZyA== +"@metaplex-foundation/mpl-candy-machine@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-candy-machine/-/mpl-candy-machine-5.1.0.tgz#9469914b312ac36b7cf608123508f3f3f5080010" + integrity sha512-pjHpUpWVOCDxK3l6dXxfmJKNQmbjBqnm5ElOl1mJAygnzO8NIPQvrP89y6xSNyo8qZsJyt4ZMYUyD0TdbtKZXQ== dependencies: - "@solana/spl-token" "^0.1.8" - "@solana/web3.js" "^1.35.1" - bs58 "^4.0.1" + "@metaplex-foundation/beet" "^0.7.1" + "@metaplex-foundation/beet-solana" "^0.4.0" + "@metaplex-foundation/cusper" "^0.0.2" + "@solana/spl-token" "^0.3.6" + "@solana/web3.js" "^1.66.2" -"@metaplex-foundation/mpl-core@^0.6.1": - version "0.6.1" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-core/-/mpl-core-0.6.1.tgz#bdc76a8b447a2ef310693973bf430e5ecec6ef0b" - integrity sha512-6R4HkfAqU2EUakNbVLcCmka0YuQTLGTbHJ62ig765+NRWuB2HNGUQ1HfHcRsGnyxhlCvwKK79JE01XUjFE+dzw== +"@metaplex-foundation/mpl-core@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-core/-/mpl-core-0.0.2.tgz#17ee2cc216e17629d6df1dbba75964625ebbd603" + integrity sha512-UUJ4BlYiWdDegAWmjsNQiNehwYU3QfSFWs3sv4VX0J6/ZrQ28zqosGhQ+I2ZCTEy216finJ82sZWNjuwSWCYyQ== dependencies: - "@solana/web3.js" "^1.35.1" + "@solana/web3.js" "^1.31.0" bs58 "^4.0.1" "@metaplex-foundation/mpl-metaplex@^0.0.5": version "0.0.5" - resolved "https://registry.npmjs.org/@metaplex-foundation/mpl-metaplex/-/mpl-metaplex-0.0.5.tgz" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-metaplex/-/mpl-metaplex-0.0.5.tgz#f4b94582831824d134337453a8556c6c1ea13642" integrity sha512-VRt3fiO/7/jcHwN+gWvTtpp+7wYhIcEDzMG1lOeV3yYyhz9fAT0E3LqEl2moifNTAopGCE4zYa84JA/OW+1YvA== dependencies: "@metaplex-foundation/mpl-auction" "^0.0.2" @@ -2995,45 +2403,53 @@ "@solana/spl-token" "^0.1.8" "@solana/web3.js" "^1.31.0" +"@metaplex-foundation/mpl-token-metadata@2.10.0": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-token-metadata/-/mpl-token-metadata-2.10.0.tgz#87785d305a23bd68075919ce995b3160408ddedc" + integrity sha512-oCAzs4Wl7m+8ZeW6VVX8NDNbMBNDbH0vbysBmY8Eh9Moq0inSjm2dtojzQGEFTpVSAEFEzinRLXtkeWqiiI3ug== + dependencies: + "@metaplex-foundation/beet" "^0.7.1" + "@metaplex-foundation/beet-solana" "^0.4.0" + "@metaplex-foundation/cusper" "^0.0.2" + "@solana/spl-token" "^0.3.6" + "@solana/web3.js" "^1.66.2" + bn.js "^5.2.0" + debug "^4.3.4" + "@metaplex-foundation/mpl-token-metadata@^0.0.2": version "0.0.2" - resolved "https://registry.npmjs.org/@metaplex-foundation/mpl-token-metadata/-/mpl-token-metadata-0.0.2.tgz" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-token-metadata/-/mpl-token-metadata-0.0.2.tgz#02058970320459e2550e90caf54c58bcacbe6bb2" integrity sha512-yKJPhFlX8MkNbSCi1iwHn4xKmguLK/xFhYa+RuYdL2seuT4CKXHj2CnR2AkcdQj46Za4/nR3jZcRFKq7QlnvBw== dependencies: "@metaplex-foundation/mpl-core" "^0.0.2" "@solana/spl-token" "^0.1.8" "@solana/web3.js" "^1.31.0" -"@metaplex-foundation/mpl-token-metadata@^2.1.2": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-token-metadata/-/mpl-token-metadata-2.2.2.tgz#91fdf9dc48af332a35ce7e07e456c140682ca7de" - integrity sha512-pYbzn4+LE6cuyPjSiX6CzxLNiwSvxYxzc17vV1Zl4EOcwQgsvR0RW1LE5kyCGU/sV390P6/k7jceO3KFHSIWLw== +"@metaplex-foundation/mpl-token-metadata@^1.1.0", "@metaplex-foundation/mpl-token-metadata@^1.2.4", "@metaplex-foundation/mpl-token-metadata@^1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-token-metadata/-/mpl-token-metadata-1.2.5.tgz#1a927b1c7d30cd634a1e4782022712a02f6865c2" + integrity sha512-pxRG53JsTSwXpiJJMHNulJhH8kO3hHztQ3QxslUoKw2hBYKXsg9TGsiHgNIhN2MPZGBJ2pDeK6kNGv0sd54HhA== dependencies: - "@metaplex-foundation/beet" "^0.4.0" - "@metaplex-foundation/beet-solana" "^0.3.0" - "@metaplex-foundation/cusper" "^0.0.2" - "@solana/spl-token" "^0.2.0" - "@solana/web3.js" "^1.35.1" - bn.js "^5.2.0" - debug "^4.3.3" + "@metaplex-foundation/mpl-core" "^0.0.2" + "@solana/spl-token" "^0.1.8" + "@solana/web3.js" "^1.31.0" -"@metaplex-foundation/mpl-token-metadata@~2.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-token-metadata/-/mpl-token-metadata-2.0.0.tgz#70fb740871325122044e343614a1310f13d7ddb0" - integrity sha512-7eg72QzZZCuC+r+6trUPDNbTiBoFytWWV2MVTOdusBeIt9LJjHKODmspyAsJdkzTZQwv3dP9WAfvTYw5t0jgEA== +"@metaplex-foundation/mpl-token-metadata@^2.11.0", "@metaplex-foundation/mpl-token-metadata@^2.2.3", "@metaplex-foundation/mpl-token-metadata@^2.5.2": + version "2.13.0" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-token-metadata/-/mpl-token-metadata-2.13.0.tgz#ea498190ad4ed1d4c0b8218a72d03bd17a883d11" + integrity sha512-Fl/8I0L9rv4bKTV/RAl5YIbJe9SnQPInKvLz+xR1fEc4/VQkuCn3RPgypfUMEKWmCznzaw4sApDxy6CFS4qmJw== dependencies: - "@metaplex-foundation/beet" "^0.1.0" - "@metaplex-foundation/beet-solana" "^0.1.1" + "@metaplex-foundation/beet" "^0.7.1" + "@metaplex-foundation/beet-solana" "^0.4.0" "@metaplex-foundation/cusper" "^0.0.2" - "@metaplex-foundation/mpl-core" "^0.0.5" - "@solana/spl-token" "^0.2.0" - "@solana/web3.js" "^1.35.1" + "@solana/spl-token" "^0.3.6" + "@solana/web3.js" "^1.66.2" bn.js "^5.2.0" - debug "^4.3.3" + debug "^4.3.4" "@metaplex-foundation/mpl-token-vault@^0.0.2": version "0.0.2" - resolved "https://registry.npmjs.org/@metaplex-foundation/mpl-token-vault/-/mpl-token-vault-0.0.2.tgz" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-token-vault/-/mpl-token-vault-0.0.2.tgz#84d2fc86f750f8413acd9e9c24f4b3c016a12c47" integrity sha512-JiVcow8OzUGW0KTs/E1QrAdmYGqE9EGKE6cc2gxNNBYqDeVdjYlgEa64IiGvNF9rvbI2g2Z3jw0mYuA9LD9S/A== dependencies: "@metaplex-foundation/mpl-core" "^0.0.2" @@ -3041,14 +2457,14 @@ "@solana/web3.js" "^1.31.0" "@metaplex/js@^4.2.1": - version "4.11.7" - resolved "https://registry.npmjs.org/@metaplex/js/-/js-4.11.7.tgz" - integrity sha512-/8X04VEHMfWF84H2DZwLY3yg0xq75vgt/VtLuChTm8iUHkj99Whnq0NLTe0OqfhiEV0qFvT5dbLFh7x2CZqrEQ== + version "4.12.0" + resolved "https://registry.yarnpkg.com/@metaplex/js/-/js-4.12.0.tgz#1190767a4e69d4e5613002aab3f4c1fb8de07896" + integrity sha512-rIUTMXo5gIXFIZt08AEHyqH4oVoLL2dMYiNePQluw9pydesRym4jDayJ5POxEmKmyc6KGqVKw/YWUIivmUY5zg== dependencies: "@metaplex-foundation/mpl-auction" "^0.0.2" "@metaplex-foundation/mpl-core" "^0.0.2" "@metaplex-foundation/mpl-metaplex" "^0.0.5" - "@metaplex-foundation/mpl-token-metadata" "^0.0.2" + "@metaplex-foundation/mpl-token-metadata" "^1.1.0" "@metaplex-foundation/mpl-token-vault" "^0.0.2" "@solana/spl-token" "^0.1.8" "@solana/web3.js" "^1.30.2" @@ -3061,97 +2477,114 @@ crypto-hash "^1.3.0" form-data "^4.0.0" -"@mithraic-labs/serum-remote@^0.0.1-rc.16": - version "0.0.1-rc.16" - resolved "https://registry.yarnpkg.com/@mithraic-labs/serum-remote/-/serum-remote-0.0.1-rc.16.tgz#c7d1d8ed7b2e662dc16712ef34214ff3e5037d1a" - integrity sha512-nGzkVROoWa+DSSUstRVL3R6geXtareYwhjRQBkpCmvB1L9Ll47dVNSu9cWE8JLbfSJeFCElAjJjaLfDey8ZQqQ== +"@multifarm/solana-realms@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@multifarm/solana-realms/-/solana-realms-1.0.6.tgz#0891f7e05973f311dd7381450363a9ff9be3f3f2" + integrity sha512-raxbJxZGofnfezNXr/yRWxJ/gwtG8HWdbTn5rcIXRZFVq4rZ3JF+kVx6z8JClrk1FbAYWOxLifkwLl3u7PJ/KA== + dependencies: + "@multifarm/widget-components" "^0.0.16" + bignumber.js "^9.1.1" + recharts "^2.4.3" + swr "^1.3.0" + +"@multifarm/widget-components@^0.0.16": + version "0.0.16" + resolved "https://registry.yarnpkg.com/@multifarm/widget-components/-/widget-components-0.0.16.tgz#333347ff03e8dd3bc031ee373f8b31c39c8bd03a" + integrity sha512-urfAWXvZKsVWgKhpqDhO4/sE5o2yI60NF4vo0x96z1QNAY2nUw2Ou6PZC1QpQnPoziCgFUIVHSjwGHdPBv7RmA== + dependencies: + "@tippyjs/react" "^4.2.6" + clsx "^1.2.1" + react-slider "^2.0.4" -"@next/bundle-analyzer@^12.1.5": +"@next/bundle-analyzer@12.1.5": version "12.1.5" resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-12.1.5.tgz#07079b892efe0a2a7e8add703ad7cacfa3cc4e88" integrity sha512-A9MkhWCPvSp1vl0Ox7IjJ/qpugDC5YAb40btGGIPPXHQtkal107Sf8dbay4fqw4Hekee5gdS0WUMfe1BaSur7w== dependencies: webpack-bundle-analyzer "4.3.0" -"@next/env@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/env/-/env-12.2.2.tgz#cc1a0a445bd254499e30f632968c03192455f4cc" - integrity sha512-BqDwE4gDl1F608TpnNxZqrCn6g48MBjvmWFEmeX5wEXDXh3IkAOw6ASKUgjT8H4OUePYFqghDFUss5ZhnbOUjw== - -"@next/swc-android-arm-eabi@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.2.tgz#f6c4111e6371f73af6bf80c9accb3d96850a92cd" - integrity sha512-VHjuCHeq9qCprUZbsRxxM/VqSW8MmsUtqB5nEpGEgUNnQi/BTm/2aK8tl7R4D0twGKRh6g1AAeFuWtXzk9Z/vQ== - -"@next/swc-android-arm64@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.2.2.tgz#b69de59c51e631a7600439e7a8993d6e82f3369e" - integrity sha512-v5EYzXUOSv0r9mO/2PX6mOcF53k8ndlu9yeFHVAWW1Dhw2jaJcvTRcCAwYYN8Q3tDg0nH3NbEltJDLKmcJOuVA== - -"@next/swc-darwin-arm64@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.2.tgz#80157c91668eff95b72d052428c353eab0fc4c50" - integrity sha512-JCoGySHKGt+YBk7xRTFGx1QjrnCcwYxIo3yGepcOq64MoiocTM3yllQWeOAJU2/k9MH0+B5E9WUSme4rOCBbpA== - -"@next/swc-darwin-x64@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.2.tgz#12be2f58e676fccff3d48a62921b9927ed295133" - integrity sha512-dztDtvfkhUqiqpXvrWVccfGhLe44yQ5tQ7B4tBfnsOR6vxzI9DNPHTlEOgRN9qDqTAcFyPxvg86mn4l8bB9Jcw== - -"@next/swc-freebsd-x64@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.2.tgz#de1363431a49059f1efb8c0f86ce6a79c53b3a95" - integrity sha512-JUnXB+2xfxqsAvhFLPJpU1NeyDsvJrKoOjpV7g3Dxbno2Riu4tDKn3kKF886yleAuD/1qNTUCpqubTvbbT2VoA== - -"@next/swc-linux-arm-gnueabihf@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.2.tgz#d5b8e0d1bb55bbd9db4d2fec018217471dc8b9e6" - integrity sha512-XeYC/qqPLz58R4pjkb+x8sUUxuGLnx9QruC7/IGkK68yW4G17PHwKI/1njFYVfXTXUukpWjcfBuauWwxp9ke7Q== - -"@next/swc-linux-arm64-gnu@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.2.tgz#3bc75984e1d5ec8f59eb53702cc382d8e1be2061" - integrity sha512-d6jT8xgfKYFkzR7J0OHo2D+kFvY/6W8qEo6/hmdrTt6AKAqxs//rbbcdoyn3YQq1x6FVUUd39zzpezZntg9Naw== - -"@next/swc-linux-arm64-musl@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.2.tgz#270db73e07a18d999f61e79a917943fa5bc1ef56" - integrity sha512-rIZRFxI9N/502auJT1i7coas0HTHUM+HaXMyJiCpnY8Rimbo0495ir24tzzHo3nQqJwcflcPTwEh/DV17sdv9A== - -"@next/swc-linux-x64-gnu@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.2.tgz#e6c72fa20478552e898c434f4d4c0c5e89d2ea78" - integrity sha512-ir1vNadlUDj7eQk15AvfhG5BjVizuCHks9uZwBfUgT5jyeDCeRvaDCo1+Q6+0CLOAnYDR/nqSCvBgzG2UdFh9A== - -"@next/swc-linux-x64-musl@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.2.tgz#b9ef9efe2c401839cdefa5e70402386aafdce15a" - integrity sha512-bte5n2GzLN3O8JdSFYWZzMgEgDHZmRz5wiispiiDssj4ik3l8E7wq/czNi8RmIF+ioj2sYVokUNa/ekLzrESWw== - -"@next/swc-win32-arm64-msvc@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.2.tgz#18fa7ec7248da3a7926a0601d9ececc53ac83157" - integrity sha512-ZUGCmcDmdPVSAlwJ/aD+1F9lYW8vttseiv4n2+VCDv5JloxiX9aY32kYZaJJO7hmTLNrprvXkb4OvNuHdN22Jg== - -"@next/swc-win32-ia32-msvc@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.2.tgz#54936e84f4a219441d051940354da7cd3eafbb4f" - integrity sha512-v7ykeEDbr9eXiblGSZiEYYkWoig6sRhAbLKHUHQtk8vEWWVEqeXFcxmw6LRrKu5rCN1DY357UlYWToCGPQPCRA== - -"@next/swc-win32-x64-msvc@12.2.2": - version "12.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.2.tgz#7460be700a60d75816f01109400b51fe929d7e89" - integrity sha512-2D2iinWUL6xx8D9LYVZ5qi7FP6uLAoWymt8m8aaG2Ld/Ka8/k723fJfiklfuAcwOxfufPJI+nRbT5VcgHGzHAQ== - -"@nfteyez/sol-rayz@^0.10.2": - version "0.10.2" - resolved "https://registry.npmjs.org/@nfteyez/sol-rayz/-/sol-rayz-0.10.2.tgz" - integrity sha512-4lj4WEVZHPHIkyfazcUQIBbjw/jl3SknSseccTmJSFh9IMsy7SoFa5jPYH1OallwZBbGmcJSnslwMv2hgZml6A== - dependencies: - "@solana/spl-name-service" "^0.1.3" - borsh "^0.6.0" - lodash.chunk "^4.2.0" - lodash.orderby "^4.6.0" +"@next/env@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.2.tgz#fb819366771f5721e9438ca3a42ad18684f0949b" + integrity sha512-upwtMaHxlv/udAWGq0kE+rg8huwmcxQPsKZFhS1R5iVO323mvxEBe1YrSXe1awLbg9sTIuEHbgxjLLt7JbeuAQ== + +"@next/swc-android-arm-eabi@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.2.tgz#806e3be9741bc14aafdfad0f0c4c6a8de5b77ee1" + integrity sha512-r2rrz+DZ8YYGqzVrbRrpP6GKzwozpOrnFbErc4k36vUTSFMag9yQahZfaBe06JYdqu/e5yhm/saIDEaSVPRP4g== + +"@next/swc-android-arm64@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.3.2.tgz#f9ec6b7fc746832a217ad6bb5478624d1a9a9822" + integrity sha512-B+TINJhCf+CrY1+b3/JWQlkecv53rAGa/gA7gi5B1cnBa/2Uvoe+Ue0JeCefTjfiyl1ScsyNx+NcESY8Ye2Ngg== + +"@next/swc-darwin-arm64@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.2.tgz#97c532d35c66ce6b6941ae24b5b8b267b9b0d0d8" + integrity sha512-PTUfe1ZrwjsiuTmr3bOM9lsoy5DCmfYsLOUF9ZVhtbi5MNJVmUTy4VZ06GfrvnCO5hGCr48z3vpFE9QZ0qLcPw== + +"@next/swc-darwin-x64@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.2.tgz#e0cb4ff4b11faaff3a891bd1d18ed72f71e30ebe" + integrity sha512-1HkjmS9awwlaeEY8Y01nRSNkSv3y+qnC/mjMPe/W66hEh3QKa/LQHqHeS7NOdEs19B2mhZ7w+EgMRXdLQ0Su8w== + +"@next/swc-freebsd-x64@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.2.tgz#d7b93dd344cb67d1969565d0796c7b7d0217fccf" + integrity sha512-h5Mx0BKDCJ5Vu/U8e07esF6PjPv1EJgmRbYWTUZMAflu13MQpCJkKEJir7+BeRfTXRfgFf+llc7uocrpd7mcrg== + +"@next/swc-linux-arm-gnueabihf@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.2.tgz#c2170a89effe00fdd65798c99684fd93a02b197c" + integrity sha512-EuRZAamoxfe/WoWRaC0zsCAoE4gs/mEhilcloNM4J5Mnb3PLY8PZV394W7t5tjBjItMCF7l2Ebwjwtm46tq2RA== + +"@next/swc-linux-arm64-gnu@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.2.tgz#26df7d7cdc18cf413f12a408179ee4ac315f383a" + integrity sha512-T9GCFyOIb4S3acA9LqflUYD+QZ94iZketHCqKdoO0Nx0OCHIgGJV5rotDe8TDXwh/goYpIfyHU4j1qqw4w4VnA== + +"@next/swc-linux-arm64-musl@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.2.tgz#fd42232a6b10d9f9a4f71433d59c280a4532d06f" + integrity sha512-hxNVZS6L3c2z3l9EH2GP0MGQ9exu6O8cohYNZyqC9WUl6C03sEn8xzDH1y+NgD3fVurvYkGU5F0PDddJJLfDIw== + +"@next/swc-linux-x64-gnu@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.2.tgz#5307579e3d8fbdb03adbe6cfc915b51548e0a103" + integrity sha512-fCPkLuwDwY8/QeXxciJJjDHG09liZym/Bhb4A+RLFQ877wUkwFsNWDUTSdUx0YXlYK/1gf67BKauqKkOKp6CYw== + +"@next/swc-linux-x64-musl@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.2.tgz#d5cb920a825a8dc80ffba8a6b797fb845af0b84c" + integrity sha512-o+GifBIQ2K+/MEFxHsxUZoU3bsuVFLXZYWd3idimFHiVdDCVYiKsY6mYMmKDlucX+9xRyOCkKL9Tjf+3tuXJpw== + +"@next/swc-win32-arm64-msvc@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.2.tgz#2a0d619e5bc0cec17ed093afd1ca6b1c37c2690c" + integrity sha512-crii66irzGGMSUR0L8r9+A06eTv7FTXqw4rgzJ33M79EwQJOdpY7RVKXLQMurUhniEeQEEOfamiEdPIi/qxisw== + +"@next/swc-win32-ia32-msvc@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.2.tgz#769bef60d0d678c3d7606a4dc7fee018d6199227" + integrity sha512-5hRUSvn3MdQ4nVRu1rmKxq5YJzpTtZfaC/NyGw6wa4NSF1noUn/pdQGUr+I5Qz3CZkd1gZzzC0eaXQHlrk0E2g== + +"@next/swc-win32-x64-msvc@12.3.2": + version "12.3.2" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.2.tgz#45beb4b9d28e6dd6abf63cab1c5b92dc84323a6b" + integrity sha512-tpQJYUH+TzPMIsdVl9fH8uDg47iwiNjKY+8e9da3dXqlkztKzjSw0OwSADoqh3KrifplXeKSta+BBGLdBqg3sg== + +"@ngraveio/bc-ur@^1.0.0", "@ngraveio/bc-ur@^1.1.5": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@ngraveio/bc-ur/-/bc-ur-1.1.6.tgz#8f8c75fff22f6a5e4dfbc5a6b540d7fe8f42cd39" + integrity sha512-G+2XgjXde2IOcEQeCwR250aS43/Swi7gw0FuETgJy2c3HqF8f88SXDMsIGgJlZ8jXd0GeHR4aX0MfjXf523UZg== + dependencies: + "@apocentre/alias-sampling" "^0.5.3" + assert "^2.0.0" + bignumber.js "^9.0.1" + cbor-sync "^1.0.4" + crc "^3.8.0" + jsbi "^3.1.5" + sha.js "^2.4.11" "@nivo/annotations@0.79.1": version "0.79.1" @@ -3172,7 +2605,7 @@ d3-format "^1.4.4" d3-time-format "^3.0.0" -"@nivo/bar@^0.79.1": +"@nivo/bar@0.79.1": version "0.79.1" resolved "https://registry.yarnpkg.com/@nivo/bar/-/bar-0.79.1.tgz#42d28169307e735cb84e57b4b6915195ef1c97fb" integrity sha512-swJ2FtFeRPWJK9O6aZiqTDi2J6GrU2Z6kIHBBCXBlFmq6+vfd5AqOHytdXPTaN80JsKDBBdtY7tqRjpRPlDZwQ== @@ -3198,7 +2631,7 @@ d3-scale-chromatic "^2.0.0" lodash "^4.17.21" -"@nivo/core@^0.79.0": +"@nivo/core@0.79.0": version "0.79.0" resolved "https://registry.yarnpkg.com/@nivo/core/-/core-0.79.0.tgz#5755212c2058c20899990e7c8ec0e918ac00e5f5" integrity sha512-e1iGodmGuXkF+QWAjhHVFc+lUnfBoUwaWqVcBXBfebzNc50tTJrTTMHyQczjgOIfTc8gEu23lAY4mVZCDKscig== @@ -3243,24 +2676,38 @@ dependencies: "@react-spring/web" "9.3.1" -"@noble/ed25519@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.0.tgz#583ac38340a479314b9e348d4572101ed9492f9d" - integrity sha512-LeAxFK0+181zQOhOUuKE8Jnd3duzYhDNd3iCLxpmzA5K+e4I1FdbrK3Ot0ZHBwZMeRD/6EojyUfTbpHZ+hkQHg== +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" -"@noble/hashes@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" - integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== +"@noble/curves@^1.1.0", "@noble/curves@^1.2.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.0.tgz#f05771ef64da724997f69ee1261b2417a49522d6" + integrity sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/ed25519@^1.6.1", "@noble/ed25519@^1.7.1": + version "1.7.3" + resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.3.tgz#57e1677bf6885354b466c38e2b620c62f45a7123" + integrity sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ== + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== -"@noble/secp256k1@^1.6.3": - version "1.6.3" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" - integrity sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ== +"@noble/hashes@1.4.0", "@noble/hashes@^1.1.3", "@noble/hashes@^1.3.1": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -3268,325 +2715,203 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@notifi-network/notifi-axios-adapter@^0.18.2": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@notifi-network/notifi-axios-adapter/-/notifi-axios-adapter-0.18.2.tgz#3ad4dd179a48aec1ce0030e5c0c67dd37c7d88ec" - integrity sha512-rxE1ScDPZj94Ww6mq/cxA86tA4P0751SDTWt+ANMzZPWgNQO0CmZiZTWfjoS+lwZUpDyh6EMrZaGxsZX28Sa1Q== - dependencies: - "@notifi-network/notifi-axios-utils" "^0.18.2" - -"@notifi-network/notifi-axios-utils@^0.18.2": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@notifi-network/notifi-axios-utils/-/notifi-axios-utils-0.18.2.tgz#805e28554c5fd83bb66212b7ee42d777a4f5379d" - integrity sha512-tKeBB35XqB4nDGDtV+iZogNEt+wrwJ6w7Lw4tw1+SkhV65socs8gnXQgcDT/xtzXCNikaEr3Rfm4knw9XaGXOQ== +"@npmcli/node-gyp@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz#a912e637418ffc5f2db375e93b85837691a43a33" + integrity sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA== -"@notifi-network/notifi-core@^0.18.2": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@notifi-network/notifi-core/-/notifi-core-0.18.2.tgz#f2a5742efe2cf80b02539f2f95ee8469c1788639" - integrity sha512-CFU76YbYQ5ztvMtu2dPzPisOm1Wgm12g8R6wOgwQc9dNiBW+B/IL2uuT2k4uxgtRW1Bz03kxGVmaH0VjYUkF8A== +"@npmcli/promise-spawn@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz#42d4e56a8e9274fba180dabc0aea6e38f29274f5" + integrity sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg== + dependencies: + infer-owner "^1.0.4" -"@notifi-network/notifi-react-hooks@0.18.2": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@notifi-network/notifi-react-hooks/-/notifi-react-hooks-0.18.2.tgz#6c24744857480945071f6ab5cda25c46128a650b" - integrity sha512-TOwg0P8K15OjSgIJZNbmg9qor+eWSOdtJB0wvuP2DMjdi2ataOPJWvBJ7Y+sf33mOfPFjw9vn0SgZgxPPQBEvA== - dependencies: - "@notifi-network/notifi-axios-adapter" "^0.18.2" - "@notifi-network/notifi-axios-utils" "^0.18.2" - axios "^0.26.0" - localforage "^1.10.0" - typedoc-plugin-missing-exports "^0.22.6" - typescript "^4.5.5" +"@npmcli/run-script@^1.8.1": + version "1.8.6" + resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-1.8.6.tgz#18314802a6660b0d4baa4c3afe7f1ad39d8c28b7" + integrity sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g== + dependencies: + "@npmcli/node-gyp" "^1.0.2" + "@npmcli/promise-spawn" "^1.3.2" + node-gyp "^7.1.0" + read-package-json-fast "^2.0.1" -"@npmcli/arborist@^2.3.0", "@npmcli/arborist@^2.5.0", "@npmcli/arborist@^2.9.0": - version "2.10.0" - resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-2.10.0.tgz#424c2d73a7ae59c960b0cc7f74fed043e4316c2c" - integrity sha512-CLnD+zXG9oijEEzViimz8fbOoFVb7hoypiaf7p6giJhvYtrxLAyY3cZAMPIFQvsG731+02eMDp3LqVBNo7BaZA== - dependencies: - "@isaacs/string-locale-compare" "^1.0.1" - "@npmcli/installed-package-contents" "^1.0.7" - "@npmcli/map-workspaces" "^1.0.2" - "@npmcli/metavuln-calculator" "^1.1.0" - "@npmcli/move-file" "^1.1.0" - "@npmcli/name-from-folder" "^1.0.1" - "@npmcli/node-gyp" "^1.0.1" - "@npmcli/package-json" "^1.0.1" - "@npmcli/run-script" "^1.8.2" - bin-links "^2.2.1" - cacache "^15.0.3" - common-ancestor-path "^1.0.1" - json-parse-even-better-errors "^2.3.1" - json-stringify-nice "^1.1.4" - mkdirp "^1.0.4" - mkdirp-infer-owner "^2.0.0" - npm-install-checks "^4.0.0" - npm-package-arg "^8.1.5" - npm-pick-manifest "^6.1.0" - npm-registry-fetch "^11.0.0" - pacote "^11.3.5" - parse-conflict-json "^1.1.1" - proc-log "^1.0.0" - promise-all-reject-late "^1.0.0" - promise-call-limit "^1.0.1" - read-package-json-fast "^2.0.2" - readdir-scoped-modules "^1.1.0" - rimraf "^3.0.2" - semver "^7.3.5" - ssri "^8.0.1" - treeverse "^1.0.4" - walk-up-path "^1.0.0" +"@parcel/watcher-android-arm64@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.0.tgz#9c93763794153e4f76920994a423b6ea3257059d" + integrity sha512-+fPtO/GsbYX1LJnCYCaDVT3EOBjvSFdQN9Mrzh9zWAOOfvidPWyScTrHIZHHfJBvlHzNA0Gy0U3NXFA/M7PHUA== -"@npmcli/ci-detect@^1.2.0", "@npmcli/ci-detect@^1.3.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@npmcli/ci-detect/-/ci-detect-1.4.0.tgz#18478bbaa900c37bfbd8a2006a6262c62e8b0fe1" - integrity sha512-3BGrt6FLjqM6br5AhWRKTr3u5GIVkjRYeAFrMp3HjnfICrg4xOrVRwFavKT6tsp++bq5dluL5t8ME/Nha/6c1Q== +"@parcel/watcher-darwin-arm64@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.0.tgz#2c79c2abde16aa24cac67e555b60802fd13fe210" + integrity sha512-T/At5pansFuQ8VJLRx0C6C87cgfqIYhW2N/kBfLCUvDhCah0EnLLwaD/6MW3ux+rpgkpQAnMELOCTKlbwncwiA== -"@npmcli/config@^2.3.0": +"@parcel/watcher-darwin-x64@2.4.0": version "2.4.0" - resolved "https://registry.yarnpkg.com/@npmcli/config/-/config-2.4.0.tgz#1447b0274f9502871dabd3ab1d8302472d515b1f" - integrity sha512-fwxu/zaZnvBJohXM3igzqa3P1IVYWi5N343XcKvKkJbAx+rTqegS5tAul4NLiMPQh6WoS5a4er6oo/ieUx1f4g== - dependencies: - ini "^2.0.0" - mkdirp-infer-owner "^2.0.0" - nopt "^5.0.0" - semver "^7.3.4" - walk-up-path "^1.0.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.0.tgz#23d82f198c5d033f047467c68d7c335f3df49b46" + integrity sha512-vZMv9jl+szz5YLsSqEGCMSllBl1gU1snfbRL5ysJU03MEa6gkVy9OMcvXV1j4g0++jHEcvzhs3Z3LpeEbVmY6Q== -"@npmcli/disparity-colors@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@npmcli/disparity-colors/-/disparity-colors-1.0.1.tgz" - integrity sha512-kQ1aCTTU45mPXN+pdAaRxlxr3OunkyztjbbxDY/aIcPS5CnCUrx+1+NvA6pTcYR7wmLZe37+Mi5v3nfbwPxq3A== - dependencies: - ansi-styles "^4.3.0" +"@parcel/watcher-freebsd-x64@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.0.tgz#7310cc86abc27dacd57624bcdba1f0ba092e76df" + integrity sha512-dHTRMIplPDT1M0+BkXjtMN+qLtqq24sLDUhmU+UxxLP2TEY2k8GIoqIJiVrGWGomdWsy5IO27aDV1vWyQ6gfHA== -"@npmcli/fs@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" - integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== - dependencies: - "@gar/promisify" "^1.0.1" - semver "^7.3.5" +"@parcel/watcher-linux-arm-glibc@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.0.tgz#c31b76e695027eeb1078d3d6f1d641d0b900c335" + integrity sha512-9NQXD+qk46RwATNC3/UB7HWurscY18CnAPMTFcI9Y8CTbtm63/eex1SNt+BHFinEQuLBjaZwR2Lp+n7pmEJPpQ== -"@npmcli/git@^2.0.7", "@npmcli/git@^2.1.0": - version "2.1.0" - resolved "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz" - integrity sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw== - dependencies: - "@npmcli/promise-spawn" "^1.3.2" - lru-cache "^6.0.0" - mkdirp "^1.0.4" - npm-pick-manifest "^6.1.1" - promise-inflight "^1.0.1" - promise-retry "^2.0.1" - semver "^7.3.5" - which "^2.0.2" +"@parcel/watcher-linux-arm64-glibc@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.0.tgz#56e09b86e9d8a4096f606be118b588da6e965080" + integrity sha512-QuJTAQdsd7PFW9jNGaV9Pw+ZMWV9wKThEzzlY3Lhnnwy7iW23qtQFPql8iEaSFMCVI5StNNmONUopk+MFKpiKg== -"@npmcli/installed-package-contents@^1.0.6", "@npmcli/installed-package-contents@^1.0.7": - version "1.0.7" - resolved "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz" - integrity sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw== - dependencies: - npm-bundled "^1.1.1" - npm-normalize-package-bin "^1.0.1" +"@parcel/watcher-linux-arm64-musl@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.0.tgz#27ffd5ca5f510ecd638f9ad22e2e813049db54e7" + integrity sha512-oyN+uA9xcTDo/45bwsd6TFHa7Lc7hKujyMlvwrCLvSckvWogndCEoVYFNfZ6JJ2KNL/6fFiGPcbjp8jJmEh5Ng== -"@npmcli/map-workspaces@^1.0.2", "@npmcli/map-workspaces@^1.0.4": - version "1.0.4" - resolved "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.4.tgz" - integrity sha512-wVR8QxhyXsFcD/cORtJwGQodeeaDf0OxcHie8ema4VgFeqwYkFsDPnSrIRSytX8xR6nKPAH89WnwTcaU608b/Q== - dependencies: - "@npmcli/name-from-folder" "^1.0.1" - glob "^7.1.6" - minimatch "^3.0.4" - read-package-json-fast "^2.0.1" +"@parcel/watcher-linux-x64-glibc@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.0.tgz#44cbbb1e5884a1ca900655f47a0775218318f934" + integrity sha512-KphV8awJmxU3q52JQvJot0QMu07CIyEjV+2Tb2ZtbucEgqyRcxOBDMsqp1JNq5nuDXtcCC0uHQICeiEz38dPBQ== -"@npmcli/metavuln-calculator@^1.1.0": - version "1.1.1" - resolved "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-1.1.1.tgz" - integrity sha512-9xe+ZZ1iGVaUovBVFI9h3qW+UuECUzhvZPxK9RaEA2mjU26o5D0JloGYWwLYvQELJNmBdQB6rrpuN8jni6LwzQ== - dependencies: - cacache "^15.0.5" - pacote "^11.1.11" - semver "^7.3.2" +"@parcel/watcher-linux-x64-musl@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.0.tgz#4c33993618c8d5113722852806239cb80360494b" + integrity sha512-7jzcOonpXNWcSijPpKD5IbC6xC7yTibjJw9jviVzZostYLGxbz8LDJLUnLzLzhASPlPGgpeKLtFUMjAAzM+gSA== -"@npmcli/move-file@^1.0.1", "@npmcli/move-file@^1.1.0": - version "1.1.2" - resolved "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz" - integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== +"@parcel/watcher-wasm@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-wasm/-/watcher-wasm-2.4.0.tgz#84a3959c8ef1cd67b36b9fec487edbc8f27719f6" + integrity sha512-MNgQ4WCbBybqQ97KwR/hqJGYTg3+s8qHpgIyFWB2qJOBvoJWbXuJGmm4ZkPLq2bMaANqCZqrXwmKYagZTkMKZA== dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" - -"@npmcli/name-from-folder@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz" - integrity sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA== - -"@npmcli/node-gyp@^1.0.1", "@npmcli/node-gyp@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz#a912e637418ffc5f2db375e93b85837691a43a33" - integrity sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA== + is-glob "^4.0.3" + micromatch "^4.0.5" + napi-wasm "^1.1.0" -"@npmcli/package-json@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@npmcli/package-json/-/package-json-1.0.1.tgz" - integrity sha512-y6jnu76E9C23osz8gEMBayZmaZ69vFOIk8vR1FJL/wbEJ54+9aVG9rLTjQKSXfgYZEr50nw1txBBFfBZZe+bYg== - dependencies: - json-parse-even-better-errors "^2.3.1" +"@parcel/watcher-win32-arm64@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.0.tgz#2a172fd2fda95fe5389298ca3e70b5a96316162a" + integrity sha512-NOej2lqlq8bQNYhUMnOD0nwvNql8ToQF+1Zhi9ULZoG+XTtJ9hNnCFfyICxoZLXor4bBPTOnzs/aVVoefYnjIg== -"@npmcli/promise-spawn@^1.2.0", "@npmcli/promise-spawn@^1.3.2": - version "1.3.2" - resolved "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz" - integrity sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg== - dependencies: - infer-owner "^1.0.4" +"@parcel/watcher-win32-ia32@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.0.tgz#279225b2ebe1fadd3c5137c9b2365ad422656904" + integrity sha512-IO/nM+K2YD/iwjWAfHFMBPz4Zqn6qBDqZxY4j2n9s+4+OuTSRM/y/irksnuqcspom5DjkSeF9d0YbO+qpys+JA== -"@npmcli/run-script@^1.8.2", "@npmcli/run-script@^1.8.3", "@npmcli/run-script@^1.8.4", "@npmcli/run-script@^1.8.6": - version "1.8.6" - resolved "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.6.tgz" - integrity sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g== - dependencies: - "@npmcli/node-gyp" "^1.0.2" - "@npmcli/promise-spawn" "^1.3.2" - node-gyp "^7.1.0" - read-package-json-fast "^2.0.1" +"@parcel/watcher-win32-x64@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.0.tgz#93e0bd0ad1bda2c9a688764b9b30b71dc5b72a71" + integrity sha512-pAUyUVjfFjWaf/pShmJpJmNxZhbMvJASUpdes9jL6bTEJ+gDxPRSpXTIemNyNsb9AtbiGXs9XduP1reThmd+dA== -"@oclif/command@^1.8.16": - version "1.8.16" - resolved "https://registry.npmjs.org/@oclif/command/-/command-1.8.16.tgz" - integrity sha512-rmVKYEsKzurfRU0xJz+iHelbi1LGlihIWZ7Qvmb/CBz1EkhL7nOkW4SVXmG2dA5Ce0si2gr88i6q4eBOMRNJ1w== +"@parcel/watcher@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.4.0.tgz#2d3c4ef8832a5cdfdbb76b914f022489933e664f" + integrity sha512-XJLGVL0DEclX5pcWa2N9SX1jCGTDd8l972biNooLFtjneuGqodupPQh6XseXIBBeVIMaaJ7bTcs3qGvXwsp4vg== dependencies: - "@oclif/config" "^1.18.2" - "@oclif/errors" "^1.3.5" - "@oclif/help" "^1.0.1" - "@oclif/parser" "^3.8.6" - debug "^4.1.1" - semver "^7.3.2" + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.4.0" + "@parcel/watcher-darwin-arm64" "2.4.0" + "@parcel/watcher-darwin-x64" "2.4.0" + "@parcel/watcher-freebsd-x64" "2.4.0" + "@parcel/watcher-linux-arm-glibc" "2.4.0" + "@parcel/watcher-linux-arm64-glibc" "2.4.0" + "@parcel/watcher-linux-arm64-musl" "2.4.0" + "@parcel/watcher-linux-x64-glibc" "2.4.0" + "@parcel/watcher-linux-x64-musl" "2.4.0" + "@parcel/watcher-win32-arm64" "2.4.0" + "@parcel/watcher-win32-ia32" "2.4.0" + "@parcel/watcher-win32-x64" "2.4.0" + +"@parcl-oss/staking-wasm@*": + version "0.0.0" + resolved "https://registry.yarnpkg.com/@parcl-oss/staking-wasm/-/staking-wasm-0.0.0.tgz#1fd89d9372eb29968b69ba4f683dfd7953889623" + integrity sha512-SwlhhBjLf79R9ipi25324OljPQWssmkgwOo/h2XJ9sAy81mfwYzwHlzx6FbxdlfQgtxXjtOQKI9BjUssrYOSJg== -"@oclif/config@1.18.2": - version "1.18.2" - resolved "https://registry.npmjs.org/@oclif/config/-/config-1.18.2.tgz" - integrity sha512-cE3qfHWv8hGRCP31j7fIS7BfCflm/BNZ2HNqHexH+fDrdF2f1D5S8VmXWLC77ffv3oDvWyvE9AZeR0RfmHCCaA== +"@parcl-oss/staking@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@parcl-oss/staking/-/staking-0.0.2.tgz#0e49fef441d0fcdb926820c01edb498354a5f445" + integrity sha512-vEY2IrKFCUVpc1Z2/h/wcojX/w1yhvsx+SyayW+1ZqJvoc1ngnet5sgqMPfXSL/FVsapdoeGxh87NznroZ/iOw== dependencies: - "@oclif/errors" "^1.3.3" - "@oclif/parser" "^3.8.0" - debug "^4.1.1" - globby "^11.0.1" - is-wsl "^2.1.1" - tslib "^2.0.0" + "@coral-xyz/anchor" "^0.29.0" + "@parcl-oss/staking-wasm" "*" + "@pythnetwork/solana-utils" "^0.4.1" + "@solana/spl-governance" "0.3.26" + "@solana/spl-token" "^0.1.8" + "@solana/web3.js" "^1.87.5" + encoding "^0.1.13" + ethers "^6.10.0" + ts-node "^10.7.0" + typescript "^4.3.5" -"@oclif/config@^1.18.2": - version "1.18.3" - resolved "https://registry.npmjs.org/@oclif/config/-/config-1.18.3.tgz" - integrity sha512-sBpko86IrTscc39EvHUhL+c++81BVTsIZ3ETu/vG+cCdi0N6vb2DoahR67A9FI2CGnxRRHjnTfa3m6LulwNATA== +"@particle-network/auth@^0.5.5": + version "0.5.6" + resolved "https://registry.yarnpkg.com/@particle-network/auth/-/auth-0.5.6.tgz#058e00980511fdf72189b6d4a7576e67934a008a" + integrity sha512-QhRr76BamasIatyWc68Whk/JpjomKUFbxT4KoHxrSWD8lmyWTOP5T8Jo8hQliyjtO2Iuzv9KLpuJ55w7mgaC/A== dependencies: - "@oclif/errors" "^1.3.5" - "@oclif/parser" "^3.8.0" - debug "^4.1.1" - globby "^11.0.1" - is-wsl "^2.1.1" - tslib "^2.3.1" + crypto-js "^4.1.1" + uuid "^8.3.2" -"@oclif/errors@1.3.5", "@oclif/errors@^1.3.3", "@oclif/errors@^1.3.5": - version "1.3.5" - resolved "https://registry.npmjs.org/@oclif/errors/-/errors-1.3.5.tgz" - integrity sha512-OivucXPH/eLLlOT7FkCMoZXiaVYf8I/w1eTAM1+gKzfhALwWTusxEx7wBmW0uzvkSg/9ovWLycPaBgJbM3LOCQ== +"@particle-network/solana-wallet@^0.5.6": + version "0.5.6" + resolved "https://registry.yarnpkg.com/@particle-network/solana-wallet/-/solana-wallet-0.5.6.tgz#701d431820c54c8c592999de29928670a26d5978" + integrity sha512-Ad0hwJsWRCbptp+mmLFsbrERDQbW+QhFQOmWRT8+6gGrY6qNTApwI9+jlpkxOzEI9rvSqFD1qKKMlqy1n+fJNA== dependencies: - clean-stack "^3.0.0" - fs-extra "^8.1" - indent-string "^4.0.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" + "@particle-network/auth" "^0.5.5" -"@oclif/help@^1.0.1": +"@pedrouid/environment@^1.0.1": version "1.0.1" - resolved "https://registry.npmjs.org/@oclif/help/-/help-1.0.1.tgz" - integrity sha512-8rsl4RHL5+vBUAKBL6PFI3mj58hjPCp2VYyXD4TAa7IMStikFfOH2gtWmqLzIlxAED2EpD0dfYwo9JJxYsH7Aw== - dependencies: - "@oclif/config" "1.18.2" - "@oclif/errors" "1.3.5" - chalk "^4.1.2" - indent-string "^4.0.0" - lodash "^4.17.21" - string-width "^4.2.0" - strip-ansi "^6.0.0" - widest-line "^3.1.0" - wrap-ansi "^6.2.0" + resolved "https://registry.yarnpkg.com/@pedrouid/environment/-/environment-1.0.1.tgz#858f0f8a057340e0b250398b75ead77d6f4342ec" + integrity sha512-HaW78NszGzRZd9SeoI3JD11JqY+lubnaOx7Pewj5pfjqWXOEATpeKIFb9Z4t2WBUK2iryiXX3lzWwmYWgUL0Ug== -"@oclif/linewrap@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz" - integrity sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw== +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@oclif/parser@^3.8.0", "@oclif/parser@^3.8.6": - version "3.8.7" - resolved "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.7.tgz" - integrity sha512-b11xBmIUK+LuuwVGJpFs4LwQN2xj2cBWj2c4z1FtiXGrJ85h9xV6q+k136Hw0tGg1jQoRXuvuBnqQ7es7vO9/Q== - dependencies: - "@oclif/errors" "^1.3.5" - "@oclif/linewrap" "^1.0.0" - chalk "^4.1.0" - tslib "^2.3.1" +"@pkgr/core@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" + integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== "@polka/url@^1.0.0-next.20": version "1.0.0-next.21" - resolved "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== -"@popperjs/core@^2.11.5": - version "2.11.5" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64" - integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw== - -"@popperjs/core@^2.8.3": - version "2.9.3" - resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.9.3.tgz" - integrity sha512-xDu17cEfh7Kid/d95kB6tZsLOmSWKCZKtprnhVepjsSaCij+lM3mItSJDuuHDMbCWTh8Ejmebwb+KONcCJ0eXQ== - -"@port.finance/port-sdk@^0.2.33": - version "0.2.67" - resolved "https://registry.yarnpkg.com/@port.finance/port-sdk/-/port-sdk-0.2.67.tgz#48ddd27af7b14c956fa6a2941d84edc61eb9c082" - integrity sha512-qm7IHdfP/vhSv41RHveEUsJSBOknPeWYuRwZS5oISwe1kvcOBHkuh/9GuJD24TlE9HaoO+JGq3rpn8YLFjNh8w== - dependencies: - "@project-serum/anchor" "^0.21.0" - "@saberhq/solana-contrib" "^1.12.53" - "@saberhq/token-utils" "^1.12.53" - "@solana/buffer-layout" "^3.0.0" - "@solana/spl-token" "^0.1.8" - "@solana/spl-token-registry" "^0.2.1107" - big.js "^6.1.1" - bignumber.js "^9.0.1" - buffer-layout "1.2.2" - jsbi "^4.1.0" - prettier "^2.4.1" - tiny-invariant "^1.2.0" - typescript "^4.3.5" - -"@project-serum/anchor-cli@^0.18.2": - version "0.18.2" - resolved "https://registry.npmjs.org/@project-serum/anchor-cli/-/anchor-cli-0.18.2.tgz" - integrity sha512-zZvLSa0DvsjsKSK8cU7ENqPB1tQ8WCT6dTY2IaJjWdG0UvXUTri8phnYyF5+Zti+frTdKyggOtI+i1QApOWhRQ== +"@popperjs/core@^2.9.0": + version "2.11.6" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" + integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== -"@project-serum/anchor@0.18.2", "@project-serum/anchor@^0.18.0", "@project-serum/anchor@^0.18.2": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.18.2.tgz#0f13b5c2046446b7c24cf28763eec90febb28485" - integrity sha512-uyjiN/3Ipp+4hrZRm/hG18HzGLZyvP790LXrCsGO3IWxSl28YRhiGEpKnZycfMW94R7nxdUoE3wY67V+ZHSQBQ== +"@project-serum/anchor@0.20.1", "@project-serum/anchor@^0.20.1": + version "0.20.1" + resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.20.1.tgz#0937807e807e8332aa708cfef4bcb6cbb88b4129" + integrity sha512-2TuBmGUn9qeYz6sJINJlElrBuPsaUAtYyUsJ3XplEBf1pczrANAgs5ceJUFzdiqGEWLn+84ObSdBeChT/AXYFA== dependencies: "@project-serum/borsh" "^0.2.2" "@solana/web3.js" "^1.17.0" base64-js "^1.5.1" bn.js "^5.1.2" bs58 "^4.0.1" - buffer-layout "^1.2.0" + buffer-layout "^1.2.2" camelcase "^5.3.1" crypto-hash "^1.3.0" eventemitter3 "^4.0.7" @@ -3596,18 +2921,19 @@ snake-case "^3.0.4" toml "^3.0.0" -"@project-serum/anchor@0.20.1", "@project-serum/anchor@^0.20.1": - version "0.20.1" - resolved "https://registry.npmjs.org/@project-serum/anchor/-/anchor-0.20.1.tgz" - integrity sha512-2TuBmGUn9qeYz6sJINJlElrBuPsaUAtYyUsJ3XplEBf1pczrANAgs5ceJUFzdiqGEWLn+84ObSdBeChT/AXYFA== +"@project-serum/anchor@0.21.0": + version "0.21.0" + resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.21.0.tgz#ad5fb33744991ec1900cdb2fd22707c908b12b5f" + integrity sha512-flRuW/F+iC8mitNokx82LOXyND7Dyk6n5UUPJpQv/+NfySFrNFlzuQZaBZJ4CG5g9s8HS/uaaIz1nVkDR8V/QA== dependencies: - "@project-serum/borsh" "^0.2.2" + "@project-serum/borsh" "^0.2.4" "@solana/web3.js" "^1.17.0" base64-js "^1.5.1" bn.js "^5.1.2" bs58 "^4.0.1" buffer-layout "^1.2.2" camelcase "^5.3.1" + cross-fetch "^3.1.5" crypto-hash "^1.3.0" eventemitter3 "^4.0.7" find "^0.3.0" @@ -3637,29 +2963,30 @@ snake-case "^3.0.4" toml "^3.0.0" -"@project-serum/anchor@0.24.2", "@project-serum/anchor@^0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.24.2.tgz#a3c52a99605c80735f446ca9b3a4885034731004" - integrity sha512-0/718g8/DnEuwAidUwh5wLYphUYXhUbiClkuRNhvNoa+1Y8a4g2tJyxoae+emV+PG/Gikd/QUBNMkIcimiIRTA== +"@project-serum/anchor@0.26.0": + version "0.26.0" + resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.26.0.tgz#99e15a3923a5d10514f8185b2d3909e5699d60d5" + integrity sha512-Nq+COIjE1135T7qfnOHEn7E0q39bQTgXLFk837/rgFe6Hkew9WML7eHsS+lSYD2p3OJaTiUOHTAq1lHy36oIqQ== dependencies: - "@project-serum/borsh" "^0.2.5" - "@solana/web3.js" "^1.36.0" + "@coral-xyz/borsh" "^0.26.0" + "@solana/web3.js" "^1.68.0" base64-js "^1.5.1" bn.js "^5.1.2" bs58 "^4.0.1" buffer-layout "^1.2.2" - camelcase "^5.3.1" + camelcase "^6.3.0" cross-fetch "^3.1.5" crypto-hash "^1.3.0" eventemitter3 "^4.0.7" js-sha256 "^0.9.0" pako "^2.0.3" snake-case "^3.0.4" + superstruct "^0.15.4" toml "^3.0.0" "@project-serum/anchor@^0.11.1": version "0.11.1" - resolved "https://registry.npmjs.org/@project-serum/anchor/-/anchor-0.11.1.tgz" + resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.11.1.tgz#155bff2c70652eafdcfd5559c81a83bb19cec9ff" integrity sha512-oIdm4vTJkUy6GmE6JgqDAuQPKI7XM4TPJkjtoIzp69RZe0iAD9JP2XHx7lV1jLdYXeYHqDXfBt3zcq7W91K6PA== dependencies: "@project-serum/borsh" "^0.2.2" @@ -3677,10 +3004,10 @@ snake-case "^3.0.4" toml "^3.0.0" -"@project-serum/anchor@^0.16.2": - version "0.16.2" - resolved "https://registry.npmjs.org/@project-serum/anchor/-/anchor-0.16.2.tgz" - integrity sha512-wOJwObd4wOZ5tRRMCKYjeMNsEmf7vuC71KQRnw6wthhErL8c/818n4gYIZCf/1ZPl/8WPruIlmtQHDSEyy2+0Q== +"@project-serum/anchor@^0.18.2": + version "0.18.2" + resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.18.2.tgz#0f13b5c2046446b7c24cf28763eec90febb28485" + integrity sha512-uyjiN/3Ipp+4hrZRm/hG18HzGLZyvP790LXrCsGO3IWxSl28YRhiGEpKnZycfMW94R7nxdUoE3wY67V+ZHSQBQ== dependencies: "@project-serum/borsh" "^0.2.2" "@solana/web3.js" "^1.17.0" @@ -3697,27 +3024,6 @@ snake-case "^3.0.4" toml "^3.0.0" -"@project-serum/anchor@^0.21.0": - version "0.21.0" - resolved "https://registry.npmjs.org/@project-serum/anchor/-/anchor-0.21.0.tgz" - integrity sha512-flRuW/F+iC8mitNokx82LOXyND7Dyk6n5UUPJpQv/+NfySFrNFlzuQZaBZJ4CG5g9s8HS/uaaIz1nVkDR8V/QA== - dependencies: - "@project-serum/borsh" "^0.2.4" - "@solana/web3.js" "^1.17.0" - base64-js "^1.5.1" - bn.js "^5.1.2" - bs58 "^4.0.1" - buffer-layout "^1.2.2" - camelcase "^5.3.1" - cross-fetch "^3.1.5" - crypto-hash "^1.3.0" - eventemitter3 "^4.0.7" - find "^0.3.0" - js-sha256 "^0.9.0" - pako "^2.0.3" - snake-case "^3.0.4" - toml "^3.0.0" - "@project-serum/anchor@^0.22.1": version "0.22.1" resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.22.1.tgz#698a9620f94691de0a12bbc650a5c8380e2f0e8a" @@ -3739,10 +3045,10 @@ snake-case "^3.0.4" toml "^3.0.0" -"@project-serum/anchor@^0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.25.0.tgz#88ee4843336005cf5a64c80636ce626f0996f503" - integrity sha512-E6A5Y/ijqpfMJ5psJvbw0kVTzLZFUcOFgs6eSM2M2iWE1lVRF18T6hWZVNl6zqZsoz98jgnNHtVGJMs+ds9A7A== +"@project-serum/anchor@^0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.24.2.tgz#a3c52a99605c80735f446ca9b3a4885034731004" + integrity sha512-0/718g8/DnEuwAidUwh5wLYphUYXhUbiClkuRNhvNoa+1Y8a4g2tJyxoae+emV+PG/Gikd/QUBNMkIcimiIRTA== dependencies: "@project-serum/borsh" "^0.2.5" "@solana/web3.js" "^1.36.0" @@ -3757,13 +3063,12 @@ js-sha256 "^0.9.0" pako "^2.0.3" snake-case "^3.0.4" - superstruct "^0.15.4" toml "^3.0.0" -"@project-serum/anchor@^0.25.0-beta.1": - version "0.25.0-beta.1" - resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.25.0-beta.1.tgz#7b113fb6604483d6740c8da9c6d86e9a5d5f6cf7" - integrity sha512-edesFlclgQzIluD2mC0xrGPnABBllKvbGd6MOtNZMCauUnx1Xbu073um8O6mrCeuZrz4PG9AhwAp1y5cOl3R4A== +"@project-serum/anchor@^0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@project-serum/anchor/-/anchor-0.25.0.tgz#88ee4843336005cf5a64c80636ce626f0996f503" + integrity sha512-E6A5Y/ijqpfMJ5psJvbw0kVTzLZFUcOFgs6eSM2M2iWE1lVRF18T6hWZVNl6zqZsoz98jgnNHtVGJMs+ds9A7A== dependencies: "@project-serum/borsh" "^0.2.5" "@solana/web3.js" "^1.36.0" @@ -3781,57 +3086,29 @@ superstruct "^0.15.4" toml "^3.0.0" -"@project-serum/borsh@^0.2.2", "@project-serum/borsh@^0.2.3", "@project-serum/borsh@^0.2.4", "@project-serum/borsh@^0.2.5": +"@project-serum/associated-token@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@project-serum/associated-token/-/associated-token-0.1.1.tgz#9acf745e84dad21e2ea26e06694704b9d698e532" + integrity sha512-Zc1wdqragbDiyBVagzIbIsMe37P7fgkArWZPIj+jJjDIoznlmYMK6ASU5mtdDZrPJ7sNABF/lzZ3+jvCCcU+oA== + +"@project-serum/borsh@^0.2.2", "@project-serum/borsh@^0.2.4", "@project-serum/borsh@^0.2.5": version "0.2.5" - resolved "https://registry.npmjs.org/@project-serum/borsh/-/borsh-0.2.5.tgz" + resolved "https://registry.yarnpkg.com/@project-serum/borsh/-/borsh-0.2.5.tgz#6059287aa624ecebbfc0edd35e4c28ff987d8663" integrity sha512-UmeUkUoKdQ7rhx6Leve1SssMR/Ghv8qrEiyywyxSWg7ooV7StdpPBhciiy5eB3T0qU1BXvdRNC8TdrkxK7WC5Q== dependencies: bn.js "^5.1.2" buffer-layout "^1.2.0" -"@project-serum/common@^0.0.1-beta.3": +"@project-serum/common@0.0.1-beta.3", "@project-serum/common@^0.0.1-beta.3": version "0.0.1-beta.3" - resolved "https://registry.npmjs.org/@project-serum/common/-/common-0.0.1-beta.3.tgz" + resolved "https://registry.yarnpkg.com/@project-serum/common/-/common-0.0.1-beta.3.tgz#53586eaff9d9fd7e8938b1e12080c935b8b6ad07" integrity sha512-gnQE/eUydTtto5okCgLWj1M97R9RRPJqnhKklikYI7jP/pnNhDmngSXC/dmfzED2GXSJEIKNIlxVw1k+E2Aw3w== dependencies: "@project-serum/serum" "^0.13.21" bn.js "^5.1.2" superstruct "0.8.3" -"@project-serum/serum@0.13.55": - version "0.13.55" - resolved "https://registry.yarnpkg.com/@project-serum/serum/-/serum-0.13.55.tgz#2ac44fe7b07651274eb57ac54ea9325789df5dd7" - integrity sha512-SPQ4NsuNbBJO3mLGnTYbjt47WCXoNIcW2C9xv0gNXyG62dxgONsAEEgErKv1gT34hWCMPsXFSpatnX6ppriq7w== - dependencies: - "@project-serum/anchor" "^0.11.1" - "@solana/spl-token" "^0.1.6" - "@solana/web3.js" "^1.21.0" - bn.js "^5.1.2" - buffer-layout "^1.2.0" - -"@project-serum/serum@0.13.64": - version "0.13.64" - resolved "https://registry.yarnpkg.com/@project-serum/serum/-/serum-0.13.64.tgz#d5a9009ded8d2539ebfd12e1ff58b9028cfcdf45" - integrity sha512-33d8K3qcbiFnL1Azv5k6IYMtJYjCqqmFkf95w5W8MPB0A+5zQfOwhEfXQuBw0ExZ8ft5s9Vy8sReLyx0SsINWA== - dependencies: - "@project-serum/anchor" "^0.11.1" - "@solana/spl-token" "^0.1.6" - "@solana/web3.js" "^1.21.0" - bn.js "^5.1.2" - buffer-layout "^1.2.0" - -"@project-serum/serum@^0.13.21", "@project-serum/serum@^0.13.61": - version "0.13.61" - resolved "https://registry.yarnpkg.com/@project-serum/serum/-/serum-0.13.61.tgz#1f0e6dfa7786a71e4317593911e9915d8b2a06e6" - integrity sha512-aebaRGQ0/K7a5kJ9UXO59BAQFJILVu5jbGobU8GD2CTSy6SPceprB6/pgZmZLQIabhXWUHaZRF/wXIClgWataA== - dependencies: - "@project-serum/anchor" "^0.11.1" - "@solana/spl-token" "^0.1.6" - "@solana/web3.js" "^1.21.0" - bn.js "^5.1.2" - buffer-layout "^1.2.0" - -"@project-serum/serum@^0.13.60", "@project-serum/serum@^0.13.65": +"@project-serum/serum@0.13.65", "@project-serum/serum@^0.13.21", "@project-serum/serum@^0.13.61": version "0.13.65" resolved "https://registry.yarnpkg.com/@project-serum/serum/-/serum-0.13.65.tgz#6d3cf07912f13985765237f053cca716fe84b0b0" integrity sha512-BHRqsTqPSfFB5p+MgI2pjvMBAQtO8ibTK2fYY96boIFkCI3TTwXDt2gUmspeChKO2pqHr5aKevmexzAcXxrSRA== @@ -3842,16 +3119,9 @@ bn.js "^5.1.2" buffer-layout "^1.2.0" -"@project-serum/sol-wallet-adapter@0.2.0": - version "0.2.0" - resolved "https://registry.npmjs.org/@project-serum/sol-wallet-adapter/-/sol-wallet-adapter-0.2.0.tgz" - dependencies: - bs58 "^4.0.1" - eventemitter3 "^4.0.4" - -"@project-serum/sol-wallet-adapter@^0.2.0", "@project-serum/sol-wallet-adapter@^0.2.6": +"@project-serum/sol-wallet-adapter@0.2.6", "@project-serum/sol-wallet-adapter@^0.2.6": version "0.2.6" - resolved "https://registry.npmjs.org/@project-serum/sol-wallet-adapter/-/sol-wallet-adapter-0.2.6.tgz" + resolved "https://registry.yarnpkg.com/@project-serum/sol-wallet-adapter/-/sol-wallet-adapter-0.2.6.tgz#b4cd25a566294354427c97c26d716112b91a0107" integrity sha512-cpIb13aWPW8y4KzkZAPDgw+Kb+DXjCC6rZoH74MGm3I/6e/zKyGnfAuW5olb2zxonFqsYgnv7ev8MQnvSgJ3/g== dependencies: bs58 "^4.0.1" @@ -3910,21 +3180,56 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== -"@pythnetwork/client@^2.5.1": - version "2.5.3" - resolved "https://registry.npmjs.org/@pythnetwork/client/-/client-2.5.3.tgz" - integrity sha512-NBLxPnA6A3tZb/DYUooD4SO63UJ70s9DzzFPGXcQNBR9itcycp7aaV+UA5oUPloD/4UHL9soo2fRuDVur0gmhA== +"@pythnetwork/client@2.17.0": + version "2.17.0" + resolved "https://registry.yarnpkg.com/@pythnetwork/client/-/client-2.17.0.tgz#b155af06958f4b729bfee1c07130c556598cf168" + integrity sha512-hv285vehmLH6N762Z4jqvPTM+hCYnXQaUp6DMgLUpDHvE0mTbwW9PvlxYoUJZGtyeCDkgn9HrTWXPtnaXTRr+Q== dependencies: - "@solana/web3.js" "^1.30.2" - assert "^2.0.0" + "@coral-xyz/anchor" "^0.26.0" + "@coral-xyz/borsh" "^0.26.0" buffer "^6.0.1" -"@pythnetwork/client@^2.7.0": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@pythnetwork/client/-/client-2.7.3.tgz#6075a16dc394d1734e76b04e907a680490a61536" - integrity sha512-+2k5JXxv/yUA6WMESSppJlg4T/AP+nZZfBnHmeG3RPCIJx+bargxFLCK4B2KgpQYdeTWb+2z8yRCNF7tHooCFQ== +"@pythnetwork/client@^2.5.1", "@pythnetwork/client@~2.21.1": + version "2.21.1" + resolved "https://registry.yarnpkg.com/@pythnetwork/client/-/client-2.21.1.tgz#524a278432dcec14fcf8ba67dfd4720df19b5cc3" + integrity sha512-nSpI1qjmbyrFTetfJSDqjzT+AAJYG3xUmDYFnExAFrnhiO5C8FPvMw1zkSYXWRvEwHFISKJLsn1sTIqU9ifaCA== + dependencies: + "@coral-xyz/anchor" "^0.29.0" + "@coral-xyz/borsh" "^0.28.0" + buffer "^6.0.1" + +"@pythnetwork/solana-utils@0.4.2", "@pythnetwork/solana-utils@^0.4.1": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@pythnetwork/solana-utils/-/solana-utils-0.4.2.tgz#3e220eed518c02ad702ebb023488afd7c5649a87" + integrity sha512-hKo7Bcs/kDWA5Fnqhg9zJSB94NMoUDIDjHjSi/uvZOzwizISUQI6oY3LWd2CXzNh4f8djjY2BS5iNHaM4cm8Bw== + dependencies: + "@coral-xyz/anchor" "^0.29.0" + "@solana/web3.js" "^1.90.0" + bs58 "^5.0.0" + jito-ts "^3.0.1" + +"@pythnetwork/staking-sdk@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@pythnetwork/staking-sdk/-/staking-sdk-0.0.2.tgz#38dfd6f8356c6544875c6d06aafa55886b7bc1a5" + integrity sha512-IfHJIJ5ZwF8x86/10/5Gs9SUAj4fgW013OiWekfzXhogI2MT27TFQqpaCGj8ndJ4XVlzMk3MDGRuOmujtGCVGA== + dependencies: + "@coral-xyz/anchor" "^0.30.1" + "@pythnetwork/solana-utils" "0.4.2" + "@solana/spl-governance" "^0.3.28" + "@solana/spl-token" "^0.3.7" + "@solana/web3.js" "^1.95.3" + +"@pythnetwork/staking-wasm@0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@pythnetwork/staking-wasm/-/staking-wasm-0.3.5.tgz#a5e524a721df9613a1f33a1a1c708de0bfcfe89f" + integrity sha512-iQpPPn6kPuc9Q1MO+PMAKAhkuv6AOUHiAZJizCbPm3aO7kS2YxRKsRSMsky9FY1GHHatSx13LX9epsJXi/MmKg== + +"@radix-ui/number@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.0.0.tgz#4c536161d0de750b3f5d55860fc3de46264f897b" + integrity sha512-Ofwh/1HX69ZfJRiRBMTy7rgjAzHmwe4kW9C9Y99HTRUcYLUuVT0KESFj15rPjRgKJs20GPq8Bm5aEDJ8DuA3vA== dependencies: - buffer "^6.0.1" + "@babel/runtime" "^7.13.10" "@radix-ui/primitive@1.0.0": version "1.0.0" @@ -3933,6 +3238,21 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-accordion@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-accordion/-/react-accordion-1.0.0.tgz#bf69dc1f13fce05d6d7560ff79954c49abc1b71b" + integrity sha512-F4vrzev+f1gjrWiU+IFQIzN43fYyvQ+AN0OicHYoDddis53xnPC0DKm16Ks4/XjvmqbISAR/FscYX0vymEHxcA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-collapsible" "1.0.0" + "@radix-ui/react-collection" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/react-arrow@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.0.tgz#c461f4c2cab3317e3d42a1ae62910a4cbb0192a1" @@ -3941,7 +3261,15 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.0" -"@radix-ui/react-aspect-ratio@^1.0.0": +"@radix-ui/react-arrow@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.1.tgz#5246adf79e97f89e819af68da51ddcf349ecf1c4" + integrity sha512-1yientwXqXcErDHEv8av9ZVNEBldH8L9scVR3is20lL+jOCfcJyMFZFEY5cgIrgexsq1qggSXqiEL/d/4f+QXA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.1" + +"@radix-ui/react-aspect-ratio@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.0.0.tgz#bc8ff46ec2ab221768e17f3bc05cc49d338a4e41" integrity sha512-/QlrIrrcWU8QPz5AccWgKdQGUFw+EKZaxzlH5eWqbOCBTmq0kM1lgaa9EbsmyJwOTtlN0Az9F83lNboQubifwg== @@ -3949,6 +3277,21 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.0" +"@radix-ui/react-collapsible@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collapsible/-/react-collapsible-1.0.0.tgz#0d94fc847c2d4bee1ab646d15c87bd3be6448873" + integrity sha512-NfZqWntvPsC43szs0NvumRjmTTJTLgaDOAnmVGDZaGsg2u6LcJwUT7YeYSKnlxWRQWN4pwwEfoYdWrtoutfO8g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/react-collection@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.0.tgz#0ec4c72fabd35a03b5787075ac799e3b17ca5710" @@ -3960,6 +3303,17 @@ "@radix-ui/react-primitive" "1.0.0" "@radix-ui/react-slot" "1.0.0" +"@radix-ui/react-collection@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.1.tgz#259506f97c6703b36291826768d3c1337edd1de5" + integrity sha512-uuiFbs+YCKjn3X1DTSx9G7BHApu4GHbi3kgiwsnFUbOKCrwejAJv4eE4Vc8C0Oaxt9T0aV4ox0WCOdx+39Xo+g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-slot" "1.0.1" + "@radix-ui/react-compose-refs@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz#37595b1f16ec7f228d698590e78eeed18ff218ae" @@ -3974,6 +3328,27 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-dialog@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.0.tgz#997e97cb183bc90bd888b26b8e23a355ac9fe5f0" + integrity sha512-Yn9YU+QlHYLWwV1XfKiqnGVpWYWk6MeBVM6x/bcoyPvxgjQGoeT35482viLPctTMWoMw0PoHgqfSox7Ig+957Q== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-dismissable-layer" "1.0.0" + "@radix-ui/react-focus-guards" "1.0.0" + "@radix-ui/react-focus-scope" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-portal" "1.0.0" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-slot" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.4" + "@radix-ui/react-direction@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.0.tgz#a2e0b552352459ecf96342c79949dd833c1e6e45" @@ -3993,7 +3368,19 @@ "@radix-ui/react-use-callback-ref" "1.0.0" "@radix-ui/react-use-escape-keydown" "1.0.0" -"@radix-ui/react-dropdown-menu@^1.0.0": +"@radix-ui/react-dismissable-layer@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.2.tgz#f04d1061bddf00b1ca304148516b9ddc62e45fb2" + integrity sha512-WjJzMrTWROozDqLB0uRWYvj4UuXsM/2L19EmQ3Au+IJWqwvwq9Bwd+P8ivo0Deg9JDPArR1I6MbWNi1CmXsskg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-escape-keydown" "1.0.2" + +"@radix-ui/react-dropdown-menu@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-1.0.0.tgz#687959e1bcdd5e8eb0de406484aff28d0974c593" integrity sha512-Ptben3TxPWrZLbInO7zjAK73kmjYuStsxfg6ujgt+EywJyREoibhZYnsSNqC+UiOtl4PdW/MOHhxVDtew5fouQ== @@ -4024,6 +3411,32 @@ "@radix-ui/react-primitive" "1.0.0" "@radix-ui/react-use-callback-ref" "1.0.0" +"@radix-ui/react-focus-scope@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.1.tgz#faea8c25f537c5a5c38c50914b63722db0e7f951" + integrity sha512-Ej2MQTit8IWJiS2uuujGUmxXjF/y5xZptIIQnyd2JHLwtV0R2j9NRVoRj/1j/gJ7e3REdaBw4Hjf4a1ImhkZcQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.0.0" + +"@radix-ui/react-hover-card@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-hover-card/-/react-hover-card-1.0.0.tgz#d8a1afb4e616ed55a2ecf4e3ab12aa56f2093a20" + integrity sha512-9Vn24lwbB0QUrVsgIKdjCmX9Y/ElBbBbGrJ4FWeT6EktaOQUWJT7y1Ao+WBSlNwbklhJIbbhZgknHm0IAoxTLA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-dismissable-layer" "1.0.0" + "@radix-ui/react-popper" "1.0.0" + "@radix-ui/react-portal" "1.0.0" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/react-id@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.0.tgz#8d43224910741870a45a8c9d092f25887bb6d11e" @@ -4032,6 +3445,17 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.0" +"@radix-ui/react-label@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-1.0.0.tgz#c6691b0bec18958512a952c18732279285b61fef" + integrity sha512-k+EbxeRaVbSJ4oaR9eUYuC0cDIGRB4TAPhilbFCIMpP9pXFNcyQPQUvRaVOQBrviuArYM80xh0BQR/0y3kjUdQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-menu@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-1.0.0.tgz#f1e07778c0011aa0c5be260fee88491d3aadf261" @@ -4057,6 +3481,49 @@ aria-hidden "^1.1.1" react-remove-scroll "2.5.4" +"@radix-ui/react-navigation-menu@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.0.0.tgz#5aaf65967794147eee52e87930191c55d08bd213" + integrity sha512-HbwG3A9z9zdcan0076EbTXqMvmQeesC3nOMEL7XtWqBnxPo8MLStk0vMs0hjIQ+9O9/KTcEJq+TeRX2pUuvuSg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-collection" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-dismissable-layer" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/react-use-previous" "1.0.0" + "@radix-ui/react-visually-hidden" "1.0.0" + +"@radix-ui/react-popover@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.2.tgz#f761c8aafb61519522b8e80501c589e619073a2c" + integrity sha512-4tqZEl9w95R5mlZ/sFdgBnfhCBOEPepLIurBA5kt/qaAhldJ1tNQd0ngr0ET0AHbPotT4mwxMPr7a+MA/wbK0g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-dismissable-layer" "1.0.2" + "@radix-ui/react-focus-guards" "1.0.0" + "@radix-ui/react-focus-scope" "1.0.1" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-popper" "1.0.1" + "@radix-ui/react-portal" "1.0.1" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-slot" "1.0.1" + "@radix-ui/react-use-controllable-state" "1.0.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + "@radix-ui/react-popper@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.0.0.tgz#fb4f937864bf39c48f27f55beee61fa9f2bef93c" @@ -4073,6 +3540,22 @@ "@radix-ui/react-use-size" "1.0.0" "@radix-ui/rect" "1.0.0" +"@radix-ui/react-popper@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.0.1.tgz#9fa8a6a493404afa225866a5cd75af23d141baa0" + integrity sha512-J4Vj7k3k+EHNWgcKrE+BLlQfpewxA7Zd76h5I0bIa+/EqaIZ3DuwrbPj49O3wqN+STnXsBuxiHLiF0iU3yfovw== + dependencies: + "@babel/runtime" "^7.13.10" + "@floating-ui/react-dom" "0.7.2" + "@radix-ui/react-arrow" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/react-use-rect" "1.0.0" + "@radix-ui/react-use-size" "1.0.0" + "@radix-ui/rect" "1.0.0" + "@radix-ui/react-portal@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.0.tgz#7220b66743394fabb50c55cb32381395cc4a276b" @@ -4081,6 +3564,14 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.0" +"@radix-ui/react-portal@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.1.tgz#169c5a50719c2bb0079cf4c91a27aa6d37e5dd33" + integrity sha512-NY2vUWI5WENgAT1nfC6JS7RU5xRYBfjZVLq0HmgEN1Ezy3rk/UruMV4+Rd0F40PEaFC5SrLS1ixYvcYIQrb4Ig== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-presence@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.0.tgz#814fe46df11f9a468808a6010e3f3ca7e0b2e84a" @@ -4098,6 +3589,40 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-slot" "1.0.0" +"@radix-ui/react-primitive@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz#c1ebcce283dd2f02e4fbefdaa49d1cb13dbc990a" + integrity sha512-fHbmislWVkZaIdeF6GZxF0A/NH/3BjrGIYj+Ae6eTmTCr7EB0RQAAVEiqsXK6p3/JcRqVSBQoceZroj30Jj3XA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-slot" "1.0.1" + +"@radix-ui/react-progress@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-progress/-/react-progress-1.0.1.tgz#49ec2f729a67ba3b580a90356fc1d871466a4212" + integrity sha512-QbDf9eguM5QtkvGcGHe/nUgloM9yfRGpJTB/Te5cn4WmVHvcbhHyHw39/rbCZxNX4E+GEPp5Vs6+mEoyIotUbg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + +"@radix-ui/react-radio-group@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-radio-group/-/react-radio-group-1.1.0.tgz#e1719e1c9af03230d1b02c1f180dee816544e1ec" + integrity sha512-7rrkZCXu0Q7oC0MxCm497X1DdV/tI78oNIGXA8sDbCkboiTkuLSe728zCCpRYHw+9PifHIx86nsbITPEq5yijg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-roving-focus" "1.0.1" + "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/react-use-previous" "1.0.0" + "@radix-ui/react-use-size" "1.0.0" + "@radix-ui/react-roving-focus@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.0.tgz#aadeb65d5dbcdbdd037078156ae1f57c2ff754ee" @@ -4114,6 +3639,76 @@ "@radix-ui/react-use-callback-ref" "1.0.0" "@radix-ui/react-use-controllable-state" "1.0.0" +"@radix-ui/react-roving-focus@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.1.tgz#475621f63aee43faa183a5270f35d49e530de3d7" + integrity sha512-TB76u5TIxKpqMpUAuYH2VqMhHYKa+4Vs1NHygo/llLvlffN6mLVsFhz0AnSFlSBAvTBYVHYAkHAyEt7x1gPJOA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-collection" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + +"@radix-ui/react-select@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-1.0.0.tgz#16d91f493a18e471d40fc06b1faff516b5686784" + integrity sha512-GfbVBxx7JPvytNT+0XYCFCOImEMmpl0Vg7hhifLaLV7p5zRottFMgQ7qrrxw8v6B8buKXz41kWYMrdRrWqsZaQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/number" "1.0.0" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-collection" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-dismissable-layer" "1.0.0" + "@radix-ui/react-focus-guards" "1.0.0" + "@radix-ui/react-focus-scope" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-label" "1.0.0" + "@radix-ui/react-portal" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-slot" "1.0.0" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/react-use-previous" "1.0.0" + "@radix-ui/react-visually-hidden" "1.0.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.4" + +"@radix-ui/react-separator@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.0.0.tgz#ae318b5e7e1436b68d77cf08b7cd25a37893021f" + integrity sha512-narSsDP+CKJWEOV9Yx9aOpw4bLaNRNIvnqmfx30mAJAJ9wPKoyVmcLzFj0Hyx3yQNZx7EokMwW6KtMyxN5jDUw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.0" + +"@radix-ui/react-slider@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slider/-/react-slider-1.1.0.tgz#b3fdaca27619150e9e6067ad9f979a4535f68d5e" + integrity sha512-5H/QB4xD3GF9UfoSCVLBx2JjlXamMcmTyL6gr4kkd/MiAGaYB0W7Exi4MQa0tJApBFJe+KmS5InKCI56p2kmjA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/number" "1.0.0" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-collection" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/react-use-previous" "1.0.0" + "@radix-ui/react-use-size" "1.0.0" + "@radix-ui/react-slot@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.0.tgz#7fa805b99891dea1e862d8f8fbe07f4d6d0fd698" @@ -4122,20 +3717,104 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-compose-refs" "1.0.0" -"@radix-ui/react-tabs@^1.0.0": +"@radix-ui/react-slot@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.1.tgz#e7868c669c974d649070e9ecbec0b367ee0b4d81" + integrity sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" + +"@radix-ui/react-tabs@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.0.0.tgz#135c67f1f2bd9ada69a3f6e38dd897d459af5fe5" + integrity sha512-oKUwEDsySVC0uuSEH7SHCVt1+ijmiDFAI9p+fHCtuZdqrRDKIFs09zp5nrmu4ggP6xqSx9lj1VSblnDH+n3IBA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-roving-focus" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + +"@radix-ui/react-toast@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-toast/-/react-toast-1.0.0.tgz#0d808e7f13376ddc74c0dbb7a4ff1c0602778ae2" + integrity sha512-mdoF6rahgushdev0OX+9a7JKoH0xZAZBo2Ktf/s779S7EnkZeL3/MFiRIV5LpRP5CtASmfdSD3FLnEvG1RHRtQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-collection" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-dismissable-layer" "1.0.0" + "@radix-ui/react-portal" "1.0.0" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/react-visually-hidden" "1.0.0" + +"@radix-ui/react-toggle-group@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-toggle-group/-/react-toggle-group-1.0.0.tgz#6e78ffb13e0b4c1f789828930330638f4ba9c06d" + integrity sha512-R/5sK4/BPgOYWAsheFaFpNFh0sLPHdqsBcqO5KW2+Foy36B2KBYrGd6Hu4HnzgivawVX+mSmVNhAwHA8Yb1hLA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-roving-focus" "1.0.0" + "@radix-ui/react-toggle" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + +"@radix-ui/react-toggle@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-toggle/-/react-toggle-1.0.0.tgz#9c8f655497b26410766b9c01aa2954159c0cb60b" + integrity sha512-RvY06eyDlZMC4rZdWK8jNovEDKf2jBvYFOB4rkQ/ypMOjFQuoh2QodlxlGakrZDrLnfxzyNnn/pg88CWVtAAdw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + +"@radix-ui/react-toolbar@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-toolbar/-/react-toolbar-1.0.0.tgz#543f5057f5d38b10a2cfce534f8e37e1a8b0eac8" + integrity sha512-IvE13O0MP7pNc4c87Q7JPOyyXKRUJBjvqfoC/wCPxLlCz4ijoW+cU7J0Rw9Rj5TScyhUyinLL014j2uBH9O0EA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/react-roving-focus" "1.0.0" + "@radix-ui/react-separator" "1.0.0" + "@radix-ui/react-toggle-group" "1.0.0" + +"@radix-ui/react-tooltip@1.0.0": version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.0.0.tgz#135c67f1f2bd9ada69a3f6e38dd897d459af5fe5" - integrity sha512-oKUwEDsySVC0uuSEH7SHCVt1+ijmiDFAI9p+fHCtuZdqrRDKIFs09zp5nrmu4ggP6xqSx9lj1VSblnDH+n3IBA== + resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.0.0.tgz#f7fcecf2bac5c31cd14666b5acd056015fc21646" + integrity sha512-RB06pov+O4Npy10ei1C6fsyB9QoOjz7Ubo8Sl3qdKtLgkL9iI96925DYtH0bxx6MH6YB2FuzLU6B75qn3AQQQw== dependencies: "@babel/runtime" "^7.13.10" "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" "@radix-ui/react-context" "1.0.0" - "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-dismissable-layer" "1.0.0" "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-popper" "1.0.0" + "@radix-ui/react-portal" "1.0.0" "@radix-ui/react-presence" "1.0.0" "@radix-ui/react-primitive" "1.0.0" - "@radix-ui/react-roving-focus" "1.0.0" + "@radix-ui/react-slot" "1.0.0" "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/react-visually-hidden" "1.0.0" "@radix-ui/react-use-callback-ref@1.0.0": version "1.0.0" @@ -4160,6 +3839,14 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-callback-ref" "1.0.0" +"@radix-ui/react-use-escape-keydown@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz#09ab6455ab240b4f0a61faf06d4e5132c4d639f6" + integrity sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-layout-effect@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.0.tgz#2fc19e97223a81de64cd3ba1dc42ceffd82374dc" @@ -4167,6 +3854,13 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-previous@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.0.0.tgz#e48a69c3a7d8078a967084038df66d0d181c56ac" + integrity sha512-RG2K8z/K7InnOKpq6YLDmT49HGjNmrK+fr82UCVKT2sW0GYfVnYp4wZWBooT/EYfQ5faA9uIjvsuMMhH61rheg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-rect@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz#b040cc88a4906b78696cd3a32b075ed5b1423b3e" @@ -4183,6 +3877,14 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.0" +"@radix-ui/react-visually-hidden@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.0.tgz#4d69d7e3b6d21ee4678ed6de5215dcd068394401" + integrity sha512-MwAhMdX+n6S4InwRKSnpUsp+lLkYG6izQF56ul6guSX2mBBLOMV9Frx7xJlkEe2GjKLzbNuHhaCS6e5gopmZNA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.0" + "@radix-ui/rect@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.0.tgz#0dc8e6a829ea2828d53cbc94b81793ba6383bf3c" @@ -4190,21 +3892,38 @@ dependencies: "@babel/runtime" "^7.13.10" -"@randlabs/communication-bridge@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@randlabs/communication-bridge/-/communication-bridge-1.0.0.tgz#9b1c0f440cf88ede8d58eb2ce641982ecb32bea9" - integrity sha512-CuJNwtMTG1LHR1LQNWUPv+8xPUdkRY9p61wGJEp8J/N3q8djmnMySvSQlyVqLBvXsTPKmYc0ZmfXEXCpb5P5Cw== +"@randlabs/communication-bridge@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@randlabs/communication-bridge/-/communication-bridge-1.0.1.tgz#d1ecfc29157afcbb0ca2d73122d67905eecb5bf3" + integrity sha512-CzS0U8IFfXNK7QaJFE4pjbxDGfPjbXBEsEaCn9FN15F+ouSAEUQkva3Gl66hrkBZOGexKFEWMwUHIDKpZ2hfVg== "@randlabs/myalgo-connect@^1.1.2": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@randlabs/myalgo-connect/-/myalgo-connect-1.2.0.tgz#4a7bd4c8898fc9f3f9c031859512b2517fbd0e8d" - integrity sha512-eUuv90M4LBrdL+A6qTrOqaICeRqmwZKW7JIfgaM6GgmfDopf8ugdK0gA2TuaCvCytA/NahEnsM5+Eup/ngUsLA== + version "1.4.2" + resolved "https://registry.yarnpkg.com/@randlabs/myalgo-connect/-/myalgo-connect-1.4.2.tgz#ce3ad97b3889ea21da75852187511d3f6be0fa05" + integrity sha512-K9hEyUi7G8tqOp7kWIALJLVbGCByhilcy6123WfcorxWwiE1sbQupPyIU5f3YdQK6wMjBsyTWiLW52ZBMp7sXA== + dependencies: + "@randlabs/communication-bridge" "1.0.1" + +"@raydium-io/raydium-sdk@^1.3.1-beta.57": + version "1.3.1-beta.58" + resolved "https://registry.yarnpkg.com/@raydium-io/raydium-sdk/-/raydium-sdk-1.3.1-beta.58.tgz#cd251bdf58a15b5aa231a0a6e16a86617c06abcc" + integrity sha512-9SMneQktR6CvxOJ6C3PxW8aMtBsg28+OViaSDwNHgZ/gJP47bvUgUTsFSmnut4Mv9blsnYFxyc5eVoIfPdXeJg== dependencies: - "@randlabs/communication-bridge" "^1.0.0" + "@solana/buffer-layout" "^4.0.1" + "@solana/spl-token" "^0.3.9" + axios "^1.6.2" + big.js "^6.2.1" + bn.js "^5.2.1" + decimal.js "^10.4.3" + decimal.js-light "^2.5.1" + fecha "^4.2.3" + lodash "^4.17.21" + toformat "^2.0.0" + tsup "^8.1.0" "@reach/dialog@^0.16.2": version "0.16.2" - resolved "https://registry.npmjs.org/@reach/dialog/-/dialog-0.16.2.tgz" + resolved "https://registry.yarnpkg.com/@reach/dialog/-/dialog-0.16.2.tgz#567e6f59d0a6dabe84b2ba4c456404efa6cb7d03" integrity sha512-qq8oX0cROgTb8LjOKWzzNm4SqaN9b89lJHr7UyVo2aQ6WbeNzZBxqXhGywFP7dkR+hNqOJnrA59PXFWhfttA9A== dependencies: "@reach/portal" "0.16.2" @@ -4216,7 +3935,7 @@ "@reach/portal@0.16.2": version "0.16.2" - resolved "https://registry.npmjs.org/@reach/portal/-/portal-0.16.2.tgz" + resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.16.2.tgz#ca83696215ee03acc2bb25a5ae5d8793eaaf2f64" integrity sha512-9ur/yxNkuVYTIjAcfi46LdKUvH0uYZPfEp4usWcpt6PIp+WDF57F/5deMe/uGi/B/nfDweQu8VVwuMVrCb97JQ== dependencies: "@reach/utils" "0.16.0" @@ -4225,12 +3944,19 @@ "@reach/utils@0.16.0": version "0.16.0" - resolved "https://registry.npmjs.org/@reach/utils/-/utils-0.16.0.tgz" + resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.16.0.tgz#5b0777cf16a7cab1ddd4728d5d02762df0ba84ce" integrity sha512-PCggBet3qaQmwFNcmQ/GqHSefadAFyNCUekq9RrWoaU9hh/S4iaFgf2MBMdM47eQj5i/Bk0Mm07cP/XPFlkN+Q== dependencies: tiny-warning "^1.0.3" tslib "^2.3.0" +"@react-native-async-storage/async-storage@^1.17.7": + version "1.17.11" + resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.17.11.tgz#7ec329c1b9f610e344602e806b04d7c928a2341d" + integrity sha512-bzs45n5HNcDq6mxXnSsOHysZWn1SbbebNxldBXCQs8dSvF8Aor9KCdpm+TpnnGweK3R6diqsT8lFhX77VX0NFw== + dependencies: + merge-options "^3.0.4" + "@react-spring/animated@~9.3.0": version "9.3.2" resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.3.2.tgz#bda85e92e9e9b6861c259f2dacb54270a37b0f39" @@ -4239,13 +3965,13 @@ "@react-spring/shared" "~9.3.0" "@react-spring/types" "~9.3.0" -"@react-spring/animated@~9.4.0": - version "9.4.2" - resolved "https://registry.npmjs.org/@react-spring/animated/-/animated-9.4.2.tgz" - integrity sha512-Dzum5Ho8e+LIAegAqRyoQFakD2IVH3ZQ2nsFXJorAFq3Xjv6IVPz/+TNxb/wSvnsMludfoF+ZIf319FSFmgD5w== +"@react-spring/animated@~9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.6.0.tgz#3ac531d82e35e4ad205456f9fe9464e2bbcb1c5f" + integrity sha512-YFBLQ3bnGlUaWA9eVcZ7K1nfgVSF30XPfwqag5hlswYcMi7C5zVriFqN4oxRyDAFHfmNpPfFCRHmgP52L3GF1A== dependencies: - "@react-spring/shared" "~9.4.0" - "@react-spring/types" "~9.4.0" + "@react-spring/shared" "~9.6.0" + "@react-spring/types" "~9.6.0" "@react-spring/core@~9.3.0": version "9.3.2" @@ -4256,25 +3982,25 @@ "@react-spring/shared" "~9.3.0" "@react-spring/types" "~9.3.0" -"@react-spring/core@~9.4.0": - version "9.4.2" - resolved "https://registry.npmjs.org/@react-spring/core/-/core-9.4.2.tgz" - integrity sha512-Ej/ULwdx8rQtMAWEpLgwbKcQEx6vPfjyG3cxLP05zAInpCoWkYpl+sXOp9tn3r99mTNQPTTt7BgQsSnmQA8+rQ== +"@react-spring/core@~9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.6.0.tgz#081c44e4005c52e7e6957ba151a697709cc0b05a" + integrity sha512-CCU6MOp6Hk29qFhC+8/Hty5Rh8b4TcHvLjFX1GP9i2iXvw77WayRyy+Wi+KCt+RD+xXO2fi9bNWcloOHPHJp/g== dependencies: - "@react-spring/animated" "~9.4.0" - "@react-spring/rafz" "~9.4.0" - "@react-spring/shared" "~9.4.0" - "@react-spring/types" "~9.4.0" + "@react-spring/animated" "~9.6.0" + "@react-spring/rafz" "~9.6.0" + "@react-spring/shared" "~9.6.0" + "@react-spring/types" "~9.6.0" "@react-spring/rafz@~9.3.0": version "9.3.2" resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.3.2.tgz#0cbd296cd17bbf1e7e49d3b3616884e026d5fb67" integrity sha512-YtqNnAYp5bl6NdnDOD5TcYS40VJmB+Civ4LPtcWuRPKDAOa/XAf3nep48r0wPTmkK936mpX8aIm7h+luW59u5A== -"@react-spring/rafz@~9.4.0": - version "9.4.2" - resolved "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.4.2.tgz" - integrity sha512-rSm+G8E/XEEpnCGtT/xYN6o8VvEXlU8wN/hyKp4Q44XAZzGSMHLIFP7pY94/MmWsxCxjkw1AxUWhiFYxWrnI5Q== +"@react-spring/rafz@~9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.6.0.tgz#8c46fff30157159775eb9007094dae3400390728" + integrity sha512-Vw8IwWXWEMszef8V/yemSR8YZe4cbX84JrMMuW+UE5Ha1/mOCznlFU59fKJxQQA/UJlfY70K9oZ+aboFgWWk0g== "@react-spring/shared@~9.3.0": version "9.3.2" @@ -4284,23 +4010,23 @@ "@react-spring/rafz" "~9.3.0" "@react-spring/types" "~9.3.0" -"@react-spring/shared@~9.4.0": - version "9.4.2" - resolved "https://registry.npmjs.org/@react-spring/shared/-/shared-9.4.2.tgz" - integrity sha512-mZtbQLpMm6Vy5+O1MSlY9KuAcMO8rdUQvtdnC7Or7y7xiZlnzj8oAILyO6Y2rD2ZC1PmgVS0gMev/8T+MykW+Q== +"@react-spring/shared@~9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.6.0.tgz#4ccdf911d64dacb409c5f292de65fdb8ad41508f" + integrity sha512-Kama7SJiAajZsjfTJAxLDndxeYr0Qin6Ust9Wn/gRCVC1maXJ79Su0gsQYapSA0+Nmkxdi+RiXJUDmGX6LMuuw== dependencies: - "@react-spring/rafz" "~9.4.0" - "@react-spring/types" "~9.4.0" + "@react-spring/rafz" "~9.6.0" + "@react-spring/types" "~9.6.0" "@react-spring/types@~9.3.0": version "9.3.2" resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.3.2.tgz#0277d436e50d7a824897dd7bb880f4842fbcd0fe" integrity sha512-u+IK9z9Re4hjNkBYKebZr7xVDYTai2RNBsI4UPL/k0B6lCNSwuqWIXfKZUDVlMOeZHtDqayJn4xz6HcSkTj3FQ== -"@react-spring/types@~9.4.0": - version "9.4.2" - resolved "https://registry.npmjs.org/@react-spring/types/-/types-9.4.2.tgz" - integrity sha512-GGiIscTM+CEUNV52anj3g5FqAZKL2+eRKtvBOAlC99qGBbvJ3qTLImrUR/I3lXY7PRuLgzI6kh34quA1oUxWYQ== +"@react-spring/types@~9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.6.0.tgz#9ba7061fef88ffa872b7898fcf008ffb29a51d90" + integrity sha512-XOWupgf+/rMhQTiIxZzjVRw+4ZNkXcO5tuha3pOBNK88a7LPGjM6imdS1aQ2kl3y1sBy0f9JrclNShfASbkvTw== "@react-spring/web@9.3.1": version "9.3.1" @@ -4313,61 +4039,176 @@ "@react-spring/types" "~9.3.0" "@react-spring/web@^9.4.2": - version "9.4.2" - resolved "https://registry.npmjs.org/@react-spring/web/-/web-9.4.2.tgz" - integrity sha512-sWfA9NkVuvVOpjSlMkD2zcF6X3i8NSHTeH/uHCGKsN3mYqgkhvAF+E8GASO/H4KKGNhbRvgCZiwJXOtOGyUg6A== + version "9.6.0" + resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.6.0.tgz#81fcdc1dc6efe6caedf2ef7f706bd18500e7b582" + integrity sha512-ztdkBmRZB020MEPEU8gXlbkE6858/IdA2P37RvcjOHq4tEpIizrsh/XTipU+T5iyrbT6UQLnh4JnIWow4jfOmg== dependencies: - "@react-spring/animated" "~9.4.0" - "@react-spring/core" "~9.4.0" - "@react-spring/shared" "~9.4.0" - "@react-spring/types" "~9.4.0" + "@react-spring/animated" "~9.6.0" + "@react-spring/core" "~9.6.0" + "@react-spring/shared" "~9.6.0" + "@react-spring/types" "~9.6.0" -"@saberhq/anchor-contrib@1.12.53": - version "1.12.53" - resolved "https://registry.yarnpkg.com/@saberhq/anchor-contrib/-/anchor-contrib-1.12.53.tgz#4cc46fdf0639315db73573b3190a1d6d5b942412" - integrity sha512-RYLHKYVxE3Oz0BeNgi6nIXH1kfGYYE4cYLgEAgBwbi4fFA3bFWNXVgXMiBDHBDBwx3wdKpKj/USDGz7xOcbtFw== +"@realms-today/spl-governance@0.3.29": + version "0.3.29" + resolved "https://registry.yarnpkg.com/@realms-today/spl-governance/-/spl-governance-0.3.29.tgz#147f70aff4fa4fbd515ebe3ebbec12b0705fc4c8" + integrity sha512-j25gdQIzSYC1MfUhRTd7O9WuBdpWzNWDHItffRt0xQCrpeIHV1jVb0zGn0rR/H5uAsmoY6PcLrJYn5aMtN+gPg== dependencies: - "@saberhq/solana-contrib" "^1.12.53" + "@solana/web3.js" "^1.22.0" + axios "^1.1.3" + bignumber.js "^9.0.1" + bn.js "^5.1.3" + borsh "^0.3.1" + bs58 "^4.0.1" + superstruct "^0.15.2" + +"@rollup/plugin-commonjs@24.0.0": + version "24.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.0.tgz#fb7cf4a6029f07ec42b25daa535c75b05a43f75c" + integrity sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g== + dependencies: + "@rollup/pluginutils" "^5.0.1" + commondir "^1.0.1" + estree-walker "^2.0.2" + glob "^8.0.3" + is-reference "1.2.1" + magic-string "^0.27.0" + +"@rollup/pluginutils@^5.0.1": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.5.tgz#bbb4c175e19ebfeeb8c132c2eea0ecb89941a66c" + integrity sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + +"@rollup/rollup-android-arm-eabi@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.1.tgz#7746deb85e4a8fb54fbfda8ac5c102692f102476" + integrity sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww== + +"@rollup/rollup-android-arm64@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.1.tgz#93de4d867709d3313794723b5afd91e1e174f906" + integrity sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A== + +"@rollup/rollup-darwin-arm64@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.1.tgz#e41e6a81673260ab196e0f59462b9940a6ac03cd" + integrity sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q== + +"@rollup/rollup-darwin-x64@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.1.tgz#2b0a0aef6e8c5317d494cfc9076d7a16b099bdcb" + integrity sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA== + +"@rollup/rollup-linux-arm-gnueabihf@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.1.tgz#e22319deb5367384ef315e66bc6de80d2bf2b3ae" + integrity sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q== + +"@rollup/rollup-linux-arm-musleabihf@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.1.tgz#d5dd68f5d7ae21b345a5c87208c94e5c813f54b8" + integrity sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw== + +"@rollup/rollup-linux-arm64-gnu@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.1.tgz#1703d3a418d33f8f025acaf93f39ca1efcd5b645" + integrity sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw== + +"@rollup/rollup-linux-arm64-musl@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.1.tgz#3f59c2c6e60f75ce8b1090bd841c555e3bb01f0e" + integrity sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw== + +"@rollup/rollup-linux-powerpc64le-gnu@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.1.tgz#3f99a0921596a6f539121a312df29af52a205f15" + integrity sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ== + +"@rollup/rollup-linux-riscv64-gnu@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.1.tgz#c08fb3e629d50d2eac31329347cfc559a1cf81d1" + integrity sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A== + +"@rollup/rollup-linux-s390x-gnu@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.1.tgz#173722cd745779d730d4b24d21386185e0e12de8" + integrity sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q== + +"@rollup/rollup-linux-x64-gnu@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.1.tgz#0af2b6541ab0f4954d2c4f96bcdc7947420dd28c" + integrity sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q== + +"@rollup/rollup-linux-x64-musl@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.1.tgz#f973f9552744764b221128f7c3629222216ace69" + integrity sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q== + +"@rollup/rollup-win32-arm64-msvc@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.1.tgz#21ac5ed84d914bc31821fec3dd909f7257cfb17b" + integrity sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA== + +"@rollup/rollup-win32-ia32-msvc@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.1.tgz#0cfe740063b35dcd5a62c4e243226631a846ce11" + integrity sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ== + +"@rollup/rollup-win32-x64-msvc@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.1.tgz#5f2c40d3f1b53ede80fb4e6964f840c0f8936832" + integrity sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg== + +"@saberhq/anchor-contrib@^1.12.47", "@saberhq/anchor-contrib@^1.12.48", "@saberhq/anchor-contrib@^1.14.1", "@saberhq/anchor-contrib@^1.14.11", "@saberhq/anchor-contrib@^1.14.9": + version "1.14.11" + resolved "https://registry.yarnpkg.com/@saberhq/anchor-contrib/-/anchor-contrib-1.14.11.tgz#cebaac040faea643ade8ecb6afeeb2dcdf5a33a2" + integrity sha512-6fOMC9XjuMSpGin/5HGqDita/dYzndjMMUNjht7yQZzD9638cdjrAutwZjvYwMUepKLdJ5CQV4bE74bSeMF9HQ== + dependencies: + "@saberhq/solana-contrib" "^1.14.11" eventemitter3 "^4.0.7" lodash.camelcase "^4.3.0" lodash.mapvalues "^4.6.0" - tslib "^2.3.1" + tslib "^2.4.0" -"@saberhq/solana-contrib@1.12.53": - version "1.12.53" - resolved "https://registry.yarnpkg.com/@saberhq/solana-contrib/-/solana-contrib-1.12.53.tgz#1a946e55ce9a63ceffe4485ec9c31cd9fc890f52" - integrity sha512-DpAKOYc2DucUpbnR6rV2P0vvlCexkMBpRYR24Y3ZMc1mgNPK/PCmV6nCm/xDYiOutQ29LeNv0jbUqlg5tdz69Q== +"@saberhq/chai-solana@^1.14.9": + version "1.14.11" + resolved "https://registry.yarnpkg.com/@saberhq/chai-solana/-/chai-solana-1.14.11.tgz#420320e7f34d76db6e19f679e1f4375685bf6085" + integrity sha512-lU8uvxNsb+GQwAlpcyvz/vkasYfrxOk5FWWLN+qif3uqYT6B9WeNYHJUasP7mz1SzgIx5O6/6RNKTiO3wqtwzw== dependencies: + "@saberhq/anchor-contrib" "^1.14.11" + "@saberhq/solana-contrib" "^1.14.11" + "@saberhq/token-utils" "^1.14.11" + "@types/chai" "^4.3.3" + "@types/chai-as-promised" "^7.1.5" "@types/promise-retry" "^1.1.3" - "@types/retry" "^0.12.1" - promise-retry "^2.0.1" - retry "^0.13.1" - tiny-invariant "^1.2.0" - tslib "^2.3.1" + chai "=4.3.4" + chai-as-promised "^7.1.1" + chai-bn "^0.3.1" + colors "^1.4.0" + tslib "^2.4.0" -"@saberhq/solana-contrib@^1.12.23", "@saberhq/solana-contrib@^1.12.26", "@saberhq/solana-contrib@^1.12.35": - version "1.12.48" - resolved "https://registry.yarnpkg.com/@saberhq/solana-contrib/-/solana-contrib-1.12.48.tgz#313df4afbd6903997b15a551b99b5186a5f8ba9d" - integrity sha512-aI6KjByqJK7/rzB8joIqpCMxQ554vQcDN3jX5iyd6HncNj03I6hyGoniOWGySxvftgwcZQC2x4/NmiIvxJ460g== +"@saberhq/option-utils@^1.14.11": + version "1.14.11" + resolved "https://registry.yarnpkg.com/@saberhq/option-utils/-/option-utils-1.14.11.tgz#db6c2e79ade3c8b15f90eb376c783c31358bf1ef" + integrity sha512-v75bHrUYp791lGN6PnbX7eg8T8WbdGSX1y591IhC3WgZDdXPxC/lY1Puv/g9pXxytyCrftTLFehv8+2odMKsyw== dependencies: - "@types/promise-retry" "^1.1.3" - "@types/retry" "^0.12.1" - promise-retry "^2.0.1" - retry "^0.13.1" - tiny-invariant "^1.2.0" - tslib "^2.3.1" + tslib "^2.4.0" -"@saberhq/solana-contrib@^1.12.53", "@saberhq/solana-contrib@^1.13.0": - version "1.13.0" - resolved "https://registry.yarnpkg.com/@saberhq/solana-contrib/-/solana-contrib-1.13.0.tgz#0e5f360cfbed90e9786d0e89db6589f8c5299bab" - integrity sha512-LNFd1KHQ9GrbeAyF61moTtIt92qC+9bRaP1nHMNyOxjp7Q0sQhBm8QrW8Nez5tz8H3OYB2ZFr7LWvQ+6ddn9fg== +"@saberhq/solana-contrib@^1.12.23", "@saberhq/solana-contrib@^1.12.26", "@saberhq/solana-contrib@^1.12.47", "@saberhq/solana-contrib@^1.12.48", "@saberhq/solana-contrib@^1.12.53", "@saberhq/solana-contrib@^1.14.1", "@saberhq/solana-contrib@^1.14.11", "@saberhq/solana-contrib@^1.14.9": + version "1.14.11" + resolved "https://registry.yarnpkg.com/@saberhq/solana-contrib/-/solana-contrib-1.14.11.tgz#d4a6a09f426afb353fc5727b06365446d4642bb7" + integrity sha512-HOEJpTZnSGmrfJG2gV18vQbtI14ET9l4/Q1yyPk4R2dkydxZIfBIPCI9SRWZ9g01/nuob3Fryd79Ca6QDk7qjw== dependencies: + "@saberhq/option-utils" "^1.14.11" "@solana/buffer-layout" "^4.0.0" "@types/promise-retry" "^1.1.3" "@types/retry" "^0.12.2" promise-retry "^2.0.1" retry "^0.13.1" - tiny-invariant "^1.2.0" + tiny-invariant "^1.3.1" tslib "^2.4.0" "@saberhq/token-utils@1.12.53": @@ -4382,203 +4223,210 @@ tiny-invariant "^1.2.0" tslib "^2.3.1" -"@saberhq/token-utils@^1.12.53": - version "1.13.0" - resolved "https://registry.yarnpkg.com/@saberhq/token-utils/-/token-utils-1.13.0.tgz#ffafb6a3a38742761a44a831c2f8d70875d6d8a8" - integrity sha512-24GxCywSRqn37Nx8tZ6w9pFjg+/RPUVbxh6pEouSBvB/H5eE3kqt5uitwIpRTIctkNcH+1x0khnEn1evk99HPg== +"@saberhq/token-utils@^1.12.48", "@saberhq/token-utils@^1.14.1", "@saberhq/token-utils@^1.14.11": + version "1.14.11" + resolved "https://registry.yarnpkg.com/@saberhq/token-utils/-/token-utils-1.14.11.tgz#bc895173245a46789b65080eb38722e99dbfeb22" + integrity sha512-C+K1IHQuLwG6APT8wbrlvJPM4arTcNHnnydqZbMpsi1Zyyis+UPM3n/PgHmyX2ydtQ+GzPMLFMgxahtjicEgXw== dependencies: - "@saberhq/solana-contrib" "^1.13.0" + "@saberhq/solana-contrib" "^1.14.11" "@solana/buffer-layout" "^4.0.0" "@solana/spl-token" "^0.1.8" - "@ubeswap/token-math" "^4.4.8" - tiny-invariant "^1.2.0" + "@ubeswap/token-math" "^5.2.1" + tiny-invariant "^1.3.1" tslib "^2.4.0" "@saberhq/use-solana@^1.12.26": - version "1.12.35" - resolved "https://registry.npmjs.org/@saberhq/use-solana/-/use-solana-1.12.35.tgz" - integrity sha512-kUUljPOb1fXuynzqVuhe2PrmaUl3lMtfIgljhVJnsO42KshO6QnU+8bv/eqyZ67kxzIzwe6sXH6GAyzuGqK6GA== - dependencies: - "@ledgerhq/hw-transport" "^6.20.0" - "@ledgerhq/hw-transport-webusb" "^6.20.0" - "@saberhq/solana-contrib" "^1.12.35" - "@solana/wallet-adapter-base" "^0.9.2" - "@solana/wallet-adapter-clover" "^0.4.2" - "@solana/wallet-adapter-coin98" "^0.5.2" - "@solana/wallet-adapter-mathwallet" "^0.9.2" - "@solana/wallet-adapter-phantom" "^0.9.2" - "@solana/wallet-adapter-slope" "^0.5.2" - "@solana/wallet-adapter-solflare" "^0.6.2" - "@solana/wallet-adapter-sollet" "^0.10.3" - "@solana/wallet-adapter-solong" "^0.9.2" - bs58 "^4.0.1" + version "1.14.11" + resolved "https://registry.yarnpkg.com/@saberhq/use-solana/-/use-solana-1.14.11.tgz#9306b51fde174302726419279f092d7aa8c3e740" + integrity sha512-nC8IAe4SW731JDY372g5zjhS16h6CRl94O/XzeBrOv3i8GVnhE05SkZqatKWGZhZAfVFeK286Ns+aZbJd4K8mg== + dependencies: + "@ledgerhq/devices" "6.27.1" + "@ledgerhq/hw-transport" "6.27.1" + "@ledgerhq/hw-transport-webusb" "6.27.1" + "@saberhq/solana-contrib" "^1.14.11" + "@saberhq/wallet-adapter-icons" "^1.14.11" + "@solana/wallet-adapter-base" "^0.9.17" + "@solana/wallet-adapter-brave" "0.1.11" + "@solana/wallet-adapter-clover" "^0.4.13" + "@solana/wallet-adapter-coin98" "^0.5.14" + "@solana/wallet-adapter-coinbase" "^0.1.12" + "@solana/wallet-adapter-exodus" "^0.1.12" + "@solana/wallet-adapter-glow" "^0.1.12" + "@solana/wallet-adapter-huobi" "^0.1.9" + "@solana/wallet-adapter-mathwallet" "^0.9.12" + "@solana/wallet-adapter-nightly" "^0.1.9" + "@solana/wallet-adapter-phantom" "^0.9.16" + "@solana/wallet-adapter-slope" "^0.5.15" + "@solana/wallet-adapter-solflare" "^0.6.16" + "@solana/wallet-adapter-sollet" "^0.11.11" + "@solana/wallet-adapter-solong" "^0.9.12" + "@solana/wallet-adapter-walletconnect" "^0.1.6" eventemitter3 "^4.0.7" fast-json-stable-stringify "^2.1.0" - tiny-invariant "^1.2.0" - tslib "^2.3.1" + tiny-invariant "^1.3.1" + tslib "^2.4.0" unstated-next "^1.1.0" -"@sentry/browser@6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/browser/-/browser-6.19.7.tgz#a40b6b72d911b5f1ed70ed3b4e7d4d4e625c0b5f" - integrity sha512-oDbklp4O3MtAM4mtuwyZLrgO1qDVYIujzNJQzXmi9YzymJCuzMLSRDvhY83NNDCRxf0pds4DShgYeZdbSyKraA== +"@saberhq/wallet-adapter-icons@^1.14.11": + version "1.14.11" + resolved "https://registry.yarnpkg.com/@saberhq/wallet-adapter-icons/-/wallet-adapter-icons-1.14.11.tgz#64346e6c8ee287475cb62952e03212ef265b33d0" + integrity sha512-KB9J5DceDq90dtbVo1SEuE6xIKCLFonusKFWGixlGPkeAT3lktizqLAiY/fswDH0XiXsB0llk5JsDq0ojy0kbA== + dependencies: + tslib "^2.4.0" + +"@samverschueren/stream-to-observable@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301" + integrity sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ== + dependencies: + any-observable "^0.3.0" + +"@sentry-internal/tracing@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.81.1.tgz#1180365cd8a9e18cb0f92e1ea970161840ec0e2e" + integrity sha512-E5xm27xrLXL10knH2EWDQsQYh5nb4SxxZzJ3sJwDGG9XGKzBdlp20UUhKqx00wixooVX9uCj3e4Jg8SvNB1hKg== + dependencies: + "@sentry/core" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" + +"@sentry/browser@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.81.1.tgz#5ee6ae3679ee80f444d2e8c5662430e7a734ae50" + integrity sha512-DNtS7bZEnFPKVoGazKs5wHoWC0FwsOFOOMNeDvEfouUqKKbjO7+RDHbr7H6Bo83zX4qmZWRBf8V+3n3YPIiJFw== dependencies: - "@sentry/core" "6.19.7" - "@sentry/types" "6.19.7" - "@sentry/utils" "6.19.7" - tslib "^1.9.3" + "@sentry-internal/tracing" "7.81.1" + "@sentry/core" "7.81.1" + "@sentry/replay" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" -"@sentry/cli@^1.73.0": - version "1.74.4" - resolved "https://registry.npmjs.org/@sentry/cli/-/cli-1.74.4.tgz#7df82f68045a155e1885bfcbb5d303e5259eb18e" - integrity sha512-BMfzYiedbModsNBJlKeBOLVYUtwSi99LJ8gxxE4Bp5N8hyjNIN0WVrozAVZ27mqzAuy6151Za3dpmOLO86YlGw== +"@sentry/cli@^1.77.1": + version "1.77.1" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.77.1.tgz#ebcf884712ef6c3c75443f491ec16f6a22148aec" + integrity sha512-OtJ7U9LeuPUAY/xow9wwcjM9w42IJIpDtClTKI/RliE685vd/OJUIpiAvebHNthDYpQynvwb/0iuF4fonh+CKw== dependencies: https-proxy-agent "^5.0.0" mkdirp "^0.5.5" node-fetch "^2.6.7" - npmlog "^4.1.2" progress "^2.0.3" proxy-from-env "^1.1.0" which "^2.0.2" -"@sentry/core@6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz#156aaa56dd7fad8c89c145be6ad7a4f7209f9785" - integrity sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw== - dependencies: - "@sentry/hub" "6.19.7" - "@sentry/minimal" "6.19.7" - "@sentry/types" "6.19.7" - "@sentry/utils" "6.19.7" - tslib "^1.9.3" - -"@sentry/hub@6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz#58ad7776bbd31e9596a8ec46365b45cd8b9cfd11" - integrity sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA== - dependencies: - "@sentry/types" "6.19.7" - "@sentry/utils" "6.19.7" - tslib "^1.9.3" - -"@sentry/integrations@6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/integrations/-/integrations-6.19.7.tgz#e6e126b692077c8731644224c754012bed65b425" - integrity sha512-yNeeFyuygJaV7Mdc5qWuDa13xVj5mVdECaaw2Xs4pfeHaXmRfRzZY17N8ypWFegKWxKBHynyQRMD10W5pBwJvA== - dependencies: - "@sentry/types" "6.19.7" - "@sentry/utils" "6.19.7" +"@sentry/core@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.81.1.tgz#082fd9122bf9a488c8e05b1754724ddbc2d5cf30" + integrity sha512-tU37yAmckOGCw/moWKSwekSCWWJP15O6luIq+u7wal22hE88F3Vc5Avo8SeF3upnPR+4ejaOFH+BJTr6bgrs6Q== + dependencies: + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" + +"@sentry/integrations@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.81.1.tgz#1b12c0cf3a7fa88224e86c0be46523ed7e3f3a43" + integrity sha512-DN5ONn0/LX5HHVPf1EBGHFssIZaZmLgkqUIeMqCNYBpB4DiOrJANnGwTcWKDPphqhdPxjnPv9AGRLaU0PdvvZQ== + dependencies: + "@sentry/core" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" localforage "^1.8.1" - tslib "^1.9.3" - -"@sentry/minimal@6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz#b3ee46d6abef9ef3dd4837ebcb6bdfd01b9aa7b4" - integrity sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ== - dependencies: - "@sentry/hub" "6.19.7" - "@sentry/types" "6.19.7" - tslib "^1.9.3" - -"@sentry/nextjs@^6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/nextjs/-/nextjs-6.19.7.tgz#2c40692d89a99ec1382189f11702b1498c91fb77" - integrity sha512-029gpqhR6gHF7zfE9oxFOf3Zm68CShDu8/6azC8mwfIfJtyLC9dqztJJi48j0Uxs+sR1TEkN5Dw3wZbfWtFd8g== - dependencies: - "@sentry/core" "6.19.7" - "@sentry/hub" "6.19.7" - "@sentry/integrations" "6.19.7" - "@sentry/node" "6.19.7" - "@sentry/react" "6.19.7" - "@sentry/tracing" "6.19.7" - "@sentry/utils" "6.19.7" - "@sentry/webpack-plugin" "1.18.8" - tslib "^1.9.3" - -"@sentry/node@6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz#32963b36b48daebbd559e6f13b1deb2415448592" - integrity sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg== - dependencies: - "@sentry/core" "6.19.7" - "@sentry/hub" "6.19.7" - "@sentry/types" "6.19.7" - "@sentry/utils" "6.19.7" - cookie "^0.4.1" + +"@sentry/nextjs@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.81.1.tgz#2d07a92555b669d6ffdb30645c4c4fff9f801b3a" + integrity sha512-Wx0QiZHttf+WJkao4UQ5szOWJVu/pmPdKZKE4FWsJuG+mUu6FviOXgh0T0Iq+NnJrgqzKzGLMN6rIWPzN9PLkg== + dependencies: + "@rollup/plugin-commonjs" "24.0.0" + "@sentry/core" "7.81.1" + "@sentry/integrations" "7.81.1" + "@sentry/node" "7.81.1" + "@sentry/react" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" + "@sentry/vercel-edge" "7.81.1" + "@sentry/webpack-plugin" "1.21.0" + chalk "3.0.0" + resolve "1.22.8" + rollup "2.78.0" + stacktrace-parser "^0.1.10" + +"@sentry/node@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.81.1.tgz#3559ee1cef22f8220c907169cc60cc44744503b1" + integrity sha512-bKS3Mb95bar8AUEZSLKQ/RTSfFXo5sCSPNiBr5dDFuVljDFdkLq6NE3svG5bisrbENqfi0bqWsB4GZ7NHRTPbA== + dependencies: + "@sentry-internal/tracing" "7.81.1" + "@sentry/core" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" https-proxy-agent "^5.0.0" - lru_map "^0.3.3" - tslib "^1.9.3" - -"@sentry/react@6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/react/-/react-6.19.7.tgz#58cc2d6da20f7d3b0df40638dfbbbc86c9c85caf" - integrity sha512-VzJeBg/v41jfxUYPkH2WYrKjWc4YiMLzDX0f4Zf6WkJ4v3IlDDSkX6DfmWekjTKBho6wiMkSNy2hJ1dHfGZ9jA== - dependencies: - "@sentry/browser" "6.19.7" - "@sentry/minimal" "6.19.7" - "@sentry/types" "6.19.7" - "@sentry/utils" "6.19.7" + +"@sentry/react@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.81.1.tgz#6a94e8e373a5bf27330cea2eb1a603ae0eb0b8ba" + integrity sha512-kk0plP/mf8KgVLOiImIpp1liYysmh3Un8uXcVAToomSuHZPGanelFAdP0XhY+0HlWU9KIfxTjhMte1iSwQ8pYw== + dependencies: + "@sentry/browser" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" hoist-non-react-statics "^3.3.2" - tslib "^1.9.3" -"@sentry/tracing@6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.19.7.tgz#54bb99ed5705931cd33caf71da347af769f02a4c" - integrity sha512-ol4TupNnv9Zd+bZei7B6Ygnr9N3Gp1PUrNI761QSlHtPC25xXC5ssSD3GMhBgyQrcvpuRcCFHVNNM97tN5cZiA== +"@sentry/replay@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.81.1.tgz#a656d55e2a00b34e42be6eeb79018d21efc223af" + integrity sha512-4ueT0C4bYjngN/9p0fEYH10dTMLovHyk9HxJ6zSTgePvGVexhg+cSEHXisoBDwHeRZVnbIvsVM0NA7rmEDXJJw== dependencies: - "@sentry/hub" "6.19.7" - "@sentry/minimal" "6.19.7" - "@sentry/types" "6.19.7" - "@sentry/utils" "6.19.7" - tslib "^1.9.3" + "@sentry-internal/tracing" "7.81.1" + "@sentry/core" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" -"@sentry/types@6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz#c6b337912e588083fc2896eb012526cf7cfec7c7" - integrity sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg== +"@sentry/types@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.81.1.tgz#2b2551fc291e1089651fd574a68f7c4175878bd5" + integrity sha512-dvJvGyctiaPMIQqa46k56Re5IODWMDxiHJ1UjBs/WYDLrmWFPGrEbyJ8w8CYLhYA+7qqrCyIZmHbWSTRIxstHw== -"@sentry/utils@6.19.7": - version "6.19.7" - resolved "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz#6edd739f8185fd71afe49cbe351c1bbf5e7b7c79" - integrity sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA== +"@sentry/utils@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.81.1.tgz#42f3e77baf90205cec1f8599eb8445a6918030bd" + integrity sha512-gq+MDXIirHKxNZ+c9/lVvCXd6y2zaZANujwlFggRH2u9SRiPaIXVilLpvMm4uJqmqBMEcY81ArujExtHvkbCqg== dependencies: - "@sentry/types" "6.19.7" - tslib "^1.9.3" + "@sentry/types" "7.81.1" -"@sentry/webpack-plugin@1.18.8": - version "1.18.8" - resolved "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-1.18.8.tgz#247a73a0aa9e28099a736bbe89ca0d35cbac7636" - integrity sha512-PtKr0NL62b5L3kPFGjwSNbIUwwcW5E5G6bQxAYZGpkgL1MFPnS4ND0SAsySuX0byQJRFFium5A19LpzyvQZSlQ== +"@sentry/vercel-edge@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-7.81.1.tgz#8d33b27b8222bee8c85388cb734f886e57fecc1d" + integrity sha512-fO5yV+2rz+024XKvhBSGhUdi502j3S1Vds+fIUJVgpgehpxsx4CQQUA1nQDaqDWEtPCB6LcBupD3XvkhBTS5Mw== dependencies: - "@sentry/cli" "^1.73.0" + "@sentry-internal/tracing" "7.81.1" + "@sentry/core" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" -"@sideway/address@^4.1.3": - version "4.1.4" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" - integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== +"@sentry/webpack-plugin@1.21.0": + version "1.21.0" + resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.21.0.tgz#bbe7cb293751f80246a4a56f9a7dd6de00f14b58" + integrity sha512-x0PYIMWcsTauqxgl7vWUY6sANl+XGKtx7DCVnnY7aOIIlIna0jChTAPANTfA2QrK+VK+4I/4JxatCEZBnXh3Og== dependencies: - "@hapi/hoek" "^9.0.0" - -"@sideway/formula@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" - integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + "@sentry/cli" "^1.77.1" + webpack-sources "^2.0.0 || ^3.0.0" -"@sideway/pinpoint@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" - integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== +"@sinclair/typebox@^0.24.1": + version "0.24.51" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" + integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== "@sinonjs/commons@^1.7.0": - version "1.8.3" - resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz" + version "1.8.6" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" + integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^8.0.1": - version "8.1.0" - resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz" - integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== +"@sinonjs/fake-timers@^9.1.2": + version "9.1.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" + integrity sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw== dependencies: "@sinonjs/commons" "^1.7.0" @@ -4587,6 +4435,47 @@ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== +"@solana-mobile/mobile-wallet-adapter-protocol-web3js@^2.0.0", "@solana-mobile/mobile-wallet-adapter-protocol-web3js@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@solana-mobile/mobile-wallet-adapter-protocol-web3js/-/mobile-wallet-adapter-protocol-web3js-2.1.2.tgz#a64b96f99540192e0b7343f30c9d58db7d8a38cd" + integrity sha512-uA6tbP/JvBCdGSwty3rNM8a0qpoHPEV+Qj234aw4XMisS++TSN8R79bclT4hLvOsg+m04on1MOkMM3oPXlQo9A== + dependencies: + "@solana-mobile/mobile-wallet-adapter-protocol" "^2.1.2" + bs58 "^5.0.0" + js-base64 "^3.7.5" + +"@solana-mobile/mobile-wallet-adapter-protocol@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@solana-mobile/mobile-wallet-adapter-protocol/-/mobile-wallet-adapter-protocol-2.1.2.tgz#e812c6bc07e7552902225ea62bc0f829ddf2acdf" + integrity sha512-z7LPeWzdEUoavU5P1PSbtxLTNE/MB6ACgaIPPAMjRdEk/jUvunquWKmbOX4vkFD6QbD98ykc4NZOt5iki7Z6hw== + dependencies: + "@solana/wallet-standard" "^1.1.2" + "@solana/wallet-standard-util" "^1.1.1" + "@wallet-standard/core" "^1.0.3" + js-base64 "^3.7.5" + +"@solana-mobile/wallet-adapter-mobile@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@solana-mobile/wallet-adapter-mobile/-/wallet-adapter-mobile-2.0.0.tgz#4429dec675e5a3339b7734521dd386d94bf3ad71" + integrity sha512-q/m0X+LUhoSYBUaQsw+9YhttbokA5+klrC2euLhbDu+Wy/n9hL4NXNvw7291bzVvNXVh9ovBi7DjoCdcfPXRWA== + dependencies: + "@react-native-async-storage/async-storage" "^1.17.7" + "@solana-mobile/mobile-wallet-adapter-protocol-web3js" "^2.0.0" + "@solana/wallet-adapter-base" "^0.9.17" + js-base64 "^3.7.2" + +"@solana-mobile/wallet-adapter-mobile@^2.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@solana-mobile/wallet-adapter-mobile/-/wallet-adapter-mobile-2.1.2.tgz#dcf289280a8baa84ea76056d48ee427ac17893f5" + integrity sha512-m7UW+vS0qB7j+FYvzBbXQx9carDW+x4Ndmdf5nbSsfZ+gr3yVAAQBkW1Cj+wgC2DFINpTr6Nt0qbuaQjRS53AA== + dependencies: + "@solana-mobile/mobile-wallet-adapter-protocol-web3js" "^2.1.2" + "@solana/wallet-adapter-base" "^0.9.23" + "@solana/wallet-standard-features" "^1.2.0" + js-base64 "^3.7.5" + optionalDependencies: + "@react-native-async-storage/async-storage" "^1.17.7" + "@solana/buffer-layout-utils@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz#b45a6cab3293a2eb7597cceb474f229889d875ca" @@ -4597,515 +4486,887 @@ bigint-buffer "^1.1.5" bignumber.js "^9.0.1" -"@solana/buffer-layout@^3.0.0": - version "3.0.0" - resolved "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-3.0.0.tgz" - integrity sha512-MVdgAKKL39tEs0l8je0hKaXLQFb7Rdfb0Xg2LjFZd8Lfdazkg6xiS98uAZrEKvaoF3i4M95ei9RydkGIDMeo3w== - dependencies: - buffer "~6.0.3" - -"@solana/buffer-layout@^4.0.0": +"@solana/buffer-layout@4.0.0", "@solana/buffer-layout@^3.0.0", "@solana/buffer-layout@^4.0.0", "@solana/buffer-layout@^4.0.1": version "4.0.0" - resolved "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.0.tgz#75b1b11adc487234821c81dfae3119b73a5fd734" integrity sha512-lR0EMP2HC3+Mxwd4YcnZb0smnaDw7Bl2IQWZiTevRH5ZZBZn6VRWn3/92E3qdU4SSImJkA6IDHawOHAnx/qUvQ== dependencies: buffer "~6.0.3" -"@solana/governance-program-library@npm:@civic/governance-program-library@0.16.9-beta.2": - version "0.16.9-beta.2" - resolved "https://registry.yarnpkg.com/@civic/governance-program-library/-/governance-program-library-0.16.9-beta.2.tgz#2e80c39a39bc3fc7b05ee961112a8daf25f7cf45" - integrity sha512-9xjdu5ifXJGVZonQ9tmxREyKChVW0c1TMU2tIT6p8Kb6RqVXcoHNjr8aFaH4Z74LshF8rOiQLSnguVGBLu3atw== +"@solana/codecs-core@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-2.0.0-preview.2.tgz#689784d032fbc1fedbde40bb25d76cdcecf6553b" + integrity sha512-gLhCJXieSCrAU7acUJjbXl+IbGnqovvxQLlimztPoGgfLQ1wFYu+XJswrEVQqknZYK1pgxpxH3rZ+OKFs0ndQg== dependencies: - "@project-serum/anchor" "^0.25.0" - "@project-serum/serum" "^0.13.61" + "@solana/errors" "2.0.0-preview.2" + +"@solana/codecs-core@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-2.0.0-preview.4.tgz#770826105f2f884110a21662573e7a2014654324" + integrity sha512-A0VVuDDA5kNKZUinOqHxJQK32aKTucaVbvn31YenGzHX1gPqq+SOnFwgaEY6pq4XEopSmaK16w938ZQS8IvCnw== + dependencies: + "@solana/errors" "2.0.0-preview.4" + +"@solana/codecs-core@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-2.0.0-rc.1.tgz#1a2d76b9c7b9e7b7aeb3bd78be81c2ba21e3ce22" + integrity sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ== + dependencies: + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs-data-structures@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-preview.2.tgz#e82cb1b6d154fa636cd5c8953ff3f32959cc0370" + integrity sha512-Xf5vIfromOZo94Q8HbR04TbgTwzigqrKII0GjYr21K7rb3nba4hUW2ir8kguY7HWFBcjHGlU5x3MevKBOLp3Zg== + dependencies: + "@solana/codecs-core" "2.0.0-preview.2" + "@solana/codecs-numbers" "2.0.0-preview.2" + "@solana/errors" "2.0.0-preview.2" + +"@solana/codecs-data-structures@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.yarnpkg.com/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-preview.4.tgz#f8a2470982a9792334737ea64000ccbdff287247" + integrity sha512-nt2k2eTeyzlI/ccutPcG36M/J8NAYfxBPI9h/nQjgJ+M+IgOKi31JV8StDDlG/1XvY0zyqugV3I0r3KAbZRJpA== + dependencies: + "@solana/codecs-core" "2.0.0-preview.4" + "@solana/codecs-numbers" "2.0.0-preview.4" + "@solana/errors" "2.0.0-preview.4" + +"@solana/codecs-data-structures@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-rc.1.tgz#d47b2363d99fb3d643f5677c97d64a812982b888" + integrity sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs-numbers@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-2.0.0-preview.2.tgz#56995c27396cd8ee3bae8bd055363891b630bbd0" + integrity sha512-aLZnDTf43z4qOnpTcDsUVy1Ci9im1Md8thWipSWbE+WM9ojZAx528oAql+Cv8M8N+6ALKwgVRhPZkto6E59ARw== + dependencies: + "@solana/codecs-core" "2.0.0-preview.2" + "@solana/errors" "2.0.0-preview.2" + +"@solana/codecs-numbers@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-2.0.0-preview.4.tgz#6a53b456bb7866f252d8c032c81a92651e150f66" + integrity sha512-Q061rLtMadsO7uxpguT+Z7G4UHnjQ6moVIxAQxR58nLxDPCC7MB1Pk106/Z7NDhDLHTcd18uO6DZ7ajHZEn2XQ== + dependencies: + "@solana/codecs-core" "2.0.0-preview.4" + "@solana/errors" "2.0.0-preview.4" + +"@solana/codecs-numbers@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-2.0.0-rc.1.tgz#f34978ddf7ea4016af3aaed5f7577c1d9869a614" + integrity sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs-strings@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/codecs-strings/-/codecs-strings-2.0.0-preview.2.tgz#8bd01a4e48614d5289d72d743c3e81305d445c46" + integrity sha512-EgBwY+lIaHHgMJIqVOGHfIfpdmmUDNoNO/GAUGeFPf+q0dF+DtwhJPEMShhzh64X2MeCZcmSO6Kinx0Bvmmz2g== + dependencies: + "@solana/codecs-core" "2.0.0-preview.2" + "@solana/codecs-numbers" "2.0.0-preview.2" + "@solana/errors" "2.0.0-preview.2" + +"@solana/codecs-strings@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.yarnpkg.com/@solana/codecs-strings/-/codecs-strings-2.0.0-preview.4.tgz#4d06bb722a55a5d04598d362021bfab4bd446760" + integrity sha512-YDbsQePRWm+xnrfS64losSGRg8Wb76cjK1K6qfR8LPmdwIC3787x9uW5/E4icl/k+9nwgbIRXZ65lpF+ucZUnw== + dependencies: + "@solana/codecs-core" "2.0.0-preview.4" + "@solana/codecs-numbers" "2.0.0-preview.4" + "@solana/errors" "2.0.0-preview.4" + +"@solana/codecs-strings@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-strings/-/codecs-strings-2.0.0-rc.1.tgz#e1d9167075b8c5b0b60849f8add69c0f24307018" + integrity sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/codecs/-/codecs-2.0.0-preview.2.tgz#d6615fec98f423166fb89409f9a4ad5b74c10935" + integrity sha512-4HHzCD5+pOSmSB71X6w9ptweV48Zj1Vqhe732+pcAQ2cMNnN0gMPMdDq7j3YwaZDZ7yrILVV/3+HTnfT77t2yA== + dependencies: + "@solana/codecs-core" "2.0.0-preview.2" + "@solana/codecs-data-structures" "2.0.0-preview.2" + "@solana/codecs-numbers" "2.0.0-preview.2" + "@solana/codecs-strings" "2.0.0-preview.2" + "@solana/options" "2.0.0-preview.2" + +"@solana/codecs@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.yarnpkg.com/@solana/codecs/-/codecs-2.0.0-preview.4.tgz#a1923cc78a6f64ebe656c7ec6335eb6b70405b22" + integrity sha512-gLMupqI4i+G4uPi2SGF/Tc1aXcviZF2ybC81x7Q/fARamNSgNOCUUoSCg9nWu1Gid6+UhA7LH80sWI8XjKaRog== + dependencies: + "@solana/codecs-core" "2.0.0-preview.4" + "@solana/codecs-data-structures" "2.0.0-preview.4" + "@solana/codecs-numbers" "2.0.0-preview.4" + "@solana/codecs-strings" "2.0.0-preview.4" + "@solana/options" "2.0.0-preview.4" + +"@solana/codecs@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/codecs/-/codecs-2.0.0-rc.1.tgz#146dc5db58bd3c28e04b4c805e6096c2d2a0a875" + integrity sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-data-structures" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/codecs-strings" "2.0.0-rc.1" + "@solana/options" "2.0.0-rc.1" + +"@solana/errors@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-2.0.0-preview.2.tgz#e0ea8b008c5c02528d5855bc1903e5e9bbec322e" + integrity sha512-H2DZ1l3iYF5Rp5pPbJpmmtCauWeQXRJapkDg8epQ8BJ7cA2Ut/QEtC3CMmw/iMTcuS6uemFNLcWvlOfoQhvQuA== + dependencies: + chalk "^5.3.0" + commander "^12.0.0" + +"@solana/errors@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-2.0.0-preview.4.tgz#056ba76b6dd900dafa70117311bec3aef0f5250b" + integrity sha512-kadtlbRv2LCWr8A9V22On15Us7Nn8BvqNaOB4hXsTB3O0fU40D1ru2l+cReqLcRPij4znqlRzW9Xi0m6J5DIhA== + dependencies: + chalk "^5.3.0" + commander "^12.1.0" + +"@solana/errors@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-2.0.0-rc.1.tgz#3882120886eab98a37a595b85f81558861b29d62" + integrity sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ== + dependencies: + chalk "^5.3.0" + commander "^12.1.0" + +"@solana/governance-program-library@npm:@civic/governance-program-library@0.18.2-beta.24": + version "0.18.2-beta.24" + resolved "https://registry.yarnpkg.com/@civic/governance-program-library/-/governance-program-library-0.18.2-beta.24.tgz#68688efd4679b125a47d03b935a9504e29cb97d0" + integrity sha512-Z+IiNKPbp7E7oFSoTZbTS6qZ6h66fE+r5gttnnhKfGuVPpj+95aALerAQpOYSGl0oQ7DkKaUO2N+lBTgLaEQCA== + dependencies: + "@coral-xyz/anchor" "^0.29.0" + "@identity.com/solana-gateway-ts" "^0.12.0" + "@solana/spl-governance" "^0.3.28" + +"@solana/options@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/options/-/options-2.0.0-preview.2.tgz#13ff008bf43a5056ef9a091dc7bb3f39321e867e" + integrity sha512-FAHqEeH0cVsUOTzjl5OfUBw2cyT8d5Oekx4xcn5hn+NyPAfQJgM3CEThzgRD6Q/4mM5pVUnND3oK/Mt1RzSE/w== + dependencies: + "@solana/codecs-core" "2.0.0-preview.2" + "@solana/codecs-numbers" "2.0.0-preview.2" + +"@solana/options@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.yarnpkg.com/@solana/options/-/options-2.0.0-preview.4.tgz#212d35d1da87c7efb13de4d3569ad9eb070f013d" + integrity sha512-tv2O/Frxql/wSe3jbzi5nVicIWIus/BftH+5ZR+r9r3FO0/htEllZS5Q9XdbmSboHu+St87584JXeDx3xm4jaA== + dependencies: + "@solana/codecs-core" "2.0.0-preview.4" + "@solana/codecs-data-structures" "2.0.0-preview.4" + "@solana/codecs-numbers" "2.0.0-preview.4" + "@solana/codecs-strings" "2.0.0-preview.4" + "@solana/errors" "2.0.0-preview.4" + +"@solana/options@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.yarnpkg.com/@solana/options/-/options-2.0.0-rc.1.tgz#06924ba316dc85791fc46726a51403144a85fc4d" + integrity sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-data-structures" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/codecs-strings" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/promises@2.0.0-canary-20240812091942": + version "2.0.0-canary-20240812091942" + resolved "https://registry.yarnpkg.com/@solana/promises/-/promises-2.0.0-canary-20240812091942.tgz#e0f1d0c200170a791f120e320b10c446d30644c9" + integrity sha512-HLYVZxrXnMatnBBtHCK1qY7T2AEnhI2AL4PY10iZZ98JIO9dE6igRwFlBulC3ts8qBBkivDf0rF6RahvkrHV0A== + +"@solana/spl-account-compression@^0.1.4", "@solana/spl-account-compression@^0.1.8": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@solana/spl-account-compression/-/spl-account-compression-0.1.9.tgz#5aeb5cd3416ca6e3a7257bec33e8c31f5ec52aaf" + integrity sha512-g/YGafUZihhK837DMCSJQGwgj9RV7sTj/bhHb6lOEmSkA0hJTAGOX8ECbv5dDwuFqyUzakno6SZ2gr4q+B0kDg== + dependencies: + "@metaplex-foundation/beet" "^0.7.1" + "@metaplex-foundation/beet-solana" "^0.4.0" + bn.js "^5.2.1" + borsh "^0.7.0" + js-sha3 "^0.8.0" + typescript-collections "^1.3.3" -"@solana/spl-governance@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@solana/spl-governance/-/spl-governance-0.0.29.tgz#8a691ace5242a1174ede73657c06267184f1c4b3" - integrity sha512-+Wrk4pHKDDzw7d2gXtpplslfLwIjWIDLB4o78LSiiPCtY+fObtKabWwyH/AVWXhebSGj+bkW6j0i9/WE4xbnCg== +"@solana/spl-account-compression@~0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@solana/spl-account-compression/-/spl-account-compression-0.2.0.tgz#a8a28a3985b50d0391bfd6374345e9d36eb8f792" + integrity sha512-nHpa+hTUpjLdV9x4LXlp7k0WIkr8kUGjY/SPh+vuTUy4SEIIDjrGJ6/B0hUdd8+mFfrq2x4j/tgJvPsm4K5AJw== dependencies: - "@solana/web3.js" "^1.22.0" - bignumber.js "^9.0.1" - bn.js "^5.1.3" - borsh "^0.3.1" - bs58 "^4.0.1" - superstruct "^0.15.2" + "@metaplex-foundation/beet" "^0.7.1" + "@metaplex-foundation/beet-solana" "^0.4.0" + bn.js "^5.2.1" + borsh "^0.7.0" + js-sha3 "^0.8.0" + typescript-collections "^1.3.3" -"@solana/spl-governance@^0.0.34": - version "0.0.34" - resolved "https://registry.yarnpkg.com/@solana/spl-governance/-/spl-governance-0.0.34.tgz#c61d81d356dbcee961bbc85e5d3538846fea57ad" - integrity sha512-tZppBiiVkUa5v+B/Ds+TqZ4yxR/vaIYLRxBk7x6R22dwk4/9SU87bVE60kRdDqTdMzqScFxIMdhaGl/fCX533A== +"@solana/spl-governance@0.3.26": + version "0.3.26" + resolved "https://registry.yarnpkg.com/@solana/spl-governance/-/spl-governance-0.3.26.tgz#1a6c56037063654d243cc3ee9503b5b3140bbd6f" + integrity sha512-L84AWKcAmEMIWhh5gcfasfDesOMT+IU4i+s0ELgKCN0O9MC/hVrSjTkn68vBhDfCElnJyJTFMAN7NqSbrweD9A== dependencies: "@solana/web3.js" "^1.22.0" + axios "^1.1.3" bignumber.js "^9.0.1" bn.js "^5.1.3" borsh "^0.3.1" bs58 "^4.0.1" superstruct "^0.15.2" -"@solana/spl-governance@^0.3.13": - version "0.3.13" - resolved "https://registry.yarnpkg.com/@solana/spl-governance/-/spl-governance-0.3.13.tgz#8262b9c0439321e5041530b3b832579371f8ad9c" - integrity sha512-qoLSXMqHmR99yvMrqLZ/FIlin0wHibMG+lHUqfFFzBLtuaoABSesXplsneSglz2Fx6AAu/LgBRkqca5M8Fc9hA== +"@solana/spl-governance@0.3.28", "@solana/spl-governance@^0.3.28": + version "0.3.28" + resolved "https://registry.yarnpkg.com/@solana/spl-governance/-/spl-governance-0.3.28.tgz#63ff71f235206f069f8ea1e66a40e7cdb6252d3f" + integrity sha512-CUi1hMvzId2rAtMFTlxMwOy0EmFeT0VcmiC+iQnDhRBuM8LLLvRrbTYBWZo3xIvtPQW9HfhVBoL7P/XNFIqYVQ== dependencies: "@solana/web3.js" "^1.22.0" + axios "^1.1.3" bignumber.js "^9.0.1" bn.js "^5.1.3" borsh "^0.3.1" bs58 "^4.0.1" superstruct "^0.15.2" -"@solana/spl-name-service@^0.1.3": - version "0.1.3" - resolved "https://registry.npmjs.org/@solana/spl-name-service/-/spl-name-service-0.1.3.tgz" - integrity sha512-NIsa5xU8Fx9nIofM/mmrNI3s472kDBtNdqI6TbhIaVeP/DTYc9m5dkjvG32T1tZdNMv0kvFIpqZ0iAJvvZ/ABg== +"@solana/spl-stake-pool@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@solana/spl-stake-pool/-/spl-stake-pool-1.1.5.tgz#a820f03195ff11c7206f3b5137789a82c322b029" + integrity sha512-fiZ7XRbtk4G4aDRdAFu+3rs0kNFv55dzfLd78HoADhrVNQT8B+vby7L02Zhp1f2DR8GPWqTQkBh5BdyAKrICBQ== dependencies: - "@solana/spl-token" "0.1.6" - "@solana/web3.js" "^1.21.0" - bip32 "^2.0.6" - bn.js "^5.1.3" - borsh "^0.4.0" - bs58 "4.0.1" - buffer-layout "^1.2.0" - core-util-is "^1.0.2" - crypto "^1.0.1" - crypto-ts "^1.0.2" - fs "^0.0.1-security" - tweetnacl "^1.0.3" - webpack-dev-server "^3.11.2" + "@solana/buffer-layout" "^4.0.1" + "@solana/spl-token" "0.4.6" + "@solana/web3.js" "^1.91.8" + bn.js "^5.2.0" + buffer "^6.0.3" + buffer-layout "^1.2.2" + superstruct "^1.0.4" -"@solana/spl-token-registry@^0.2.1107": - version "0.2.3797" - resolved "https://registry.yarnpkg.com/@solana/spl-token-registry/-/spl-token-registry-0.2.3797.tgz#48e5ca97c2dc064724ac4997aeb96abb2278a28c" - integrity sha512-NrRVdM66Kvjef4bYQc9ynJvJtNW/JIWu7PvtuwqwR9R5Omzr5Cm5JWyM5NQDcDO/L8F8xJ8BYXA7PUKu0AkUxA== +"@solana/spl-token-group@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@solana/spl-token-group/-/spl-token-group-0.0.4.tgz#4f45d9526c96a33b9a1929a264d0aa21c7e38a2d" + integrity sha512-7+80nrEMdUKlK37V6kOe024+T7J4nNss0F8LQ9OOPYdWCCfJmsGUzVx2W3oeizZR4IHM6N4yC9v1Xqwc3BTPWw== dependencies: - cross-fetch "3.0.6" + "@solana/codecs" "2.0.0-preview.2" + "@solana/spl-type-length-value" "0.1.0" -"@solana/spl-token-registry@^0.2.3775": - version "0.2.4389" - resolved "https://registry.yarnpkg.com/@solana/spl-token-registry/-/spl-token-registry-0.2.4389.tgz#e3bbc16e4360bd6bebd3ecdb3349e0aec6d626fa" - integrity sha512-AGcyMr0wphSMDzL6stPV1V2lLIYGPtPhr1L3HC1NeTB+wAojcQFDr8ngHAWoAH5TDWnYxIpH2LN3Viggf/eNag== +"@solana/spl-token-group@^0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@solana/spl-token-group/-/spl-token-group-0.0.5.tgz#f955dcca782031c85e862b2b46878d1bb02db6c2" + integrity sha512-CLJnWEcdoUBpQJfx9WEbX3h6nTdNiUzswfFdkABUik7HVwSNA98u5AYvBVK2H93d9PGMOHAak2lHW9xr+zAJGQ== dependencies: - cross-fetch "3.0.6" + "@solana/codecs" "2.0.0-preview.4" + "@solana/spl-type-length-value" "0.1.0" -"@solana/spl-token@0.1.5": +"@solana/spl-token-metadata@^0.1.2", "@solana/spl-token-metadata@^0.1.3", "@solana/spl-token-metadata@^0.1.4": version "0.1.5" - resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.1.5.tgz#dcb6cb4bd7acb3c6457500502b6e62c75d18d05b" - integrity sha512-2rlgKbH3lCTIuxwm4A+R2/t+w3Rt2tJLpGH6jefQQUpM6MyxlQWV+P9pB7+lozuWDOJ7A2OyKkUEt/HlxyHFjw== + resolved "https://registry.yarnpkg.com/@solana/spl-token-metadata/-/spl-token-metadata-0.1.5.tgz#91616470d6862ec6b762e6cfcf882b8a8a24b1e8" + integrity sha512-DSBlo7vjuLe/xvNn75OKKndDBkFxlqjLdWlq6rf40StnrhRn7TDntHGLZpry1cf3uzQFShqeLROGNPAJwvkPnA== + dependencies: + "@solana/codecs" "2.0.0-rc.1" + "@solana/spl-type-length-value" "0.1.0" + +"@solana/spl-token-registry@0.2.3775": + version "0.2.3775" + resolved "https://registry.yarnpkg.com/@solana/spl-token-registry/-/spl-token-registry-0.2.3775.tgz#96abffc351fe156917aedb8bba7db94600abed6e" + integrity sha512-3a6wn6LZ1ZdCt50p9Bz2s8tIh1cJvJue4vvlPlzZ1n2j/0H2Coy4Xx92nIsYot399TjtO9NeLU2NowBDH4vtpg== + dependencies: + cross-fetch "3.0.6" + +"@solana/spl-token@0.1.8", "@solana/spl-token@^0.1.6", "@solana/spl-token@^0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.1.8.tgz#f06e746341ef8d04165e21fc7f555492a2a0faa6" + integrity sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ== dependencies: "@babel/runtime" "^7.10.5" - "@solana/web3.js" "^1.12.0" + "@solana/web3.js" "^1.21.0" bn.js "^5.1.0" buffer "6.0.3" buffer-layout "^1.2.0" dotenv "10.0.0" -"@solana/spl-token@0.1.6": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.1.6.tgz#fa136b0a3db84f07a99bc0e54cf4e91f2d6da2e8" - integrity sha512-fYj+a3w1bqWN6Ibf85XF3h2JkuxevI3Spvqi+mjsNqVUEo2AgxxTZmujNLn/jIzQDNdWkBfF/wYzH5ikcGHmfw== +"@solana/spl-token@0.3.8": + version "0.3.8" + resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.8.tgz#8e9515ea876e40a4cc1040af865f61fc51d27edf" + integrity sha512-ogwGDcunP9Lkj+9CODOWMiVJEdRtqHAtX2rWF62KxnnSWtMZtV9rDhTrZFshiyJmxDnRL/1nKE1yJHg4jjs3gg== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/buffer-layout-utils" "^0.2.0" + buffer "^6.0.3" + +"@solana/spl-token@0.4.6": + version "0.4.6" + resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.4.6.tgz#eb44e5080ea7b6fc976abcb39457223211bd9076" + integrity sha512-1nCnUqfHVtdguFciVWaY/RKcQz1IF4b31jnKgAmjU9QVN1q7dRUkTEWJZgTYIEtsULjVnC9jRqlhgGN39WbKKA== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/buffer-layout-utils" "^0.2.0" + "@solana/spl-token-group" "^0.0.4" + "@solana/spl-token-metadata" "^0.1.4" + buffer "^6.0.3" + +"@solana/spl-token@0.4.8": + version "0.4.8" + resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.4.8.tgz#a84e4131af957fa9fbd2727e5fc45dfbf9083586" + integrity sha512-RO0JD9vPRi4LsAbMUdNbDJ5/cv2z11MGhtAvFeRzT4+hAGE/FUzRi0tkkWtuCfSIU3twC6CtmAihRp/+XXjWsA== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/buffer-layout-utils" "^0.2.0" + "@solana/spl-token-group" "^0.0.5" + "@solana/spl-token-metadata" "^0.1.3" + buffer "^6.0.3" + +"@solana/spl-token@^0.3.11", "@solana/spl-token@^0.3.4", "@solana/spl-token@^0.3.5", "@solana/spl-token@^0.3.6", "@solana/spl-token@^0.3.7", "@solana/spl-token@^0.3.8", "@solana/spl-token@^0.3.9": + version "0.3.11" + resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.11.tgz#cdc10f9472b29b39c8983c92592cadd06627fb9a" + integrity sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/buffer-layout-utils" "^0.2.0" + "@solana/spl-token-metadata" "^0.1.2" + buffer "^6.0.3" + +"@solana/spl-type-length-value@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@solana/spl-type-length-value/-/spl-type-length-value-0.1.0.tgz#b5930cf6c6d8f50c7ff2a70463728a4637a2f26b" + integrity sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA== + dependencies: + buffer "^6.0.3" + +"@solana/wallet-adapter-alpha@^0.1.9": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-alpha/-/wallet-adapter-alpha-0.1.9.tgz#863ae3f7108046c9e022c80023bb1b0877a6dec5" + integrity sha512-GruswNb+4ft/OaqEvFsSJkA6UDOAtyMazgcqHZycWm3axd215KdBB0Jyx3lpOIafU+3IRqbUc773LUzqrYG6VA== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-avana@^0.1.12": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-avana/-/wallet-adapter-avana-0.1.12.tgz#1e10429a22cf92f1310f48f41c3432c5025e72f5" + integrity sha512-BIvddokNhRx+NKfIx+Y8tqiAzI4xloY6bGcrBVNUJF9gcMOX2sDaF6Q1iFxFuxja9ZfIabdb6lyzcjf1bYlzqg== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-backpack@0.1.13", "@solana/wallet-adapter-backpack@^0.1.13": + version "0.1.13" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-backpack/-/wallet-adapter-backpack-0.1.13.tgz#36a816bc6d620cde3ab9cb161194ecd201fb21a4" + integrity sha512-vt2OcV39uvuS2bBJU4xFwZkWwjRci6TsnQDs6pGQcbrryt8ahICxyCybhRKY3Y58uRnaejW0EDc7P3tBSsDmig== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-base@0.9.22": + version "0.9.22" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.22.tgz#97812eaf6aebe01e5fe714326b3c9a0614ae6112" + integrity sha512-xbLEZPGSJFvgTeldG9D55evhl7QK/3e/F7vhvcA97mEt1eieTgeKMnGlmmjs3yivI3/gtZNZeSk1XZLnhKcQvw== + dependencies: + "@solana/wallet-standard-features" "^1.0.1" + "@wallet-standard/base" "^1.0.1" + "@wallet-standard/features" "^1.0.3" + eventemitter3 "^4.0.7" + +"@solana/wallet-adapter-base@^0.9.17", "@solana/wallet-adapter-base@^0.9.2", "@solana/wallet-adapter-base@^0.9.21", "@solana/wallet-adapter-base@^0.9.22", "@solana/wallet-adapter-base@^0.9.23": + version "0.9.23" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.23.tgz#3b17c28afd44e173f44f658bf9700fd637e12a11" + integrity sha512-apqMuYwFp1jFi55NxDfvXUX2x1T0Zh07MxhZ/nCCTGys5raSfYUh82zen2BLv8BSDj/JxZ2P/s7jrQZGrX8uAw== + dependencies: + "@solana/wallet-standard-features" "^1.1.0" + "@wallet-standard/base" "^1.0.1" + "@wallet-standard/features" "^1.0.3" + eventemitter3 "^4.0.7" + +"@solana/wallet-adapter-bitkeep@^0.3.18": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-bitkeep/-/wallet-adapter-bitkeep-0.3.18.tgz#00e500d216b9d363bdb024aeb7eb8d7e33f584af" + integrity sha512-RtF0utV6y7Otmquh/Pc8MxfzGGOejrNRlsV6gbK7+vzmLueNgRWi2m++pqpEDUvaSWMU/s+Cd9cgkKHyVju7nw== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-bitpie@^0.5.17": + version "0.5.17" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-bitpie/-/wallet-adapter-bitpie-0.5.17.tgz#f1eebce0c0cefdf19f21b639d7eca4b8987eaca5" + integrity sha512-fYcNz3Sn44217olI6qWiOaozpwpQIIntgVUwr0pnmxJuLanaxE/CO+mnw2UAps68k7p5/CXBY1VqFmWZwExEUg== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-blocto@^0.5.21": + version "0.5.21" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-blocto/-/wallet-adapter-blocto-0.5.21.tgz#c0c554861f64efad75bfd600dd21c80d98e56f00" + integrity sha512-USspnk+qQiGrt+cGfhtkIXyV+WW8NW9z4ni+AniVEgqSlooV2ByF1KSCx/K9pwrXHQEFkqVBmSpn632M49IoKw== + dependencies: + "@blocto/sdk" "^0.2.22" + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-brave@0.1.11": + version "0.1.11" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-brave/-/wallet-adapter-brave-0.1.11.tgz#22500f2e8cc0133a9b4f15a40465180370d4ea19" + integrity sha512-j9ukING7K+svHNvhBk1yrACICgCSQTHLpqgatdvSmWfp+2dxDNZ9TjKWabstte1dVuKspk0s9vnO/977Hwlo9w== + dependencies: + "@solana/wallet-adapter-base" "^0.9.17" + +"@solana/wallet-adapter-brave@^0.1.16": + version "0.1.16" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-brave/-/wallet-adapter-brave-0.1.16.tgz#54bd17028eae9f37a9371205a291ecb3d48faacc" + integrity sha512-ypdweCoRzL8l0aT1Zp7Lbfu9oht2ucYLpqd17DCEBUFtCv4yMZ/dOoW06pV3u8ykdhFz7M8aVsXI2TXvVzwqDQ== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-censo@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-censo/-/wallet-adapter-censo-0.1.3.tgz#c948df54d8cb5569dea8a350bf01f08eb1d8cb20" + integrity sha512-+eUF2VfOc04uc/qZIR3Y4UcM4tFLfN46myk1tCd1r3g7iZSeDa7mo5vD1WZXAyjcG756WPpiR08nVim5DHDeJw== + dependencies: + "@censo-custody/solana-wallet-adapter" "^0.1.0" + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-clover@^0.4.13", "@solana/wallet-adapter-clover@^0.4.18": + version "0.4.18" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-clover/-/wallet-adapter-clover-0.4.18.tgz#6592db21bc26e489b311330dee3847fc2a55ff27" + integrity sha512-n2MtGi81+KeWxy6sd3zkTylZ1yRD7Hcpg1WYZURwa1H7nZ808HSoU5aSzwpRUQ75VWyi5Ks2l28sP3oLOugmsQ== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-coin98@^0.5.14", "@solana/wallet-adapter-coin98@^0.5.19": + version "0.5.19" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-coin98/-/wallet-adapter-coin98-0.5.19.tgz#40f704b0b6f327f98c1dd89a5c0b6e0bd8db4179" + integrity sha512-as32x9i8OEjHHSXSeBWEnIKBqCDvmFVHpRoCWuJUtiogE4OHwhmnF9wRPk1ljmce/FGTFwdkTksxNYRI69qOfw== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + bs58 "^4.0.1" + +"@solana/wallet-adapter-coinbase@^0.1.12", "@solana/wallet-adapter-coinbase@^0.1.17": + version "0.1.17" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-coinbase/-/wallet-adapter-coinbase-0.1.17.tgz#0685fd9ac68b21b8d30eea5c41f7f77ddafea23f" + integrity sha512-3Le+FlLUwdhCGsOGwcy3b7U1268+xEfjY5/IYQE6Ez9DJNDB2ymZkuF7kpJnJMJEvXR94jSAnJvlTMzANAVtIQ== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-coinhub@^0.3.17": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-coinhub/-/wallet-adapter-coinhub-0.3.17.tgz#ddd4406852617abfe3479b8621124290f75c4070" + integrity sha512-bdniCFBh//ubx+cQVc6p4zNWpiTkF97yalckeTW2PSN5a76jHQeZPzDDsNk8Bvzo08gO2JuK+B+eCvhWK13QJg== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-exodus@0.1.17", "@solana/wallet-adapter-exodus@^0.1.12", "@solana/wallet-adapter-exodus@^0.1.17": + version "0.1.17" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-exodus/-/wallet-adapter-exodus-0.1.17.tgz#16d8ba4c4b851dd76a86d2ffa2b5dee1a7431ecc" + integrity sha512-oGP8Z8Irjdk7ofiqR/Vy4MRMOb5nm69IyI/rsI5MBfEOBzxK15Tmh21yQagneVkl7OSVZMjuXu2ImJQLpZtZJw== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-fractal@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-fractal/-/wallet-adapter-fractal-0.1.7.tgz#8ed049f62b5b3957336ad50ee8d1df7bf51467e0" + integrity sha512-lhIo8hFbRSOsOxKgBB+t78ymM0pqj2PZG0myMeMqgNP4O6mpvaVcqZ9/tEVoEK+ceraRMuHMLoOfDZhg4coYTw== + dependencies: + "@fractalwagmi/solana-wallet-adapter" "^0.1.1" + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-glow@0.1.17", "@solana/wallet-adapter-glow@^0.1.12", "@solana/wallet-adapter-glow@^0.1.17": + version "0.1.17" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-glow/-/wallet-adapter-glow-0.1.17.tgz#f99751ed32b780146258b92fde7982ed176a3e40" + integrity sha512-DcRMKUQSVenPDOjs+O2ouNk9F5YlzKZ+uG2KMTAE9hzBS6CQoQkb+4skLVrs16l+RhU5HTQV+EOw2tFkkW/Teg== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-huobi@^0.1.14", "@solana/wallet-adapter-huobi@^0.1.9": + version "0.1.14" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-huobi/-/wallet-adapter-huobi-0.1.14.tgz#a2ec07662daaa2f2e2c7752a44bf9371951bd8d6" + integrity sha512-1XdAL9nwI1hamMLzN60tSVu1UUcWCK9k4RvnEJPRyjCB1kHoW0AddLs+hZ8DNpiDjfRXNcmuTjXdIGWHjxvqvw== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-hyperpay@^0.1.13": + version "0.1.13" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-hyperpay/-/wallet-adapter-hyperpay-0.1.13.tgz#ee7eda55be3010812053b4e38799b742d6849abd" + integrity sha512-2xUSZsfR76/TEmxMha+mwUvo3HhYY/IKTsC7aU7/ay0A0DlIQstZUwNxGLpCqr9n37/pIXBjl2dGSQ5DxnUONg== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-keystone@^0.1.11": + version "0.1.11" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-keystone/-/wallet-adapter-keystone-0.1.11.tgz#d3d321462d2c36b4d7a0d74d5f2275ca49da7eaa" + integrity sha512-DChjMuj5l0Mp8CryD6VscfctxSdScVPsuO5kopBTxCFyQJI41ut0WTPrKH5badLUd+xC4arLFZ8x/U8jiRoqNQ== dependencies: - "@babel/runtime" "^7.10.5" - "@solana/web3.js" "^1.12.0" - bn.js "^5.1.0" - buffer "6.0.3" - buffer-layout "^1.2.0" - dotenv "10.0.0" + "@keystonehq/sol-keyring" "^0.3.1" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/spl-token@0.1.8", "@solana/spl-token@^0.1.5", "@solana/spl-token@^0.1.6", "@solana/spl-token@^0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.1.8.tgz#f06e746341ef8d04165e21fc7f555492a2a0faa6" - integrity sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ== +"@solana/wallet-adapter-krystal@^0.1.11": + version "0.1.11" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-krystal/-/wallet-adapter-krystal-0.1.11.tgz#f729015749fed59f3b4e818acd49dbf5b34eaaa4" + integrity sha512-Jz1HdEohjzUCBK/mQCBtXf3Z1R/rifc1OIt46InKX/b4WCdRMwU2UDhKWwzeNiqFPbI2BaIBKctoKCPKq0uq+w== dependencies: - "@babel/runtime" "^7.10.5" - "@solana/web3.js" "^1.21.0" - bn.js "^5.1.0" - buffer "6.0.3" - buffer-layout "^1.2.0" - dotenv "10.0.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/spl-token@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.2.0.tgz#329bb6babb5de0f9c40035ddb1657f01a8347acd" - integrity sha512-RWcn31OXtdqIxmkzQfB2R+WpsJOVS6rKuvpxJFjvik2LyODd+WN58ZP3Rpjpro03fscGAkzlFuP3r42doRJgyQ== +"@solana/wallet-adapter-ledger@^0.9.24": + version "0.9.24" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-ledger/-/wallet-adapter-ledger-0.9.24.tgz#4f3882e4b908b100236bf2c8d0fd5ea248df4da3" + integrity sha512-TjrAu6hUdictAZU8wYO6MUzvx8+ZDEBIGnFpjrq+sXlo0NK84WFh8UykFfOtdBaUhwkUkYTgLo+2lMV0OhtT2A== dependencies: - "@solana/buffer-layout" "^4.0.0" - "@solana/buffer-layout-utils" "^0.2.0" - "@solana/web3.js" "^1.32.0" - start-server-and-test "^1.14.0" + "@ledgerhq/devices" "6.27.1" + "@ledgerhq/hw-transport" "6.27.1" + "@ledgerhq/hw-transport-webhid" "6.27.1" + "@solana/wallet-adapter-base" "^0.9.22" + buffer "^6.0.3" -"@solana/wallet-adapter-backpack@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-backpack/-/wallet-adapter-backpack-0.1.0.tgz#cc53e95597736772b8675c20d1c1dbd672d4dd78" - integrity sha512-jQfZM8t9oIWpVyc82NU1su1rGxJt7D1+Xp1RSmB5zXEKmeGuQol3T3bSwLXbrwMn1Q9ktldWwsv4jzb0o4jPkQ== +"@solana/wallet-adapter-magiceden@^0.1.12": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-magiceden/-/wallet-adapter-magiceden-0.1.12.tgz#819fda35df3c2cd9a9b558589b5369f8143e7046" + integrity sha512-0w53joZfoA4IZSTRuw5jDnkhihqfxZ3INr5yaAq4Bzu13E7UwZYZhqBjnOc+bHorrsbcTUuZk3IgVmoFgzZpHA== dependencies: - "@solana/wallet-adapter-base" "^0.9.9" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-base@^0.9.1", "@solana/wallet-adapter-base@^0.9.2": - version "0.9.2" - resolved "https://registry.npmjs.org/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.2.tgz" - integrity sha512-lHMHE506oKIJM8Tm/yBUpwR2tOdBADQqKhES/U64oAoACprulLBSGx0A+v7NP3rlcTmBMSh7qSQnf5Iic6jexQ== +"@solana/wallet-adapter-mathwallet@^0.9.12", "@solana/wallet-adapter-mathwallet@^0.9.17": + version "0.9.17" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-mathwallet/-/wallet-adapter-mathwallet-0.9.17.tgz#74a36585edaa965622cd2b72bf4580bb32008fb3" + integrity sha512-gyXCZoltA1sbXczVFUbUdxDdey+HawRDoW2bwHHIDWRi26JPAnij671zQkwB5hTIgDRTRDmURSjVvzB9OGNMyw== dependencies: - "@solana/web3.js" "^1.20.0" - eventemitter3 "^4.0.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-base@^0.9.12": - version "0.9.12" - resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.12.tgz#2a2e7944ea2f8803296b4460cc863a1c76511394" - integrity sha512-4pwhvCLlGNHV8WmrG/2OYI145zp2ZFKUmyBJj+ID54D1xA7wJI+oHCdiqhtp3m2OrEu0AKWhhgy8R3Dns7UF7A== +"@solana/wallet-adapter-neko@^0.2.11": + version "0.2.11" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-neko/-/wallet-adapter-neko-0.2.11.tgz#caeaca7bdd86790e51196968bb14f34c56e20a1c" + integrity sha512-r9koZ1s6t9cvcg0PxZnyG3arh4gQdTjm2nOMiZK1cJKpVpve/p/xMnfrl6xb6FM2KMVDx4qhrkigqSUMplIf7g== dependencies: - eventemitter3 "^4.0.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-base@^0.9.3", "@solana/wallet-adapter-base@^0.9.4", "@solana/wallet-adapter-base@^0.9.5": - version "0.9.5" - resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.5.tgz#6780dd096d30f0e1ffc9c7869029ec37b2a2fc9e" - integrity sha512-KCrSB2s8lA38Bd+aPvHlwPEHZU1owD6LSCikjumUaR3HCcpv+V1lxgQX+tdNaDyEVTKlAYNd0uJU+yQfQlkiOA== +"@solana/wallet-adapter-nightly@^0.1.15", "@solana/wallet-adapter-nightly@^0.1.9": + version "0.1.16" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-nightly/-/wallet-adapter-nightly-0.1.16.tgz#51be8f39d8ccac609c59c96ea1f5df95d71274ca" + integrity sha512-JaPzT8R4HHUqGn/QdElx9iRW98h0NaANBt0j3CZZYWlqsdG0f8fFfy2xofILA+qnDL6NaRI9AzQ4NcQGuVZsVQ== dependencies: - "@solana/web3.js" "^1.36.0" - eventemitter3 "^4.0.0" + "@solana/wallet-adapter-base" "^0.9.23" -"@solana/wallet-adapter-base@^0.9.9": - version "0.9.9" - resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.9.tgz#110f99bc9eee18af2625fd6170264e4363e25ffd" - integrity sha512-Z0zB+36JWRytE2OzMiB2DACRyVwiUdEg2Xy1nPR0rESCTXKI8wQGTb4g6ELjmTTU7+elKqsPE+fhFsJykn76pQ== +"@solana/wallet-adapter-nufi@^0.1.16": + version "0.1.17" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-nufi/-/wallet-adapter-nufi-0.1.17.tgz#131a02453905aafdecaef12d251b0b0aaab08a44" + integrity sha512-ggTZKvYPJS3m/9hsMaGSH0F8kqumPqP0WdY7WNihWR6O4Pr401kDBdgXPXNSGorIahdPrRBzp5UrahnrlodvTQ== dependencies: - eventemitter3 "^4.0.0" + "@solana/wallet-adapter-base" "^0.9.23" -"@solana/wallet-adapter-clover@^0.4.2": - version "0.4.2" - resolved "https://registry.npmjs.org/@solana/wallet-adapter-clover/-/wallet-adapter-clover-0.4.2.tgz" - integrity sha512-HXK6xxst1Fc3+E3ZaqYHiJFCzdoeQ08CWBTb6LCagJsb2m+GEuomz7Tr59nPpME0UN7evKwgztJIhQmZhnzACg== +"@solana/wallet-adapter-onto@^0.1.6": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-onto/-/wallet-adapter-onto-0.1.6.tgz#305512820ae30ab23616df11d106680a0e41409d" + integrity sha512-/JQ1dOvvFCViHLRRUTxcmMQhgC40WF3zKkL3SoQUjWD4MFxdGC8C4J+hndSA3rwUoI23fTGDFDhZc5/Elg72xw== dependencies: - "@solana/wallet-adapter-base" "^0.9.1" - "@solana/web3.js" "^1.20.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-coin98@^0.5.2": - version "0.5.2" - resolved "https://registry.npmjs.org/@solana/wallet-adapter-coin98/-/wallet-adapter-coin98-0.5.2.tgz" - integrity sha512-WjosOpOoFf+Nm4Z0Oli4N2u/bgbZoOXS/anFcimHE+NFI3PoD02u67WLuRWz95X7ID9HzopCGH0YOtpzK5Wt8g== +"@solana/wallet-adapter-particle@^0.1.9": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-particle/-/wallet-adapter-particle-0.1.9.tgz#f3f24f216d8a1457643b9e9b251c7b2f373c19a7" + integrity sha512-S4A/D7305JQSd9SZh9C9Yhgtm4KaOCZDwoR2OVxtYJs8ZFr2p+/XO+nDpAAf68cNiqGW8ZQKRc9s/cmELd63sg== dependencies: - "@solana/wallet-adapter-base" "^0.9.1" - "@solana/web3.js" "^1.20.0" - "@types/bs58" "^4.0.1" - bs58 "^4.0.0" + "@particle-network/solana-wallet" "^0.5.6" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-exodus@^0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-exodus/-/wallet-adapter-exodus-0.1.8.tgz#62591c073a0f371427b4a3127d684460451c544d" - integrity sha512-81Tk4aBVKkhfWOTdhTkuGHJsBGkVP/x/INJZDdjo0uHRcH6x4xGBPRfbFSxg+2XFHqnpwesJ3S8PJn332S7cDA== +"@solana/wallet-adapter-phantom@0.9.22", "@solana/wallet-adapter-phantom@^0.9.16", "@solana/wallet-adapter-phantom@^0.9.22": + version "0.9.22" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-phantom/-/wallet-adapter-phantom-0.9.22.tgz#16a56c9d92129a0f4ed022db3b5b52a2a426506d" + integrity sha512-4Fkbv/LN2X23y+Fk3irndrcC7QIOOkjkRh8RFJVzmvaiXdqH71VT8h5H+6LroF7ZaFaozeQF/XzQQqpF2nOgPQ== dependencies: - "@solana/wallet-adapter-base" "^0.9.12" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-glow@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-glow/-/wallet-adapter-glow-0.1.1.tgz#4db395b2ccf73eb2d6c1d9362e26cbfd260fc19f" - integrity sha512-ZYVNtplMAbUQUAzWQ+bhPpIiUO2Jz8Pvx6Ypas+xuZJBgc0vb+iaYFGLHEdg+SE19P20QIPQE75qPRQvsMqpCQ== +"@solana/wallet-adapter-react@0.15.32": + version "0.15.32" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-react/-/wallet-adapter-react-0.15.32.tgz#3e8a949dbf183460d54fee707374f22799199c01" + integrity sha512-dnbMVQeO2WBvK13M4kiUo1TBONJpfpO1r9JA5FuXG/Zwdt4RbGT+h6HSOaplHPO6pzDVk2nT/bU8wjqI9GxTYQ== dependencies: - "@solana/wallet-adapter-base" "^0.9.3" - "@solana/web3.js" "^1.36.0" + "@solana-mobile/wallet-adapter-mobile" "^2.0.0" + "@solana/wallet-adapter-base" "^0.9.22" + "@solana/wallet-standard-wallet-adapter-react" "^1.0.1" -"@solana/wallet-adapter-mathwallet@^0.9.2": - version "0.9.2" - resolved "https://registry.npmjs.org/@solana/wallet-adapter-mathwallet/-/wallet-adapter-mathwallet-0.9.2.tgz" - integrity sha512-seCpyllK7sx38NBIevTILFKNkLxU9Ij4Ss1EO1OHbr9QOoCMQN7xnsRRvS3OemrKe/ZKhP5Shy2e81bo9xJBaw== +"@solana/wallet-adapter-safepal@^0.5.17": + version "0.5.17" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-safepal/-/wallet-adapter-safepal-0.5.17.tgz#0155dd8041a056c9f6527c73a479fd766395ec39" + integrity sha512-Hp14EZ7UvNSiTfuCrvLRY4hqT40gSmRL+z5K7XpOW+oJgIpjhRfvv2o34rKL+qX1QoJUlUN3N6pRu570oytaGQ== dependencies: - "@solana/wallet-adapter-base" "^0.9.1" - "@solana/web3.js" "^1.20.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-phantom@^0.9.2": - version "0.9.2" - resolved "https://registry.npmjs.org/@solana/wallet-adapter-phantom/-/wallet-adapter-phantom-0.9.2.tgz" - integrity sha512-ooYz+EnwjNqAnNt5OwfRJykL/GbASDCuZ0V+TBeUki8NC0d1lPJsiPR0Bgs3e192eTxzE2SnD6cGePOiSP3MEw== +"@solana/wallet-adapter-saifu@^0.1.14": + version "0.1.14" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-saifu/-/wallet-adapter-saifu-0.1.14.tgz#887e7743e6bc10aa371fd9edbe857570b8ef7c53" + integrity sha512-3T9p/IszI6J7BJ94hl2vjMytKZr4YY5vv26pBdmth6AK3Vep0Z381cC/+M/6RyJUOYxiyQKDmi9ZpMZUDraCwQ== dependencies: - "@solana/wallet-adapter-base" "^0.9.1" - "@solana/web3.js" "^1.20.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-phantom@^0.9.3": - version "0.9.3" - resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-phantom/-/wallet-adapter-phantom-0.9.3.tgz#68832deccf43af0043d70498fcd11a9006e27b46" - integrity sha512-XBDgG5BzxRolHW2OchaIccvsPeQ0PKl/Xy303x7oHS3rW+HUwjIMqaKKpmV66A6rMr1x+ytL+tp6p7t3M2oD3Q== +"@solana/wallet-adapter-salmon@^0.1.13": + version "0.1.13" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-salmon/-/wallet-adapter-salmon-0.1.13.tgz#27166a2f36b5fcfcf3059bf32b5e1f87a9aaf3e5" + integrity sha512-NZsoqiFTlmxVWvJC9XNxyEYL9Q9ODJoHRcLqRW91VwnnWaEhjKLppWd6y/HjajewbMzWFH9Yqs34/SYsGypQBw== dependencies: - "@solana/wallet-adapter-base" "^0.9.3" - "@solana/web3.js" "^1.20.0" + "@solana/wallet-adapter-base" "^0.9.22" + salmon-adapter-sdk "^1.1.1" -"@solana/wallet-adapter-slope@^0.5.2": - version "0.5.2" - resolved "https://registry.npmjs.org/@solana/wallet-adapter-slope/-/wallet-adapter-slope-0.5.2.tgz" - integrity sha512-maeZBvbQmohkwG1/7T31GoZIP9qdykrEOLF+ApA+OMbaCMyi25a1zx1CRoVm66QO488pywG+8u+GAZj9BK0bEA== +"@solana/wallet-adapter-sky@^0.1.14": + version "0.1.14" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-sky/-/wallet-adapter-sky-0.1.14.tgz#f76d2f079bf0f72a366da888231a81a41fa46182" + integrity sha512-qQmb1eXPE4W3ECIEexfd07BjXDEdvxKD00BObZXAHYhe06G9I2h083IUNe0ZULfuZq54M/Ebo937P5bUSttoKw== dependencies: - "@solana/wallet-adapter-base" "^0.9.1" - "@solana/web3.js" "^1.20.0" - "@types/bs58" "^4.0.1" - bs58 "^4.0.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-solflare@^0.6.2": - version "0.6.2" - resolved "https://registry.npmjs.org/@solana/wallet-adapter-solflare/-/wallet-adapter-solflare-0.6.2.tgz" - integrity sha512-w/Gpe07d/S2tSbmsT7DrhovoUYx0o6Rk2ZKyMY5JEBCjIYOs3O75KO72B7qS22s5Eiv8NRzqmNaKAOGIDIDyOQ== +"@solana/wallet-adapter-slope@^0.5.15", "@solana/wallet-adapter-slope@^0.5.20": + version "0.5.20" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-slope/-/wallet-adapter-slope-0.5.20.tgz#0a0dab0e4506c94de752d61946865ad835910fbd" + integrity sha512-KeC9wkptJ8qAD4vysB/lWUKmvnLdFHmaINidQzIq5xKI7ca9uXJtf6mdxdvC58nWpFehKgqUqHnFUkMlkSbcYA== dependencies: - "@solana/wallet-adapter-base" "^0.9.1" - "@solana/web3.js" "^1.20.0" + "@solana/wallet-adapter-base" "^0.9.22" + bs58 "^4.0.1" -"@solana/wallet-adapter-solflare@^0.6.6": - version "0.6.6" - resolved "https://registry.npmjs.org/@solana/wallet-adapter-solflare/-/wallet-adapter-solflare-0.6.6.tgz" - integrity sha512-4H4FbRpvUeCGQ9HevLpCc9hCtwjRL4pf7kk/4QoGdu+jLbXo1doKTiT8sY1svksNS8JWrcr0kn7SpePmiy7xhg== +"@solana/wallet-adapter-solflare@0.6.28", "@solana/wallet-adapter-solflare@^0.6.16", "@solana/wallet-adapter-solflare@^0.6.24": + version "0.6.28" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-solflare/-/wallet-adapter-solflare-0.6.28.tgz#3de42a43220cca361050ebd1755078012a5b0fe2" + integrity sha512-iiUQtuXp8p4OdruDawsm1dRRnzUCcsu+lKo8OezESskHtbmZw2Ifej0P99AbJbBAcBw7q4GPI6987Vh05Si5rw== dependencies: - "@solana/wallet-adapter-base" "^0.9.4" - "@solana/web3.js" "^1.20.0" - "@solflare-wallet/sdk" "^1.0.11" + "@solana/wallet-adapter-base" "^0.9.23" + "@solana/wallet-standard-chains" "^1.1.0" + "@solflare-wallet/metamask-sdk" "^1.0.2" + "@solflare-wallet/sdk" "^1.3.0" + "@wallet-standard/wallet" "^1.0.1" -"@solana/wallet-adapter-sollet@^0.10.3": - version "0.10.3" - resolved "https://registry.npmjs.org/@solana/wallet-adapter-sollet/-/wallet-adapter-sollet-0.10.3.tgz" - integrity sha512-2CXFWhRu+/00LV0xcuhGFQ9zinPqQ9eRKV19v8+yJEUE9MDCI8qCS92O+t44FNTbImL5cgh/2ettreDM/GkzSQ== +"@solana/wallet-adapter-sollet@0.11.16", "@solana/wallet-adapter-sollet@^0.11.11", "@solana/wallet-adapter-sollet@^0.11.16": + version "0.11.16" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-sollet/-/wallet-adapter-sollet-0.11.16.tgz#02462f27f29d17e2f869e344ab9f729d5dfa4105" + integrity sha512-QokMgSSTNbPvF78pn2Vx3xW5Ds4i2KRG6Dr6PpRvUw0t1eZ+Agh+GiQZ74Xb/pPCMDwFxhfeyebH0llJNa98/w== dependencies: "@project-serum/sol-wallet-adapter" "^0.2.6" - "@solana/wallet-adapter-base" "^0.9.1" - "@solana/web3.js" "^1.20.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-sollet@^0.11.1": - version "0.11.1" - resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-sollet/-/wallet-adapter-sollet-0.11.1.tgz#021ec1c8f402601c8898175e1fb39b504a25cb43" - integrity sha512-lRgz8+57g2piBqxYHA4HqKuHY/gDCVY5vCqEa2pColfKtIETqKRcpF1P34R4MD5mLuMjLEQP9Hjt285NIOeVjQ== +"@solana/wallet-adapter-solong@^0.9.12", "@solana/wallet-adapter-solong@^0.9.17": + version "0.9.17" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-solong/-/wallet-adapter-solong-0.9.17.tgz#ea68415688fec5e51a49ffe2d6249d60cc7487b4" + integrity sha512-Dye8MohD2FYDly2I7dqwcMEotLqjVvri+FLuTSy7qu9jEPAXlwd23+SszLajQv8eK8OkPwAIErU11naZBJj9Lg== dependencies: - "@project-serum/sol-wallet-adapter" "^0.2.6" - "@solana/wallet-adapter-base" "^0.9.4" - "@solana/web3.js" "^1.20.0" + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-spot@^0.1.14": + version "0.1.14" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-spot/-/wallet-adapter-spot-0.1.14.tgz#16f216b1e98c2a41a43bf1eee8c6ff756be6d1dc" + integrity sha512-e7X2GFHUSBwfcmIwU1VaI2OZaaXNNmbtLFykl422hn+35TQiFG8Vb/1UZAxbED8U5kQ7LQCG6n3PLinfdbtqhA== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-strike@^0.1.12": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-strike/-/wallet-adapter-strike-0.1.12.tgz#f72d987f403261f90e7039b8a37921980ba473f0" + integrity sha512-3BFGG5qQxbxGdwAjLj+j18jbDqXodua3fv1ltX8qXkBtlxu2vJjeG6Iiem0/Ab0OGHtQrE2mve6vmf4iiYkT5g== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + "@strike-protocols/solana-wallet-adapter" "^0.1.8" + +"@solana/wallet-adapter-tokenary@^0.1.11": + version "0.1.11" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-tokenary/-/wallet-adapter-tokenary-0.1.11.tgz#259ff5966d983628d30789b902795e2c63992dd9" + integrity sha512-rfb9k0wBD62Nm+fI80E/v2pWEbsytiR0K1dHrD/WWXmkHS4rDELRtxJ23wLYUx3Rbc3BGIEZWNJRH+JycD3s1w== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-solong@^0.9.2": - version "0.9.2" - resolved "https://registry.npmjs.org/@solana/wallet-adapter-solong/-/wallet-adapter-solong-0.9.2.tgz" - integrity sha512-PKTfQmmCwl7w8cRVHQmrLTEO2Vz/LN8YcrDDJhUnXF45cJ27fHriXjY6BtqoteDbOZQs4QKEccDcG5WLsY4U8w== +"@solana/wallet-adapter-tokenpocket@^0.4.18": + version "0.4.18" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-tokenpocket/-/wallet-adapter-tokenpocket-0.4.18.tgz#0f35f323f81050f40886a4728e39e4350323206a" + integrity sha512-+xxAdRYp5Bw1zp/N3Wk3gy6iCA31aKZgQo/MSCedli+lihdx1eFLA/+o5pnM8AcYwn2IwAtSloMBg8VlVn8LBQ== dependencies: - "@solana/wallet-adapter-base" "^0.9.1" - "@solana/web3.js" "^1.20.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/wallet-adapter-torus@^0.11.11": - version "0.11.11" - resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-torus/-/wallet-adapter-torus-0.11.11.tgz#74092f409df97eab964b73b8992a59a6d97f1c56" - integrity sha512-U6qt2QEkMwOVUV19jbsXlzW8a2ff/vo34SXEGekFXe8hg847u2N8GmByDRdnEyAqbQ9TZPbbiPjID7xhLZY6Wg== +"@solana/wallet-adapter-torus@0.11.27", "@solana/wallet-adapter-torus@^0.11.27": + version "0.11.27" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-torus/-/wallet-adapter-torus-0.11.27.tgz#4725187f381b69940d9d21043e4e807693a1dfc1" + integrity sha512-0Fadxkvxq1fHtpK5p/0j5YvwzckqurCwcmKVcEuX62QL5ly+EzrojOi4vwrQXQshArCXExf8y4laAgmt5yc+DQ== dependencies: - "@solana/wallet-adapter-base" "^0.9.4" - "@solana/web3.js" "^1.20.0" - "@toruslabs/solana-embed" "^0.1.5" + "@solana/wallet-adapter-base" "^0.9.22" + "@toruslabs/solana-embed" "^0.3.3" assert "^2.0.0" + crypto-browserify "^3.12.0" process "^0.11.10" stream-browserify "^3.0.0" -"@solana/web3.js@1.39.0": - version "1.39.0" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.39.0.tgz#67183c36709e33441f8c3d44b0b744e4953f0851" - integrity sha512-6Z7I7oGpnCDqcj9em3/QajBFBORuUtIFaE29KjU4z39+nLshs+9oysDgp2aPMdiEPCNF1ioNQLdBsjD4x1Pv3w== +"@solana/wallet-adapter-trust@^0.1.12": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-trust/-/wallet-adapter-trust-0.1.12.tgz#e5aceed172951ccbdd7cc8ae1da758c053d50ef8" + integrity sha512-asFldlDEkmXiSihlccMjJvQsyXthr3Lcq5ExhSWlPu+q4acoXaYM4AL5kQOxLhJ74NrsTSSM1LVCwne0CQ4uew== dependencies: - "@babel/runtime" "^7.12.5" - "@ethersproject/sha2" "^5.5.0" - "@solana/buffer-layout" "^4.0.0" - bn.js "^5.0.0" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.1" - cross-fetch "^3.1.4" - jayson "^3.4.4" - js-sha3 "^0.8.0" - rpc-websockets "^7.4.2" - secp256k1 "^4.0.2" - superstruct "^0.14.2" - tweetnacl "^1.0.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/web3.js@^1.12.0", "@solana/web3.js@^1.17.0", "@solana/web3.js@^1.20.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.22.0", "@solana/web3.js@^1.29.2", "@solana/web3.js@^1.30.2", "@solana/web3.js@^1.31.0", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.37.1": - version "1.41.0" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.41.0.tgz#f83af98d4ead2b45aa064036d8bdb006a83d1bae" - integrity sha512-m8NDOorYficxn/SbPTCJH1Rwnv/bBIkSr1HABzdSSshRjf92ndrilMCNp61egNGMyd+hAjKfNJkHM5bKvPu5iA== +"@solana/wallet-adapter-unsafe-burner@^0.1.6": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-unsafe-burner/-/wallet-adapter-unsafe-burner-0.1.6.tgz#70f2e9328ceea26cd6d640e1a41ed0f5b65e2734" + integrity sha512-uDPsYkrDbPFuLZpMPiaDk3OjiimMby+TywRoGrNMs80Ij/mPQIN9mJRFaI1pNumzav3LF1bPGjzJ/LVDB814qQ== + dependencies: + "@solana/wallet-adapter-base" "^0.9.22" + +"@solana/wallet-adapter-walletconnect@0.1.16", "@solana/wallet-adapter-walletconnect@^0.1.14", "@solana/wallet-adapter-walletconnect@^0.1.6": + version "0.1.16" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-walletconnect/-/wallet-adapter-walletconnect-0.1.16.tgz#c335970ddec1247e546a4811fceb4f5edf9487de" + integrity sha512-jNaQwSho8hT7gF1ifePE8TJc1FULx8jCF16KX3fZPtzXDxKrj0R4VUpHMGcw4MlDknrnZNLOJAVvyiawAkPCRQ== + dependencies: + "@jnwng/walletconnect-solana" "^0.2.0" + "@solana/wallet-adapter-base" "^0.9.23" + +"@solana/wallet-adapter-wallets@0.19.16": + version "0.19.16" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-wallets/-/wallet-adapter-wallets-0.19.16.tgz#07bf9db5378c3f338b22aa6aae1774c5fd38d67e" + integrity sha512-Q+6Tv+oIkD+fhsUuPp+jLb+dyoB3hrX7XT+Xr5vMZvxQuB5bcUn7m0ZWGoAh0dw1FsfsOXMTGu1aNwS3XSqxtw== + dependencies: + "@solana/wallet-adapter-alpha" "^0.1.9" + "@solana/wallet-adapter-avana" "^0.1.12" + "@solana/wallet-adapter-backpack" "^0.1.13" + "@solana/wallet-adapter-bitkeep" "^0.3.18" + "@solana/wallet-adapter-bitpie" "^0.5.17" + "@solana/wallet-adapter-blocto" "^0.5.21" + "@solana/wallet-adapter-brave" "^0.1.16" + "@solana/wallet-adapter-censo" "^0.1.3" + "@solana/wallet-adapter-clover" "^0.4.18" + "@solana/wallet-adapter-coin98" "^0.5.19" + "@solana/wallet-adapter-coinbase" "^0.1.17" + "@solana/wallet-adapter-coinhub" "^0.3.17" + "@solana/wallet-adapter-exodus" "^0.1.17" + "@solana/wallet-adapter-fractal" "^0.1.7" + "@solana/wallet-adapter-glow" "^0.1.17" + "@solana/wallet-adapter-huobi" "^0.1.14" + "@solana/wallet-adapter-hyperpay" "^0.1.13" + "@solana/wallet-adapter-keystone" "^0.1.11" + "@solana/wallet-adapter-krystal" "^0.1.11" + "@solana/wallet-adapter-ledger" "^0.9.24" + "@solana/wallet-adapter-magiceden" "^0.1.12" + "@solana/wallet-adapter-mathwallet" "^0.9.17" + "@solana/wallet-adapter-neko" "^0.2.11" + "@solana/wallet-adapter-nightly" "^0.1.15" + "@solana/wallet-adapter-nufi" "^0.1.16" + "@solana/wallet-adapter-onto" "^0.1.6" + "@solana/wallet-adapter-particle" "^0.1.9" + "@solana/wallet-adapter-phantom" "^0.9.22" + "@solana/wallet-adapter-safepal" "^0.5.17" + "@solana/wallet-adapter-saifu" "^0.1.14" + "@solana/wallet-adapter-salmon" "^0.1.13" + "@solana/wallet-adapter-sky" "^0.1.14" + "@solana/wallet-adapter-slope" "^0.5.20" + "@solana/wallet-adapter-solflare" "^0.6.24" + "@solana/wallet-adapter-sollet" "^0.11.16" + "@solana/wallet-adapter-solong" "^0.9.17" + "@solana/wallet-adapter-spot" "^0.1.14" + "@solana/wallet-adapter-strike" "^0.1.12" + "@solana/wallet-adapter-tokenary" "^0.1.11" + "@solana/wallet-adapter-tokenpocket" "^0.4.18" + "@solana/wallet-adapter-torus" "^0.11.27" + "@solana/wallet-adapter-trust" "^0.1.12" + "@solana/wallet-adapter-unsafe-burner" "^0.1.6" + "@solana/wallet-adapter-walletconnect" "^0.1.14" + "@solana/wallet-adapter-xdefi" "^0.1.6" + +"@solana/wallet-adapter-xdefi@^0.1.6": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-xdefi/-/wallet-adapter-xdefi-0.1.6.tgz#8e94c360c2d53084573375fcaaefb745d8192f3f" + integrity sha512-Fj1LLsqmxqPU8/DwOMzdl4HVi7sM8xgkzS1+iNaB1McNXf1HjJ0iQr6BWmkm/7aBdNFo4GrVYa1nYz1NIp/3+Q== dependencies: - "@babel/runtime" "^7.12.5" - "@ethersproject/sha2" "^5.5.0" - "@solana/buffer-layout" "^4.0.0" - bn.js "^5.0.0" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.1" - cross-fetch "^3.1.4" - jayson "^3.4.4" - js-sha3 "^0.8.0" - rpc-websockets "^7.4.2" - secp256k1 "^4.0.2" - superstruct "^0.14.2" - tweetnacl "^1.0.0" + "@solana/wallet-adapter-base" "^0.9.22" -"@solana/web3.js@^1.15.0", "@solana/web3.js@^1.37.0", "@solana/web3.js@^1.48.0": - version "1.55.0" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.55.0.tgz#9d7ceb7f71a7316b1e5dbd4434ef82f6537de5d9" - integrity sha512-hXEc5CtA/5tZMvwEy0Cv6iynBpWoSLk6ud2PmoiGfWrZXZqkrfgTPkgd4yBw+VNZJRBRMKVbs/P7kT1sBwZUrw== +"@solana/wallet-standard-chains@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-chains/-/wallet-standard-chains-1.1.0.tgz#459b297e71b0d9c1196c11a0578b38c85998be7d" + integrity sha512-IRJHf94UZM8AaRRmY18d34xCJiVPJej1XVwXiTjihHnmwD0cxdQbc/CKjrawyqFyQAKJx7raE5g9mnJsAdspTg== dependencies: - "@babel/runtime" "^7.12.5" - "@noble/ed25519" "^1.7.0" - "@noble/hashes" "^1.1.2" - "@noble/secp256k1" "^1.6.3" - "@solana/buffer-layout" "^4.0.0" - bigint-buffer "^1.1.5" - bn.js "^5.0.0" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.1" - fast-stable-stringify "^1.0.0" - jayson "^3.4.4" - js-sha3 "^0.8.0" - node-fetch "2" - rpc-websockets "^7.5.0" - superstruct "^0.14.2" + "@wallet-standard/base" "^1.0.1" -"@solana/web3.js@^1.16.1": - version "1.44.2" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.44.2.tgz#5303efd94a7f2d6054a1483a4b4db4a26eb2a392" - integrity sha512-DvrJMoKonLuaX0/KyyJXcP/+w+9q8mve4gN3hC2Ptg51K/Gi1/cx6oQN2lbRZb4wYPBd2s2GDAJAJUAwZGsEug== +"@solana/wallet-standard-core@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-core/-/wallet-standard-core-1.1.1.tgz#7187c085dcee38719902217a7ecdd1bf3f27afa3" + integrity sha512-DoQ5Ryly4GAZtxRUmW2rIWrgNvTYVCWrFCFFjZI5s4zu2QNsP7sHZUax3kc1GbmFLXNL1FWRZlPOXRs6e0ZEng== dependencies: - "@babel/runtime" "^7.12.5" - "@ethersproject/sha2" "^5.5.0" - "@solana/buffer-layout" "^4.0.0" - bigint-buffer "^1.1.5" - bn.js "^5.0.0" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.1" - fast-stable-stringify "^1.0.0" - jayson "^3.4.4" - js-sha3 "^0.8.0" - node-fetch "2" - rpc-websockets "^7.4.2" - secp256k1 "^4.0.2" - superstruct "^0.14.2" - tweetnacl "^1.0.0" + "@solana/wallet-standard-chains" "^1.1.0" + "@solana/wallet-standard-features" "^1.2.0" + "@solana/wallet-standard-util" "^1.1.1" -"@solana/web3.js@^1.32.0": - version "1.41.4" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.41.4.tgz#595aa29a4a61c181b8c8f5cf0bbef80b4739cfab" - integrity sha512-2/mjqUcGsBkLEvKxA+rWFE1vODBycAMa62r3wm3Uzb6nmsXQQNTotB+6YoeLQmF0mxVoy8ZA+/QENzBkGkPzSg== +"@solana/wallet-standard-features@^1.0.1", "@solana/wallet-standard-features@^1.1.0", "@solana/wallet-standard-features@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-features/-/wallet-standard-features-1.2.0.tgz#be8b3824abf5ebcfeaa7298445bf53f76a27c935" + integrity sha512-tUd9srDLkRpe1BYg7we+c4UhRQkq+XQWswsr/L1xfGmoRDF47BPSXf4zE7ZU2GRBGvxtGt7lwJVAufQyQYhxTQ== dependencies: - "@babel/runtime" "^7.12.5" - "@ethersproject/sha2" "^5.5.0" - "@solana/buffer-layout" "^4.0.0" - "@solana/buffer-layout-utils" "^0.2.0" - bn.js "^5.0.0" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.1" - cross-fetch "^3.1.4" - fast-stable-stringify "^1.0.0" - jayson "^3.4.4" - js-sha3 "^0.8.0" - rpc-websockets "^7.4.2" - secp256k1 "^4.0.2" - sinon-chai "^3.7.0" - superstruct "^0.14.2" - tweetnacl "^1.0.0" + "@wallet-standard/base" "^1.0.1" + "@wallet-standard/features" "^1.0.3" -"@solana/web3.js@^1.35.0": - version "1.43.5" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.43.5.tgz#ab12bb6ab3fff0a08e8c7453b4fc4cda9f66df11" - integrity sha512-/PF4Fp+2jvCt9R3hYrf+tVUZXpPXZaHcwpaY/ytgdcswy8YiYf2snug52BJTCTlxwiXJipS4JpIo7rJJO0nN6w== +"@solana/wallet-standard-util@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-util/-/wallet-standard-util-1.1.1.tgz#f645fdd8b7d3c553a3b59aa19c25c51a1badce66" + integrity sha512-dPObl4ntmfOc0VAGGyyFvrqhL8UkHXmVsgbj0K9RcznKV4KB3MgjGwzo8CTSX5El5lkb0rDeEzFqvToJXRz3dw== dependencies: - "@babel/runtime" "^7.12.5" - "@ethersproject/sha2" "^5.5.0" - "@solana/buffer-layout" "^4.0.0" - bigint-buffer "^1.1.5" - bn.js "^5.0.0" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.1" - fast-stable-stringify "^1.0.0" - jayson "^3.4.4" - js-sha3 "^0.8.0" - node-fetch "2" - rpc-websockets "^7.4.2" - secp256k1 "^4.0.2" - superstruct "^0.14.2" - tweetnacl "^1.0.0" + "@noble/curves" "^1.1.0" + "@solana/wallet-standard-chains" "^1.1.0" + "@solana/wallet-standard-features" "^1.2.0" -"@solana/web3.js@^1.35.1", "@solana/web3.js@^1.44.0", "@solana/web3.js@^1.47.3": - version "1.48.0" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.48.0.tgz#331281b2d80640431fb3b6fdc6b704ec325917aa" - integrity sha512-Gb6XvdhGjGI7CdAXLmlMIEvEYvrwqc78JOtwCsSrTqzz7Ek/BhJpZ/Cv89gxRDrWxf6kHegAfaN2FxwuYMmDZQ== +"@solana/wallet-standard-wallet-adapter-base@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-wallet-adapter-base/-/wallet-standard-wallet-adapter-base-1.1.2.tgz#f030f412cd16b06e95c6da5548a03113319d3620" + integrity sha512-DqhzYbgh3disHMgcz6Du7fmpG29BYVapNEEiL+JoVMa+bU9d4P1wfwXUNyJyRpGGNXtwhyZjIk2umWbe5ZBNaQ== + dependencies: + "@solana/wallet-adapter-base" "^0.9.23" + "@solana/wallet-standard-chains" "^1.1.0" + "@solana/wallet-standard-features" "^1.2.0" + "@solana/wallet-standard-util" "^1.1.1" + "@wallet-standard/app" "^1.0.1" + "@wallet-standard/base" "^1.0.1" + "@wallet-standard/features" "^1.0.3" + "@wallet-standard/wallet" "^1.0.1" + +"@solana/wallet-standard-wallet-adapter-react@^1.0.1", "@solana/wallet-standard-wallet-adapter-react@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-wallet-adapter-react/-/wallet-standard-wallet-adapter-react-1.1.2.tgz#a7bc71786e8f891d2dd83f7de30db4708767a56a" + integrity sha512-bN6W4QkzenyjUoUz3sC5PAed+z29icGtPh9VSmLl1ZrRO7NbFB49a8uwUUVXNxhL/ZbMsyVKhb9bNj47/p8uhQ== dependencies: - "@babel/runtime" "^7.12.5" - "@ethersproject/sha2" "^5.5.0" - "@solana/buffer-layout" "^4.0.0" - bigint-buffer "^1.1.5" - bn.js "^5.0.0" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.1" - fast-stable-stringify "^1.0.0" - jayson "^3.4.4" - js-sha3 "^0.8.0" - node-fetch "2" - react-native-url-polyfill "^1.3.0" - rpc-websockets "^7.5.0" - secp256k1 "^4.0.2" - superstruct "^0.14.2" - tweetnacl "^1.0.0" + "@solana/wallet-standard-wallet-adapter-base" "^1.1.2" + "@wallet-standard/app" "^1.0.1" + "@wallet-standard/base" "^1.0.1" -"@solana/web3.js@^1.42.0": - version "1.43.1" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.43.1.tgz#f0cfffe7feb798563440f9ca0b0e9ba099e13967" - integrity sha512-s6TRcWz3rYvxM8gg1eQmUAUJQeoXIFMG9MbSWb/uRrLU0q7Xd9Ic1PNbACp1n1O0wyCogTAyFWXXPK476aIVSg== +"@solana/wallet-standard-wallet-adapter@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-wallet-adapter/-/wallet-standard-wallet-adapter-1.1.2.tgz#a9ff9e4d5c379e4f38c03a2b69c9a221904181b6" + integrity sha512-lCwoA+vhPfmvjcmJOhSRV94wouVWTfJv1Z7eeULAe+GodCeKA/0T9/uBYgXHUxQjLHd7o8LpLYIkfm+xjA5sMA== dependencies: - "@babel/runtime" "^7.12.5" - "@ethersproject/sha2" "^5.5.0" - "@solana/buffer-layout" "^4.0.0" - bigint-buffer "^1.1.5" - bn.js "^5.0.0" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.1" - cross-fetch "^3.1.4" - fast-stable-stringify "^1.0.0" - jayson "^3.4.4" - js-sha3 "^0.8.0" - rpc-websockets "^7.4.2" - secp256k1 "^4.0.2" - superstruct "^0.14.2" - tweetnacl "^1.0.0" + "@solana/wallet-standard-wallet-adapter-base" "^1.1.2" + "@solana/wallet-standard-wallet-adapter-react" "^1.1.2" -"@solana/web3.js@^1.43.5": - version "1.44.0" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.44.0.tgz#233f7bd268520a0ce852ff7f92ded150c5fad0f5" - integrity sha512-KHf7o8sM5FlxYGHGroD7IJeCCOmjFITdBIXq4cO5xPFQ8O6Y26FWfYqIXqY1dXI29t240g0m1GYPssCp5UVgZg== +"@solana/wallet-standard@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard/-/wallet-standard-1.1.2.tgz#b68e38db863f6945979fe278f2cecc2e21f84c2d" + integrity sha512-o7wk+zr5/QgyE393cGRC04K1hacR4EkBu3MB925ddaLvCVaXjwr2asgdviGzN9PEm3FiEJp3sMmMKYHFnwOITQ== dependencies: - "@babel/runtime" "^7.12.5" - "@ethersproject/sha2" "^5.5.0" + "@solana/wallet-standard-core" "^1.1.1" + "@solana/wallet-standard-wallet-adapter" "^1.1.2" + +"@solana/web3.js@1.56.0", "@solana/web3.js@1.78.8", "@solana/web3.js@^1.17.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.22.0", "@solana/web3.js@^1.30.2", "@solana/web3.js@^1.31.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.35.1", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.43.4", "@solana/web3.js@^1.44.3", "@solana/web3.js@^1.50.1", "@solana/web3.js@^1.53.0", "@solana/web3.js@^1.54.0", "@solana/web3.js@^1.56.2", "@solana/web3.js@^1.59.1", "@solana/web3.js@^1.63.0", "@solana/web3.js@^1.63.1", "@solana/web3.js@^1.66.2", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.73.0", "@solana/web3.js@^1.73.2", "@solana/web3.js@^1.77.3", "@solana/web3.js@^1.87.5", "@solana/web3.js@^1.87.6", "@solana/web3.js@^1.89.1", "@solana/web3.js@^1.90.0", "@solana/web3.js@^1.91.8", "@solana/web3.js@^1.93.0", "@solana/web3.js@^1.95.0", "@solana/web3.js@^1.95.2", "@solana/web3.js@^1.95.3", "@solana/web3.js@~1.77.3": + version "1.78.8" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.78.8.tgz#d635bcccaac9e36270c6b16340bfeb5502737831" + integrity sha512-y6kMa0ohRjamBGtxIGX4TkdAzL8Cs2bzM4JDPCyYLFPdo7kWk0Cx+BkbhX8hEV4IfvCONF92KIniV7hDvHuq8A== + dependencies: + "@babel/runtime" "^7.22.6" + "@noble/curves" "^1.2.0" + "@noble/hashes" "^1.3.1" "@solana/buffer-layout" "^4.0.0" + agentkeepalive "^4.3.0" bigint-buffer "^1.1.5" - bn.js "^5.0.0" + bn.js "^5.2.1" borsh "^0.7.0" bs58 "^4.0.1" - buffer "6.0.1" + buffer "6.0.3" fast-stable-stringify "^1.0.0" - jayson "^3.4.4" - js-sha3 "^0.8.0" - node-fetch "2" - rpc-websockets "^7.4.2" - secp256k1 "^4.0.2" + jayson "^4.1.0" + node-fetch "^2.6.12" + rpc-websockets "^7.5.1" superstruct "^0.14.2" - tweetnacl "^1.0.0" - -"@solendprotocol/solend-sdk@^0.4.4": - version "0.4.9" - resolved "https://registry.yarnpkg.com/@solendprotocol/solend-sdk/-/solend-sdk-0.4.9.tgz#c0e3f24148c4951bf0cfdf16c884bc4ffbb42b7b" - integrity sha512-tVsvE0kap58/eMeeSonv0tEiqlnvYC0x90MXKoGz2D0oyQBx9Eneba5wXDh9FJ3S5S2RFqwXIAnmdOzTLZzV/A== - dependencies: - "@pythnetwork/client" "^2.5.1" - "@solana/buffer-layout" "^3.0.0" - "@solana/spl-token" "^0.1.8" - "@solana/web3.js" "^1.31.0" - axios "^0.24.0" - bignumber.js "^9.0.2" - bn.js "^5.2.0" - buffer "^6.0.3" - buffer-layout "^1.2.0" - isomorphic-fetch "^3.0.0" -"@solendprotocol/solend-sdk@^0.5.5": +"@solendprotocol/solend-sdk@0.5.5": version "0.5.5" resolved "https://registry.yarnpkg.com/@solendprotocol/solend-sdk/-/solend-sdk-0.5.5.tgz#a8077532e1ca2ecd7d619fee4f339cd6b33e4a04" integrity sha512-7eZSM/vl7Bijbg3n/vnO4z5p3VX7eb453pKkVeiT6FmQuC403GrNU3wUz3TVJZlzhsg76X81udK2qZaOKaWrZQ== @@ -5121,15 +5382,64 @@ buffer-layout "^1.2.0" isomorphic-fetch "^3.0.0" -"@solflare-wallet/sdk@^1.0.11": - version "1.0.11" - resolved "https://registry.npmjs.org/@solflare-wallet/sdk/-/sdk-1.0.11.tgz" - integrity sha512-zm+snfxpxfEvPytz0CdPn+LSMLrtYIl8qDjC2jhey4hWTkkZmumgKMKfNb9w6cpHtGgWiQkxSP2KI48xuKmuxw== +"@solflare-wallet/metamask-sdk@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@solflare-wallet/metamask-sdk/-/metamask-sdk-1.0.3.tgz#3baaa22de2c86515e6ba6025285cd1f5d74b04e5" + integrity sha512-os5Px5PTMYKGS5tzOoyjDxtOtj0jZKnbI1Uwt8+Jsw1HHIA+Ib2UACCGNhQ/un2f8sIbTfLD1WuucNMOy8KZpQ== dependencies: - "@project-serum/sol-wallet-adapter" "0.2.0" - bs58 "^4.0.1" - eventemitter3 "^4.0.7" - uuid "^8.3.2" + "@solana/wallet-standard-features" "^1.1.0" + "@wallet-standard/base" "^1.0.1" + bs58 "^5.0.0" + eventemitter3 "^5.0.1" + uuid "^9.0.0" + +"@solflare-wallet/sdk@^1.3.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@solflare-wallet/sdk/-/sdk-1.4.2.tgz#630b9a26f7bca255ee4a7088f287ae8c8335e345" + integrity sha512-jrseNWipwl9xXZgrzwZF3hhL0eIVxuEtoZOSLmuPuef7FgHjstuTtNJAeT4icA7pzdDV4hZvu54pI2r2f7SmrQ== + dependencies: + bs58 "^5.0.0" + eventemitter3 "^5.0.1" + uuid "^9.0.0" + +"@solworks/soltoolkit-sdk@^0.0.23": + version "0.0.23" + resolved "https://registry.yarnpkg.com/@solworks/soltoolkit-sdk/-/soltoolkit-sdk-0.0.23.tgz#ef32d0aa79f888bcf0f639d280005b2e97cdc624" + integrity sha512-O6lXT3EBR4gmcjt0/33i97VMHVEImwXGi+4TNrDDdifn3tyOUB7V6PR1VGxlavQb9hqmVai3xhedg/rmbQzX7w== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/spl-token" "^0.3.4" + "@solana/web3.js" "^1.54.0" + "@types/bn.js" "^5.1.0" + "@types/node" "^18.7.13" + "@types/node-fetch" "^2.6.2" + bn.js "^5.2.1" + decimal.js "^10.4.0" + typescript "^4.8.2" + +"@soncodi/signal@~2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@soncodi/signal/-/signal-2.0.7.tgz#0a2c361b02dbfdbcf4e66b78e5f711e0a13d6e83" + integrity sha512-zA2oZluZmVvgZEDjF243KWD1S2J+1SH1MVynI0O1KRgDt1lU8nqk7AK3oQfW/WpwT51L5waGSU0xKF/9BTP5Cw== + +"@sqds/iframe-adapter@1.0.16": + version "1.0.16" + resolved "https://registry.yarnpkg.com/@sqds/iframe-adapter/-/iframe-adapter-1.0.16.tgz#2439045b2eff89237bc194a45198288adf4297db" + integrity sha512-Qt210kDzA9N4hWWl2sXennoP6eyCb87hWAA7+wawDqP9phcgRuFZEfEh/ebrhBg05cEOMY/cWxUHCF7A8LOAEw== + dependencies: + "@solana/wallet-adapter-base" "^0.9.21" + "@solana/web3.js" "^1.73.2" + bs58 "^5.0.0" + encoding "^0.1.13" + +"@sqds/mesh@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@sqds/mesh/-/mesh-1.0.6.tgz#b3538a04b3232645d61db3ac7377511b5e742e63" + integrity sha512-z+x1GjixJm8K3uPwaDebTsssU3B71zJzRCkywmtz2ZZoMvoz9w/C4nY+v7v6Wg/9OTbfSDgcX/Hoo/FlphkWvg== + dependencies: + "@project-serum/anchor" "^0.25.0" + "@solana/web3.js" "^1.53.0" + bn.js "^5.2.1" "@stablelib/aead@^1.0.1": version "1.0.1" @@ -5153,7 +5463,7 @@ resolved "https://registry.yarnpkg.com/@stablelib/bytes/-/bytes-1.0.1.tgz#0f4aa7b03df3080b878c7dea927d01f42d6a20d8" integrity sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ== -"@stablelib/chacha20poly1305@^1.0.1": +"@stablelib/chacha20poly1305@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz#de6b18e283a9cb9b7530d8767f99cde1fec4c2ee" integrity sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA== @@ -5192,6 +5502,24 @@ resolved "https://registry.yarnpkg.com/@stablelib/hash/-/hash-1.0.1.tgz#3c944403ff2239fad8ebb9015e33e98444058bc5" integrity sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg== +"@stablelib/hkdf@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/hkdf/-/hkdf-1.0.1.tgz#b4efd47fd56fb43c6a13e8775a54b354f028d98d" + integrity sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g== + dependencies: + "@stablelib/hash" "^1.0.1" + "@stablelib/hmac" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/hmac@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/hmac/-/hmac-1.0.1.tgz#3d4c1b8cf194cb05d28155f0eed8a299620a07ec" + integrity sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA== + dependencies: + "@stablelib/constant-time" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + "@stablelib/int@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008" @@ -5220,7 +5548,7 @@ "@stablelib/binary" "^1.0.1" "@stablelib/wipe" "^1.0.1" -"@stablelib/sha256@^1.0.1": +"@stablelib/sha256@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/sha256/-/sha256-1.0.1.tgz#77b6675b67f9b0ea081d2e31bda4866297a3ae4f" integrity sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ== @@ -5238,17 +5566,12 @@ "@stablelib/hash" "^1.0.1" "@stablelib/wipe" "^1.0.1" -"@stablelib/utf8@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/utf8/-/utf8-1.0.1.tgz#fd5e7ad353b7e3cd1ce85e49099360e57693cfd1" - integrity sha512-FrYD1xadah/TtAP6VJ04lDD5h9rdDj/d8wH/jMYTtHqZBv9z2btdvEU8vTxdjdkFmo1b/BH+t3R1wi/mYhCCNg== - "@stablelib/wipe@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36" integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg== -"@stablelib/x25519@^1.0.2": +"@stablelib/x25519@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@stablelib/x25519/-/x25519-1.0.3.tgz#13c8174f774ea9f3e5e42213cbf9fc68a3c7b7fd" integrity sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw== @@ -5257,130 +5580,147 @@ "@stablelib/random" "^1.0.2" "@stablelib/wipe" "^1.0.1" -"@stablelib/xchacha20@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/xchacha20/-/xchacha20-1.0.1.tgz#e98808d1f7d8b20e3ff37c71a3062a2a955d9a8c" - integrity sha512-1YkiZnFF4veUwBVhDnDYwo6EHeKzQK4FnLiO7ezCl/zu64uG0bCCAUROJaBkaLH+5BEsO3W7BTXTguMbSLlWSw== - dependencies: - "@stablelib/binary" "^1.0.1" - "@stablelib/chacha" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/xchacha20poly1305@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/xchacha20poly1305/-/xchacha20poly1305-1.0.1.tgz#addcaf30b92dd956f76b3357888e2f91b92e7a61" - integrity sha512-B1Abj0sMJ8h3HNmGnJ7vHBrAvxuNka6cJJoZ1ILN7iuacXp7sUYcgOVEOTLWj+rtQMpspY9tXSCRLPmN1mQNWg== - dependencies: - "@stablelib/aead" "^1.0.1" - "@stablelib/chacha20poly1305" "^1.0.1" - "@stablelib/constant-time" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - "@stablelib/xchacha20" "^1.0.1" - -"@streamflow/stream@3.0.10": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@streamflow/stream/-/stream-3.0.10.tgz#1fb67784079b2b65bf67105a1cb6a9058de728bd" - integrity sha512-6ahU0znOLhXOsh3l7pTEIYGgeNJ+IfbYWljugch8rh+QPd4f7SetZ5zh3aOK6nY4BL04VEH7kdhbpXJcCGugvg== +"@strike-protocols/solana-wallet-adapter@^0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@strike-protocols/solana-wallet-adapter/-/solana-wallet-adapter-0.1.8.tgz#19cef6f1f7a81dfa838b990f48929c4f63b91218" + integrity sha512-8gZAfjkoFgwf5fLFzrVuE2MtxAc7Pc0loBgi0zfcb3ijOy/FEpm5RJKLruKOhcThS6CHrfFxDU80AsZe+msObw== dependencies: - "@project-serum/anchor" "^0.16.2" - "@project-serum/common" "^0.0.1-beta.3" - "@solana/spl-token" "^0.1.8" - "@solana/wallet-adapter-base" "^0.9.2" - "@solana/web3.js" "^1.42.0" - bn.js "^5.2.0" - buffer-layout "^1.2.1" + "@solana/web3.js" "^1.44.3" + bs58 "^4.0.1" + eventemitter3 "^4.0.7" + uuid "^8.3.2" "@supercharge/promise-pool@^2.1.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@supercharge/promise-pool/-/promise-pool-2.3.0.tgz#9528b11d69a63ff2a342d404afb13cd011c9651a" - integrity sha512-KLf3JBWW4JymplvT/c5JCZhc4KrNE9EBf15FPjvklQiGcoUczSLInpV23iV5dITnvktJlwQ5xq08wfNwBk71Rg== + version "2.3.2" + resolved "https://registry.yarnpkg.com/@supercharge/promise-pool/-/promise-pool-2.3.2.tgz#6366894a7e7bc699bb65e58d8c828113729cf481" + integrity sha512-f5+C7zv+QQivcUO1FH5lXi7GcuJ3CFuJF3Eg06iArhUs5ma0szCLEQwIY4+VQyh7m/RLVZdzvr4E4ZDnLe9MNg== -"@swc/helpers@0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.2.tgz#ed1f6997ffbc22396665d9ba74e2a5c0a2d782f8" - integrity sha512-556Az0VX7WR6UdoTn4htt/l3zPQ7bsQWK+HqdG4swV7beUCxo/BqmvbOpUkTIm/9ih86LIf1qsUnywNL3obGHw== +"@swc/helpers@0.4.11": + version "0.4.11" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.11.tgz#db23a376761b3d31c26502122f349a21b592c8de" + integrity sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw== dependencies: tslib "^2.4.0" -"@switchboard-xyz/switchboard-api@^0.2.150", "@switchboard-xyz/switchboard-api@^0.2.61": - version "0.2.179" - resolved "https://registry.npmjs.org/@switchboard-xyz/switchboard-api/-/switchboard-api-0.2.179.tgz" - integrity sha512-8YW+9+qaNlEwdTPwu03nNR9XnmO9ODrg9HG6JeDdmu2f/89IIXd4vte2MI29Ij+8C1GZ+4QARP3O3qIdbGk39w== +"@switchboard-xyz/common@^2.3.16", "@switchboard-xyz/common@^2.4.4", "@switchboard-xyz/common@^2.4.7": + version "2.4.7" + resolved "https://registry.yarnpkg.com/@switchboard-xyz/common/-/common-2.4.7.tgz#7b582e7cdd4c17a3d4e36beead520a5363f4f0a8" + integrity sha512-gkUuy7n15gq+D0IKkqKsSqgWb1w5t3rfpjdTkJX0AAlL75QXZfi5fL4Ttwb22ALOWYLYuvYCD0uXFyczgMMkIQ== dependencies: - "@solana/web3.js" "^1.17.0" - "@switchboard-xyz/switchboard-api" "^0.2.61" - form-data "^4.0.0" - protobufjs "^6.10.2" - rpc-websockets "^7.4.12" - typedoc "^0.20.36" - ws "^7.4.6" + "@solana/web3.js" "^1.93.0" + axios "^1.7.2" + big.js "^6.2.1" + bn.js "^5.2.1" + bs58 "^5.0.0" + cron-validator "^1.3.1" + decimal.js "^10.4.3" + js-sha256 "^0.11.0" + lodash "^4.17.21" + protobufjs "^7.2.6" + yaml "^2.5.0" + +"@switchboard-xyz/on-demand@^1.2.38": + version "1.2.38" + resolved "https://registry.yarnpkg.com/@switchboard-xyz/on-demand/-/on-demand-1.2.38.tgz#de368176a89b05c365d916c5cb419e1cf918acf3" + integrity sha512-BaZc78dDbmofJmk60SD0dDsf953rnQ9MaTeUrFyn8Z0zRiu79hTJMeKisKbC/pOCG7EMpZZRF/sqXujRfG6QFw== + dependencies: + "@brokerloop/ttlcache" "^3.2.3" + "@coral-xyz/anchor-30" "npm:@coral-xyz/anchor@0.30.1" + "@solana/web3.js" "^1.95.0" + "@solworks/soltoolkit-sdk" "^0.0.23" + "@switchboard-xyz/common" "^2.4.7" + axios "^1.7.4" + big.js "^6.2.1" + bs58 "^5.0.0" + js-yaml "^4.1.0" + protobufjs "^7.2.6" -"@switchboard-xyz/switchboard-v2@^0.0.110": - version "0.0.110" - resolved "https://registry.yarnpkg.com/@switchboard-xyz/switchboard-v2/-/switchboard-v2-0.0.110.tgz#b01b74fa368d33659f0b2b7b232eee7f8193dc53" - integrity sha512-T5bgO/SA66fwQbAYBFqP5KOhiQ4JUQG06XUMhxtLgyWQ0qYrpjC1EINyaq0TZzEB6r6cjZufvYBTFA3zhPKydg== +"@switchboard-xyz/sbv2-lite@0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@switchboard-xyz/sbv2-lite/-/sbv2-lite-0.2.4.tgz#fb8e189124d89fbffa5060a8009f8e0886cc7368" + integrity sha512-rJNwMalZ26D4bxtrxneZ6gBIwwtQ0KiSy8jY4c81KPEad/USMyl0iGPyhKKOr6dNRDKy5BgOslnU8xnZF+rnuQ== dependencies: - "@project-serum/anchor" "^0.24.2" - "@solana/spl-governance" "^0.0.34" - assert "^2.0.0" + "@coral-xyz/anchor" "^0.28.0" big.js "^6.1.1" - bs58 "^4.0.1" - chan "^0.6.1" - crypto-js "^4.0.0" - long "^4.0.0" - mocha "^9.1.1" - node-fetch "^3.2.3" - protobufjs "^6.11.3" - -"@switchboard-xyz/switchboard-v2@^0.0.34": - version "0.0.34" - resolved "https://registry.npmjs.org/@switchboard-xyz/switchboard-v2/-/switchboard-v2-0.0.34.tgz" - integrity sha512-7yFWF2A/S4EwP3SEDQGS3HXptDlLLVctCDmDtxDpWL4mlU6RuK/4kntGyGs+s65uIaKpqvJtA1IUow1nX7yE6A== - dependencies: - "@project-serum/anchor" "^0.18.0" - "@project-serum/anchor-cli" "^0.18.2" - "@solana/spl-token" "^0.1.8" - "@solana/web3.js" "^1.29.2" - "@switchboard-xyz/switchboard-api" "^0.2.150" - assert "^2.0.0" + +"@switchboard-xyz/sbv2-lite@^0.1.6": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@switchboard-xyz/sbv2-lite/-/sbv2-lite-0.1.6.tgz#dc3fbb5b3b028dbd3c688b991bcc48a670131ddb" + integrity sha512-yNNBBPpqefrf6QaUw7pKj1MYOtITaH5lqpGKdSMOqzGmtTOCBPI9P9Hz/ZfQEzbuRIUws1aNEazxYzitBo1q7Q== + dependencies: + "@project-serum/anchor" "^0.24.2" big.js "^6.1.1" - bs58 "^4.0.1" - buffer-layout "^1.2.0" - chan "^0.6.1" - crypto-js "^4.0.0" - dotenv "^8.6.0" - events "^3.3.0" - fs "0.0.1-security" - i "^0.3.7" - long "^4.0.0" - microseconds "^0.2.0" - mz "^2.7.0" - node-fetch "^2.6.1" - npm "^7.24.1" - prompt-sync "^4.1.6" - protobufjs "^6.10.2" - readline-sync "^1.4.10" - resolve-dir "^1.0.1" - set-interval-async "1.0.34" - ts-proto "^1.79.0" - typescript "^4.2.4" - wait-for-event "^2.0.1" - ws "^7.4.6" + +"@switchboard-xyz/solana.js@3.2.5", "@switchboard-xyz/solana.js@^3.2.5": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@switchboard-xyz/solana.js/-/solana.js-3.2.5.tgz#c4bd3218d0b3b6bfae19215990a21cc0d5a97efa" + integrity sha512-gCovHDTHCr+JPSwB5+JXqoKPwLs4GKM0sqUEEcQHJZXLpIAzE3Q0RDQOS76rgnpNR0sDYzv8a9aneab8GTG4Ag== + dependencies: + "@coral-xyz/anchor" "^0.29.0" + "@coral-xyz/borsh" "^0.29.0" + "@solana/spl-token" "^0.3.11" + "@solana/web3.js" "^1.89.1" + "@switchboard-xyz/common" "^2.3.16" + cron-validator "^1.3.1" + cross-fetch "^4.0.0" + dotenv "^16.3.1" + lodash "^4.17.21" + zod "^3.22.2" + zod-error "^1.5.0" + +"@symmetry-hq/baskets-sdk@0.0.45": + version "0.0.45" + resolved "https://registry.yarnpkg.com/@symmetry-hq/baskets-sdk/-/baskets-sdk-0.0.45.tgz#19d1c96bb0f659eccd7969aad3513bc4a7006a6b" + integrity sha512-w5w3yZl+qTwEAL8b21XGesuLX3HPpaQYyYkkRbwQBheqCJ8Geyg7/NyuZRF+8/a0XdubiQfW70QzBHZch6J0nA== + dependencies: + "@coral-xyz/anchor" "0.29.0" + "@metaplex-foundation/js" "0.19.4" + "@pythnetwork/client" "2.17.0" + "@solana/web3.js" "1.78.8" + "@types/crypto-js" "4.1.1" + axios "0.26.1" + crypto-js "4.1.1" + +"@tailwindcss/forms@0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.5.3.tgz#e4d7989686cbcaf416c53f1523df5225332a86e7" + integrity sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q== + dependencies: + mini-svg-data-uri "^1.2.3" + +"@tailwindcss/line-clamp@0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz#f353c5a8ab2c939c6267ac5b907f012e5ee130f9" + integrity sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw== + +"@tanstack/query-core@4.14.3": + version "4.14.3" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.14.3.tgz#9ab6763b61d5e491816483f3aeed771c1fbd657b" + integrity sha512-1OrxZk5jSKAjTIDgH/OHa6GfVpgGDVbCVf3KHQjXLFdutK4PSSXQIyX7I1HvBR3mYKyvFPo6yXKNG7QrkwUj9g== + +"@tanstack/react-query@4.14.3": + version "4.14.3" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.14.3.tgz#3bafea000480463de35721c742265730e2973550" + integrity sha512-PP7DEFsOMl/JaGQr1B4IeGN3lqHrC5EpG+AgG03OlVIOQMtXNhb0N66Nt1pdrladvzYsKD20L3O3550rBzgLtg== + dependencies: + "@tanstack/query-core" "4.14.3" + use-sync-external-store "^1.2.0" "@testing-library/dom@^7.28.1": - version "7.30.4" - resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-7.30.4.tgz" + version "7.31.2" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.31.2.tgz#df361db38f5212b88555068ab8119f5d841a8c4a" + integrity sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ== dependencies: "@babel/code-frame" "^7.10.4" "@babel/runtime" "^7.12.5" "@types/aria-query" "^4.2.0" aria-query "^4.2.2" chalk "^4.1.0" - dom-accessibility-api "^0.5.4" + dom-accessibility-api "^0.5.6" lz-string "^1.4.4" pretty-format "^26.6.2" -"@testing-library/jest-dom@^5.16.4": +"@testing-library/jest-dom@5.16.4": version "5.16.4" resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.4.tgz#938302d7b8b483963a3ae821f1c0808f872245cd" integrity sha512-Gy+IoFutbMQcky0k+bqqumXZ1cTGswLsFqmNLzNdSKkU9KGV2u9oXhukCbbJ9/LRPKiqwxEE8VpV/+YZlfkPUA== @@ -5395,59 +5735,56 @@ lodash "^4.17.15" redent "^3.0.0" -"@testing-library/react@^11.2.5": - version "11.2.6" - resolved "https://registry.npmjs.org/@testing-library/react/-/react-11.2.6.tgz" +"@testing-library/react@11.2.5": + version "11.2.5" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.5.tgz#ae1c36a66c7790ddb6662c416c27863d87818eb9" + integrity sha512-yEx7oIa/UWLe2F2dqK0FtMF9sJWNXD+2PPtp39BvE0Kh9MJ9Kl0HrZAgEuhUJR+Lx8Di6Xz+rKwSdEPY2UV8ZQ== dependencies: "@babel/runtime" "^7.12.5" "@testing-library/dom" "^7.28.1" -"@tippyjs/react@^4.2.6": +"@tippyjs/react@4.2.6", "@tippyjs/react@^4.2.6": version "4.2.6" resolved "https://registry.yarnpkg.com/@tippyjs/react/-/react-4.2.6.tgz#971677a599bf663f20bb1c60a62b9555b749cc71" integrity sha512-91RicDR+H7oDSyPycI13q3b7o4O60wa2oRbjlz2fyRLmHImc4vyDwuUP8NtZaN0VARJY5hybvDYrFzhY9+Lbyw== dependencies: tippy.js "^6.3.1" -"@tootallnate/once@1": - version "1.1.2" - resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz" - integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== - -"@toruslabs/base-controllers@^1.6.1": - version "1.6.18" - resolved "https://registry.yarnpkg.com/@toruslabs/base-controllers/-/base-controllers-1.6.18.tgz#a45737e062bb530504df22e4836088da0d57fd26" - integrity sha512-C/NGlVeB9x3H5c/+tX4ZTnFYpDzb9Sz+G/061s24Rubr+MRsjncaG7zN8C1y48D83JUvUkSJX9MAFt3m7aTFFA== - dependencies: - "@toruslabs/broadcast-channel" "^4.13.0" - "@toruslabs/http-helpers" "^2.2.0" - "@toruslabs/openlogin-jrpc" "^1.7.3" - async-mutex "^0.3.2" - bignumber.js "^9.0.2" +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@toruslabs/base-controllers@^2.2.6": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@toruslabs/base-controllers/-/base-controllers-2.5.0.tgz#b0f93281f1be7b88f161c41d8d8a020071f4afde" + integrity sha512-NL4l/Tu8Zk8wgW+2iEpmUwwg9tuZixTGKoC/hU6rki7cIVC7KUHjEcY8BQUxL5Zj+YM70EBAy+zHeFAMUt7GDg== + dependencies: + "@toruslabs/broadcast-channel" "^6.1.1" + "@toruslabs/http-helpers" "^3.2.0" + "@toruslabs/openlogin-jrpc" "^2.9.0" + async-mutex "^0.4.0" + bignumber.js "^9.1.1" bowser "^2.11.0" eth-rpc-errors "^4.0.3" - ethereumjs-util "^7.1.4" + ethereumjs-util "^7.1.5" json-rpc-random-id "^1.0.1" lodash "^4.17.21" - loglevel "^1.8.0" + loglevel "^1.8.1" -"@toruslabs/broadcast-channel@^4.13.0": - version "4.13.0" - resolved "https://registry.yarnpkg.com/@toruslabs/broadcast-channel/-/broadcast-channel-4.13.0.tgz#f47a3624a70f9e395d0412bcde5bf2035e7c39f0" - integrity sha512-qPpVzLtqjiLRNW5C5xnCNwzWNBcGLSx/rC8C7UTP08Z9HnTIP3JxR+NbdtjR7/AjA2VemdcLQq3n+trJf9gUKQ== +"@toruslabs/broadcast-channel@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@toruslabs/broadcast-channel/-/broadcast-channel-6.1.1.tgz#119ac53aed467f505dff7f085b2043d42d28f6f4" + integrity sha512-FapnmyPLpqfrdbfyawlReRpluEKQ2riqCNOOZQz9KHPF8a/XsgYi/UAdrR02k6BHaZYyV6D52Oji1gM6CPj6EQ== dependencies: - "@babel/runtime" "^7.17.9" + "@babel/runtime" "^7.19.4" "@toruslabs/eccrypto" "^1.1.8" - "@toruslabs/metadata-helpers" "^2.5.0" + "@toruslabs/metadata-helpers" "^3.0.0" bowser "^2.11.0" - detect-node "^2.1.0" keccak "^3.0.2" loglevel "^1.8.0" - microtime "3.0.0" oblivious-set "1.1.1" - p-queue "6.6.2" - rimraf "^3.0.2" - socket.io-client "^4.5.0" + socket.io-client "^4.5.3" unload "^2.3.1" "@toruslabs/eccrypto@^1.1.8": @@ -5462,31 +5799,31 @@ optionalDependencies: secp256k1 "^3.8.0" -"@toruslabs/http-helpers@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@toruslabs/http-helpers/-/http-helpers-2.2.0.tgz#c494984701ff60eb93c0eaef279daa93b5bcea81" - integrity sha512-xkzZZuE+DmWmJBTYneCrMJY24izNQCOdoJMpsXKQx20Va/rTQvNPbdkpx9LBf/pisk8jOwETNAfFQ8YTBc/bZw== +"@toruslabs/http-helpers@^3.0.0", "@toruslabs/http-helpers@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@toruslabs/http-helpers/-/http-helpers-3.2.0.tgz#9e33dd23936ef90852133372c831f03b7a8badc5" + integrity sha512-fCfvBHfYzd7AyOYlBo7wihh5nj6+4Ik6V5+nI7H63oiKICjMlByTXSauTUa/qm2mjZJn/OmVYeV5guPIgxoW1w== dependencies: lodash.merge "^4.6.2" loglevel "^1.8.0" -"@toruslabs/metadata-helpers@^2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@toruslabs/metadata-helpers/-/metadata-helpers-2.5.0.tgz#691bb02d663c5e489b27a641364b1d0283a59ba6" - integrity sha512-zhAAGhPcy5Fz68Zg3FXXmYKHHsFBCWsxXurSbdPMFldDrq9GwKChbAbvKBF0sz+juhEOO5gX1BbVah580YVobg== +"@toruslabs/metadata-helpers@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@toruslabs/metadata-helpers/-/metadata-helpers-3.0.0.tgz#ebc613bcd05ed7cfcf4ac1eb01e9558500a2e590" + integrity sha512-0eWCIbKpaBx3/z3BDyWebxUisCS37Uxb0zxOEWizSXjGH/T6TJCrBeZFPmANN3hq47GoNCsRiku9cgfij1UMTQ== dependencies: "@toruslabs/eccrypto" "^1.1.8" - "@toruslabs/http-helpers" "^2.2.0" + "@toruslabs/http-helpers" "^3.0.0" elliptic "^6.5.4" json-stable-stringify "^1.0.1" keccak "^3.0.2" -"@toruslabs/openlogin-jrpc@^1.4.0", "@toruslabs/openlogin-jrpc@^1.7.3": - version "1.7.3" - resolved "https://registry.yarnpkg.com/@toruslabs/openlogin-jrpc/-/openlogin-jrpc-1.7.3.tgz#0bbdc2f7989b4a1f19b8a54d3e66721d424d185f" - integrity sha512-xjixDKPLZN7T5hCjwmGTU58NttdZiHn3YlK6II2z4v8IifPUwoquYP08XfaE79ksxamgDYkGERf7bQGkV5Wf5w== +"@toruslabs/openlogin-jrpc@^2.6.0", "@toruslabs/openlogin-jrpc@^2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@toruslabs/openlogin-jrpc/-/openlogin-jrpc-2.9.0.tgz#766fb4ebe65e8dd9c1bf74adf031059ba5321cc6" + integrity sha512-68SMBSsFqayTi/uVJe1cffnz6QxYMtVLCF7h4HxlWxM27dd3030FspPrNJHFqt7o2u8/WSCB9pax9BrbTwYglw== dependencies: - "@toruslabs/openlogin-utils" "^1.7.0" + "@toruslabs/openlogin-utils" "^2.1.0" end-of-stream "^1.4.4" eth-rpc-errors "^4.0.3" events "^3.3.0" @@ -5495,69 +5832,60 @@ pump "^3.0.0" readable-stream "^3.6.0" -"@toruslabs/openlogin-utils@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@toruslabs/openlogin-utils/-/openlogin-utils-1.7.0.tgz#1762e2f1f67590d0c6cb8e4c4ade82d59ba13a18" - integrity sha512-y+j22v+h6EfzN4sfFnmtmMrcxEdkScdJOAgbtvX42BpUYOuFa1Tv0SZjdtsGGDE4g5szmL3rb9NGMHdBF1rZtg== +"@toruslabs/openlogin-utils@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@toruslabs/openlogin-utils/-/openlogin-utils-2.1.0.tgz#ae77dd4611970cbeb1222d90c3f4f37b3d94b407" + integrity sha512-UVgjco4winOn4Gj0VRTvjSZgBA84h2OIkKuxrBFjS+yWhgxQBF4hXGp83uicSgx1MujtjyUOdhJrpV2joRHt9w== dependencies: base64url "^3.0.1" keccak "^3.0.2" randombytes "^2.1.0" -"@toruslabs/solana-embed@^0.1.5": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@toruslabs/solana-embed/-/solana-embed-0.1.6.tgz#c21ba9fe485ce33975577cb909cc2a168485e6cb" - integrity sha512-+WcF97qLTyW6xJ/oDmsLRc4KUN0w8/0pPx2QstcUV0OPgV3VON9LXgRFmSLXNvBVjFzie7aOWJFORUIL6Odqhw== +"@toruslabs/solana-embed@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@toruslabs/solana-embed/-/solana-embed-0.3.3.tgz#8a04c672386163f516de182ce64e34743b21363e" + integrity sha512-Edw0p1oNNG+fk+3XIZZiIiwdi75lgtOpCjIK7G7PbR3ygJPVgM7e6L0MCOVNkX0LSJTc5HJFi9E0MiAf4cG7UQ== dependencies: - "@solana/web3.js" "^1.35.0" - "@toruslabs/base-controllers" "^1.6.1" - "@toruslabs/http-helpers" "^2.2.0" - "@toruslabs/openlogin-jrpc" "^1.4.0" + "@solana/web3.js" "^1.63.1" + "@toruslabs/base-controllers" "^2.2.6" + "@toruslabs/http-helpers" "^3.2.0" + "@toruslabs/openlogin-jrpc" "^2.6.0" eth-rpc-errors "^4.0.3" fast-deep-equal "^3.1.3" - is-stream "^2.0.0" + is-stream "^2.0.1" lodash-es "^4.17.21" loglevel "^1.8.0" pump "^3.0.0" "@tsconfig/node10@^1.0.7": - version "1.0.8" - resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz" - integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== "@tsconfig/node12@^1.0.7": - version "1.0.9" - resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz" - integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== "@tsconfig/node14@^1.0.0": - version "1.0.1" - resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz" - integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": - version "1.0.2" - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz" - integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== "@types/aria-query@^4.2.0": - version "4.2.1" - resolved "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.1.tgz" - -"@types/babel__core@^7.0.0": - version "7.1.14" - resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz" - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" + version "4.2.2" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc" + integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig== "@types/babel__core@^7.1.14": - version "7.1.17" - resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.17.tgz" - integrity sha512-6zzkezS9QEIL8yCBvXWxPTJPNuMeECJVxSOhxNY/jfq9LxOTHivaYTqr37n9LknWWRTIkzqH2UilS5QFvfa90A== + version "7.1.20" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.20.tgz#e168cdd612c92a2d335029ed62ac94c95b362359" + integrity sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -5566,32 +5894,33 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.2" - resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.2.tgz" + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": - version "7.4.0" - resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.0.tgz" + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": - version "7.11.1" - resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.1.tgz" +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.18.3" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.3.tgz#dfc508a85781e5698d5b33443416b6268c4b3e8d" + integrity sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w== dependencies: "@babel/types" "^7.3.0" -"@types/bn.js@^4.11.5": - version "4.11.6" - resolved "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" +"@types/big.js@^6.1.6": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@types/big.js/-/big.js-6.2.0.tgz#e1f6a9a6ce64bc7c131137e71fbad34a5574f987" + integrity sha512-ubLURWoc4tCw/8Yds0P3CE9cBG5q+aoycwWBiXXx4gp7XPYZy9ch0L9+Pv6osSoSRgvuQNqJdlwEhP5QhKKl6w== -"@types/bn.js@^5.1.0": +"@types/bn.js@5.1.0", "@types/bn.js@^4.11.5", "@types/bn.js@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== @@ -5600,22 +5929,44 @@ "@types/bs58@^4.0.1": version "4.0.1" - resolved "https://registry.npmjs.org/@types/bs58/-/bs58-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/@types/bs58/-/bs58-4.0.1.tgz#3d51222aab067786d3bc3740a84a7f5a0effaa37" integrity sha512-yfAgiWgVLjFCmRv8zAcOIHywYATEwiTVccTLnRp6UxTNavT55M9d/uhK3T03St/+8/z/wW+CRjGKUNmEqoHHCA== dependencies: base-x "^3.0.6" +"@types/carbon__icons-react@11.7.0": + version "11.7.0" + resolved "https://registry.yarnpkg.com/@types/carbon__icons-react/-/carbon__icons-react-11.7.0.tgz#7793dcaf17a1782b522ff156af31b0ae0aa43a8b" + integrity sha512-FGH05n4lxzbjXrbJHJJc4lkE76cYdRbll80puMY4G3qihmNAP3KfHZwq161NxhIaLVZmgi/xb/DfZ7LMpVXwMA== + +"@types/chai-as-promised@^7.1.5": + version "7.1.5" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz#6e016811f6c7a64f2eed823191c3a6955094e255" + integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== + dependencies: + "@types/chai" "*" + +"@types/chai@*", "@types/chai@^4.3.3": + version "4.3.4" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" + integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== + "@types/connect@^3.4.33": version "3.4.35" - resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== dependencies: "@types/node" "*" -"@types/d3-array@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.3.tgz#87d990bf504d14ad6b16766979d04e943c046dac" - integrity sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ== +"@types/crypto-js@4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.1.1.tgz#602859584cecc91894eb23a4892f38cfa927890d" + integrity sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA== + +"@types/d3-array@*", "@types/d3-array@^3.0.3": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.4.tgz#44eebe40be57476cad6a0cd6a85b0f57d54185a2" + integrity sha512-nwvEkG9vYOc0Ic7G7kwgviY4AQlTfYGIZ0fqB7CQHXGyYM6nO7kJh5EguSNA3jfh4rq7Sb7eMVq8isuvg2/miQ== "@types/d3-axis@*": version "3.0.1" @@ -5671,7 +6022,7 @@ resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.0.tgz#f3c61fb117bd493ec0e814856feb804a14cfc311" integrity sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A== -"@types/d3-ease@*": +"@types/d3-ease@*", "@types/d3-ease@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.0.tgz#c29926f8b596f9dadaeca062a32a45365681eae0" integrity sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA== @@ -5705,7 +6056,7 @@ resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.0.tgz#4561bb7ace038f247e108295ef77b6a82193ac25" integrity sha512-g+sey7qrCa3UbsQlMZZBOHROkFqx7KZKvUpRzI/tAp/8erZWpYq7FgNKvYwebi2LaEiVs1klhUfd3WCThxmmWQ== -"@types/d3-interpolate@*": +"@types/d3-interpolate@*", "@types/d3-interpolate@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz#e7d17fa4a5830ad56fe22ce3b4fac8541a9572dc" integrity sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw== @@ -5737,22 +6088,22 @@ resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#103124777e8cdec85b20b51fd3397c682ee1e954" integrity sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw== -"@types/d3-scale@*": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.2.tgz#41be241126af4630524ead9cb1008ab2f0f26e69" - integrity sha512-Yk4htunhPAwN0XGlIwArRomOjdoBFXC3+kCxK2Ubg7I9shQlVSJy/pG/Ht5ASN+gdMIalpk8TJ5xV74jFsetLA== +"@types/d3-scale@*", "@types/d3-scale@^4.0.2": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.3.tgz#7a5780e934e52b6f63ad9c24b105e33dd58102b5" + integrity sha512-PATBiMCpvHJSMtZAMEhc2WyL+hnzarKzI6wAHYjhsonjWJYGq5BXTzQjv4l8m2jO183/4wZ90rKvSeT7o72xNQ== dependencies: "@types/d3-time" "*" "@types/d3-selection@*": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.2.tgz#23e48a285b24063630bbe312cc0cfe2276de4a59" - integrity sha512-d29EDd0iUBrRoKhPndhDY6U/PYxOWqgIZwKTooy2UkBfU7TNZNpRho0yLWPxlatQrFWk2mnTu71IZQ4+LRgKlQ== + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.3.tgz#57be7da68e7d9c9b29efefd8ea5a9ef1171e42ba" + integrity sha512-Mw5cf6nlW1MlefpD9zrshZ+DAWL4IQ5LnWfRheW6xwsdaWOb6IRRu2H7XPAQcyXEx1D7XQWgdoKR83ui1/HlEA== -"@types/d3-shape@*": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.0.tgz#1d87a6ddcf28285ef1e5c278ca4bdbc0658f3505" - integrity sha512-jYIYxFFA9vrJ8Hd4Se83YI6XF+gzDL1aC5DCsldai4XYYiVNdhtpGbA/GM6iyQ8ayhSp3a148LY34hy7A4TxZA== +"@types/d3-shape@*", "@types/d3-shape@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.1.tgz#15cc497751dac31192d7aef4e67a8d2c62354b95" + integrity sha512-6Uh86YFF7LGg4PQkuO2oG6EMBRLuW9cbavUW46zkIO5kuS2PfTqo2o9SkgtQzguBHbLgNnU90UNsITpsX1My+A== dependencies: "@types/d3-path" "*" @@ -5761,20 +6112,20 @@ resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.0.tgz#ee7b6e798f8deb2d9640675f8811d0253aaa1946" integrity sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw== -"@types/d3-time@*": +"@types/d3-time@*", "@types/d3-time@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.0.tgz#e1ac0f3e9e195135361fa1a1d62f795d87e6e819" integrity sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg== -"@types/d3-timer@*": +"@types/d3-timer@*", "@types/d3-timer@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.0.tgz#e2505f1c21ec08bda8915238e397fb71d2fc54ce" integrity sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g== "@types/d3-transition@*": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.1.tgz#c9a96125567173d6163a6985b874f79154f4cc3d" - integrity sha512-Sv4qEI9uq3bnZwlOANvYK853zvpdKEm1yz9rcc8ZTsxvRklcs9Fx4YFuGA3gXoQN/c/1T6QkVNjhaRO/cWj94g== + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.2.tgz#393dc3e3d55009a43cc6f252e73fccab6d78a8a4" + integrity sha512-jo5o/Rf+/u6uerJ/963Dc39NI16FQzqwOc54bwvksGAdVfvDrqDpVeq95bEvPtBwLCVZutAEyAtmSyEMxN7vxQ== dependencies: "@types/d3-selection" "*" @@ -5786,7 +6137,7 @@ "@types/d3-interpolate" "*" "@types/d3-selection" "*" -"@types/d3@^7.4.0": +"@types/d3@7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.0.tgz#fc5cac5b1756fc592a3cf1f3dc881bf08225f515" integrity sha512-jIfNVK0ZlxcuRDKtRS/SypEyOQ6UHaFQBKv032X45VvxSJ6Yi5G9behy9h6tNTHTDGh5Vq+KbmBjUWLgY4meCA== @@ -5824,146 +6175,155 @@ "@types/debug@^4.0.0": version "4.1.7" - resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== dependencies: "@types/ms" "*" -"@types/express-serve-static-core@^4.17.9": - version "4.17.28" - resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz" - integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" +"@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/geojson@*": - version "7946.0.8" - resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca" - integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA== + version "7946.0.10" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.10.tgz#6dfbf5ea17142f7f9a043809f1cd4c448cb68249" + integrity sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA== -"@types/glob@^7.1.1": - version "7.2.0" - resolved "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz" - integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - -"@types/graceful-fs@^4.1.2": +"@types/graceful-fs@^4.1.3": version "4.1.5" - resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== dependencies: "@types/node" "*" "@types/hast@^2.0.0": version "2.3.4" - resolved "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== dependencies: "@types/unist" "*" "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.3" - resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz" + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== "@types/istanbul-lib-report@*": version "3.0.0" - resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": - version "3.0.0" - resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz" + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@*", "@types/jest@^27.4.1": - version "27.4.1" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d" - integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw== +"@types/jest@*": + version "29.2.4" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.2.4.tgz#9c155c4b81c9570dbd183eb8604aa0ae80ba5a5b" + integrity sha512-PipFB04k2qTRPePduVLTRiPzQfvMeLwUN3Z21hsAKaB/W9IIzgB2pizCL466ftJlcyZqnHoC9ZHpxLGl3fS86A== dependencies: - jest-matcher-utils "^27.0.0" - pretty-format "^27.0.0" + expect "^29.0.0" + pretty-format "^29.0.0" -"@types/json-schema@^7.0.9": - version "7.0.9" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== +"@types/jest@29.2.0": + version "29.2.0" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.2.0.tgz#fa98e08b46ab119f1a74a9552c48c589f5378a96" + integrity sha512-KO7bPV21d65PKwv3LLsD8Jn3E05pjNjRZvkm+YTacWhVmykAb07wW6IkZUmQAltwQafNcDUEUrMO2h3jeBSisg== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + +"@types/js-cookie@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-3.0.2.tgz#451eaeece64c6bdac8b2dde0caab23b085899e0d" + integrity sha512-6+0ekgfusHftJNYpihfkMu8BWdeHs9EOJuGcSofErjstGPfPGEu9yTu4t460lTzzAMl2cM5zngQJqPMHbbnvYA== + +"@types/jsdom@^20.0.0": + version "20.0.1" + resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-20.0.1.tgz#07c14bc19bd2f918c1929541cdaacae894744808" + integrity sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ== + dependencies: + "@types/node" "*" + "@types/tough-cookie" "*" + parse5 "^7.0.0" "@types/json5@^0.0.29": version "0.0.29" - resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= - -"@types/lodash@^4.14.159": - version "4.14.178" - resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz" - integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw== + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/lodash@^4.14.175": - version "4.14.175" - resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.175.tgz" - integrity sha512-XmdEOrKQ8a1Y/yxQFOMbC47G/V2VDO1GvMRnl4O75M4GW/abC5tnfzadQYkqEveqRM1dEJGFFegfPNA2vvx2iw== - -"@types/long@^4.0.1": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" - integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + version "4.14.191" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.191.tgz#09511e7f7cba275acd8b419ddac8da9a6a79e2fa" + integrity sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ== "@types/mdast@^3.0.0": version "3.0.10" - resolved "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== dependencies: "@types/unist" "*" "@types/mdurl@^1.0.0": version "1.0.2" - resolved "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== -"@types/minimatch@*": - version "3.0.5" - resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz" - integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== +"@types/mocha@^9.1.0": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== "@types/ms@*": version "0.7.31" - resolved "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== -"@types/node@*", "@types/node@>=13.7.0": - version "17.0.38" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.38.tgz#f8bb07c371ccb1903f3752872c89f44006132947" - integrity sha512-5jY9RhV7c0Z4Jy09G+NIDTsCZ5G0L5n+Z+p+Y7t5VJHM30bgwzSjVtlcBxqAj+6L/swIlvtOSzr8rBk/aNyV2g== +"@types/node-fetch@^2.6.2": + version "2.6.11" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24" + integrity sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g== + dependencies: + "@types/node" "*" + form-data "^4.0.0" -"@types/node@10.12.18": - version "10.12.18" - resolved "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz" - integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== +"@types/node@*", "@types/node@>=13.7.0": + version "20.5.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.0.tgz#7fc8636d5f1aaa3b21e6245e97d56b7f56702313" + integrity sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q== "@types/node@11.11.6": version "11.11.6" resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== -"@types/node@^12.12.54": - version "12.20.42" - resolved "https://registry.npmjs.org/@types/node/-/node-12.20.42.tgz" - integrity sha512-aI3/oo5DzyiI5R/xAhxxRzfZlWlsbbqdgxfTPkqu/Zt+23GXiJvMCyPJT4+xKSXOnLqoL8jJYMLTwvK2M3a5hw== +"@types/node@14.14.25": + version "14.14.25" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.25.tgz#15967a7b577ff81383f9b888aa6705d43fbbae93" + integrity sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ== -"@types/node@^14.0.1", "@types/node@^14.14.25": - version "14.18.12" - resolved "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz" - integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== -"@types/object-hash@^1.3.0": - version "1.3.4" - resolved "https://registry.npmjs.org/@types/object-hash/-/object-hash-1.3.4.tgz" - integrity sha512-xFdpkAkikBgqBdG9vIlsqffDV8GpvnPEzs0IUtr1v3BEB97ijsFQ4RXVbUZwjFThhB4MDSTUfvmxUD5PGx0wXA== +"@types/node@^12.12.54": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + +"@types/node@^18.7.13": + version "18.19.42" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.42.tgz#b54ed4752c85427906aab40917b0f7f3d724bf72" + integrity sha512-d2ZFc/3lnK2YCYhos8iaNIYu9Vfhr92nHiyJHRltXWjXUBjEE+A4I58Tdbnw4VhggSW+2j5y5gTrLs4biNnubg== + dependencies: + undici-types "~5.26.4" "@types/parse-json@^4.0.0": version "4.0.0" @@ -5978,32 +6338,30 @@ "@types/node" "*" "@types/prettier@^2.1.5": - version "2.4.2" - resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.2.tgz" - integrity sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA== + version "2.7.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" + integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow== "@types/promise-retry@^1.1.3": version "1.1.3" - resolved "https://registry.npmjs.org/@types/promise-retry/-/promise-retry-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/@types/promise-retry/-/promise-retry-1.1.3.tgz#baab427419da9088a1d2f21bf56249c21b3dd43c" integrity sha512-LxIlEpEX6frE3co3vCO2EUJfHIta1IOmhDlcAsR4GMMv9hev1iTI9VwberVGkePJAuLZs5rMucrV8CziCfuJMw== dependencies: "@types/retry" "*" "@types/prop-types@*": - version "15.7.3" - resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz" - -"@types/qs@*": - version "6.9.7" - resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + version "15.7.5" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== -"@types/range-parser@*": - version "1.2.4" - resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== +"@types/ramda@0.28.15": + version "0.28.15" + resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.28.15.tgz#36bb4c8de430e3bbcd29590537569aef64409716" + integrity sha512-FCaLNVZry65jW8x/FDnKgjgkCNQxgc5AYMQwdNn6yW5M+62R+0nt2Y36U43dTNora9hcquemfrY5gxhE5pcilQ== + dependencies: + ts-toolbelt "^6.15.1" -"@types/react@^17.0.44": +"@types/react@17.0.44": version "17.0.44" resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.44.tgz#c3714bd34dd551ab20b8015d9d0dbec812a51ec7" integrity sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g== @@ -6012,19 +6370,15 @@ "@types/scheduler" "*" csstype "^3.0.2" -"@types/retry@*", "@types/retry@^0.12.1": - version "0.12.1" - resolved "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz" - integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== - -"@types/retry@^0.12.2": +"@types/retry@*", "@types/retry@^0.12.2": version "0.12.2" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== "@types/scheduler@*": - version "0.16.1" - resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz" + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== "@types/secp256k1@^4.0.1": version "4.0.3" @@ -6034,126 +6388,135 @@ "@types/node" "*" "@types/stack-utils@^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz" + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== "@types/testing-library__jest-dom@^5.9.1": - version "5.14.2" - resolved "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.2.tgz" - integrity sha512-vehbtyHUShPxIa9SioxDwCvgxukDMH//icJG90sXQBUm5lJOHLT5kNeU9tnivhnA/TkOFMzGIXN2cTc4hY8/kg== + version "5.14.5" + resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz#d113709c90b3c75fdb127ec338dad7d5f86c974f" + integrity sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ== dependencies: "@types/jest" "*" +"@types/tough-cookie@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" + integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw== + "@types/unist@*", "@types/unist@^2.0.0": version "2.0.6" - resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== "@types/ws@^7.4.4": version "7.4.7" - resolved "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== dependencies: "@types/node" "*" "@types/yargs-parser@*": - version "20.2.0" - resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz" + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== "@types/yargs@^15.0.0": - version "15.0.13" - resolved "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz" + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== dependencies: "@types/yargs-parser" "*" -"@types/yargs@^16.0.0": - version "16.0.4" - resolved "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz" - integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== +"@types/yargs@^17.0.8": + version "17.0.17" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.17.tgz#5672e5621f8e0fca13f433a8017aae4b7a2a03e7" + integrity sha512-72bWxFKTK6uwWJAVT+3rF6Jo6RTojiJ27FQo8Rf60AL+VZbzoVPnMFhKsUnbjR8A3BTCYQ7Mv3hnl8T0A+CX9g== dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.30.6": - version "5.30.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz#9c6017b6c1d04894141b4a87816388967f64c359" - integrity sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg== - dependencies: - "@typescript-eslint/scope-manager" "5.30.6" - "@typescript-eslint/type-utils" "5.30.6" - "@typescript-eslint/utils" "5.30.6" - debug "^4.3.4" - functional-red-black-tree "^1.0.1" - ignore "^5.2.0" - regexpp "^3.2.0" - semver "^7.3.7" - tsutils "^3.21.0" +"@typescript-eslint/eslint-plugin@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.1.0.tgz#3c020deeaaba82a6f741d00dacf172c53be4911f" + integrity sha512-LlNBaHFCEBPHyD4pZXb35mzjGkuGKXU5eeCA1SxvHfiRES0E82dOounfVpL4DCqYvJEKab0bZIA0gCRpdLKkCw== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.1.0" + "@typescript-eslint/type-utils" "8.1.0" + "@typescript-eslint/utils" "8.1.0" + "@typescript-eslint/visitor-keys" "8.1.0" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^1.3.0" -"@typescript-eslint/parser@^5.30.6": - version "5.30.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.6.tgz#add440db038fa9d777e4ebdaf66da9e7fb7abe92" - integrity sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA== +"@typescript-eslint/parser@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.1.0.tgz#b7e77f5fa212df59eba51ecd4986f194bccc2303" + integrity sha512-U7iTAtGgJk6DPX9wIWPPOlt1gO57097G06gIcl0N0EEnNw8RGD62c+2/DiP/zL7KrkqnnqF7gtFGR7YgzPllTA== dependencies: - "@typescript-eslint/scope-manager" "5.30.6" - "@typescript-eslint/types" "5.30.6" - "@typescript-eslint/typescript-estree" "5.30.6" + "@typescript-eslint/scope-manager" "8.1.0" + "@typescript-eslint/types" "8.1.0" + "@typescript-eslint/typescript-estree" "8.1.0" + "@typescript-eslint/visitor-keys" "8.1.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.30.6": - version "5.30.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz#ce1b49ff5ce47f55518d63dbe8fc9181ddbd1a33" - integrity sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g== +"@typescript-eslint/scope-manager@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.1.0.tgz#dd8987d2efebb71d230a1c71d82e84a7aead5c3d" + integrity sha512-DsuOZQji687sQUjm4N6c9xABJa7fjvfIdjqpSIIVOgaENf2jFXiM9hIBZOL3hb6DHK9Nvd2d7zZnoMLf9e0OtQ== dependencies: - "@typescript-eslint/types" "5.30.6" - "@typescript-eslint/visitor-keys" "5.30.6" + "@typescript-eslint/types" "8.1.0" + "@typescript-eslint/visitor-keys" "8.1.0" -"@typescript-eslint/type-utils@5.30.6": - version "5.30.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz#a64aa9acbe609ab77f09f53434a6af2b9685f3af" - integrity sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA== +"@typescript-eslint/type-utils@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.1.0.tgz#dbf5a4308166dfc37a36305390dea04a3a3b5048" + integrity sha512-oLYvTxljVvsMnldfl6jIKxTaU7ok7km0KDrwOt1RHYu6nxlhN3TIx8k5Q52L6wR33nOwDgM7VwW1fT1qMNfFIA== dependencies: - "@typescript-eslint/utils" "5.30.6" + "@typescript-eslint/typescript-estree" "8.1.0" + "@typescript-eslint/utils" "8.1.0" debug "^4.3.4" - tsutils "^3.21.0" + ts-api-utils "^1.3.0" -"@typescript-eslint/types@5.30.6": - version "5.30.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.6.tgz#86369d0a7af8c67024115ac1da3e8fb2d38907e1" - integrity sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg== +"@typescript-eslint/types@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.1.0.tgz#fbf1eaa668a7e444ac507732ca9d3c3468e5db9c" + integrity sha512-q2/Bxa0gMOu/2/AKALI0tCKbG2zppccnRIRCW6BaaTlRVaPKft4oVYPp7WOPpcnsgbr0qROAVCVKCvIQ0tbWog== -"@typescript-eslint/typescript-estree@5.30.6": - version "5.30.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz#a84a0d6a486f9b54042da1de3d671a2c9f14484e" - integrity sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A== +"@typescript-eslint/typescript-estree@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.1.0.tgz#c44e5667683c0bb5caa43192e27de6a994f4e4c4" + integrity sha512-NTHhmufocEkMiAord/g++gWKb0Fr34e9AExBRdqgWdVBaKoei2dIyYKD9Q0jBnvfbEA5zaf8plUFMUH6kQ0vGg== dependencies: - "@typescript-eslint/types" "5.30.6" - "@typescript-eslint/visitor-keys" "5.30.6" + "@typescript-eslint/types" "8.1.0" + "@typescript-eslint/visitor-keys" "8.1.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.30.6": - version "5.30.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.6.tgz#1de2da14f678e7d187daa6f2e4cdb558ed0609dc" - integrity sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA== - dependencies: - "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.30.6" - "@typescript-eslint/types" "5.30.6" - "@typescript-eslint/typescript-estree" "5.30.6" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - -"@typescript-eslint/visitor-keys@5.30.6": - version "5.30.6" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz#94dd10bb481c8083378d24de1742a14b38a2678c" - integrity sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA== - dependencies: - "@typescript-eslint/types" "5.30.6" - eslint-visitor-keys "^3.3.0" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/utils@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.1.0.tgz#a922985a43d2560ce0d293be79148fa80c1325e0" + integrity sha512-ypRueFNKTIFwqPeJBfeIpxZ895PQhNyH4YID6js0UoBImWYoSjBsahUn9KMiJXh94uOjVBgHD9AmkyPsPnFwJA== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.1.0" + "@typescript-eslint/types" "8.1.0" + "@typescript-eslint/typescript-estree" "8.1.0" + +"@typescript-eslint/visitor-keys@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.1.0.tgz#ab2b3a9699a8ddebf0c205e133f114c1fed9daad" + integrity sha512-ba0lNI19awqZ5ZNKh6wCModMwoZs457StTebQ0q1NP58zSi2F6MOZRXwfKZy+jB78JNJ/WH8GSh2IQNzXX8Nag== + dependencies: + "@typescript-eslint/types" "8.1.0" + eslint-visitor-keys "^3.4.3" -"@ubeswap/token-math@^4.4.4", "@ubeswap/token-math@^4.4.8": +"@ubeswap/token-math@^4.4.4": version "4.4.8" resolved "https://registry.yarnpkg.com/@ubeswap/token-math/-/token-math-4.4.8.tgz#7530627c6d11ecfb3a8159b66567764256352f9e" integrity sha512-/j8fld29BlWUA3hfBgFPuVorzOkhvnUyORk053pPJX0m9zhoFieRIT65A2sOGgF5Cffxj/OjN1ycAatD8vv6xg== @@ -6164,125 +6527,453 @@ toformat "^2.0.0" tslib "^2.4.0" -"@ungap/promise-all-settled@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" - integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== +"@ubeswap/token-math@^5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@ubeswap/token-math/-/token-math-5.2.1.tgz#66e70ba8d65b5fdb1b7459332fbdad4ddec32a64" + integrity sha512-wkIKDKIl6rml4CVK3fvjjLVk55Z8qEYTgjxZx7MnrTwECazyhiDuekb9WAaDPXcW5QNffCu8uv4Ba8wE96CJsg== + dependencies: + "@types/big.js" "^6.1.6" + big.js "^6.2.1" + decimal.js-light "^2.5.1" + tiny-invariant "^1.2.0" + tslib "^2.4.0" + +"@urql/core@>=3.0.0", "@urql/core@^3.0.3": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@urql/core/-/core-3.1.1.tgz#a49cd572360d01f2469a786b294fba2269a65e53" + integrity sha512-Mnxtq4I4QeFJsgs7Iytw+HyhiGxISR6qtyk66c9tipozLZ6QVxrCiUPF2HY4BxNIabaxcp+rivadvm8NAnXj4Q== + dependencies: + wonka "^6.1.2" + +"@urql/exchange-auth@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@urql/exchange-auth/-/exchange-auth-1.0.0.tgz#cf846189632662330b616704387b1cf762561638" + integrity sha512-79hqPQab+ifeINOxvQykvqub4ixWHBEIagN4U67ijcHGMfp3c4yEWRk4IJMPwF+OMT7LrRFuv+jRIZTQn/9VwQ== + dependencies: + "@urql/core" ">=3.0.0" + wonka "^6.0.0" + +"@urql/exchange-graphcache@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@urql/exchange-graphcache/-/exchange-graphcache-5.0.1.tgz#3c051d971ba79cccf4aadc2cf87b413c6682cbd3" + integrity sha512-sbornx6SaAADycfEex0+npdJwhImSKa+76DAnOjF48wls5bYlG+ewDe0ipWdmV+gQ+t9SDFPLAHBzFURTlQacQ== + dependencies: + "@urql/core" ">=3.0.0" + wonka "^6.0.0" + +"@urql/exchange-multipart-fetch@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@urql/exchange-multipart-fetch/-/exchange-multipart-fetch-1.0.1.tgz#83d0b892897bb95d436a03af615442f635af22c5" + integrity sha512-fjxRrKR/D9Rs52L8wJMvqsGQBC/mjFcg/VdkSkU5IXmqCb5KmicXl2208hoCnaBl/QLA6NDpCNnG3zjDniMOTg== + dependencies: + "@urql/core" ">=3.0.0" + extract-files "^11.0.0" + wonka "^6.0.0" + +"@urql/exchange-persisted-fetch@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@urql/exchange-persisted-fetch/-/exchange-persisted-fetch-2.0.0.tgz#40522065525718f79a199bb594f90d0d12c09597" + integrity sha512-Cb6VJ3kt/ucpvuzUXHvkNhfFWZudqwZ63w9xs/Sr5Ck/vkjnXNa8YkwmPJRXBPkRRyS7++n4yGMsPtl8Aa1OlA== + dependencies: + "@urql/core" ">=3.0.0" + wonka "^6.0.0" + +"@urql/exchange-request-policy@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@urql/exchange-request-policy/-/exchange-request-policy-1.0.0.tgz#ebaf0abc6f608c9875df7fc7cca25c5fcd09c599" + integrity sha512-Kq+C7SqgbShqhN/fzx9enPZnTH+P2a4FGnVZcx1Sc0IsfRiwPAn41+ebZ4CUpY5T8pzAg3USuvSy62uaRaKaxA== + dependencies: + "@urql/core" ">=3.0.0" + wonka "^6.0.0" + +"@wallet-standard/app@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@wallet-standard/app/-/app-1.0.1.tgz#f83c3ae887f7fb52497a7b259bba734ae10a2994" + integrity sha512-LnLYq2Vy2guTZ8GQKKSXQK3+FRGPil75XEdkZqE6fiLixJhZJoJa5hT7lXxwe0ykVTt9LEThdTbOpT7KadS26Q== + dependencies: + "@wallet-standard/base" "^1.0.1" + +"@wallet-standard/base@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@wallet-standard/base/-/base-1.0.1.tgz#860dd94d47c9e3c5c43b79d91c6afdbd7a36264e" + integrity sha512-1To3ekMfzhYxe0Yhkpri+Fedq0SYcfrOfJi3vbLjMwF2qiKPjTGLwZkf2C9ftdQmxES+hmxhBzTwF4KgcOwf8w== + +"@wallet-standard/core@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@wallet-standard/core/-/core-1.0.3.tgz#3b6743e207ca4e1e725ae20f1838b400fb0694ff" + integrity sha512-Jb33IIjC1wM1HoKkYD7xQ6d6PZ8EmMZvyc8R7dFgX66n/xkvksVTW04g9yLvQXrLFbcIjHrCxW6TXMhvpsAAzg== + dependencies: + "@wallet-standard/app" "^1.0.1" + "@wallet-standard/base" "^1.0.1" + "@wallet-standard/features" "^1.0.3" + "@wallet-standard/wallet" "^1.0.1" + +"@wallet-standard/features@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@wallet-standard/features/-/features-1.0.3.tgz#c992876c5e4f7a0672f8869c4146c87e0dfe48c8" + integrity sha512-m8475I6W5LTatTZuUz5JJNK42wFRgkJTB0I9tkruMwfqBF2UN2eomkYNVf9RbrsROelCRzSFmugqjKZBFaubsA== + dependencies: + "@wallet-standard/base" "^1.0.1" + +"@wallet-standard/wallet@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@wallet-standard/wallet/-/wallet-1.0.1.tgz#95438941a2a1ee12a794444357b59d53e19b374c" + integrity sha512-qkhJeuQU2afQTZ02yMZE5SFc91Fo3hyFjFkpQglHudENNyiSG0oUKcIjky8X32xVSaumgTZSQUAzpXnCTWHzKQ== + dependencies: + "@wallet-standard/base" "^1.0.1" + +"@walletconnect/browser-utils@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/browser-utils/-/browser-utils-1.8.0.tgz#33c10e777aa6be86c713095b5206d63d32df0951" + integrity sha512-Wcqqx+wjxIo9fv6eBUFHPsW1y/bGWWRboni5dfD8PtOmrihrEpOCmvRJe4rfl7xgJW8Ea9UqKEaq0bIRLHlK4A== + dependencies: + "@walletconnect/safe-json" "1.0.0" + "@walletconnect/types" "^1.8.0" + "@walletconnect/window-getters" "1.0.0" + "@walletconnect/window-metadata" "1.0.0" + detect-browser "5.2.0" + +"@walletconnect/core@2.11.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.11.0.tgz#3a4e301077b2f858fd916b7a20b5b984d1afce63" + integrity sha512-2Tjp5BCevI7dbmqo/OrCjX4tqgMqwJNQLlQAlphqPfvwlF9+tIu6pGcVbSN3U9zyXzWIZCeleqEaWUeSeET4Ew== + dependencies: + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-provider" "1.0.13" + "@walletconnect/jsonrpc-types" "1.0.3" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/jsonrpc-ws-connection" "1.0.14" + "@walletconnect/keyvaluestorage" "^1.1.1" + "@walletconnect/logger" "^2.0.1" + "@walletconnect/relay-api" "^1.0.9" + "@walletconnect/relay-auth" "^1.0.4" + "@walletconnect/safe-json" "^1.0.2" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.11.0" + "@walletconnect/utils" "2.11.0" + events "^3.3.0" + isomorphic-unfetch "3.1.0" + lodash.isequal "4.5.0" + uint8arrays "^3.1.0" + +"@walletconnect/environment@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/environment/-/environment-1.0.1.tgz#1d7f82f0009ab821a2ba5ad5e5a7b8ae3b214cd7" + integrity sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg== + dependencies: + tslib "1.14.1" + +"@walletconnect/events@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/events/-/events-1.0.1.tgz#2b5f9c7202019e229d7ccae1369a9e86bda7816c" + integrity sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ== + dependencies: + keyvaluestorage-interface "^1.0.0" + tslib "1.14.1" + +"@walletconnect/heartbeat@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@walletconnect/heartbeat/-/heartbeat-1.2.1.tgz#afaa3a53232ae182d7c9cff41c1084472d8f32e9" + integrity sha512-yVzws616xsDLJxuG/28FqtZ5rzrTA4gUjdEMTbWB5Y8V1XHRmqq4efAxCw5ie7WjbXFSUyBHaWlMR+2/CpQC5Q== + dependencies: + "@walletconnect/events" "^1.0.1" + "@walletconnect/time" "^1.0.2" + tslib "1.14.1" + +"@walletconnect/jsonrpc-provider@1.0.13": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.13.tgz#9a74da648d015e1fffc745f0c7d629457f53648b" + integrity sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.8" + "@walletconnect/safe-json" "^1.0.2" + tslib "1.14.1" + +"@walletconnect/jsonrpc-types@1.0.3", "@walletconnect/jsonrpc-types@^1.0.2", "@walletconnect/jsonrpc-types@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.3.tgz#65e3b77046f1a7fa8347ae02bc1b841abe6f290c" + integrity sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw== + dependencies: + keyvaluestorage-interface "^1.0.0" + tslib "1.14.1" + +"@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz#82d0cc6a5d6ff0ecc277cb35f71402c91ad48d72" + integrity sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw== + dependencies: + "@walletconnect/environment" "^1.0.1" + "@walletconnect/jsonrpc-types" "^1.0.3" + tslib "1.14.1" + +"@walletconnect/jsonrpc-ws-connection@1.0.14": + version "1.0.14" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.14.tgz#eec700e74766c7887de2bd76c91a0206628732aa" + integrity sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.6" + "@walletconnect/safe-json" "^1.0.2" + events "^3.3.0" + ws "^7.5.1" + +"@walletconnect/keyvaluestorage@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz#dd2caddabfbaf80f6b8993a0704d8b83115a1842" + integrity sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA== + dependencies: + "@walletconnect/safe-json" "^1.0.1" + idb-keyval "^6.2.1" + unstorage "^1.9.0" + +"@walletconnect/logger@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/logger/-/logger-2.0.1.tgz#7f489b96e9a1ff6bf3e58f0fbd6d69718bf844a8" + integrity sha512-SsTKdsgWm+oDTBeNE/zHxxr5eJfZmE9/5yp/Ku+zJtcTAjELb3DXueWkDXmE9h8uHIbJzIb5wj5lPdzyrjT6hQ== + dependencies: + pino "7.11.0" + tslib "1.14.1" + +"@walletconnect/mobile-registry@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@walletconnect/mobile-registry/-/mobile-registry-1.4.0.tgz#502cf8ab87330841d794819081e748ebdef7aee5" + integrity sha512-ZtKRio4uCZ1JUF7LIdecmZt7FOLnX72RPSY7aUVu7mj7CSfxDwUn6gBuK6WGtH+NZCldBqDl5DenI5fFSvkKYw== + +"@walletconnect/qrcode-modal@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/qrcode-modal/-/qrcode-modal-1.8.0.tgz#ddd6f5c9b7ee52c16adf9aacec2a3eac4994caea" + integrity sha512-BueaFefaAi8mawE45eUtztg3ZFbsAH4DDXh1UNwdUlsvFMjqcYzLUG0xZvDd6z2eOpbgDg2N3bl6gF0KONj1dg== + dependencies: + "@walletconnect/browser-utils" "^1.8.0" + "@walletconnect/mobile-registry" "^1.4.0" + "@walletconnect/types" "^1.8.0" + copy-to-clipboard "^3.3.1" + preact "10.4.1" + qrcode "1.4.4" + +"@walletconnect/relay-api@^1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@walletconnect/relay-api/-/relay-api-1.0.9.tgz#f8c2c3993dddaa9f33ed42197fc9bfebd790ecaf" + integrity sha512-Q3+rylJOqRkO1D9Su0DPE3mmznbAalYapJ9qmzDgK28mYF9alcP3UwG/og5V7l7CFOqzCLi7B8BvcBUrpDj0Rg== + dependencies: + "@walletconnect/jsonrpc-types" "^1.0.2" + tslib "1.14.1" + +"@walletconnect/relay-auth@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz#0b5c55c9aa3b0ef61f526ce679f3ff8a5c4c2c7c" + integrity sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ== + dependencies: + "@stablelib/ed25519" "^1.0.2" + "@stablelib/random" "^1.0.1" + "@walletconnect/safe-json" "^1.0.1" + "@walletconnect/time" "^1.0.2" + tslib "1.14.1" + uint8arrays "^3.0.0" + +"@walletconnect/safe-json@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.0.tgz#12eeb11d43795199c045fafde97e3c91646683b2" + integrity sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg== + +"@walletconnect/safe-json@^1.0.1", "@walletconnect/safe-json@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.2.tgz#7237e5ca48046e4476154e503c6d3c914126fa77" + integrity sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA== + dependencies: + tslib "1.14.1" + +"@walletconnect/sign-client@^2.7.2": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.11.0.tgz#de10f976cc1b8ab04b7f7c27f6a298e4e083ab25" + integrity sha512-H2ukscibBS+6WrzQWh+WyVBqO5z4F5et12JcwobdwgHnJSlqIoZxqnUYYWNCI5rUR5UKsKWaUyto4AE9N5dw4Q== + dependencies: + "@walletconnect/core" "2.11.0" + "@walletconnect/events" "^1.0.1" + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/logger" "^2.0.1" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.11.0" + "@walletconnect/utils" "2.11.0" + events "^3.3.0" + +"@walletconnect/time@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/time/-/time-1.0.2.tgz#6c5888b835750ecb4299d28eecc5e72c6d336523" + integrity sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g== + dependencies: + tslib "1.14.1" + +"@walletconnect/types@2.11.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.11.0.tgz#474a009c56faa9ef4063b76ed84415c801dc9f1e" + integrity sha512-AB5b1lrEbCGHxqS2vqfCkIoODieH+ZAUp9rA1O2ftrhnqDJiJK983Df87JhYhECsQUBHHfALphA8ydER0q+9sw== + dependencies: + "@walletconnect/events" "^1.0.1" + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-types" "1.0.3" + "@walletconnect/keyvaluestorage" "^1.1.1" + "@walletconnect/logger" "^2.0.1" + events "^3.3.0" + +"@walletconnect/types@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.8.0.tgz#3f5e85b2d6b149337f727ab8a71b8471d8d9a195" + integrity sha512-Cn+3I0V0vT9ghMuzh1KzZvCkiAxTq+1TR2eSqw5E5AVWfmCtECFkVZBP6uUJZ8YjwLqXheI+rnjqPy7sVM4Fyg== + +"@walletconnect/utils@2.11.0", "@walletconnect/utils@^2.4.5": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.11.0.tgz#31c95151c823022077883dda61800cdea71879b7" + integrity sha512-hxkHPlTlDQILHfIKXlmzgNJau/YcSBC3XHUSuZuKZbNEw3duFT6h6pm3HT/1+j1a22IG05WDsNBuTCRkwss+BQ== + dependencies: + "@stablelib/chacha20poly1305" "1.0.1" + "@stablelib/hkdf" "1.0.1" + "@stablelib/random" "^1.0.2" + "@stablelib/sha256" "1.0.1" + "@stablelib/x25519" "^1.0.3" + "@walletconnect/relay-api" "^1.0.9" + "@walletconnect/safe-json" "^1.0.2" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.11.0" + "@walletconnect/window-getters" "^1.0.1" + "@walletconnect/window-metadata" "^1.0.1" + detect-browser "5.3.0" + query-string "7.1.3" + uint8arrays "^3.1.0" + +"@walletconnect/window-getters@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.0.tgz#1053224f77e725dfd611c83931b5f6c98c32bfc8" + integrity sha512-xB0SQsLaleIYIkSsl43vm8EwETpBzJ2gnzk7e0wMF3ktqiTGS6TFHxcprMl5R44KKh4tCcHCJwolMCaDSwtAaA== + +"@walletconnect/window-getters@^1.0.0", "@walletconnect/window-getters@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.1.tgz#f36d1c72558a7f6b87ecc4451fc8bd44f63cbbdc" + integrity sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q== + dependencies: + tslib "1.14.1" + +"@walletconnect/window-metadata@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.0.tgz#93b1cc685e6b9b202f29c26be550fde97800c4e5" + integrity sha512-9eFvmJxIKCC3YWOL97SgRkKhlyGXkrHwamfechmqszbypFspaSk+t2jQXAEU7YClHF6Qjw5eYOmy1//zFi9/GA== + dependencies: + "@walletconnect/window-getters" "^1.0.0" + +"@walletconnect/window-metadata@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz#2124f75447b7e989e4e4e1581d55d25bc75f7be5" + integrity sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA== + dependencies: + "@walletconnect/window-getters" "^1.0.1" + tslib "1.14.1" + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== JSONStream@^1.3.5: version "1.3.5" - resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== dependencies: jsonparse "^1.2.0" through ">=2.2.7 <3" -abab@^2.0.3, abab@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz" +abab@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== -abbrev@1, abbrev@~1.1.1: +abbrev@1: version "1.1.1" - resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn-globals@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz" +acorn-globals@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3" + integrity sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q== dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" + acorn "^8.1.0" + acorn-walk "^8.0.2" acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn-node@^1.6.1, acorn-node@^1.8.2: +acorn-node@^1.8.2: version "1.8.2" - resolved "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== dependencies: acorn "^7.0.0" acorn-walk "^7.0.0" xtend "^4.0.2" -acorn-walk@^7.0.0, acorn-walk@^7.1.1: +acorn-walk@^7.0.0: version "7.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn-walk@^8.0.0, acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== +acorn-walk@^8.0.0, acorn-walk@^8.0.2, acorn-walk@^8.1.1: + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== -acorn@^7.0.0, acorn@^7.1.1: +acorn@^7.0.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.4, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.7.1: - version "8.7.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" - integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== +acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.3, acorn@^8.12.0, acorn@^8.4.1, acorn@^8.8.1: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + +add-to-calendar-button-react@2.6.13: + version "2.6.13" + resolved "https://registry.yarnpkg.com/add-to-calendar-button-react/-/add-to-calendar-button-react-2.6.13.tgz#4a0254983f90b74ad7f23fc613beb994f3519cf7" + integrity sha512-GQZNxHTkUBZ+I8Y9ojIjFpRRtfVxy5zKdru9PZM0hVJIq2nWuvjU7XgAMXhYQ41adTIXiZa/A5LUC4Xm4+CH7g== + dependencies: + add-to-calendar-button "^2.6.13" + +add-to-calendar-button@^2.6.13: + version "2.6.13" + resolved "https://registry.yarnpkg.com/add-to-calendar-button/-/add-to-calendar-button-2.6.13.tgz#e52c22ee5dc6262d842c5f124e809df3f6eee78b" + integrity sha512-Me2n/8uV8AWq3guJI0tbBpVgeXTsMVXAXmxfZeCFPh6PHItr1pQjKlPRKZmf84BSdDJHvVLXG7kGKE/X78D2pA== + dependencies: + timezones-ical-library "^1.8.2" aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== -agent-base@6, agent-base@^6.0.2: +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + +agent-base@6: version "6.0.2" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: - debug "4" - -agentkeepalive@^4.1.3: - version "4.2.1" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" - integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA== - dependencies: - debug "^4.1.0" - depd "^1.1.2" - humanize-ms "^1.2.1" - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + debug "4" -ajv-keywords@^3.1.0: - version "3.5.2" - resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== +agentkeepalive@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== + dependencies: + humanize-ms "^1.2.1" -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -6290,77 +6981,80 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + algo-msgpack-with-bigint@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/algo-msgpack-with-bigint/-/algo-msgpack-with-bigint-2.1.1.tgz#38bb717220525b3ff42232eefdcd9efb9ad405d6" integrity sha512-F1tGh056XczEaEAqu7s+hlZUDWwOBT70Eq0lfMpBP2YguSQVyxRbprLq5rELXKQOyOaixTWYhMeMQMzP0U5FoQ== algosdk@^1.13.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/algosdk/-/algosdk-1.18.1.tgz#b9be65a713af98712f62f31188bf185c12972e28" - integrity sha512-P0mlSfMSbylMfUG2SZgxnhSE1JvQFIK4wT8O9ZvBvy1+pxs53MdAKfYkfC95cK3VqCvq616PuXM6bzI2mpQbPA== + version "1.24.1" + resolved "https://registry.yarnpkg.com/algosdk/-/algosdk-1.24.1.tgz#afc4102457ae0c38a32de6b84f4d713aedfc9e89" + integrity sha512-9moZxdqeJ6GdE4N6fA/GlUP4LrbLZMYcYkt141J4Ss68OfEgH9qW0wBuZ3ZOKEx/xjc5bg7mLP2Gjg7nwrkmww== dependencies: algo-msgpack-with-bigint "^2.1.1" buffer "^6.0.2" + cross-fetch "^3.1.5" hi-base32 "^0.5.1" js-sha256 "^0.9.0" js-sha3 "^0.8.0" js-sha512 "^0.8.0" json-bigint "^1.0.0" - superagent "^6.1.0" tweetnacl "^1.0.3" + vlq "^2.0.4" -ansi-colors@4.1.1, ansi-colors@^4.1.1: +ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== -ansi-colors@^3.0.0: - version "3.2.4" - resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz" - integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== +ansi-escapes@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== -ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: +ansi-escapes@^4.2.1: version "4.3.2" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" -ansi-html-community@0.0.8: - version "0.0.8" - resolved "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz" - integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== -ansi-regex@^5.0.0, ansi-regex@^5.0.1: +"ansi-regex@>=3.0.1 <=5.0.1", ansi-regex@^2.0.0, ansi-regex@^3.0.0, ansi-regex@^4.1.0, ansi-regex@^5.0.0, ansi-regex@^5.0.1, ansi-regex@^6.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^4.3.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" @@ -6369,51 +7063,45 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansicolors@^0.3.2, ansicolors@~0.3.2: +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +ansicolors@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" - integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= + integrity sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg== -ansistyles@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539" - integrity sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk= +any-observable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" + integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== any-promise@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" +anymatch@^3.0.3, anymatch@^3.1.3, anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" aproba@^1.0.3: version "1.2.0" - resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -"aproba@^1.0.3 || ^2.0.0", aproba@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz" - integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== - arbundles@^0.6.19: - version "0.6.19" - resolved "https://registry.yarnpkg.com/arbundles/-/arbundles-0.6.19.tgz#550f8835014ea7a4b4c51d6d22870db1108de99b" - integrity sha512-OenrPZOXuihEatKAT2R0ZtbHmkTcDV4Y0fsz28gHFeVP13cZl/eNR9UiWFCrvxA0hQIanmPYAX9tgfEmk4OJHw== + version "0.6.22" + resolved "https://registry.yarnpkg.com/arbundles/-/arbundles-0.6.22.tgz#0fd58ec76514f1d6c2db7c5870a6232314f52de6" + integrity sha512-QlSavBHk59mNqgQ6ScxlqaBJlDbSmSrK/uTcF3HojLAZ/4aufTkVTBjl1hSfZ/ZN45oIPgJC05R8SmVARF+8VA== dependencies: + "@noble/ed25519" "^1.6.1" "@randlabs/myalgo-connect" "^1.1.2" "@solana/wallet-adapter-base" "^0.9.2" algosdk "^1.13.1" @@ -6426,17 +7114,9 @@ arbundles@^0.6.19: ethers "^5.5.1" keccak "^3.0.2" multistream "^4.1.0" - noble-ed25519 "^1.2.6" process "^0.11.10" secp256k1 "^4.0.2" tmp-promise "^3.0.2" - ts-node "^10.5.0" - tslib "^2.3.0" - -archy@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" - integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= arconnect@^0.4.2: version "0.4.2" @@ -6445,14 +7125,6 @@ arconnect@^0.4.2: dependencies: arweave "^1.10.13" -are-we-there-yet@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz" - integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== - dependencies: - delegates "^1.0.0" - readable-stream "^3.6.0" - are-we-there-yet@~1.1.2: version "1.1.7" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" @@ -6463,83 +7135,66 @@ are-we-there-yet@~1.1.2: arg@^4.1.0: version "4.1.3" - resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== arg@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz" - integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA== - -arg@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== argparse@^1.0.7: version "1.0.10" - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== aria-hidden@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.3.tgz#bb48de18dc84787a3c6eee113709c473c64ec254" - integrity sha512-RhVWFtKH5BiGMycI72q2RAFMLQi8JP9bLuQXgR5a8Znp7P5KOIADSJeyfI8PCVxLEp067B2HbP5JIiI/PXIZeA== + version "1.2.2" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.2.tgz#8c4f7cc88d73ca42114106fdf6f47e68d31475b8" + integrity sha512-6y/ogyDTk/7YAe91T3E2PR1ALVKyM2QbTio5HwM+N1Q6CMlCKhvClyIjkckBswa0f2xJhjsfzIGa1yVSe1UMVA== dependencies: - tslib "^1.0.0" + tslib "^2.0.0" aria-query@^4.2.2: version "4.2.2" - resolved "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" + integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== dependencies: "@babel/runtime" "^7.10.2" "@babel/runtime-corejs3" "^7.10.2" aria-query@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz" - integrity sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg== - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-flatten@^2.1.0: - version "2.1.2" - resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-includes@^3.1.2, array-includes@^3.1.4: - version "3.1.4" - resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz" - integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== + version "5.1.3" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" + integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - get-intrinsic "^1.1.1" + deep-equal "^2.0.5" + +array-buffer-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" + integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== + dependencies: + call-bind "^1.0.5" + is-array-buffer "^3.0.4" + +array-includes@^3.1.5, array-includes@^3.1.7, array-includes@^3.1.8: + version "3.1.8" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" + integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" is-string "^1.0.7" array-move@^3.0.1: @@ -6547,46 +7202,93 @@ array-move@^3.0.1: resolved "https://registry.yarnpkg.com/array-move/-/array-move-3.0.1.tgz#179645cc0987b65953a4fc06b6df9045e4ba9618" integrity sha512-H3Of6NIn2nNU1gsVDqDnYKY/LCdWvCMMOWifNGhKcVQgiZ6nOek39aESOvro6zmueP07exSl93YLvkN4fZOkSg== -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - array-union@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +array.prototype.findlast@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" -array.prototype.flatmap@^1.2.5: +array.prototype.findlastindex@^1.2.3: version "1.2.5" - resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz" - integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA== + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" + integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - es-abstract "^1.19.0" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" + +array.prototype.flat@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.tosorted@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" + +arraybuffer.prototype.slice@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" + integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.2.1" + get-intrinsic "^1.2.3" + is-array-buffer "^3.0.4" + is-shared-array-buffer "^1.0.2" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== arweave-stream-tx@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arweave-stream-tx/-/arweave-stream-tx-1.1.0.tgz#288fbaee30f6aa5cadb0b7cd2efd5b34147e867f" - integrity sha512-1BEYGFSP+FP1ACfclTjSjSTWx5PV/7a+0TwGZu+MlkmnnZTQ3hCOr5Md2Pi/T6dc69Fj+BRezSckiIhKFwTc3g== + version "1.2.2" + resolved "https://registry.yarnpkg.com/arweave-stream-tx/-/arweave-stream-tx-1.2.2.tgz#2d5c66554301baacd02586a152fbb198b422112f" + integrity sha512-bNt9rj0hbAEzoUZEF2s6WJbIz8nasZlZpxIw03Xm8fzb9gRiiZlZGW3lxQLjfc9Z0VRUWDzwtqoYeEoB/JDToQ== dependencies: exponential-backoff "^3.1.0" - stream-chunker "^1.2.8" -arweave@^1.10.13, arweave@^1.11.4: +arweave@1.11.4: version "1.11.4" resolved "https://registry.yarnpkg.com/arweave/-/arweave-1.11.4.tgz#19e5850d3b9f655cacb0953b36a12ac6596b195c" integrity sha512-EPUms1OMet/VFmYMefgxIpj17PIlIZzIteiHAn0tetN+d/LRV6N9CCsrg/t22hL6yLGdGRHrYlDEdsWqjwSSYg== @@ -6598,12 +7300,24 @@ arweave@^1.10.13, arweave@^1.11.4: bignumber.js "^9.0.2" util "^0.12.4" -asap@^2.0.0: +arweave@^1.10.13, arweave@^1.11.4: + version "1.11.8" + resolved "https://registry.yarnpkg.com/arweave/-/arweave-1.11.8.tgz#09376e0c6cec40a661cbb27a306cb11c0a663cd8" + integrity sha512-58ODeNPIC4OjaOCl2bXjKbOFGsiVZFs+DkQg3BvQGvFWNqw1zTJ4Jp01xGUz+GbdOaDyJcCC0g3l0HwdJfFPyw== + dependencies: + arconnect "^0.4.2" + asn1.js "^5.4.1" + axios "^0.27.2" + base64-js "^1.5.1" + bignumber.js "^9.0.2" + util "^0.12.4" + +asap@~2.0.3: version "2.0.6" - resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== -asn1.js@^5.4.1: +asn1.js@^5.2.0, asn1.js@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== @@ -6622,12 +7336,12 @@ asn1@~0.2.3: assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== assert@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== dependencies: es6-object-assign "^1.1.0" @@ -6635,31 +7349,17 @@ assert@^2.0.0: object-is "^1.0.1" util "^0.12.0" -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -async-mutex@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.3.2.tgz#1485eda5bda1b0ec7c8df1ac2e815757ad1831df" - integrity sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA== +async-mutex@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.4.0.tgz#ae8048cd4d04ace94347507504b3cf15e631c25f" + integrity sha512-eJFZ1YhRR8UN8eBLoNzcDPcy/jqjsg6I1AP+KvWQX80BqOSW1oJPJXDylPUEeMr2ZQvHgnQ//Lp6f3RQ1zI7HA== dependencies: - tslib "^2.3.1" + tslib "^2.4.0" async-retry@^1.3.3: version "1.3.3" @@ -6668,78 +7368,57 @@ async-retry@^1.3.3: dependencies: retry "0.13.1" -async@^2.6.2: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== atob@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + attr-accept@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.2.tgz#646613809660110749e92f2c10833b70968d929b" integrity sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg== -auction-house-sdk@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/auction-house-sdk/-/auction-house-sdk-0.0.4.tgz#24243ae949d8771a12bd122373c8e5d8368f863a" - integrity sha512-RK/tK0KhhemvUW4oTRasnKQPPr291uQfNcrdBqH8O5jyjdeOcl1NCgD7MkJM0ZKeN6LfxbnWH1CsVeXVlfKVNA== - dependencies: - "@bonfida/aaob" "^0.0.4" - "@project-serum/anchor" "^0.22.1" - "@project-serum/borsh" "^0.2.5" - "@project-serum/sol-wallet-adapter" "^0.2.6" - "@solana/buffer-layout" "^4.0.0" - "@solana/spl-token" "^0.2.0" - "@solana/wallet-adapter-base" "^0.9.5" - "@solana/wallet-adapter-phantom" "^0.9.3" - "@solana/wallet-adapter-sollet" "^0.11.1" - "@solana/web3.js" "^1.37.0" - dayjs "^1.11.2" - immer "^9.0.7" - tweetnacl "^1.0.3" - autoprefixer@^10.2.5: - version "10.2.5" - resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.2.5.tgz" + version "10.4.13" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8" + integrity sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg== dependencies: - browserslist "^4.16.3" - caniuse-lite "^1.0.30001196" - colorette "^1.2.2" - fraction.js "^4.0.13" + browserslist "^4.21.4" + caniuse-lite "^1.0.30001426" + fraction.js "^4.2.0" normalize-range "^0.1.2" - postcss-value-parser "^4.1.0" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" autoprefixer@^9.6.1: - version "9.8.6" - resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz" + version "9.8.8" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.8.tgz#fd4bd4595385fa6f06599de749a4d5f7a474957a" + integrity sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA== dependencies: browserslist "^4.12.0" caniuse-lite "^1.0.30001109" - colorette "^1.2.1" normalize-range "^0.1.2" num2fraction "^1.2.2" + picocolors "^0.2.1" postcss "^7.0.32" postcss-value-parser "^4.1.0" -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" "avsc@https://github.com/Bundlr-Network/avsc#csp-fixes": version "5.4.7" @@ -6747,15 +7426,22 @@ available-typed-arrays@^1.0.5: aws-sign2@~0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: version "1.11.0" - resolved "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axios@^0.21.1, axios@^0.21.3: +axios@0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" + integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== + dependencies: + follow-redirects "^1.14.8" + +axios@^0.21.0, axios@^0.21.3: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== @@ -6771,18 +7457,11 @@ axios@^0.24.0: axios@^0.25.0: version "0.25.0" - resolved "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== dependencies: follow-redirects "^1.14.7" -axios@^0.26.0, axios@^0.26.1: - version "0.26.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" - integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== - dependencies: - follow-redirects "^1.14.8" - axios@^0.27.2: version "0.27.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" @@ -6791,67 +7470,82 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" -babel-jest@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-27.4.5.tgz" - integrity sha512-3uuUTjXbgtODmSv/DXO9nZfD52IyC2OYTFaXGRzL0kpykzroaquCrD5+lZNafTvZlnNqZHt5pb0M08qVBZnsnA== +axios@^1.1.3, axios@^1.3.6, axios@^1.4.0, axios@^1.6.2, axios@^1.7.2, axios@^1.7.4: + version "1.7.5" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.5.tgz#21eed340eb5daf47d29b6e002424b3e88c8c54b1" + integrity sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +babel-jest@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.3.1.tgz#05c83e0d128cd48c453eea851482a38782249f44" + integrity sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA== dependencies: - "@jest/transform" "^27.4.5" - "@jest/types" "^27.4.2" + "@jest/transform" "^29.3.1" "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^27.4.0" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.2.0" chalk "^4.0.0" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" slash "^3.0.0" -babel-plugin-istanbul@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz" +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@istanbuljs/load-nyc-config" "^1.0.0" "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^4.0.0" + istanbul-lib-instrument "^5.0.4" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^27.4.0: - version "27.4.0" - resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.4.0.tgz" - integrity sha512-Jcu7qS4OX5kTWBc45Hz7BMmgXuJqRnhatqpUhnzGC3OBYpOmf2tv6jFNwZpwM7wU7MUuv2r9IPS/ZlYOuburVw== +babel-plugin-jest-hoist@^29.2.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz#23ee99c37390a98cfddf3ef4a78674180d823094" + integrity sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" - "@types/babel__core" "^7.0.0" + "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-macros@^2.6.1, babel-plugin-macros@^2.8.0: +babel-plugin-macros@^2.8.0: version "2.8.0" - resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" + integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== dependencies: "@babel/runtime" "^7.7.2" cosmiconfig "^6.0.0" resolve "^1.12.0" -"babel-plugin-styled-components@>= 1.12.0": - version "2.0.7" - resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz#c81ef34b713f9da2b7d3f5550df0d1e19e798086" - integrity sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA== +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== dependencies: - "@babel/helper-annotate-as-pure" "^7.16.0" - "@babel/helper-module-imports" "^7.16.0" - babel-plugin-syntax-jsx "^6.18.0" - lodash "^4.17.11" - picomatch "^2.3.0" + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" -babel-plugin-syntax-jsx@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - integrity sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw== +"babel-plugin-styled-components@>= 1.12.0": + version "2.1.4" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz#9a1f37c7f32ef927b4b008b529feb4a2c82b1092" + integrity sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-module-imports" "^7.22.5" + "@babel/plugin-syntax-jsx" "^7.22.5" + lodash "^4.17.21" + picomatch "^2.3.1" babel-preset-current-node-syntax@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" @@ -6866,27 +7560,27 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^27.4.0: - version "27.4.0" - resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.4.0.tgz" - integrity sha512-NK4jGYpnBvNxcGo7/ZpZJr51jCGT+3bwwpVIDY2oNfTxJJldRtB4VAcYdgp1loDE50ODuTu+yBjpMAswv5tlpg== +babel-preset-jest@^29.2.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz#3048bea3a1af222e3505e4a767a974c95a7620dc" + integrity sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA== dependencies: - babel-plugin-jest-hoist "^27.4.0" + babel-plugin-jest-hoist "^29.2.0" babel-preset-current-node-syntax "^1.0.0" bail@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/bail/-/bail-2.0.1.tgz" - integrity sha512-d5FoTAr2S5DSUPKl85WNm2yUwsINN8eidIdIwsOge2t33DaOfOdSmmsI11jMN3GmALCXaw+Y6HMVHDzePshFAA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" + integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw== balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base-x@^3.0.2, base-x@^3.0.6: version "3.0.9" - resolved "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== dependencies: safe-buffer "^5.0.1" @@ -6898,7 +7592,7 @@ base-x@^4.0.0: base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== base64url@^3.0.1: @@ -6906,28 +7600,10 @@ base64url@^3.0.1: resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== -base@^0.11.1: - version "0.11.2" - resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - bcrypt-pbkdf@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== dependencies: tweetnacl "^0.14.3" @@ -6936,15 +7612,10 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== -bech32@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" - integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== - -big.js@^6.1.1: - version "6.1.1" - resolved "https://registry.npmjs.org/big.js/-/big.js-6.1.1.tgz" - integrity sha512-1vObw81a8ylZO5ePrtMay0n018TcftpTA5HFKDaSuiUDBo8biRBtjIobw60OpwuvrGk+FsxKamqN4cnmj/eXdg== +big.js@^6.1.1, big.js@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.2.1.tgz#7205ce763efb17c2e41f26f121c420c6a7c2744f" + integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== bigint-buffer@^1.1.5: version "1.1.5" @@ -6953,58 +7624,46 @@ bigint-buffer@^1.1.5: dependencies: bindings "^1.3.0" -bignumber.js@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.1.1.tgz#4b072ae5aea9c20f6730e4e5d529df1271c4d885" - integrity sha512-QD46ppGintwPGuL1KqmwhR0O+N2cZUg8JG/VzwI2e28sM9TqHjQB10lI4QAaMHVbLzwVLLAwEglpKPViWX+5NQ== - -bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.0.2: +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== -bin-links@^2.2.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-2.3.0.tgz#1ff241c86d2c29b24ae52f49544db5d78a4eb967" - integrity sha512-JzrOLHLwX2zMqKdyYZjkDgQGT+kHDkIhv2/IK2lJ00qLxV4TmFoHi8drDBb6H5Zrz1YfgHkai4e2MGPqnoUhqA== +bin-links@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.1.tgz#afeb0549e642f61ff889b58ea2f8dca78fb9d8d3" + integrity sha512-bmFEM39CyX336ZGGRsGPlc6jZHriIoHacOQcTt72MktIjpPhZoP4te2jOyUXF3BLILmJ8aNLncoPVeIIFlrDeA== dependencies: - cmd-shim "^4.0.1" - mkdirp-infer-owner "^2.0.0" - npm-normalize-package-bin "^1.0.0" - read-cmd-shim "^2.0.0" - rimraf "^3.0.0" - write-file-atomic "^3.0.3" + cmd-shim "^6.0.0" + npm-normalize-package-bin "^3.0.0" + read-cmd-shim "^4.0.0" + write-file-atomic "^5.0.0" -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== +binance-api-node@^0.12.7: + version "0.12.7" + resolved "https://registry.yarnpkg.com/binance-api-node/-/binance-api-node-0.12.7.tgz#bce64742d5dc5a9398df3cbd861c486b4d4df075" + integrity sha512-hEIPaZg1YwZClOznAJo5Zb1JyxsqdYjT8twG48rhOwhbNVrLJRxkeGj+PTa881wFXOtyOtyrXsDytsEcI2EUHA== + dependencies: + https-proxy-agent "^5.0.0" + isomorphic-fetch "^3.0.0" + isomorphic-ws "^4.0.1" + json-bigint "^1.0.0" + lodash.zipobject "^4.1.3" + reconnecting-websocket "^4.2.0" + ws "^7.2.0" -binary-extensions@^2.0.0, binary-extensions@^2.2.0: +binary-extensions@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== bindings@^1.3.0, bindings@^1.5.0: version "1.5.0" - resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== dependencies: file-uri-to-path "1.0.0" -bip32@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz" - integrity sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA== - dependencies: - "@types/node" "10.12.18" - bs58check "^2.1.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - tiny-secp256k1 "^1.1.3" - typeforce "^1.11.5" - wif "^2.0.6" - bip39-light@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/bip39-light/-/bip39-light-1.0.7.tgz#06a72f251b89389a136d3f177f29b03342adc5ba" @@ -7044,57 +7703,23 @@ blakejs@^1.1.0: resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== -bluebird@3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -bn.js@5.2.0, bn.js@^5.0.0, bn.js@^5.1.0, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0: - version "5.2.0" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz" - integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== - -bn.js@^4.0.0, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.12.0: - version "4.12.0" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +bn.js@4.11.6, bn.js@5.1.3, bn.js@5.2.0, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.12.0, bn.js@^5.0.0, bn.js@^5.1.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.1.3" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" + integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== -body-parser@1.19.1: - version "1.19.1" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz" - integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== - dependencies: - bytes "3.1.1" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.6" - raw-body "2.4.2" - type-is "~1.6.18" - -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= +borsh@0.7.0, borsh@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" + integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" - dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" + bn.js "^5.2.0" + bs58 "^4.0.0" + text-encoding-utf-8 "^1.0.2" borsh@^0.3.1: version "0.3.1" - resolved "https://registry.npmjs.org/borsh/-/borsh-0.3.1.tgz" + resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.3.1.tgz#c31c3a149610e37913deada80e89073fb15cf55b" integrity sha512-gJoSTnhwLxN/i2+15Y7uprU8h3CKI+Co4YKZKvrGYUy0FwHWM20x5Sx7eU8Xv4HQqV+7rb4r3P7K1cBIQe3q8A== dependencies: "@types/bn.js" "^4.11.5" @@ -7104,7 +7729,7 @@ borsh@^0.3.1: borsh@^0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/borsh/-/borsh-0.4.0.tgz" + resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.4.0.tgz#9dd6defe741627f1315eac2a73df61421f6ddb9f" integrity sha512-aX6qtLya3K0AkT66CmYWCCDr77qsE9arV05OmdFpmat9qu8Pg9J5tBUPDztAW5fNh/d/MyVG/OYziP52Ndzx1g== dependencies: "@types/bn.js" "^4.11.5" @@ -7114,22 +7739,13 @@ borsh@^0.4.0: borsh@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/borsh/-/borsh-0.6.0.tgz" + resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.6.0.tgz#a7c9eeca6a31ca9e0607cb49f329cb659eb791e1" integrity sha512-sl5k89ViqsThXQpYa9XDtz1sBl3l1lI313cFUY1HKr+wvMILnb+58xpkqTNrYbelh99dY7K8usxoCusQmqix9Q== dependencies: bn.js "^5.2.0" bs58 "^4.0.0" text-encoding-utf-8 "^1.0.2" -borsh@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" - integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== - dependencies: - bn.js "^5.2.0" - bs58 "^4.0.0" - text-encoding-utf-8 "^1.0.2" - bowser@^2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" @@ -7143,44 +7759,31 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@~3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" -brorand@^1.1.0: +brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browser-process-hrtime@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -browserify-aes@^1.0.6, browserify-aes@^1.2.0: +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -7192,31 +7795,69 @@ browserify-aes@^1.0.6, browserify-aes@^1.2.0: inherits "^2.0.1" safe-buffer "^5.0.1" -browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.3, browserslist@^4.6.4: - version "4.16.5" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.5.tgz" +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: - caniuse-lite "^1.0.30001214" - colorette "^1.2.2" - electron-to-chromium "^1.3.719" - escalade "^3.1.1" - node-releases "^1.1.71" + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" -browserslist@^4.17.5: - version "4.19.1" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz" - integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: - caniuse-lite "^1.0.30001286" - electron-to-chromium "^1.4.17" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserslist@^4.12.0, browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^4.6.4: + version "4.21.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== + dependencies: + caniuse-lite "^1.0.30001400" + electron-to-chromium "^1.4.251" + node-releases "^2.0.6" + update-browserslist-db "^1.0.9" + +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" bs58@4.0.1, bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz" - integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== dependencies: base-x "^3.0.2" @@ -7227,7 +7868,7 @@ bs58@^5.0.0: dependencies: base-x "^4.0.0" -bs58check@<3.0.0, bs58check@^2.1.1, bs58check@^2.1.2: +bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== @@ -7238,46 +7879,58 @@ bs58check@<3.0.0, bs58check@^2.1.1, bs58check@^2.1.2: bser@2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== dependencies: node-int64 "^0.4.0" -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== + +buffer-from@^1.0.0, buffer-from@^1.1.0, buffer-from@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer-layout@1.2.2, buffer-layout@^1.2.0, buffer-layout@^1.2.1, buffer-layout@^1.2.2: +buffer-layout@1.2.2, buffer-layout@^1.2.0, buffer-layout@^1.2.2: version "1.2.2" - resolved "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz" + resolved "https://registry.yarnpkg.com/buffer-layout/-/buffer-layout-1.2.2.tgz#b9814e7c7235783085f9ca4966a0cfff112259d5" integrity sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA== +buffer-reverse@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-reverse/-/buffer-reverse-1.0.1.tgz#49283c8efa6f901bc01fa3304d06027971ae2f60" + integrity sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg== + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== -buffer@6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.1.tgz" - integrity sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - buffer@6.0.3, buffer@^6.0.1, buffer@^6.0.2, buffer@^6.0.3, buffer@~6.0.3: version "6.0.3" - resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== dependencies: base64-js "^1.3.1" ieee754 "^1.2.1" -buffer@^5.4.3, buffer@^5.5.0: +buffer@^5.1.0, buffer@^5.4.3, buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -7285,86 +7938,45 @@ buffer@^5.4.3, buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" -bufferutil@^4.0.1: - version "4.0.6" - resolved "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz" - integrity sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw== +bufferutil@^4.0.1, bufferutil@^4.0.6: + version "4.0.7" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== dependencies: node-gyp-build "^4.3.0" -builtins@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz" - integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= - -bytebuffer@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd" - integrity sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0= +bundle-require@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/bundle-require/-/bundle-require-5.0.0.tgz#071521bdea6534495cf23e92a83f889f91729e93" + integrity sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w== dependencies: - long "~3" - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - -bytes@3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz" - integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== + load-tsconfig "^0.2.3" bytes@^3.0.0: version "3.1.2" - resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacache@^15.0.3, cacache@^15.0.5, cacache@^15.2.0, cacache@^15.3.0: - version "15.3.0" - resolved "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz" - integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== - dependencies: - "@npmcli/fs" "^1.0.0" - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== +caip@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/caip/-/caip-1.1.0.tgz#0ccd5bf1bff822459389ccec0a8555712a30c374" + integrity sha512-yOO3Fu4ygyKYAdznuoaqschMKIZzcdgyMpBNtrIfrUhnOeaOWG+dh0c13wcOS6B/46IGGbncoyzJlio79jU7rw== + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" callsites@^3.0.0: version "3.1.0" @@ -7373,42 +7985,28 @@ callsites@^3.0.0: camelcase-css@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: +camelcase@^6.0.0, camelcase@^6.2.0, camelcase@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -camelcase@^6.2.0: - version "6.2.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz" - integrity sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA== - camelize@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" - integrity sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg== - -caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001196, caniuse-lite@^1.0.30001214, caniuse-lite@^1.0.30001286: - version "1.0.30001327" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001327.tgz" - -caniuse-lite@^1.0.30001332: - version "1.0.30001364" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001364.tgz#1e118f0e933ed2b79f8d461796b8ce45398014a0" - integrity sha512-9O0xzV3wVyX0SlegIQ6knz+okhBB5pE0PC40MNdwcipjwpxoUEHL24uJ+gG42cgklPjfO5ZjZPme9FTSN3QT2Q== + version "1.0.1" + resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" + integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== -canonicalize@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/canonicalize/-/canonicalize-1.0.8.tgz#24d1f1a00ed202faafd9bf8e63352cd4450c6df1" - integrity sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A== +caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001426: + version "1.0.30001439" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz#ab7371faeb4adff4b74dad1718a6fd122e45d9cb" + integrity sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A== capability@^0.2.5: version "0.2.5" @@ -7417,24 +8015,44 @@ capability@^0.2.5: caseless@~0.12.0: version "0.12.0" - resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +cbor-sync@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cbor-sync/-/cbor-sync-1.0.4.tgz#5a11a1ab75c2a14d1af1b237fd84aa8c1593662f" + integrity sha512-GWlXN4wiz0vdWWXBU71Dvc1q3aBo0HytqwAZnXF1wOwjqNnDWA1vZ1gDMFLlqohak31VQzmhiYfiCX5QSSfagA== ccount@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== +chai-as-promised@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" + check-error "^1.0.2" + +chai-bn@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/chai-bn/-/chai-bn-0.3.1.tgz#677cd3c0b58bae83ffe51604a811d0b3c6f41544" + integrity sha512-vuzEy0Cb+k8zqi2SHOmvZdRSbKcSOJfS1Nv8+6YDJIyCzfxkTCHLNRyjRIoRJ3WJtYb/c7OHjrvLoGeyO4A/gA== -chalk@^3.0.0: +chai@=4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" + integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@3.0.0, chalk@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== @@ -7442,56 +8060,62 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0: - version "4.1.1" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz" - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: +chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" -chan@^0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/chan/-/chan-0.6.1.tgz" - integrity sha1-7ArRMuW8YsJ+8QzL/E2NzYygBkA= +chalk@^1.0.0, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== char-regex@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" - -character-entities-legacy@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-2.0.0.tgz" - integrity sha512-YwaEtEvWLpFa6Wh3uVLrvirA/ahr9fki/NUd/Bd4OR6EdJ8D22hovYQEOUCBfQfcqnC4IAMGMsHXY1eXgL4ZZA== + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== character-entities@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/character-entities/-/character-entities-2.0.0.tgz" - integrity sha512-oHqMj3eAuJ77/P5PaIRcqk+C3hdfNwyCD2DAUcD5gyXkegAuF2USC40CEqPscDk4I8FRGMTojGJQkXDsN5QlJA== - -character-reference-invalid@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.0.tgz" - integrity sha512-pE3Z15lLRxDzWJy7bBHBopRwfI20sbrMVLQTC7xsPglCHf4Wv1e167OgYAFP78co2XlhojDyAqA+IAJse27//g== + version "2.0.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" + integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -check-more-types@2.24.0: - version "2.24.0" - resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" - integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= +check-error@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== + dependencies: + get-func-name "^2.0.2" -chokidar@3.5.3, chokidar@^3.5.2, chokidar@^3.5.3: +chokidar@3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -7506,132 +8130,115 @@ chokidar@3.5.3, chokidar@^3.5.2, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== +chokidar@^3.5.2, chokidar@^3.5.3, chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" optionalDependencies: - fsevents "^1.2.7" + fsevents "~2.3.2" chownr@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== ci-info@^3.2.0: - version "3.3.0" - resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz" - integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== - -cidr-regex@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/cidr-regex/-/cidr-regex-3.1.1.tgz" - integrity sha512-RBqYd32aDwbCMFJRL6wHOlDNYJsPNTt8vC82ErHF5vKt8QQzxm1FrkW8s/R5pVrXMf17sba09Uoy91PKiddAsw== - dependencies: - ip-regex "^4.1.0" + version "3.7.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.0.tgz#6d01b3696c59915b6ce057e4aa4adfc2fa25f5ef" + integrity sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" -circular-json@^0.5.9: - version "0.5.9" - resolved "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz" - integrity sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ== +citty@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.5.tgz#fe37ceae5dc764af75eb2fece99d2bf527ea4e50" + integrity sha512-AS7n5NSc0OQVMV9v6wt3ByujNIrne0/cTjiC2MYqhvao57VNfiuVksTSr2p17nVOhEr2KtqiAkGwHcgMC/qUuQ== + dependencies: + consola "^3.2.3" cjs-module-lexer@^1.0.0: version "1.2.2" - resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" +classnames@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" + integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== classnames@2.x, classnames@^2.2.1, classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1: - version "2.3.1" - resolved "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz" + version "2.3.2" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" + integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== clean-set@^1.1.1: version "1.1.2" - resolved "https://registry.npmjs.org/clean-set/-/clean-set-1.1.2.tgz" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" - -clean-stack@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz" - integrity sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg== - dependencies: - escape-string-regexp "4.0.0" + resolved "https://registry.yarnpkg.com/clean-set/-/clean-set-1.1.2.tgz#76d8bf238c3e27827bfa73073ecdfdc767187070" + integrity sha512-cA8uCj0qSoG9e0kevyOWXwPaELRPVg5Pxp6WskLMwerx257Zfnh8Nl0JBH59d7wQzij2CK7qEfJQK3RjuKKIug== -cli-columns@^3.1.2: - version "3.1.2" - resolved "https://registry.npmjs.org/cli-columns/-/cli-columns-3.1.2.tgz" - integrity sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4= +cli-cursor@^2.0.0, cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== dependencies: - string-width "^2.0.0" - strip-ansi "^3.0.1" + restore-cursor "^2.0.0" cli-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== dependencies: restore-cursor "^3.1.0" cli-spinners@^2.5.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" - integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== - -cli-table3@^0.6.0: - version "0.6.2" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.2.tgz#aaf5df9d8b5bf12634dc8b3040806a0c07120d2a" - integrity sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw== - dependencies: - string-width "^4.2.0" - optionalDependencies: - "@colors/colors" "1.5.0" + version "2.7.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a" + integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz" +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + integrity sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg== dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" + slice-ansi "0.0.4" + string-width "^1.0.1" cli-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== +client-only@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + +clipboardy@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-4.0.0.tgz#e73ced93a76d19dd379ebf1f297565426dffdca1" + integrity sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w== + dependencies: + execa "^8.0.1" + is-wsl "^3.1.0" + is64bit "^2.0.0" + cliui@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== dependencies: string-width "^3.1.0" @@ -7640,70 +8247,72 @@ cliui@^5.0.0: cliui@^7.0.2: version "7.0.4" - resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" strip-ansi "^6.0.0" wrap-ansi "^7.0.0" -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" clone@^1.0.2: version "1.0.4" - resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== -clsx@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" - integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== +clsx@1.2.1, clsx@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== -cmd-shim@^4.0.1: - version "4.1.0" - resolved "https://registry.npmjs.org/cmd-shim/-/cmd-shim-4.1.0.tgz" - integrity sha512-lb9L7EM4I/ZRVuljLPEtUJOP+xiQVknZ4ZMpMgEp4JzNldPb27HU03hi6K1/6CoIuit/Zm/LQXySErFeXxDprw== - dependencies: - mkdirp-infer-owner "^2.0.0" +clsx@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +cluster-key-slot@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== + +cmd-shim@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.1.tgz#a65878080548e1dca760b3aea1e21ed05194da9d" + integrity sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q== co@^4.6.0: version "4.6.0" - resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== code-point-at@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== collect-v8-coverage@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz" - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" @@ -7711,7 +8320,7 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: version "1.1.4" @@ -7719,52 +8328,34 @@ color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.6.0, color-string@^1.9.0: - version "1.9.0" - resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz" - integrity sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ== + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" -color-support@^1.1.2: - version "1.1.3" - resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - color@^3.1.3: version "3.2.1" - resolved "https://registry.npmjs.org/color/-/color-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== dependencies: color-convert "^1.9.3" color-string "^1.6.0" color@^4.0.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/color/-/color-4.2.1.tgz#498aee5fce7fc982606c8875cab080ac0547c884" - integrity sha512-MFJr0uY4RvTQUKvPq7dh9grVOTYSFeXja2mBXioCGjnjJoXrAp9jJ1NQTDR73c9nwBSAQiNKloKl5zq9WB9UPw== + version "4.2.3" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" + integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== dependencies: color-convert "^2.0.1" color-string "^1.9.0" -colorette@^1.2.1, colorette@^1.2.2: - version "1.4.0" - resolved "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== - colors@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -columnify@~1.5.4: - version "1.5.4" - resolved "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz" - integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs= - dependencies: - strip-ansi "^3.0.0" - wcwidth "^1.0.0" - combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -7773,141 +8364,111 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: delayed-stream "~1.0.0" comma-separated-tokens@^2.0.0: - version "2.0.2" - resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz" - integrity sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" + integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== commander@7: version "7.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +commander@^12.0.0, commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + commander@^2.20.3: version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^4.0.0, commander@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + commander@^6.2.0: version "6.2.1" - resolved "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== commander@^8.0.0, commander@^8.2.0: version "8.3.0" - resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== -common-ancestor-path@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz" - integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w== - -component-emitter@^1.2.1, component-emitter@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -compressible@~2.0.16: - version "2.0.18" - resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" +commander@^9.4.0: + version "9.4.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" + integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== +consola@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f" + integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ== -console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: +console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz" - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== -cookie@0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz" - integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== - -cookie@^0.4.1: - version "0.4.2" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== +convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== -cookiejar@^2.1.2, cookiejar@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" - integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= +cookie-es@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cookie-es/-/cookie-es-1.0.0.tgz#4759684af168dfc54365b2c2dda0a8d7ee1e4865" + integrity sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ== copy-to-clipboard@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" - integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== + version "3.3.3" + resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" + integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== dependencies: toggle-selection "^1.0.6" -core-js-pure@^3.0.0: - version "3.11.0" - resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.11.0.tgz" +core-js-pure@^3.25.1: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.26.1.tgz#653f4d7130c427820dcecd3168b594e8bb095a33" + integrity sha512-VVXcDpp/xJ21KdULRq/lXdLzQAtX7+37LzpyfFM973il0tWSsDEoyzG38G14AjTpK9VTfiNM9jnFauq/CpaWGQ== + +core-js@^3.6.4: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e" + integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA== core-util-is@1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== -core-util-is@^1.0.2, core-util-is@~1.0.0: +core-util-is@~1.0.0: version "1.0.3" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== cosmiconfig@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" + integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== dependencies: "@types/parse-json" "^4.0.0" import-fresh "^3.1.0" @@ -7915,9 +8476,10 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" -cosmiconfig@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz" +cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" import-fresh "^3.2.1" @@ -7925,20 +8487,29 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -cosmiconfig@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== +crc@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" + integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" + buffer "^5.1.0" + +crc@^4.1.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/crc/-/crc-4.3.2.tgz#49b7821cbf2cf61dfd079ed93863bbebd5469b9a" + integrity sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A== + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" @@ -7947,9 +8518,9 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@1.1.7, create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@1.1.7, create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" - resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" @@ -7961,67 +8532,80 @@ create-hmac@1.1.7, create-hmac@^1.1.4, create-hmac@^1.1.7: create-require@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cron-validator@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/cron-validator/-/cron-validator-1.3.1.tgz#8f2fe430f92140df77f91178ae31fc1e3a48a20e" + integrity sha512-C1HsxuPCY/5opR55G5/WNzyEGDWFVG+6GLrA+fW/sCTcP6A6NTjUP2AK7B8n2PyFs90kDG2qzwm8LMheADku6A== + cross-fetch@3.0.6: version "3.0.6" - resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c" integrity sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ== dependencies: node-fetch "2.6.1" -cross-fetch@^3.1.4, cross-fetch@^3.1.5: - version "3.1.5" - resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== +cross-fetch@^3.0.4, cross-fetch@^3.1.5: + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== dependencies: - node-fetch "2.6.7" + node-fetch "^2.6.12" -cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== +cross-fetch@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" + integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" + node-fetch "^2.6.12" cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" which "^2.0.1" +crossws@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/crossws/-/crossws-0.1.1.tgz#3a85a8140568e4828d9747a884171ea7e6a8bbe2" + integrity sha512-c9c/o7bS3OjsdpSkvexpka0JNlesBF2JU9B2V1yNsYGwRbAafxhJQ7VI9b48D5bpONz/oxbPGMzBojy9sXoQIQ== + +crypto-browserify@^3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + crypto-hash@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/crypto-hash/-/crypto-hash-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/crypto-hash/-/crypto-hash-1.3.0.tgz#b402cb08f4529e9f4f09346c3e275942f845e247" integrity sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg== -crypto-js@^4.0.0: - version "4.1.1" - resolved "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz" - integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== - -crypto-ts@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/crypto-ts/-/crypto-ts-1.0.2.tgz" - integrity sha1-wq5HtC8aiv/PM73b4yg5gxUMigU= - dependencies: - tslib "^1.7.1" - -crypto@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz" - integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig== +crypto-js@4.1.1, crypto-js@>=4.1.1, crypto-js@^3.1.9-1, crypto-js@^4.1.1, crypto-js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== css-blank-pseudo@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz" + resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" + integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== dependencies: postcss "^7.0.5" @@ -8032,12 +8616,13 @@ css-color-keywords@^1.0.0: css-color-names@^0.0.4: version "0.0.4" - resolved "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + integrity sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q== css-has-pseudo@^0.10.0: version "0.10.0" - resolved "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz" + resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" + integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== dependencies: postcss "^7.0.6" postcss-selector-parser "^5.0.0-rc.4" @@ -8049,14 +8634,15 @@ css-mediaquery@^0.1.2: css-prefers-color-scheme@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" + integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== dependencies: postcss "^7.0.5" css-to-react-native@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756" - integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ== + version "3.2.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32" + integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ== dependencies: camelize "^1.0.0" css-color-keywords "^1.0.0" @@ -8064,17 +8650,17 @@ css-to-react-native@^3.0.0: css-unit-converter@^1.1.1: version "1.1.2" - resolved "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21" integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA== css.escape@^1.5.1: version "1.5.1" - resolved "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz" - integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== css@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/css/-/css-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ== dependencies: inherits "^2.0.4" @@ -8083,64 +8669,65 @@ css@^3.0.0: cssdb@^4.4.0: version "4.4.0" - resolved "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" + integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== cssesc@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== cssesc@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssom@^0.4.4: - version "0.4.4" - resolved "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz" +cssom@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" + integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== cssom@~0.3.6: version "0.3.8" - resolved "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== cssstyle@^2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== dependencies: cssom "~0.3.6" csstype@^3.0.2: - version "3.0.8" - resolved "https://registry.npmjs.org/csstype/-/csstype-3.0.8.tgz" - -csv-generate@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csv-generate/-/csv-generate-4.2.0.tgz#06e23634415c1d5a7cb111102bbea868b0857e6f" - integrity sha512-zlIESlGQaYqIhNYwBN2pj5KXNMYbAXZYMOgNoVSoYV8MQyGZwcNWX+kx5LHxocp+zQDqzSgeKh+e+AZs+nCq4Q== + version "3.1.1" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== -csv-parse@^5.0.4: - version "5.0.4" - resolved "https://registry.npmjs.org/csv-parse/-/csv-parse-5.0.4.tgz" - integrity sha512-5AIdl8l6n3iYQYxan5djB5eKDa+vBnhfWZtRpJTcrETWfVLYN0WSj3L9RwvgYt+psoO77juUr8TG8qpfGZifVQ== +csv-generate@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/csv-generate/-/csv-generate-4.2.1.tgz#2a0c5f0d9a5b6f7a0c1fee40f028707af048b31b" + integrity sha512-w6GFHjvApv6bcJ2xdi9JGsH6ZvUBfC+vUdfefnEzurXG6hMRwzkBLnhztU2H7v7+zfCk1I/knnQ+tGbgpxWrBw== -csv-parse@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-5.3.0.tgz#85cc02fc9d1c89bd1b02e69069c960f8b8064322" - integrity sha512-UXJCGwvJ2fep39purtAn27OUYmxB1JQto+zhZ4QlJpzsirtSFbzLvip1aIgziqNdZp/TptvsKEV5BZSxe10/DQ== +csv-parse@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-5.3.3.tgz#3b75d2279e2edb550cbc54c65b25cbbf3d0033ad" + integrity sha512-kEWkAPleNEdhFNkHQpFHu9RYPogsFj3dx6bCxL847fsiLgidzWg0z/O0B1kVWMJUc5ky64zGp18LX2T3DQrOfw== -csv-stringify@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/csv-stringify/-/csv-stringify-6.2.0.tgz#f89881e8f61293bf5af11f421266b5da7b744030" - integrity sha512-dcUbQLRTTDcgQxgEU8V9IctkaCwHZjZfzUZ5ZB3RY8Y+pXtdtl5iVQHfGzANytFFkRKanYzBXrkfpNdGR7eviA== +csv-stringify@^6.2.3: + version "6.2.3" + resolved "https://registry.yarnpkg.com/csv-stringify/-/csv-stringify-6.2.3.tgz#fefd25e66fd48f8f42f43b85a66a4663a2c3e796" + integrity sha512-4qGjUMwnlaRc00gc2jrIYh2w/h1fo25B0mTuY9K8fBiIgtmCX3LcgUbrEGViL98Ci4Se/F5LFEtu8k+dItJVZQ== csv@^6.0.5: - version "6.2.0" - resolved "https://registry.yarnpkg.com/csv/-/csv-6.2.0.tgz#edab9979067fe9bb4c6a4381aaebba96ef5b3017" - integrity sha512-yT7dkCsJLJ36NUW0d0ei7parOcUCx/QVkK77puwA/rF4bMciTB5Kf+wuegL+7zh8s6revFM+BFQ2h+U2k4jgBQ== + version "6.2.5" + resolved "https://registry.yarnpkg.com/csv/-/csv-6.2.5.tgz#e01fd3db2f0856a120ae9140bd179c1a186ee2b9" + integrity sha512-T+K0H7MIrlrnP6KxYKo3lK+uLl6OC2Gmwdd81TG/VdkhKvpatl35sR7tyRSpDLGl22y2T+q9KvNHnVtn4OAscQ== dependencies: - csv-generate "^4.2.0" - csv-parse "^5.3.0" - csv-stringify "^6.2.0" - stream-transform "^3.2.0" + csv-generate "^4.2.1" + csv-parse "^5.3.3" + csv-stringify "^6.2.3" + stream-transform "^3.2.1" d3-array@2, d3-array@^2.3.0: version "2.12.1" @@ -8149,10 +8736,10 @@ d3-array@2, d3-array@^2.3.0: dependencies: internmap "^1.0.0" -"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3: - version "3.1.6" - resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.1.6.tgz#0342c835925826f49b4d16eb7027aec334ffc97d" - integrity sha512-DCbBBNuKOeiR9h04ySRBMW52TFVc91O9wJziuyXw6Ztmy8D3oZbmCkOO3UHKC7ceNJsN2Mavo9+vwV8EAEUXzA== +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.1.6: + version "3.2.2" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.2.tgz#f8ac4705c5b06914a7e0025bbf8d5f1513f6a86e" + integrity sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ== dependencies: internmap "1 - 2" @@ -8179,20 +8766,15 @@ d3-chord@3: dependencies: d3-path "1 - 3" -"d3-color@1 - 2", d3-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e" - integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ== - -"d3-color@1 - 3", d3-color@3: +"d3-color@1 - 2", "d3-color@1 - 3", d3-color@3, d3-color@3.1.0, d3-color@^2.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== d3-contour@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-3.0.1.tgz#2c64255d43059599cd0dba8fe4cc3d51ccdd9bbd" - integrity sha512-0Oc4D0KyhwhM7ZL0RMnfGycLN7hxHB8CMmwZ3+H26PWAG0ozNuYG5hXSDNgmP1SgJkQMrlG6cP20HoaSbvcJTQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-3.1.0.tgz#708484a5d89be9558dfdda4a95b3df2fdebb65ab" + integrity sha512-vV3xtwrYK5p1J4vyukr70m57mtFTEQYqoaDC1ylBfht/hkdUF0nfWZ1b3V2EPBUVkUkoqq5/fbRoBImBWJgOsg== dependencies: d3-array "2 - 3" @@ -8225,7 +8807,7 @@ d3-delaunay@6: iconv-lite "0.6" rw "1" -"d3-ease@1 - 3", d3-ease@3: +"d3-ease@1 - 3", d3-ease@3, d3-ease@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== @@ -8280,7 +8862,7 @@ d3-hierarchy@3: dependencies: d3-color "1 - 2" -"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3, d3-interpolate@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== @@ -8292,10 +8874,10 @@ d3-path@1: resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== -"d3-path@1 - 3", d3-path@3: - version "3.0.1" - resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e" - integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w== +"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== d3-polygon@3: version "3.0.1" @@ -8328,7 +8910,7 @@ d3-scale-chromatic@^2.0.0: d3-color "1 - 2" d3-interpolate "1 - 2" -d3-scale@4: +d3-scale@4, d3-scale@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== @@ -8355,12 +8937,12 @@ d3-scale@^3.2.3: resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== -d3-shape@3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.1.0.tgz#c8a495652d83ea6f524e482fca57aa3f8bc32556" - integrity sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ== +d3-shape@3, d3-shape@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== dependencies: - d3-path "1 - 3" + d3-path "^3.1.0" d3-shape@^1.2.2, d3-shape@^1.3.5: version "1.3.7" @@ -8390,10 +8972,10 @@ d3-shape@^1.2.2, d3-shape@^1.3.5: dependencies: d3-array "2" -"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975" - integrity sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ== +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3, d3-time@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== dependencies: d3-array "2 - 3" @@ -8402,7 +8984,7 @@ d3-time@^1.0.11: resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1" integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA== -"d3-timer@1 - 3", d3-timer@3: +"d3-timer@1 - 3", d3-timer@3, d3-timer@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== @@ -8429,7 +9011,7 @@ d3-zoom@3: d3-selection "2 - 3" d3-transition "2 - 3" -d3@^7.4.4: +d3@7.4.4: version "7.4.4" resolved "https://registry.yarnpkg.com/d3/-/d3-7.4.4.tgz#bfbf87487c37d3196efebd5a63e3a0ed8299d8ff" integrity sha512-97FE+MYdAlV3R9P74+R3Uar7wUKkIFu89UWMjEaDhiJ9VxKvqaMxauImy8PC2DdBkdM2BxJOIoLxPrcZUyrKoQ== @@ -8468,194 +9050,191 @@ d3@^7.4.4: dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== dependencies: assert-plus "^1.0.0" -data-uri-to-buffer@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" - integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== +data-urls@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" + integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== + dependencies: + abab "^2.0.6" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" -data-urls@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz" +data-view-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" + integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" + integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== dependencies: - abab "^2.0.3" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.0.0" + call-bind "^1.0.7" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" + integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +date-fns@2.29.2: + version "2.29.2" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.2.tgz#0d4b3d0f3dff0f920820a070920f0d9662c51931" + integrity sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA== -dataloader@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz" - integrity sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw== +date-fns@^1.27.2: + version "1.30.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" + integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== -dayjs@^1.11.1: +dayjs@1.11.1: version "1.11.1" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.1.tgz#90b33a3dda3417258d48ad2771b415def6545eb0" integrity sha512-ER7EjqVAMkRRsxNCC5YqJ9d9VQYuWdGt7aiH2qA5R5wt8ZmWaP2dLUSIK6y/kVzLMlmh1Tvu5xUf4M/wdGJ5KA== -dayjs@^1.11.2: - version "1.11.5" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93" - integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA== - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5, debug@~4.3.1, debug@~4.3.2: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== dependencies: - ms "2.0.0" + ms "2.1.2" -debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: +debug@4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - -debug@4.3.3: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -debug@^3.1.1, debug@^3.2.6: +debug@^3.2.7: version "3.2.7" - resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" -debuglog@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz" - integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= - decamelize@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== -decimal.js-light@^2.5.1: +decimal.js-light@^2.4.1, decimal.js-light@^2.5.1: version "2.5.1" - resolved "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz" + resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== -decimal.js@^10.2.1, decimal.js@^10.3.1: - version "10.3.1" - resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz" - integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== +decimal.js@10.4.3, decimal.js@^10.4.0, decimal.js@^10.4.2, decimal.js@^10.4.3: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== decode-named-character-reference@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.1.tgz" - integrity sha512-YV/0HQHreRwKb7uBopyIkLG17jG6Sv2qUchk9qSoVJ2f+flwRsPNBO0hAnjt6mTNYUT+vw9Gy2ihXg4sUWPi2w== + version "1.0.2" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" + integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== dependencies: character-entities "^2.0.0" -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +decode-uri-component@^0.2.0, decode-uri-component@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== dedent@^0.7.0: version "0.7.0" - resolved "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" + type-detect "^4.0.0" + +deep-equal@^2.0.5: + version "2.1.0" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.1.0.tgz#5ba60402cf44ab92c2c07f3f3312c3d857a0e1dd" + integrity sha512-2pxgvWu3Alv1PoWEyVg7HS8YhGlUFUV7N5oOvfL6d+7xAmLSemMwv/c8Zv/i9KFzxV5Kt5CAvQc70fLwVuf4UA== + dependencies: + call-bind "^1.0.2" + es-get-iterator "^1.1.2" + get-intrinsic "^1.1.3" + is-arguments "^1.1.1" + is-date-object "^1.0.5" + is-regex "^1.1.4" + isarray "^2.0.5" + object-is "^1.1.5" object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + side-channel "^1.0.4" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.8" deep-is@^0.1.3, deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz" + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== deepmerge@^4.2.2: version "4.2.2" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" - -default-gateway@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz" - integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== - dependencies: - execa "^1.0.0" - ip-regex "^2.1.0" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== dependencies: clone "^1.0.2" -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== dependencies: - is-descriptor "^1.0.0" + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== +define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" defined@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz" - integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + version "1.0.1" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" + integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== -del@^4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/del/-/del-4.1.1.tgz" - integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== - dependencies: - "@types/glob" "^7.1.1" - globby "^6.1.0" - is-path-cwd "^2.0.0" - is-path-in-cwd "^2.0.0" - p-map "^2.0.0" - pify "^4.0.1" - rimraf "^2.6.3" +defu@^6.1.3, defu@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" + integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== delaunator@5: version "5.0.0" @@ -8666,62 +9245,83 @@ delaunator@5: delay@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== delegates@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -depd@^1.1.2, depd@~1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +denque@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" + integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== depd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + dequal@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destr@^2.0.1, destr@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz" - integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug== + resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.2.tgz#8d3c0ee4ec0a76df54bc8b819bca215592a8c218" + integrity sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg== -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +detect-browser@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.2.0.tgz#c9cd5afa96a6a19fda0bbe9e9be48a6b6e1e9c97" + integrity sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA== + +detect-browser@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" + integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w== + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== detect-newline@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== detect-node-es@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== -detect-node@2.1.0, detect-node@^2.0.4, detect-node@^2.1.0: +detect-node@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== detective@^5.2.0: - version "5.2.0" - resolved "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz" - integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg== - dependencies: - acorn-node "^1.6.1" - defined "^1.0.0" - minimist "^1.1.1" - -detective@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034" integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw== @@ -8730,32 +9330,7 @@ detective@^5.2.1: defined "^1.0.0" minimist "^1.2.6" -dezalgo@1.0.3, dezalgo@^1.0.0: - version "1.0.3" - resolved "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz" - integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= - dependencies: - asap "^2.0.0" - wrappy "1" - -"did-jwt@git+https://github.com/civicteam/did-jwt": - version "6.1.0" - resolved "git+https://github.com/civicteam/did-jwt#d4e318df78bd88e3127e62784915c7a334881eb6" - dependencies: - "@stablelib/ed25519" "^1.0.2" - "@stablelib/random" "^1.0.1" - "@stablelib/sha256" "^1.0.1" - "@stablelib/x25519" "^1.0.2" - "@stablelib/xchacha20poly1305" "^1.0.1" - bech32 "^2.0.0" - canonicalize "^1.0.8" - did-resolver "^3.1.5" - elliptic "^6.5.4" - js-sha3 "^0.8.0" - multiformats "^9.6.4" - uint8arrays "^3.0.0" - -did-resolver@^3.0.1, did-resolver@^3.1.5, did-resolver@^3.2.0: +did-resolver@^3.0.1, did-resolver@^3.2.0, did-resolver@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/did-resolver/-/did-resolver-3.2.2.tgz#6f4e252a810f785d1b28a10265fad6dffee25158" integrity sha512-Eeo2F524VM5N3W4GwglZrnul2y6TLTwMQP3In62JdG34NZoqihYyOZLk+5wUW8sSgvIYIcJM8Dlt3xsdKZZ3tg== @@ -8765,110 +9340,114 @@ didyoumean@^1.2.2: resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== -diff-sequences@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" - integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== +diff-sequences@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e" + integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ== -diff@5.0.0, diff@^5.0.0: +diff@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== +diff@^3.1.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + diff@^4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dijkstrajs@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23" + integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA== + dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" dlv@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" - -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= - dependencies: - buffer-indexof "^1.0.0" - doctrine@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" - dependencies: - esutils "^2.0.2" - -dom-accessibility-api@^0.5.4, dom-accessibility-api@^0.5.6: - version "0.5.10" - resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.10.tgz" - integrity sha512-Xu9mD0UjrJisTmv7lmVSDMagQcU9R5hwAbxsaAE/35XPnPLJobbuREfV/rraiSaEj/UOvgrzQs66zyTWTlyd+g== +dom-accessibility-api@^0.5.6: + version "0.5.14" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz#56082f71b1dc7aac69d83c4285eef39c15d93f56" + integrity sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg== dom-align@^1.7.0: - version "1.12.0" - resolved "https://registry.npmjs.org/dom-align/-/dom-align-1.12.0.tgz" + version "1.12.4" + resolved "https://registry.yarnpkg.com/dom-align/-/dom-align-1.12.4.tgz#3503992eb2a7cfcb2ed3b2a6d21e0b9c00d54511" + integrity sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw== -dom-helpers@^5.0.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" - integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== +dom-helpers@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" + integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== dependencies: - "@babel/runtime" "^7.8.7" - csstype "^3.0.2" + "@babel/runtime" "^7.1.2" -domexception@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz" +domexception@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673" + integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw== dependencies: - webidl-conversions "^5.0.0" + webidl-conversions "^7.0.0" dot-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== dependencies: no-case "^3.0.4" tslib "^2.0.3" -dotenv-expand@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-6.0.1.tgz" - integrity sha512-GNHcCOyRKLCXWnH3L/+sJ04PQxxgTOZDCPuQQnqkqPMGIilyoxHZ2JUNmh2VWKCfzVKH/AZsqcbuSYlDDVb/xw== - -dotenv@10.0.0, dotenv@^10.0.0: +dotenv@10.0.0: version "10.0.0" - resolved "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== -dotenv@^8.6.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" - integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== +dotenv@^16.0.3, dotenv@^16.3.1: + version "16.3.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" + integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== + +draft-js@0.11.7: + version "0.11.7" + resolved "https://registry.yarnpkg.com/draft-js/-/draft-js-0.11.7.tgz#be293aaa255c46d8a6647f3860aa4c178484a206" + integrity sha512-ne7yFfN4sEL82QPQEn80xnADR8/Q6ALVworbC5UOSzOvjffmYfFsr3xSZtxbIirti14R7Y33EZC5rivpLgIbsg== + dependencies: + fbjs "^2.0.0" + immutable "~3.7.4" + object-assign "^4.1.1" drbg.js@^1.0.1: version "1.0.1" @@ -8879,54 +9458,66 @@ drbg.js@^1.0.1: create-hash "^1.1.2" create-hmac "^1.1.4" -dset@^2.0.1: - version "2.1.0" - resolved "https://registry.npmjs.org/dset/-/dset-2.1.0.tgz" +dset@3.1.2, dset@^2.0.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a" + integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q== -duplexer@^0.1.2, duplexer@~0.1.1: +duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== +duplexify@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" + integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ecc-jsbn@~0.1.1: version "0.1.2" - resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" -ed2curve-esm@^0.3.0-alpha-1: - version "0.3.0-alpha-1" - resolved "https://registry.yarnpkg.com/ed2curve-esm/-/ed2curve-esm-0.3.0-alpha-1.tgz#67a5722ea97976c3310aeaf0990a2b58ee383aef" - integrity sha512-Ydrqcf0NwKUBT4gL0Nnxp8/O5NG8iatN+/zbEgs/7eMGjgSVbgfE1YfWld2qYnoNIxOQvSWOFy5uBoaL3jCanw== - dependencies: - tweetnacl "^1.0.1" - -ed2curve@0.3.0, ed2curve@^0.3.0: +ed2curve@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/ed2curve/-/ed2curve-0.3.0.tgz#322b575152a45305429d546b071823a93129a05d" integrity sha512-8w2fmmq3hv9rCrcI7g9hms2pMunQr1JINfcjwR9tAyZqhtyaMN991lF/ZfHfr5tzZQ8c7y7aBgZbjfbd0fjFwQ== dependencies: tweetnacl "1.x.x" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= +eip1193-provider@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/eip1193-provider/-/eip1193-provider-1.0.1.tgz#420d29cf4f6c443e3f32e718fb16fafb250637c3" + integrity sha512-kSuqwQ26d7CzuS/t3yRXo2Su2cVH0QfvyKbr2H7Be7O5YDyIq4hQGCNTo5wRdP07bt+E2R/8nPCzey4ojBHf7g== + dependencies: + "@json-rpc-tools/provider" "^1.5.5" -electron-to-chromium@^1.3.719: - version "1.3.720" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.720.tgz" +electron-to-chromium@^1.4.251: + version "1.4.284" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== -electron-to-chromium@^1.4.17: - version "1.4.21" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.21.tgz" - integrity sha512-T04U2ciApGbm+dESFEBbewi2Xt0Dgyww8M4n4sOt9lnmFuYbaHEDWCROkx4jvAZDUWWry9YOdnAs+7468q80Qg== +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" + integrity sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ== -elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.4: +elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" - resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== dependencies: bn.js "^4.11.9" @@ -8937,43 +9528,44 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -emittery@^0.8.1: - version "0.8.1" - resolved "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz" - integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== emoji-regex@^7.0.1: version "7.0.3" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -encoding@^0.1.12, encoding@^0.1.13: +encoding@^0.1.13: version "0.1.13" - resolved "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.1.0, end-of-stream@^1.4.4: +end-of-stream@^1.1.0, end-of-stream@^1.4.1, end-of-stream@^1.4.4: version "1.4.4" - resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -engine.io-client@~6.2.1: - version "6.2.2" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.2.2.tgz#c6c5243167f5943dcd9c4abee1bfc634aa2cbdd0" - integrity sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ== +engine.io-client@~6.2.3: + version "6.2.3" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.2.3.tgz#a8cbdab003162529db85e9de31575097f6d29458" + integrity sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw== dependencies: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" @@ -8986,32 +9578,18 @@ engine.io-parser@~5.0.3: resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.4.tgz#0b13f704fa9271b3ec4f33112410d8f3f41d0fc0" integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg== -enhanced-resolve@^5.0.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" - integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -enhanced-resolve@^5.7.0: - version "5.9.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz#44a342c012cbc473254af5cc6ae20ebd0aae5d88" - integrity sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow== +enhanced-resolve@^5.0.0, enhanced-resolve@^5.10.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" + integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" -enquirer@^2.3.6: - version "2.3.6" - resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" - dependencies: - ansi-colors "^4.1.1" - -entities@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" + integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== env-paths@^2.2.0: version "2.2.1" @@ -9023,13 +9601,6 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -errno@^0.1.3: - version "0.1.8" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" - integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== - dependencies: - prr "~1.0.1" - error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -9046,35 +9617,130 @@ error-polyfill@^0.1.3: o3 "^1.0.3" u3 "^0.1.1" -es-abstract@^1.18.5, es-abstract@^1.19.0, es-abstract@^1.19.1: - version "1.19.1" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz" - integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== - dependencies: - call-bind "^1.0.2" +es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: + version "1.23.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" + integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + data-view-buffer "^1.0.1" + data-view-byte-length "^1.0.1" + data-view-byte-offset "^1.0.0" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + hasown "^2.0.2" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" + is-callable "^1.2.7" + is-data-view "^1.0.1" + is-negative-zero "^2.0.3" is-regex "^1.1.4" - is-shared-array-buffer "^1.0.1" + is-shared-array-buffer "^1.0.3" is-string "^1.0.7" - is-weakref "^1.0.1" - object-inspect "^1.11.0" + is-typed-array "^1.1.13" + is-weakref "^1.0.2" + object-inspect "^1.13.1" object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.2" + safe-regex-test "^1.0.3" + string.prototype.trim "^1.2.9" + string.prototype.trimend "^1.0.8" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.2" + typed-array-length "^1.0.6" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.15" + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.2.1, es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-get-iterator@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7" + integrity sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.0" + has-symbols "^1.0.1" + is-arguments "^1.1.0" + is-map "^2.0.2" + is-set "^2.0.2" + is-string "^1.0.5" + isarray "^2.0.5" + +es-iterator-helpers@^1.0.19: + version "1.0.19" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8" + integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + globalthis "^1.0.3" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + internal-slot "^1.0.7" + iterator.prototype "^1.1.2" + safe-array-concat "^1.1.2" + +es-object-atoms@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" + integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== + dependencies: + get-intrinsic "^1.2.4" + has-tostringtag "^1.0.2" + hasown "^2.0.1" + +es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + dependencies: + hasown "^2.0.0" es-to-primitive@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" @@ -9083,64 +9749,80 @@ es-to-primitive@^1.2.1: es6-object-assign@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz" - integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= + resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" + integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw== es6-promise@^4.0.3, es6-promise@^4.2.8: version "4.2.8" - resolved "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== es6-promisify@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== dependencies: es6-promise "^4.0.3" +esbuild@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.23.0.tgz#de06002d48424d9fdb7eb52dbe8e95927f852599" + integrity sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA== + optionalDependencies: + "@esbuild/aix-ppc64" "0.23.0" + "@esbuild/android-arm" "0.23.0" + "@esbuild/android-arm64" "0.23.0" + "@esbuild/android-x64" "0.23.0" + "@esbuild/darwin-arm64" "0.23.0" + "@esbuild/darwin-x64" "0.23.0" + "@esbuild/freebsd-arm64" "0.23.0" + "@esbuild/freebsd-x64" "0.23.0" + "@esbuild/linux-arm" "0.23.0" + "@esbuild/linux-arm64" "0.23.0" + "@esbuild/linux-ia32" "0.23.0" + "@esbuild/linux-loong64" "0.23.0" + "@esbuild/linux-mips64el" "0.23.0" + "@esbuild/linux-ppc64" "0.23.0" + "@esbuild/linux-riscv64" "0.23.0" + "@esbuild/linux-s390x" "0.23.0" + "@esbuild/linux-x64" "0.23.0" + "@esbuild/netbsd-x64" "0.23.0" + "@esbuild/openbsd-arm64" "0.23.0" + "@esbuild/openbsd-x64" "0.23.0" + "@esbuild/sunos-x64" "0.23.0" + "@esbuild/win32-arm64" "0.23.0" + "@esbuild/win32-ia32" "0.23.0" + "@esbuild/win32-x64" "0.23.0" + escalade@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== escape-string-regexp@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== -escodegen@^1.8.1: - version "1.14.3" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" - integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== - dependencies: - esprima "^4.0.1" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - escodegen@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== dependencies: esprima "^4.0.1" estraverse "^5.2.0" @@ -9149,160 +9831,193 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" - integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== +eslint-config-prettier@9.1.0, eslint-config-prettier@^9.0.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" + integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== -eslint-plugin-react-hooks@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.5.0.tgz#5f762dfedf8b2cf431c689f533c9d3fa5dcf25ad" - integrity sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw== +eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-module-utils@^2.8.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" + integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== + dependencies: + debug "^3.2.7" + +eslint-plugin-import@2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" + integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== + dependencies: + array-includes "^3.1.7" + array.prototype.findlastindex "^1.2.3" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.8.0" + hasown "^2.0.0" + is-core-module "^2.13.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.7" + object.groupby "^1.0.1" + object.values "^1.1.7" + semver "^6.3.1" + tsconfig-paths "^3.15.0" -eslint-plugin-react@^7.29.4: - version "7.29.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz#4717de5227f55f3801a5fd51a16a4fa22b5914d2" - integrity sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ== +eslint-plugin-prettier@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz#d1c8f972d8f60e414c25465c163d16f209411f95" + integrity sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw== dependencies: - array-includes "^3.1.4" - array.prototype.flatmap "^1.2.5" + prettier-linter-helpers "^1.0.0" + synckit "^0.9.1" + +eslint-plugin-react-hooks@4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596" + integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== + +eslint-plugin-react@7.35.0: + version "7.35.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz#00b1e4559896710e58af6358898f2ff917ea4c41" + integrity sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA== + dependencies: + array-includes "^3.1.8" + array.prototype.findlast "^1.2.5" + array.prototype.flatmap "^1.3.2" + array.prototype.tosorted "^1.1.4" doctrine "^2.1.0" + es-iterator-helpers "^1.0.19" estraverse "^5.3.0" + hasown "^2.0.2" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" - object.entries "^1.1.5" - object.fromentries "^2.0.5" - object.hasown "^1.1.0" - object.values "^1.1.5" + object.entries "^1.1.8" + object.fromentries "^2.0.8" + object.values "^1.2.0" prop-types "^15.8.1" - resolve "^2.0.0-next.3" - semver "^6.3.0" - string.prototype.matchall "^4.0.6" + resolve "^2.0.0-next.5" + semver "^6.3.1" + string.prototype.matchall "^4.0.11" + string.prototype.repeat "^1.0.0" -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" +eslint-plugin-unused-imports@4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.3.tgz#079ef6f51914a981e657b3834935a6a417bf3f45" + integrity sha512-lqrNZIZjFMUr7P06eoKtQLwyVRibvG7N+LtfKtObYGizAAGrcqLkc3tDx+iAik2z7q0j/XI3ihjupIqxhFabFA== -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== +eslint-scope@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.2.tgz#5cbb33d4384c9136083a71190d548158fe128f94" + integrity sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.14.0: - version "8.17.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.17.0.tgz#1cfc4b6b6912f77d24b874ca1506b0fe09328c21" - integrity sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw== - dependencies: - "@eslint/eslintrc" "^1.3.0" - "@humanwhocodes/config-array" "^0.9.2" - ajv "^6.10.0" +eslint-visitor-keys@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" + integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== + +eslint@9.9.0: + version "9.9.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.9.0.tgz#8d214e69ae4debeca7ae97daebbefe462072d975" + integrity sha512-JfiKJrbx0506OEerjK2Y1QlldtBxkAlLxT5OEcRF8uaQ86noDe2k31Vw9rnSWv+MXZHj7OOUV/dA0AhdLFcyvA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.11.0" + "@eslint/config-array" "^0.17.1" + "@eslint/eslintrc" "^3.1.0" + "@eslint/js" "9.9.0" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.3.0" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" - doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.3.2" - esquery "^1.4.0" + eslint-scope "^8.0.2" + eslint-visitor-keys "^4.0.0" + espree "^10.1.0" + esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^6.0.1" - globals "^13.15.0" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" ignore "^5.2.0" - import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - js-yaml "^4.1.0" + is-path-inside "^3.0.3" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" minimatch "^3.1.2" natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" + optionator "^0.9.3" strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" text-table "^0.2.0" - v8-compile-cache "^2.0.3" -espree@^9.3.2: - version "9.3.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596" - integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA== +espree@^10.0.1, espree@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.1.0.tgz#8788dae611574c0f070691f522e4116c5a11fc56" + integrity sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA== dependencies: - acorn "^8.7.1" + acorn "^8.12.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" - -esprima@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.2.2.tgz#76a0fd66fcfe154fd292667dc264019750b1657b" - integrity sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A== + eslint-visitor-keys "^4.0.0" esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz" +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" -estraverse@^4.1.1, estraverse@^4.2.0: - version "4.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: version "5.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - eth-rpc-errors@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-4.0.3.tgz#6ddb6190a4bf360afda82790bb7d9d5e724f423a" @@ -9310,6 +10025,13 @@ eth-rpc-errors@^4.0.3: dependencies: fast-safe-stringify "^2.0.6" +ethereum-bloom-filters@^1.0.6: + version "1.0.10" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" + integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== + dependencies: + js-sha3 "^0.8.0" + ethereum-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" @@ -9331,10 +10053,10 @@ ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" -ethereumjs-util@^7.1.4: - version "7.1.4" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz#a6885bcdd92045b06f596c7626c3e89ab3312458" - integrity sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A== +ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== dependencies: "@types/bn.js" "^5.1.0" bn.js "^5.1.2" @@ -9343,77 +10065,78 @@ ethereumjs-util@^7.1.4: rlp "^2.2.4" ethers@^5.5.1: - version "5.6.9" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.9.tgz#4e12f8dfcb67b88ae7a78a9519b384c23c576a4d" - integrity sha512-lMGC2zv9HC5EC+8r429WaWu3uWJUCgUCt8xxKCFqkrFuBDZXDYIdzDUECxzjf2BMF8IVBByY1EBoGSL3RTm8RA== - dependencies: - "@ethersproject/abi" "5.6.4" - "@ethersproject/abstract-provider" "5.6.1" - "@ethersproject/abstract-signer" "5.6.2" - "@ethersproject/address" "5.6.1" - "@ethersproject/base64" "5.6.1" - "@ethersproject/basex" "5.6.1" - "@ethersproject/bignumber" "5.6.2" - "@ethersproject/bytes" "5.6.1" - "@ethersproject/constants" "5.6.1" - "@ethersproject/contracts" "5.6.2" - "@ethersproject/hash" "5.6.1" - "@ethersproject/hdnode" "5.6.2" - "@ethersproject/json-wallets" "5.6.1" - "@ethersproject/keccak256" "5.6.1" - "@ethersproject/logger" "5.6.0" - "@ethersproject/networks" "5.6.4" - "@ethersproject/pbkdf2" "5.6.1" - "@ethersproject/properties" "5.6.0" - "@ethersproject/providers" "5.6.8" - "@ethersproject/random" "5.6.1" - "@ethersproject/rlp" "5.6.1" - "@ethersproject/sha2" "5.6.1" - "@ethersproject/signing-key" "5.6.2" - "@ethersproject/solidity" "5.6.1" - "@ethersproject/strings" "5.6.1" - "@ethersproject/transactions" "5.6.2" - "@ethersproject/units" "5.6.1" - "@ethersproject/wallet" "5.6.2" - "@ethersproject/web" "5.6.1" - "@ethersproject/wordlists" "5.6.1" - -event-stream@=3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +ethers@^6.10.0: + version "6.11.1" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.11.1.tgz#96aae00b627c2e35f9b0a4d65c7ab658259ee6af" + integrity sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" -eventemitter3@^4.0.0, eventemitter3@^4.0.4, eventemitter3@^4.0.7: +eventemitter3@^4.0.1, eventemitter3@^4.0.7: version "4.0.7" - resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + events@^3.3.0: version "3.3.0" - resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== -eventsource@^1.0.7: - version "1.1.1" - resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.1.tgz#4544a35a57d7120fba4fa4c86cb4023b2c09df2f" - integrity sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA== - dependencies: - original "^1.0.0" - -evp_bytestokey@^1.0.3: +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== @@ -9421,7 +10144,23 @@ evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@5.1.1, execa@^5.0.0: +execa@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" + integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +execa@^5.0.0, execa@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -9436,128 +10175,50 @@ execa@5.1.1, execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz" +execa@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" + integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== dependencies: - cross-spawn "^7.0.0" - get-stream "^5.0.0" - human-signals "^1.1.1" - is-stream "^2.0.0" + cross-spawn "^7.0.3" + get-stream "^8.0.1" + human-signals "^5.0.0" + is-stream "^3.0.0" merge-stream "^2.0.0" - npm-run-path "^4.0.0" - onetime "^5.1.0" - signal-exit "^3.0.2" - strip-final-newline "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^4.1.0" + strip-final-newline "^3.0.0" + +exenv@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" + integrity sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw== exit@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= - dependencies: - homedir-polyfill "^1.0.1" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expect@^27.4.2: - version "27.4.2" - resolved "https://registry.npmjs.org/expect/-/expect-27.4.2.tgz" - integrity sha512-BjAXIDC6ZOW+WBFNg96J22D27Nq5ohn+oGcuP2rtOtcjuxNoV9McpQ60PcQWhdFOSBIQdR72e+4HdnbZTFSTyg== +expect@^29.0.0, expect@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.3.1.tgz#92877aad3f7deefc2e3f6430dd195b92295554a6" + integrity sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA== dependencies: - "@jest/types" "^27.4.2" - ansi-styles "^5.0.0" - jest-get-type "^27.4.0" - jest-matcher-utils "^27.4.2" - jest-message-util "^27.4.2" - jest-regex-util "^27.4.0" + "@jest/expect-utils" "^29.3.1" + jest-get-type "^29.2.0" + jest-matcher-utils "^29.3.1" + jest-message-util "^29.3.1" + jest-util "^29.3.1" exponential-backoff@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.0.tgz#9409c7e579131f8bd4b32d7d8094a911040f2e68" integrity sha512-oBuz5SYz5zzyuHINoe9ooePwSu0xApKWgeNzok4hZ5YKXFh9zrQBEM15CXqoZkJJPuI2ArvqjPQd8UKJA753XA== -express@^4.17.1: - version "4.17.2" - resolved "https://registry.npmjs.org/express/-/express-4.17.2.tgz" - integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.1" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.4.1" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.9.6" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.17.2" - serve-static "1.14.2" - setprototypeof "1.2.0" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - extend@^3.0.0, extend@~3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== external-editor@^3.0.3: @@ -9569,51 +10230,50 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extract-files@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" - integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== - -extsprintf@1.3.0, extsprintf@^1.2.0: +extract-files@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-11.0.0.tgz#b72d428712f787eef1f5193aff8ab5351ca8469a" + integrity sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ== + +extsprintf@1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== eyes@^0.1.8: version "0.1.8" - resolved "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz" - integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== -fast-csv@^4.3.6: - version "4.3.6" - resolved "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz" - integrity sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw== - dependencies: - "@fast-csv/format" "4.3.5" - "@fast-csv/parse" "4.3.6" +fast-copy@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.1.tgz#9e89ef498b8c04c1cd76b33b8e14271658a732aa" + integrity sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-equals@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-4.0.3.tgz#72884cc805ec3c6679b99875f6b7654f39f0e8c7" + integrity sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg== fast-glob@^3.2.11, fast-glob@^3.2.7, fast-glob@^3.2.9: - version "3.2.11" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" - integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -9621,15 +10281,22 @@ fast-glob@^3.2.11, fast-glob@^3.2.7, fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-redact@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.3.0.tgz#7c83ce3a7be4898241a46560d51de10f653f7634" + integrity sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ== -fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.0.7, fast-safe-stringify@^2.1.1: +fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== @@ -9637,62 +10304,84 @@ fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.0.7, fast-safe-stringify@^2.1 fast-stable-stringify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz#5c5543462b22aeeefd36d05b34e51c78cb86d313" - integrity sha1-XFVDRisiru79NtBbNOUceMuG0xM= - -fast-xml-parser@3.19.0: - version "3.19.0" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz#cb637ec3f3999f51406dd8ff0e6fc4d83e520d01" - integrity sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg== - -fastest-levenshtein@^1.0.12: - version "1.0.12" - resolved "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz" - integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== + integrity sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag== fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + version "1.14.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.14.0.tgz#107f69d7295b11e0fccc264e1fc6389f623731ce" + integrity sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg== dependencies: reusify "^1.0.4" -faye-websocket@^0.11.3: - version "0.11.4" - resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz" - integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== - dependencies: - websocket-driver ">=0.5.1" - fb-watchman@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz" + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== dependencies: bser "2.1.1" -fetch-blob@^3.1.2, fetch-blob@^3.1.4: - version "3.1.5" - resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.1.5.tgz#0077bf5f3fcdbd9d75a0b5362f77dbb743489863" - integrity sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg== +fbjs-css-vars@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" + integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== + +fbjs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-2.0.0.tgz#01fb812138d7e31831ed3e374afe27b9169ef442" + integrity sha512-8XA8ny9ifxrAWlyhAbexXcs3rRMtxWcs3M0lctLfB49jRDHiaxj+Mo0XxbwE7nKZYzgCFoq64FS+WFd4IycPPQ== + dependencies: + core-js "^3.6.4" + cross-fetch "^3.0.4" + fbjs-css-vars "^1.0.0" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.18" + +fecha@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" + integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== + +fetch-retry@^5.0.6: + version "5.0.6" + resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-5.0.6.tgz#17d0bc90423405b7a88b74355bf364acd2a7fa56" + integrity sha512-3yurQZ2hD9VISAhJJP9bpYFNQrHHBXE2JxxjY5aLEcDi46RmAzJE2OC9FAde0yis5ElW0jTTzs0zfg/Cca4XqQ== + +figlet@1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.5.2.tgz#dda34ff233c9a48e36fcff6741aeb5bafe49b634" + integrity sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ== + +figures@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + integrity sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ== dependencies: - node-domexception "^1.0.0" - web-streams-polyfill "^3.0.3" + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" -fetch-retry-ts@^1.1.24: - version "1.1.25" - resolved "https://registry.yarnpkg.com/fetch-retry-ts/-/fetch-retry-ts-1.1.25.tgz#25849a87a5a016cc772f90986d95dd5049eeb5ac" - integrity sha512-kjJcfBYDbajnxMBfBa85hrS0Z+A0bDKuZWuzh5uHpaLSm2qZ3eAND5sDVfFUuIJg51sTd91cdB+Ayqo3magB/g== +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== + dependencies: + escape-string-regexp "^1.0.5" -figures@^3.0.0, figures@^3.2.0: +figures@^3.0.0: version "3.2.0" - resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: - flat-cache "^3.0.4" + flat-cache "^4.0.0" file-selector@^0.6.0: version "0.6.0" @@ -9703,44 +10392,27 @@ file-selector@^0.6.0: file-uri-to-path@1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - fill-range@^7.0.1: version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: to-regex-range "^5.0.1" -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" +filter-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" + integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== find-root@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up@5.0.0: +find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== @@ -9750,101 +10422,84 @@ find-up@5.0.0: find-up@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" path-exists "^4.0.0" find@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/find/-/find-0.3.0.tgz" + resolved "https://registry.yarnpkg.com/find/-/find-0.3.0.tgz#4082e8fc8d8320f1a382b5e4f521b9bc50775cb8" integrity sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw== dependencies: traverse-chain "~0.1.0" -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" + flatted "^3.2.9" + keyv "^4.5.4" flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^3.1.0: - version "3.2.5" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" - integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== flatten@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== -focus-lock@^0.10.1: - version "0.10.2" - resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.10.2.tgz#561c62bae8387ecba1dd8e58a6df5ec29835c644" - integrity sha512-DSaI/UHZ/02sg1P616aIWgToQcrKKBmcCvomDZ1PZvcJFj350PnWhSJxJ76T3e5/GbtQEARIACtbrdlrF9C5kA== +focus-lock@^0.11.2: + version "0.11.4" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.11.4.tgz#fbf84894d7c384f25a2c7cf5d97c848131d97f6f" + integrity sha512-LzZWJcOBIcHslQ46N3SUu/760iLPSrUtp8omM4gh9du438V2CQdks8TcOu1yvmu2C68nVOBnl1WFiKGPbQ8L6g== dependencies: tslib "^2.0.3" -focus-visible@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-5.2.0.tgz#3a9e41fccf587bd25dcc2ef045508284f0a4d6b3" - integrity sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ== - -follow-redirects@^1.0.0, follow-redirects@^1.14.4, follow-redirects@^1.14.7, follow-redirects@^1.14.8: - version "1.14.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== - -follow-redirects@^1.14.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.0.tgz#06441868281c86d0dda4ad8bdaead2d02dca89d4" - integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ== - -follow-redirects@^1.14.9: - version "1.15.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" - integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== +follow-redirects@^1.14.0, follow-redirects@^1.14.4, follow-redirects@^1.14.7, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +foreground-child@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7" + integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" forever-agent@~0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== form-data@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== dependencies: asynckit "^0.4.0" @@ -9853,98 +10508,35 @@ form-data@^4.0.0: form-data@~2.3.2: version "2.3.3" - resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" combined-stream "^1.0.6" mime-types "^2.1.12" -formdata-polyfill@^4.0.10: - version "4.0.10" - resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" - integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== - dependencies: - fetch-blob "^3.1.2" - -formidable@^1.2.2: - version "1.2.6" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.6.tgz#d2a51d60162bbc9b4a055d8457a7c75315d1a168" - integrity sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ== - -formidable@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.0.1.tgz#4310bc7965d185536f9565184dee74fbb75557ff" - integrity sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ== - dependencies: - dezalgo "1.0.3" - hexoid "1.0.0" - once "1.4.0" - qs "6.9.3" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fp-ts@^2.12.2: +fp-ts@2.12.2: version "2.12.2" resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.12.2.tgz#a191db2dbbb04f48a0e75050b94f57cc876c7b40" integrity sha512-v8J7ud+nTkP5Zz17GhpCsY19wiRbB9miuj61nBcCJyDpu52zs9Z4O7OLDfYoKFQMJ9EsSZA7W1vRgC1d3jy5qw== -fraction.js@^4.0.13: +fraction.js@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= - fs-extra@^10.0.0: - version "10.0.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz" - integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^8.1: - version "8.1.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: - at-least-node "^1.0.0" graceful-fs "^4.2.0" jsonfile "^6.0.1" universalify "^2.0.0" -fs-minipass@^2.0.0, fs-minipass@^2.1.0: +fs-minipass@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: minipass "^3.0.0" @@ -9952,55 +10544,37 @@ fs-minipass@^2.0.0, fs-minipass@^2.1.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fs@0.0.1-security, fs@^0.0.1-security: - version "0.0.1-security" - resolved "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz" - integrity sha1-invTcYa23d84E/I4WLV+yq9eQdQ= - -fsevents@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -gauge@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" - integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== dependencies: - aproba "^1.0.3 || ^2.0.0" - color-support "^1.1.2" - console-control-strings "^1.0.0" - has-unicode "^2.0.1" - object-assign "^4.1.1" - signal-exit "^3.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wide-align "^1.1.2" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== gauge@~2.7.3: version "2.7.4" - resolved "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -10013,79 +10587,83 @@ gauge@~2.7.3: gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" +get-func-name@^2.0.0, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== + +get-intrinsic@^1.1.0, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" get-nonce@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" - resolved "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== get-package-type@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" +get-port-please@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.2.tgz#502795e56217128e4183025c89a48c71652f4e49" + integrity sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ== get-stream@^5.0.0: version "5.2.0" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" get-stream@^6.0.0: version "6.0.1" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" +get-stream@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" + integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= +get-symbol-description@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" + integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== + dependencies: + call-bind "^1.0.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" getpass@^0.1.1: version "0.1.7" - resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== dependencies: assert-plus "^1.0.0" -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -10100,7 +10678,7 @@ glob-parent@^6.0.1, glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@7.2.0, glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7, glob@^7.2.0: +glob@7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -10112,51 +10690,62 @@ glob@7.2.0, glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.4, glob@^7.1.6, glo once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.1, glob@^7.1.3: - version "7.1.6" - resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" +glob@^10.3.10: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^7.1.3, glob@^7.1.4, glob@^7.1.7: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" -global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== - dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" - -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= +glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" globals@^11.1.0: version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== -globals@^13.15.0: - version "13.15.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" - integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== +globalthis@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== dependencies: - type-fest "^0.20.2" + define-properties "^1.2.1" + gopd "^1.0.1" -globby@^11.0.1, globby@^11.1.0: +globby@^11.1.0: version "11.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" @@ -10166,165 +10755,117 @@ globby@^11.0.1, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz" - integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -goblingold-sdk@^1.2.35: - version "1.2.35" - resolved "https://registry.yarnpkg.com/goblingold-sdk/-/goblingold-sdk-1.2.35.tgz#918ba1dddadfbf12132d10f0d841d62525612e68" - integrity sha512-TiDwIenuLKrlCzlZVYXxALa2YOfR/tG3GxHc5w7qv2UXqAZDnQ9eIUJVEk/FMR20dX/MPrfxfiJxXH8zVO8xrg== +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== dependencies: - "@project-serum/anchor" "^0.24.2" - "@solana/buffer-layout" "^4.0.0" - "@solana/buffer-layout-utils" "^0.2.0" - "@solana/spl-token" "^0.2.0" - "@solana/web3.js" "^1.42.0" - isomorphic-unfetch "^3.1.0" - sha256-uint8array "^0.10.3" - typescript "^4.6.2" + get-intrinsic "^1.1.3" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.8: +graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -graphql-request@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-4.3.0.tgz#b934e08fcae764aa2cdc697d3c821f046cb5dbf2" - integrity sha512-2v6hQViJvSsifK606AliqiNiijb1uwWp6Re7o0RTyH+uRTv/u7Uqm2g4Fjq/LgZIzARB38RZEvVBFOQOVdlBow== - dependencies: - cross-fetch "^3.1.5" - extract-files "^9.0.0" - form-data "^3.0.0" +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -graphql@^16.5.0: +graphql@16.5.0: version "16.5.0" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85" integrity sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA== -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - gzip-size@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== dependencies: duplexer "^0.1.2" -handle-thing@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz" - integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== - -handlebars@^4.7.7: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.0" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" +h3@^1.10.1, h3@^1.8.2: + version "1.10.1" + resolved "https://registry.yarnpkg.com/h3/-/h3-1.10.1.tgz#221634ca9bdb216a6b359bd2915be466a179b8a1" + integrity sha512-UBAUp47hmm4BB5/njB4LrEa9gpuvZj4/Qf/ynSMzO6Ku2RXaouxEfiG2E2IFnv6fxbhAkzjasDxmo6DFdEeXRg== + dependencies: + cookie-es "^1.0.0" + defu "^6.1.4" + destr "^2.0.2" + iron-webcrypto "^1.0.0" + ohash "^1.1.3" + radix3 "^1.1.0" + ufo "^1.3.2" + uncrypto "^0.1.3" + unenv "^1.9.0" har-schema@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== har-validator@~5.1.3: version "5.1.5" - resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: ajv "^6.12.3" har-schema "^2.0.0" -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1, has-symbols@^1.0.2: +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: - has-symbols "^1.0.2" - -has-unicode@^2.0.0, has-unicode@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" + es-define-property "^1.0.0" -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" +has-proto@^1.0.1, has-proto@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= +has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" + has-symbols "^1.0.3" -has@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== hash-base@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== dependencies: inherits "^2.0.4" @@ -10333,12 +10874,19 @@ hash-base@^3.0.0: hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: version "1.1.7" - resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -10346,14 +10894,9 @@ he@1.2.0: hex-color-regex@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -hexoid@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" - integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== - hi-base32@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/hi-base32/-/hi-base32-0.5.1.tgz#1279f2ddae2673219ea5870c2121d2a33132857e" @@ -10361,8 +10904,8 @@ hi-base32@^0.5.1: hmac-drbg@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -10370,77 +10913,41 @@ hmac-drbg@^1.0.1: hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" - resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== dependencies: react-is "^16.7.0" -homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - -hosted-git-info@^4.0.1, hosted-git-info@^4.0.2: - version "4.1.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" - integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== - dependencies: - lru-cache "^6.0.0" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - hsl-regex@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz" - integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + integrity sha512-M5ezZw4LzXbBKMruP+BNANf0k+19hDQMgpzBIYnya//Al+fjNct9Wf3b1WedLqdEs2hKBvxq/jh+DsHJLj0F9A== hsla-regex@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz" - integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + integrity sha512-7Wn5GMLuHBjZCb2bTmnDOycho0p/7UVaAeqXZGbHrBCl6Yd/xDhQJAXe6Ga9AXJH2I5zY1dEdYw2u1UptnSBJA== -html-encoding-sniffer@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz" +html-encoding-sniffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" + integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== dependencies: - whatwg-encoding "^1.0.5" - -html-entities@^1.3.1: - version "1.4.0" - resolved "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz" - integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== + whatwg-encoding "^2.0.0" html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" - -html-tags@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz" - integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== - -http-cache-semantics@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= +html-tags@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" + integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== -http-errors@1.8.1, http-errors@^1.7.2: +http-errors@^1.7.2: version "1.8.1" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== dependencies: depd "~1.1.2" @@ -10449,83 +10956,60 @@ http-errors@1.8.1, http-errors@^1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.1" -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-parser-js@>=0.5.1: - version "0.5.5" - resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz" - integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== - -http-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== dependencies: - "@tootallnate/once" "1" + "@tootallnate/once" "2" agent-base "6" debug "4" -http-proxy-middleware@0.19.1: - version "0.19.1" - resolved "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz" - integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== - dependencies: - http-proxy "^1.17.0" - is-glob "^4.0.0" - lodash "^4.17.11" - micromatch "^3.1.10" - -http-proxy@^1.17.0: - version "1.18.1" - resolved "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" +http-shutdown@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/http-shutdown/-/http-shutdown-1.2.2.tgz#41bc78fc767637c4c95179bc492f312c0ae64c5f" + integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw== http-signature@~1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" -https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== +https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" debug "4" human-signals@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== human-signals@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +human-signals@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" + integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== + humanize-ms@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz" - integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== dependencies: ms "^2.0.0" -husky@^8.0.1: +husky@8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.1.tgz#511cb3e57de3e3190514ae49ed50f6bc3f50b3e9" integrity sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw== @@ -10535,28 +11019,28 @@ hyphenate-style-name@^1.0.0: resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== -i@^0.3.7: - version "0.3.7" - resolved "https://registry.npmjs.org/i/-/i-0.3.7.tgz" - integrity sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q== +iconv-lite@0.6, iconv-lite@0.6.3, iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" -iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@^0.4.24: version "0.4.24" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@0.6, iconv-lite@^0.6.2: - version "0.6.3" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" +idb-keyval@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.1.tgz#94516d625346d16f56f3b33855da11bfded2db33" + integrity sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg== ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== iframe-resizer-react@^1.1.0: @@ -10568,126 +11052,93 @@ iframe-resizer-react@^1.1.0: warning "^4.0.3" iframe-resizer@^4.3.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/iframe-resizer/-/iframe-resizer-4.3.2.tgz#42dd88345d18b9e377b6044dddb98c664ab0ce6b" - integrity sha512-gOWo2hmdPjMQsQ+zTKbses08mDfDEMh4NneGQNP4qwePYujY1lguqP6gnbeJkf154gojWlBhIltlgnMfYjGHWA== - -ignore-walk@^3.0.3: - version "3.0.4" - resolved "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz" - integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ== - dependencies: - minimatch "^3.0.4" + version "4.3.6" + resolved "https://registry.yarnpkg.com/iframe-resizer/-/iframe-resizer-4.3.6.tgz#61d92c1adefe5d416bff4fbf80c7f1f74be70ec0" + integrity sha512-wz0WodRIF6eP0oGQa5NIP1yrITAZ59ZJvVaVJqJRjaeCtfm461vy2C3us6CKx0e7pooqpIGLpVMSTzrfAjX9Sg== -ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +ignore@^5.2.0, ignore@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== immediate@~3.0.5: version "3.0.6" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" - integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= - -immer@^9.0.12: - version "9.0.12" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" - integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== -immer@^9.0.14, immer@^9.0.7: +immer@9.0.15: version "9.0.15" resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc" integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ== -import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: +immutable@~3.7.4: + version "3.7.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" + integrity sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw== + +import-fresh@^3.1.0, import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" -import-local@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - import-local@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz" + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + integrity sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ== indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== indexes-of@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA== infer-owner@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.4: - version "1.3.8" - resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -ini@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - -init-package-json@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/init-package-json/-/init-package-json-2.0.5.tgz" - integrity sha512-u1uGAtEFu3VA6HNl/yUWw57jmKEMx8SKOxHhxjGnOFUiIlFnohKDFg4ZrPpv9wWqk44nDxGJAtqjdQFm+9XXQA== - dependencies: - npm-package-arg "^8.1.5" - promzard "^0.3.0" - read "~1.0.1" - read-package-json "^4.1.1" - semver "^7.3.5" - validate-npm-package-license "^3.0.4" - validate-npm-package-name "^3.0.0" - inline-style-parser@0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== inquirer@^8.2.0: - version "8.2.4" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.4.tgz#ddbfe86ca2f67649a67daa6f1051c128f684f0b4" - integrity sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg== + version "8.2.5" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.5.tgz#d8654a7542c35a9b9e069d27e2df4858784d54f8" + integrity sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ== dependencies: ansi-escapes "^4.2.1" chalk "^4.1.1" @@ -10705,20 +11156,13 @@ inquirer@^8.2.0: through "^2.3.6" wrap-ansi "^7.0.0" -internal-ip@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz" - integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== - dependencies: - default-gateway "^4.2.0" - ipaddr.js "^1.9.0" - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz" +internal-slot@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" + integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" + es-errors "^1.3.0" + hasown "^2.0.0" side-channel "^1.0.4" "internmap@1 - 2": @@ -10731,143 +11175,107 @@ internmap@^1.0.0: resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - invariant@^2.2.4: version "2.2.4" - resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz" - integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= - -ip-regex@^4.1.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz" - integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== - -ip@^1.1.0, ip@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - -ipaddr.js@1.9.1, ipaddr.js@^1.9.0: - version "1.9.1" - resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-absolute-url@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz" - integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== +io-ts@2.2.18: + version "2.2.18" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.18.tgz#dfb41aded5f0e598ccf2a25a483c205444210173" + integrity sha512-3JxUUzRtPQPs5sOwB7pW0+Xb54nOzqA6M1sRB1hwgsRmkWMeGTjtOrCynGTJhIj+mBLUj2S37DAq2+BrPh9kTQ== -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= +ioredis@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.3.2.tgz#9139f596f62fc9c72d873353ac5395bcf05709f7" + integrity sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA== dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: + "@ioredis/commands" "^1.1.1" + cluster-key-slot "^1.1.0" + debug "^4.3.4" + denque "^2.1.0" + lodash.defaults "^4.2.0" + lodash.isarguments "^3.1.0" + redis-errors "^1.2.0" + redis-parser "^3.0.0" + standard-as-callback "^2.1.0" + +iron-webcrypto@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-alphabetical@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.0.tgz" - integrity sha512-5OV8Toyq3oh4eq6sbWTYzlGdnMT/DPI5I0zxUBxjiigQsZycpkKF3kskkao3JyYGuYDHvhgJF+DrjMQp9SX86w== - -is-alphanumerical@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.0.tgz" - integrity sha512-t+2GlJ+hO9yagJ+jU3+HSh80VKvz/3cG2cxbGGm4S0hjKuhWQXgPVUVOZz3tqZzMjhmphZ+1TIJTlRZRoe6GCQ== - dependencies: - is-alphabetical "^2.0.0" - is-decimal "^2.0.0" + resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-1.0.0.tgz#e3b689c0c61b434a0a4cb82d0aeabbc8b672a867" + integrity sha512-anOK1Mktt8U1Xi7fCM3RELTuYbnFikQY5VtrDj7kPgpejV7d43tWKhzgioO0zpkazLEL/j/iayRqnJhrGfqUsg== -is-arguments@^1.0.4: +is-arguments@^1.0.4, is-arguments@^1.1.0, is-arguments@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== dependencies: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-array-buffer@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" + integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-arrayish@^0.3.1: version "0.3.2" - resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== +is-async-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + dependencies: + has-tostringtag "^1.0.0" + is-bigint@^1.0.1: version "1.0.4" - resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== dependencies: has-bigints "^1.0.1" -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-boolean-object@^1.1.0: version "1.1.2" - resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== dependencies: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-buffer@^2.0.0: version "2.0.5" - resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-cidr@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/is-cidr/-/is-cidr-4.0.2.tgz" - integrity sha512-z4a1ENUajDbEl/Q6/pVBpTR1nBjjEE1X7qb7bmWYanNnPoKAvUCPFKeXV6Fe4mgTkWKBqiHIcwsI3SndiO5FeA== - dependencies: - cidr-regex "^3.1.1" +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-color-stop@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz" - integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + integrity sha512-H1U8Vz0cfXNujrJzEcvvwMDW9Ra+biSYA3ThdQvAnMLJkEHQXn6bWzLkxHtVYJ+Sdbx0b6finn3jZiaVe7MAHA== dependencies: css-color-names "^0.0.4" hex-color-regex "^1.1.0" @@ -10876,97 +11284,55 @@ is-color-stop@^1.1.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" -is-core-module@^2.2.0, is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== - dependencies: - has "^1.0.3" - -is-core-module@^2.5.0, is-core-module@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" - integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== - dependencies: - has "^1.0.3" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= +is-core-module@^2.13.0, is-core-module@^2.13.1: + version "2.15.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea" + integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA== dependencies: - kind-of "^3.0.2" + hasown "^2.0.2" -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== +is-data-view@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" + integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== dependencies: - kind-of "^6.0.0" + is-typed-array "^1.1.13" -is-date-object@^1.0.1: +is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== dependencies: has-tostringtag "^1.0.0" -is-decimal@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.0.tgz" - integrity sha512-QfrfjQV0LjoWQ1K1XSoEZkTAzSa14RKVMa5zg3SdAfzEmQzRM4+tbSFWb78creCeA9rNBzaZal92opi1TwPWZw== +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-descriptor@^1.0.0, is-descriptor@^1.0.2: +is-finalizationregistry@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-docker@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + call-bind "^1.0.2" is-fullwidth-code-point@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -10978,96 +11344,83 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-generator-function@^1.0.7: +is-generator-function@^1.0.10, is-generator-function@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== dependencies: has-tostringtag "^1.0.0" -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" -is-hexadecimal@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.0.tgz" - integrity sha512-vGOtYkiaxwIiR0+Ng/zNId+ZZehGfINwTzdrDqc6iubbnQWhnPuYymOzOKUDqa2cSl59yHnEh2h6MvRLQsyNug== +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== + +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" is-interactive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== -is-lambda@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz" - integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= +is-map@^2.0.2, is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== is-nan@^1.2.1: version "1.3.2" - resolved "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== dependencies: call-bind "^1.0.0" define-properties "^1.1.3" -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== dependencies: has-tostringtag "^1.0.0" -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-obj@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" - -is-path-cwd@^2.0.0: - version "2.2.0" - resolved "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== -is-path-in-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz" - integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== +is-observable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" + integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA== dependencies: - is-path-inside "^2.1.0" + symbol-observable "^1.1.0" -is-path-inside@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz" - integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== - dependencies: - path-is-inside "^1.0.2" +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== is-plain-obj@^2.1.0: version "2.1.0" @@ -11075,25 +11428,30 @@ is-plain-obj@^2.1.0: integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== is-plain-obj@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.0.0.tgz" - integrity sha512-NXRbBtUdBioI73y/HmOhogw/U5msYPC9DAtGkJXeFcFWSFZw0mCUsPxk/snTuJHzNKA8kLBK4rH97RMB1BfCXw== - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" + version "4.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== is-potential-custom-element-name@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-regex@^1.0.4, is-regex@^1.1.4: +is-promise@^2.1.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + +is-reference@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + +is-regex@^1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: call-bind "^1.0.2" @@ -11101,109 +11459,125 @@ is-regex@^1.0.4, is-regex@^1.1.4: is-regexp@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== -is-shared-array-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz" - integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== +is-set@^2.0.2, is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" + integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== + dependencies: + call-bind "^1.0.7" is-stream@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== -is-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz" +is-stream@^2.0.0, is-stream@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== dependencies: has-tostringtag "^1.0.0" is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.3, is-typed-array@^1.1.7: - version "1.1.8" - resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz" - integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== +is-typed-array@^1.1.13, is-typed-array@^1.1.3: + version "1.1.13" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" + which-typed-array "^1.1.14" -is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== is-unicode-supported@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-weakref@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz" - integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ== - dependencies: - call-bind "^1.0.0" +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== -is-windows@^1.0.1, is-windows@^1.0.2: +is-weakref@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= +is-weakset@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" + integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" -is-wsl@^2.1.1: - version "2.2.0" - resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== + dependencies: + is-inside-container "^1.0.0" + +is64bit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is64bit/-/is64bit-2.0.0.tgz#198c627cbcb198bbec402251f88e5e1a51236c07" + integrity sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw== dependencies: - is-docker "^2.0.0" + system-architecture "^0.1.0" -isarray@1.0.0, isarray@~1.0.0: +isarray@^2.0.1, isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isarray@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isomorphic-fetch@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== dependencies: node-fetch "^2.6.1" whatwg-fetch "^3.4.1" -isomorphic-unfetch@^3.1.0: +isomorphic-unfetch@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz#87341d5f4f7b63843d468438128cb087b7c3e98f" integrity sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q== @@ -11213,58 +11587,87 @@ isomorphic-unfetch@^3.1.0: isomorphic-ws@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== +isomorphic-ws@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + isstream@~0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== -istanbul-lib-coverage@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz" +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== -istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz" +istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== dependencies: - "@babel/core" "^7.7.5" + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.0.0" + istanbul-lib-coverage "^3.2.0" semver "^6.3.0" istanbul-lib-report@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== dependencies: istanbul-lib-coverage "^3.0.0" make-dir "^3.0.0" supports-color "^7.1.0" istanbul-lib-source-maps@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz" + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== dependencies: debug "^4.1.1" istanbul-lib-coverage "^3.0.0" source-map "^0.6.1" -istanbul-reports@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz" +istanbul-reports@^3.1.3: + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jayson@^3.4.4: - version "3.6.6" - resolved "https://registry.npmjs.org/jayson/-/jayson-3.6.6.tgz" - integrity sha512-f71uvrAWTtrwoww6MKcl9phQTC+56AopLyEenWvKVAIMz+q0oVGj6tenLZ7Z6UiPBkJtKLj4kt0tACllFQruGQ== +iterator.prototype@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" + integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== + dependencies: + define-properties "^1.2.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + reflect.getprototypeof "^1.0.4" + set-function-name "^2.0.1" + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jayson@^4.0.0, jayson@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.1.tgz#282ff13d3cea09776db684b7eeca98c47b2fa99a" + integrity sha512-5ZWm4Q/0DHPyeMfAsrwViwUS2DMVsQgWh8bEEIVTkfb3DzHZ2L3G5WUnF+AKmGjjM9r1uAv73SaqC1/U4RL45w== dependencies: "@types/connect" "^3.4.33" - "@types/express-serve-static-core" "^4.17.9" - "@types/lodash" "^4.14.159" "@types/node" "^12.12.54" "@types/ws" "^7.4.4" JSONStream "^1.3.5" @@ -11274,444 +11677,426 @@ jayson@^3.4.4: eyes "^0.1.8" isomorphic-ws "^4.0.1" json-stringify-safe "^5.0.1" - lodash "^4.17.20" uuid "^8.3.2" - ws "^7.4.5" + ws "^7.5.10" -jest-changed-files@^27.4.2: - version "27.4.2" - resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.4.2.tgz" - integrity sha512-/9x8MjekuzUQoPjDHbBiXbNEBauhrPU2ct7m8TfCg69ywt1y/N+yYwGh3gCpnqUS3klYWDU/lSNgv+JhoD2k1A== +jest-changed-files@^29.2.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.2.0.tgz#b6598daa9803ea6a4dce7968e20ab380ddbee289" + integrity sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA== dependencies: - "@jest/types" "^27.4.2" execa "^5.0.0" - throat "^6.0.1" + p-limit "^3.1.0" -jest-circus@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-circus/-/jest-circus-27.4.5.tgz" - integrity sha512-eTNWa9wsvBwPykhMMShheafbwyakcdHZaEYh5iRrQ0PFJxkDP/e3U/FvzGuKWu2WpwUA3C3hPlfpuzvOdTVqnw== +jest-circus@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.3.1.tgz#177d07c5c0beae8ef2937a67de68f1e17bbf1b4a" + integrity sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg== dependencies: - "@jest/environment" "^27.4.4" - "@jest/test-result" "^27.4.2" - "@jest/types" "^27.4.2" + "@jest/environment" "^29.3.1" + "@jest/expect" "^29.3.1" + "@jest/test-result" "^29.3.1" + "@jest/types" "^29.3.1" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" dedent "^0.7.0" - expect "^27.4.2" is-generator-fn "^2.0.0" - jest-each "^27.4.2" - jest-matcher-utils "^27.4.2" - jest-message-util "^27.4.2" - jest-runtime "^27.4.5" - jest-snapshot "^27.4.5" - jest-util "^27.4.2" - pretty-format "^27.4.2" + jest-each "^29.3.1" + jest-matcher-utils "^29.3.1" + jest-message-util "^29.3.1" + jest-runtime "^29.3.1" + jest-snapshot "^29.3.1" + jest-util "^29.3.1" + p-limit "^3.1.0" + pretty-format "^29.3.1" slash "^3.0.0" stack-utils "^2.0.3" - throat "^6.0.1" -jest-cli@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-27.4.5.tgz" - integrity sha512-hrky3DSgE0u7sQxaCL7bdebEPHx5QzYmrGuUjaPLmPE8jx5adtvGuOlRspvMoVLTTDOHRnZDoRLYJuA+VCI7Hg== +jest-cli@^29.2.0: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.3.1.tgz#e89dff427db3b1df50cea9a393ebd8640790416d" + integrity sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ== dependencies: - "@jest/core" "^27.4.5" - "@jest/test-result" "^27.4.2" - "@jest/types" "^27.4.2" + "@jest/core" "^29.3.1" + "@jest/test-result" "^29.3.1" + "@jest/types" "^29.3.1" chalk "^4.0.0" exit "^0.1.2" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" import-local "^3.0.2" - jest-config "^27.4.5" - jest-util "^27.4.2" - jest-validate "^27.4.2" + jest-config "^29.3.1" + jest-util "^29.3.1" + jest-validate "^29.3.1" prompts "^2.0.1" - yargs "^16.2.0" + yargs "^17.3.1" -jest-config@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-config/-/jest-config-27.4.5.tgz" - integrity sha512-t+STVJtPt+fpqQ8GBw850NtSQbnDOw/UzdPfzDaHQ48/AylQlW7LHj3dH+ndxhC1UxJ0Q3qkq7IH+nM1skwTwA== +jest-config@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.3.1.tgz#0bc3dcb0959ff8662957f1259947aedaefb7f3c6" + integrity sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg== dependencies: - "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^27.4.5" - "@jest/types" "^27.4.2" - babel-jest "^27.4.5" + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.3.1" + "@jest/types" "^29.3.1" + babel-jest "^29.3.1" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" - glob "^7.1.1" - graceful-fs "^4.2.4" - jest-circus "^27.4.5" - jest-environment-jsdom "^27.4.4" - jest-environment-node "^27.4.4" - jest-get-type "^27.4.0" - jest-jasmine2 "^27.4.5" - jest-regex-util "^27.4.0" - jest-resolve "^27.4.5" - jest-runner "^27.4.5" - jest-util "^27.4.2" - jest-validate "^27.4.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.3.1" + jest-environment-node "^29.3.1" + jest-get-type "^29.2.0" + jest-regex-util "^29.2.0" + jest-resolve "^29.3.1" + jest-runner "^29.3.1" + jest-util "^29.3.1" + jest-validate "^29.3.1" micromatch "^4.0.4" - pretty-format "^27.4.2" + parse-json "^5.2.0" + pretty-format "^29.3.1" slash "^3.0.0" + strip-json-comments "^3.1.1" -jest-diff@^27.4.2, jest-diff@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" - integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== +jest-diff@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.3.1.tgz#d8215b72fed8f1e647aed2cae6c752a89e757527" + integrity sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw== dependencies: chalk "^4.0.0" - diff-sequences "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" + diff-sequences "^29.3.1" + jest-get-type "^29.2.0" + pretty-format "^29.3.1" -jest-docblock@^27.4.0: - version "27.4.0" - resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.4.0.tgz" - integrity sha512-7TBazUdCKGV7svZ+gh7C8esAnweJoG+SvcF6Cjqj4l17zA2q1cMwx2JObSioubk317H+cjcHgP+7fTs60paulg== +jest-docblock@^29.2.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.2.0.tgz#307203e20b637d97cee04809efc1d43afc641e82" + integrity sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A== dependencies: detect-newline "^3.0.0" -jest-each@^27.4.2: - version "27.4.2" - resolved "https://registry.npmjs.org/jest-each/-/jest-each-27.4.2.tgz" - integrity sha512-53V2MNyW28CTruB3lXaHNk6PkiIFuzdOC9gR3C6j8YE/ACfrPnz+slB0s17AgU1TtxNzLuHyvNlLJ+8QYw9nBg== +jest-each@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.3.1.tgz#bc375c8734f1bb96625d83d1ca03ef508379e132" + integrity sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^29.3.1" chalk "^4.0.0" - jest-get-type "^27.4.0" - jest-util "^27.4.2" - pretty-format "^27.4.2" - -jest-environment-jsdom@^27.4.4: - version "27.4.4" - resolved "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.4.4.tgz" - integrity sha512-cYR3ndNfHBqQgFvS1RL7dNqSvD//K56j/q1s2ygNHcfTCAp12zfIromO1w3COmXrxS8hWAh7+CmZmGCIoqGcGA== - dependencies: - "@jest/environment" "^27.4.4" - "@jest/fake-timers" "^27.4.2" - "@jest/types" "^27.4.2" + jest-get-type "^29.2.0" + jest-util "^29.3.1" + pretty-format "^29.3.1" + +jest-environment-jsdom@29.2.2: + version "29.2.2" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-29.2.2.tgz#1e2d9f1f017fbaa7362a83e670b569158b4b8527" + integrity sha512-5mNtTcky1+RYv9kxkwMwt7fkzyX4EJUarV7iI+NQLigpV4Hz4sgfOdP4kOpCHXbkRWErV7tgXoXLm2CKtucr+A== + dependencies: + "@jest/environment" "^29.2.2" + "@jest/fake-timers" "^29.2.2" + "@jest/types" "^29.2.1" + "@types/jsdom" "^20.0.0" "@types/node" "*" - jest-mock "^27.4.2" - jest-util "^27.4.2" - jsdom "^16.6.0" - -jest-environment-node@^27.4.4: - version "27.4.4" - resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.4.4.tgz" - integrity sha512-D+v3lbJ2GjQTQR23TK0kY3vFVmSeea05giInI41HHOaJnAwOnmUHTZgUaZL+VxUB43pIzoa7PMwWtCVlIUoVoA== - dependencies: - "@jest/environment" "^27.4.4" - "@jest/fake-timers" "^27.4.2" - "@jest/types" "^27.4.2" + jest-mock "^29.2.2" + jest-util "^29.2.1" + jsdom "^20.0.0" + +jest-environment-node@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.3.1.tgz#5023b32472b3fba91db5c799a0d5624ad4803e74" + integrity sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag== + dependencies: + "@jest/environment" "^29.3.1" + "@jest/fake-timers" "^29.3.1" + "@jest/types" "^29.3.1" "@types/node" "*" - jest-mock "^27.4.2" - jest-util "^27.4.2" - -jest-get-type@^27.4.0: - version "27.4.0" - resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.4.0.tgz" - integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ== - -jest-get-type@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" - integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== - -jest-haste-map@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.4.5.tgz" - integrity sha512-oJm1b5qhhPs78K24EDGifWS0dELYxnoBiDhatT/FThgB9yxqUm5F6li3Pv+Q+apMBmmPNzOBnZ7ZxWMB1Leq1Q== - dependencies: - "@jest/types" "^27.4.2" - "@types/graceful-fs" "^4.1.2" + jest-mock "^29.3.1" + jest-util "^29.3.1" + +jest-get-type@^29.2.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408" + integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA== + +jest-haste-map@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.3.1.tgz#af83b4347f1dae5ee8c2fb57368dc0bb3e5af843" + integrity sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A== + dependencies: + "@jest/types" "^29.3.1" + "@types/graceful-fs" "^4.1.3" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" - graceful-fs "^4.2.4" - jest-regex-util "^27.4.0" - jest-serializer "^27.4.0" - jest-util "^27.4.2" - jest-worker "^27.4.5" + graceful-fs "^4.2.9" + jest-regex-util "^29.2.0" + jest-util "^29.3.1" + jest-worker "^29.3.1" micromatch "^4.0.4" - walker "^1.0.7" + walker "^1.0.8" optionalDependencies: fsevents "^2.3.2" -jest-jasmine2@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.4.5.tgz" - integrity sha512-oUnvwhJDj2LhOiUB1kdnJjkx8C5PwgUZQb9urF77mELH9DGR4e2GqpWQKBOYXWs5+uTN9BGDqRz3Aeg5Wts7aw== +jest-leak-detector@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz#95336d020170671db0ee166b75cd8ef647265518" + integrity sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA== dependencies: - "@babel/traverse" "^7.1.0" - "@jest/environment" "^27.4.4" - "@jest/source-map" "^27.4.0" - "@jest/test-result" "^27.4.2" - "@jest/types" "^27.4.2" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - expect "^27.4.2" - is-generator-fn "^2.0.0" - jest-each "^27.4.2" - jest-matcher-utils "^27.4.2" - jest-message-util "^27.4.2" - jest-runtime "^27.4.5" - jest-snapshot "^27.4.5" - jest-util "^27.4.2" - pretty-format "^27.4.2" - throat "^6.0.1" - -jest-leak-detector@^27.4.2: - version "27.4.2" - resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.4.2.tgz" - integrity sha512-ml0KvFYZllzPBJWDei3mDzUhyp/M4ubKebX++fPaudpe8OsxUE+m+P6ciVLboQsrzOCWDjE20/eXew9QMx/VGw== - dependencies: - jest-get-type "^27.4.0" - pretty-format "^27.4.2" - -jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.4.2: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" - integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== + jest-get-type "^29.2.0" + pretty-format "^29.3.1" + +jest-matcher-utils@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz#6e7f53512f80e817dfa148672bd2d5d04914a572" + integrity sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ== dependencies: chalk "^4.0.0" - jest-diff "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" + jest-diff "^29.3.1" + jest-get-type "^29.2.0" + pretty-format "^29.3.1" -jest-message-util@^27.4.2: - version "27.4.2" - resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.4.2.tgz" - integrity sha512-OMRqRNd9E0DkBLZpFtZkAGYOXl6ZpoMtQJWTAREJKDOFa0M6ptB7L67tp+cszMBkvSgKOhNtQp2Vbcz3ZZKo/w== +jest-message-util@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.3.1.tgz#37bc5c468dfe5120712053dd03faf0f053bd6adb" + integrity sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^27.4.2" + "@jest/types" "^29.3.1" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" micromatch "^4.0.4" - pretty-format "^27.4.2" + pretty-format "^29.3.1" slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^27.4.2: - version "27.4.2" - resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-27.4.2.tgz" - integrity sha512-PDDPuyhoukk20JrQKeofK12hqtSka7mWH0QQuxSNgrdiPsrnYYLS6wbzu/HDlxZRzji5ylLRULeuI/vmZZDrYA== +jest-mock@^29.2.2, jest-mock@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.3.1.tgz#60287d92e5010979d01f218c6b215b688e0f313e" + integrity sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^29.3.1" "@types/node" "*" + jest-util "^29.3.1" jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz" + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== -jest-regex-util@^27.4.0: - version "27.4.0" - resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.4.0.tgz" - integrity sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg== +jest-regex-util@^29.2.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.2.0.tgz#82ef3b587e8c303357728d0322d48bbfd2971f7b" + integrity sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA== -jest-resolve-dependencies@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.4.5.tgz" - integrity sha512-elEVvkvRK51y037NshtEkEnukMBWvlPzZHiL847OrIljJ8yIsujD2GXRPqDXC4rEVKbcdsy7W0FxoZb4WmEs7w== +jest-resolve-dependencies@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz#a6a329708a128e68d67c49f38678a4a4a914c3bf" + integrity sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA== dependencies: - "@jest/types" "^27.4.2" - jest-regex-util "^27.4.0" - jest-snapshot "^27.4.5" + jest-regex-util "^29.2.0" + jest-snapshot "^29.3.1" -jest-resolve@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.4.5.tgz" - integrity sha512-xU3z1BuOz/hUhVUL+918KqUgK+skqOuUsAi7A+iwoUldK6/+PW+utK8l8cxIWT9AW7IAhGNXjSAh1UYmjULZZw== +jest-resolve@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.3.1.tgz#9a4b6b65387a3141e4a40815535c7f196f1a68a7" + integrity sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw== dependencies: - "@jest/types" "^27.4.2" chalk "^4.0.0" - graceful-fs "^4.2.4" - jest-haste-map "^27.4.5" + graceful-fs "^4.2.9" + jest-haste-map "^29.3.1" jest-pnp-resolver "^1.2.2" - jest-util "^27.4.2" - jest-validate "^27.4.2" + jest-util "^29.3.1" + jest-validate "^29.3.1" resolve "^1.20.0" resolve.exports "^1.1.0" slash "^3.0.0" -jest-runner@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-27.4.5.tgz" - integrity sha512-/irauncTfmY1WkTaRQGRWcyQLzK1g98GYG/8QvIPviHgO1Fqz1JYeEIsSfF+9mc/UTA6S+IIHFgKyvUrtiBIZg== +jest-runner@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.3.1.tgz#a92a879a47dd096fea46bb1517b0a99418ee9e2d" + integrity sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA== dependencies: - "@jest/console" "^27.4.2" - "@jest/environment" "^27.4.4" - "@jest/test-result" "^27.4.2" - "@jest/transform" "^27.4.5" - "@jest/types" "^27.4.2" + "@jest/console" "^29.3.1" + "@jest/environment" "^29.3.1" + "@jest/test-result" "^29.3.1" + "@jest/transform" "^29.3.1" + "@jest/types" "^29.3.1" "@types/node" "*" chalk "^4.0.0" - emittery "^0.8.1" - exit "^0.1.2" - graceful-fs "^4.2.4" - jest-docblock "^27.4.0" - jest-environment-jsdom "^27.4.4" - jest-environment-node "^27.4.4" - jest-haste-map "^27.4.5" - jest-leak-detector "^27.4.2" - jest-message-util "^27.4.2" - jest-resolve "^27.4.5" - jest-runtime "^27.4.5" - jest-util "^27.4.2" - jest-worker "^27.4.5" - source-map-support "^0.5.6" - throat "^6.0.1" - -jest-runtime@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.4.5.tgz" - integrity sha512-CIYqwuJQXHQtPd/idgrx4zgJ6iCb6uBjQq1RSAGQrw2S8XifDmoM1Ot8NRd80ooAm+ZNdHVwsktIMGlA1F1FAQ== - dependencies: - "@jest/console" "^27.4.2" - "@jest/environment" "^27.4.4" - "@jest/globals" "^27.4.4" - "@jest/source-map" "^27.4.0" - "@jest/test-result" "^27.4.2" - "@jest/transform" "^27.4.5" - "@jest/types" "^27.4.2" - "@types/yargs" "^16.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.2.0" + jest-environment-node "^29.3.1" + jest-haste-map "^29.3.1" + jest-leak-detector "^29.3.1" + jest-message-util "^29.3.1" + jest-resolve "^29.3.1" + jest-runtime "^29.3.1" + jest-util "^29.3.1" + jest-watcher "^29.3.1" + jest-worker "^29.3.1" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.3.1.tgz#21efccb1a66911d6d8591276a6182f520b86737a" + integrity sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A== + dependencies: + "@jest/environment" "^29.3.1" + "@jest/fake-timers" "^29.3.1" + "@jest/globals" "^29.3.1" + "@jest/source-map" "^29.2.0" + "@jest/test-result" "^29.3.1" + "@jest/transform" "^29.3.1" + "@jest/types" "^29.3.1" + "@types/node" "*" chalk "^4.0.0" cjs-module-lexer "^1.0.0" collect-v8-coverage "^1.0.0" - execa "^5.0.0" - exit "^0.1.2" glob "^7.1.3" - graceful-fs "^4.2.4" - jest-haste-map "^27.4.5" - jest-message-util "^27.4.2" - jest-mock "^27.4.2" - jest-regex-util "^27.4.0" - jest-resolve "^27.4.5" - jest-snapshot "^27.4.5" - jest-util "^27.4.2" - jest-validate "^27.4.2" + graceful-fs "^4.2.9" + jest-haste-map "^29.3.1" + jest-message-util "^29.3.1" + jest-mock "^29.3.1" + jest-regex-util "^29.2.0" + jest-resolve "^29.3.1" + jest-snapshot "^29.3.1" + jest-util "^29.3.1" slash "^3.0.0" strip-bom "^4.0.0" - yargs "^16.2.0" -jest-serializer@^27.4.0: - version "27.4.0" - resolved "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.4.0.tgz" - integrity sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ== +jest-snapshot@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.3.1.tgz#17bcef71a453adc059a18a32ccbd594b8cc4e45e" + integrity sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA== dependencies: - "@types/node" "*" - graceful-fs "^4.2.4" - -jest-snapshot@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.4.5.tgz" - integrity sha512-eCi/iM1YJFrJWiT9de4+RpWWWBqsHiYxFG9V9o/n0WXs6GpW4lUt4FAHAgFPTLPqCUVzrMQmSmTZSgQzwqR7IQ== - dependencies: - "@babel/core" "^7.7.2" + "@babel/core" "^7.11.6" "@babel/generator" "^7.7.2" - "@babel/parser" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/traverse" "^7.7.2" - "@babel/types" "^7.0.0" - "@jest/transform" "^27.4.5" - "@jest/types" "^27.4.2" - "@types/babel__traverse" "^7.0.4" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.3.1" + "@jest/transform" "^29.3.1" + "@jest/types" "^29.3.1" + "@types/babel__traverse" "^7.0.6" "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^27.4.2" - graceful-fs "^4.2.4" - jest-diff "^27.4.2" - jest-get-type "^27.4.0" - jest-haste-map "^27.4.5" - jest-matcher-utils "^27.4.2" - jest-message-util "^27.4.2" - jest-resolve "^27.4.5" - jest-util "^27.4.2" + expect "^29.3.1" + graceful-fs "^4.2.9" + jest-diff "^29.3.1" + jest-get-type "^29.2.0" + jest-haste-map "^29.3.1" + jest-matcher-utils "^29.3.1" + jest-message-util "^29.3.1" + jest-util "^29.3.1" natural-compare "^1.4.0" - pretty-format "^27.4.2" - semver "^7.3.2" + pretty-format "^29.3.1" + semver "^7.3.5" -jest-util@^27.4.2: - version "27.4.2" - resolved "https://registry.npmjs.org/jest-util/-/jest-util-27.4.2.tgz" - integrity sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA== +jest-util@^29.0.0, jest-util@^29.2.1, jest-util@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.3.1.tgz#1dda51e378bbcb7e3bc9d8ab651445591ed373e1" + integrity sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^29.3.1" "@types/node" "*" chalk "^4.0.0" ci-info "^3.2.0" - graceful-fs "^4.2.4" + graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-validate@^27.4.2: - version "27.4.2" - resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-27.4.2.tgz" - integrity sha512-hWYsSUej+Fs8ZhOm5vhWzwSLmVaPAxRy+Mr+z5MzeaHm9AxUpXdoVMEW4R86y5gOobVfBsMFLk4Rb+QkiEpx1A== +jest-validate@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.3.1.tgz#d56fefaa2e7d1fde3ecdc973c7f7f8f25eea704a" + integrity sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g== dependencies: - "@jest/types" "^27.4.2" + "@jest/types" "^29.3.1" camelcase "^6.2.0" chalk "^4.0.0" - jest-get-type "^27.4.0" + jest-get-type "^29.2.0" leven "^3.1.0" - pretty-format "^27.4.2" + pretty-format "^29.3.1" -jest-watcher@^27.4.2: - version "27.4.2" - resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.4.2.tgz" - integrity sha512-NJvMVyyBeXfDezhWzUOCOYZrUmkSCiatpjpm+nFUid74OZEHk6aMLrZAukIiFDwdbqp6mTM6Ui1w4oc+8EobQg== +jest-watcher@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.3.1.tgz#3341547e14fe3c0f79f9c3a4c62dbc3fc977fd4a" + integrity sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg== dependencies: - "@jest/test-result" "^27.4.2" - "@jest/types" "^27.4.2" + "@jest/test-result" "^29.3.1" + "@jest/types" "^29.3.1" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^27.4.2" + emittery "^0.13.1" + jest-util "^29.3.1" string-length "^4.0.1" -jest-worker@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz" - integrity sha512-f2s8kEdy15cv9r7q4KkzGXvlY0JTcmCbMHZBfSQDwW77REr45IDWwd0lksDFeVHH2jJ5pqb90T77XscrjeGzzg== +jest-worker@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.3.1.tgz#e9462161017a9bb176380d721cab022661da3d6b" + integrity sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw== dependencies: "@types/node" "*" + jest-util "^29.3.1" merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^27.4.5: - version "27.4.5" - resolved "https://registry.npmjs.org/jest/-/jest-27.4.5.tgz" - integrity sha512-uT5MiVN3Jppt314kidCk47MYIRilJjA/l2mxwiuzzxGUeJIvA8/pDaJOAX5KWvjAo7SCydcW0/4WEtgbLMiJkg== - dependencies: - "@jest/core" "^27.4.5" - import-local "^3.0.2" - jest-cli "^27.4.5" +jest@29.2.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.2.0.tgz#e7997bc603f31e04edbbe87dd24cf6e7c432abac" + integrity sha512-6krPemKUXCEu5Fh3j6ZVoLMjpTQVm0OCU+7f3K/9gllX8wNIE6NSCQ6s0q2RDoiKLRaQlVRHyscjSPRPqCI0Fg== + dependencies: + "@jest/core" "^29.2.0" + "@jest/types" "^29.2.0" + import-local "^3.0.2" + jest-cli "^29.2.0" + +jiti@^1.21.0: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" + integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== + +jito-ts@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/jito-ts/-/jito-ts-3.0.1.tgz#24126389896e042c26d303c4e802064b249ed27e" + integrity sha512-TSofF7KqcwyaWGjPaSYC8RDoNBY1TPRNBHdrw24bdIi7mQ5bFEDdYK3D//llw/ml8YDvcZlgd644WxhjLTS9yg== + dependencies: + "@grpc/grpc-js" "^1.8.13" + "@noble/ed25519" "^1.7.1" + "@solana/web3.js" "~1.77.3" + agentkeepalive "^4.3.0" + dotenv "^16.0.3" + jayson "^4.0.0" + node-fetch "^2.6.7" + superstruct "^1.0.3" + +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== -joi@^17.4.0: - version "17.6.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.0.tgz#0bb54f2f006c09a96e75ce687957bd04290054b2" - integrity sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw== - dependencies: - "@hapi/hoek" "^9.0.0" - "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.3" - "@sideway/formula" "^3.0.0" - "@sideway/pinpoint" "^2.0.0" +js-base64@^3.7.2, js-base64@^3.7.5: + version "3.7.7" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.7.tgz#e51b84bf78fbf5702b9541e2cb7bfcb893b43e79" + integrity sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw== + +js-sha256@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.11.0.tgz#256a921d9292f7fe98905face82e367abaca9576" + integrity sha512-6xNlKayMZvds9h1Y1VWc0fQHQ82BxTXizWPEtEeGvmOUYpBRy4gbWroHLpzowe6xiQhHpelCQiE7HEdznyBL9Q== js-sha256@^0.9.0: version "0.9.0" - resolved "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz" + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== js-sha3@0.8.0, js-sha3@^0.8.0: version "0.8.0" - resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== js-sha512@^0.8.0: @@ -11721,7 +12106,7 @@ js-sha512@^0.8.0: "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@4.1.0, js-yaml@^4.1.0: @@ -11733,57 +12118,58 @@ js-yaml@4.1.0, js-yaml@^4.1.0: js-yaml@^3.13.1: version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" esprima "^4.0.0" -jsbi@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/jsbi/-/jsbi-4.1.0.tgz" - integrity sha512-384Z4keIsJtYpnVggsxaB255MZctILbxv+ihtwoWPF7KNOlYHn1LFpRnUw5qsAspUAA2+I7qzjVJxVYtHVjxNw== +jsbi@^3.1.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.2.5.tgz#b37bb90e0e5c2814c1c2a1bcd8c729888a2e37d6" + integrity sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ== jsbn@~0.1.0: version "0.1.1" - resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -jsdom@^16.6.0: - version "16.7.0" - resolved "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz" - integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== - dependencies: - abab "^2.0.5" - acorn "^8.2.4" - acorn-globals "^6.0.0" - cssom "^0.4.4" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + +jsdom@^20.0.0: + version "20.0.3" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-20.0.3.tgz#886a41ba1d4726f67a8858028c99489fed6ad4db" + integrity sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ== + dependencies: + abab "^2.0.6" + acorn "^8.8.1" + acorn-globals "^7.0.0" + cssom "^0.5.0" cssstyle "^2.3.0" - data-urls "^2.0.0" - decimal.js "^10.2.1" - domexception "^2.0.1" + data-urls "^3.0.2" + decimal.js "^10.4.2" + domexception "^4.0.0" escodegen "^2.0.0" - form-data "^3.0.0" - html-encoding-sniffer "^2.0.1" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" + form-data "^4.0.0" + html-encoding-sniffer "^3.0.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.1" is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.0" - parse5 "6.0.1" - saxes "^5.0.1" + nwsapi "^2.2.2" + parse5 "^7.1.1" + saxes "^6.0.0" symbol-tree "^3.2.4" - tough-cookie "^4.0.0" - w3c-hr-time "^1.0.2" - w3c-xmlserializer "^2.0.0" - webidl-conversions "^6.1.0" - whatwg-encoding "^1.0.5" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.5.0" - ws "^7.4.6" - xml-name-validator "^3.0.0" + tough-cookie "^4.1.2" + w3c-xmlserializer "^4.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^2.0.0" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" + ws "^8.11.0" + xml-name-validator "^4.0.0" jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== json-bigint@^1.0.0: version "1.0.0" @@ -11792,7 +12178,12 @@ json-bigint@^1.0.0: dependencies: bignumber.js "^9.0.0" -json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -11800,11 +12191,17 @@ json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: json-rpc-random-id@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= + integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== json-schema@0.4.0: version "0.4.0" @@ -11813,87 +12210,56 @@ json-schema@0.4.0: json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" + integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== dependencies: - jsonify "~0.0.0" - -json-stringify-nice@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz" - integrity sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw== + jsonify "^0.0.1" json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json3@^3.3.3: - version "3.3.3" - resolved "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz" - integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== +json5@^1.0.1, json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz" - dependencies: - minimist "^1.2.5" - -jsonc-parser@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22" - integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA== +json5@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.2.tgz#64471c5bdcc564c18f7c1d4df2e2297f2457c5ab" + integrity sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ== -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" +jsonc-parser@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" + integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== jsonfile@^6.0.1: version "6.1.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== dependencies: universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== -jsonparse@^1.2.0, jsonparse@^1.3.1: +jsonparse@^1.2.0: version "1.3.1" - resolved "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz" - integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= - -jsonpath@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/jsonpath/-/jsonpath-1.1.1.tgz#0ca1ed8fb65bb3309248cc9d5466d12d5b0b9901" - integrity sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w== - dependencies: - esprima "1.2.2" - static-eval "2.0.2" - underscore "1.12.1" - -jsonschema@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab" - integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ== + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== jsprim@^1.2.2: version "1.4.2" @@ -11905,22 +12271,27 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" +jsqr@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsqr/-/jsqr-1.4.0.tgz#8efb8d0a7cc6863cb6d95116b9069123ce9eb2d1" + integrity sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A== + "jsx-ast-utils@^2.4.1 || ^3.0.0": - version "3.2.0" - resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz" + version "3.3.3" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" + integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw== dependencies: - array-includes "^3.1.2" - object.assign "^4.1.2" + array-includes "^3.1.5" + object.assign "^4.1.3" -just-diff-apply@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/just-diff-apply/-/just-diff-apply-3.1.2.tgz#710d8cda00c65dc4e692df50dbe9bac5581c2193" - integrity sha512-TCa7ZdxCeq6q3Rgms2JCRHTCfWAETPZ8SzYUbkYF6KR3I03sN29DaOIC+xyWboIcMvjAsD5iG2u/RWzHD8XpgQ== - -just-diff@^3.0.1: - version "3.1.1" - resolved "https://registry.npmjs.org/just-diff/-/just-diff-3.1.1.tgz" - integrity sha512-sdMWKjRq8qWZEjDcVA6llnUT8RDEBIfOiGpYFPYa9u+2c39JCsejktSP7mj5eRid5EIvTzIpQ2kDOCw1Nq9BjQ== +keccak256@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/keccak256/-/keccak256-1.0.6.tgz#dd32fb771558fed51ce4e45a035ae7515573da58" + integrity sha512-8GLiM01PkdJVGUhR1e6M/AvWnSqYS0HaERI+K/QtStGDGlSTx2B1zTqZk4Zlqu5TxHJNTxWAdP9Y+WI50OApUw== + dependencies: + bn.js "^5.2.0" + buffer "^6.0.3" + keccak "^3.0.2" keccak@^3.0.0, keccak@^3.0.2: version "3.0.2" @@ -11931,177 +12302,55 @@ keccak@^3.0.0, keccak@^3.0.2: node-gyp-build "^4.2.0" readable-stream "^3.6.0" -killable@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz" - integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: - is-buffer "^1.1.5" + json-buffer "3.0.1" -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== +keyvaluestorage-interface@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff" + integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g== -kind-of@^6.0.0, kind-of@^6.0.2: +kind-of@^6.0.2: version "6.0.3" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== kleur@^3.0.3: version "3.0.3" - resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== kleur@^4.0.3: - version "4.1.4" - resolved "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz" - integrity sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA== - -lazy-ass@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" - integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= + version "4.1.5" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" + integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== leven@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== levn@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" type-check "~0.4.0" levn@~0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" -libnpmaccess@^4.0.2: - version "4.0.3" - resolved "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-4.0.3.tgz" - integrity sha512-sPeTSNImksm8O2b6/pf3ikv4N567ERYEpeKRPSmqlNt1dTZbvgpJIzg5vAhXHpw2ISBsELFRelk0jEahj1c6nQ== - dependencies: - aproba "^2.0.0" - minipass "^3.1.1" - npm-package-arg "^8.1.2" - npm-registry-fetch "^11.0.0" - -libnpmdiff@^2.0.4: - version "2.0.4" - resolved "https://registry.npmjs.org/libnpmdiff/-/libnpmdiff-2.0.4.tgz" - integrity sha512-q3zWePOJLHwsLEUjZw3Kyu/MJMYfl4tWCg78Vl6QGSfm4aXBUSVzMzjJ6jGiyarsT4d+1NH4B1gxfs62/+y9iQ== - dependencies: - "@npmcli/disparity-colors" "^1.0.1" - "@npmcli/installed-package-contents" "^1.0.7" - binary-extensions "^2.2.0" - diff "^5.0.0" - minimatch "^3.0.4" - npm-package-arg "^8.1.1" - pacote "^11.3.0" - tar "^6.1.0" - -libnpmexec@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/libnpmexec/-/libnpmexec-2.0.1.tgz" - integrity sha512-4SqBB7eJvJWmUKNF42Q5qTOn20DRjEE4TgvEh2yneKlAiRlwlhuS9MNR45juWwmoURJlf2K43bozlVt7OZiIOw== - dependencies: - "@npmcli/arborist" "^2.3.0" - "@npmcli/ci-detect" "^1.3.0" - "@npmcli/run-script" "^1.8.4" - chalk "^4.1.0" - mkdirp-infer-owner "^2.0.0" - npm-package-arg "^8.1.2" - pacote "^11.3.1" - proc-log "^1.0.0" - read "^1.0.7" - read-package-json-fast "^2.0.2" - walk-up-path "^1.0.0" - -libnpmfund@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/libnpmfund/-/libnpmfund-1.1.0.tgz" - integrity sha512-Kfmh3pLS5/RGKG5WXEig8mjahPVOxkik6lsbH4iX0si1xxNi6eeUh/+nF1MD+2cgalsQif3O5qyr6mNz2ryJrQ== - dependencies: - "@npmcli/arborist" "^2.5.0" - -libnpmhook@^6.0.2: - version "6.0.3" - resolved "https://registry.npmjs.org/libnpmhook/-/libnpmhook-6.0.3.tgz" - integrity sha512-3fmkZJibIybzmAvxJ65PeV3NzRc0m4xmYt6scui5msocThbEp4sKFT80FhgrCERYDjlUuFahU6zFNbJDHbQ++g== - dependencies: - aproba "^2.0.0" - npm-registry-fetch "^11.0.0" - -libnpmorg@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/libnpmorg/-/libnpmorg-2.0.3.tgz" - integrity sha512-JSGl3HFeiRFUZOUlGdiNcUZOsUqkSYrg6KMzvPZ1WVZ478i47OnKSS0vkPmX45Pai5mTKuwIqBMcGWG7O8HfdA== - dependencies: - aproba "^2.0.0" - npm-registry-fetch "^11.0.0" - -libnpmpack@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/libnpmpack/-/libnpmpack-2.0.1.tgz" - integrity sha512-He4/jxOwlaQ7YG7sIC1+yNeXeUDQt8RLBvpI68R3RzPMZPa4/VpxhlDo8GtBOBDYoU8eq6v1wKL38sq58u4ibQ== - dependencies: - "@npmcli/run-script" "^1.8.3" - npm-package-arg "^8.1.0" - pacote "^11.2.6" - -libnpmpublish@^4.0.1: - version "4.0.2" - resolved "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-4.0.2.tgz" - integrity sha512-+AD7A2zbVeGRCFI2aO//oUmapCwy7GHqPXFJh3qpToSRNU+tXKJ2YFUgjt04LPPAf2dlEH95s6EhIHM1J7bmOw== - dependencies: - normalize-package-data "^3.0.2" - npm-package-arg "^8.1.2" - npm-registry-fetch "^11.0.0" - semver "^7.1.3" - ssri "^8.0.1" - -libnpmsearch@^3.1.1: - version "3.1.2" - resolved "https://registry.npmjs.org/libnpmsearch/-/libnpmsearch-3.1.2.tgz" - integrity sha512-BaQHBjMNnsPYk3Bl6AiOeVuFgp72jviShNBw5aHaHNKWqZxNi38iVNoXbo6bG/Ccc/m1To8s0GtMdtn6xZ1HAw== - dependencies: - npm-registry-fetch "^11.0.0" - -libnpmteam@^2.0.3: - version "2.0.4" - resolved "https://registry.npmjs.org/libnpmteam/-/libnpmteam-2.0.4.tgz" - integrity sha512-FPrVJWv820FZFXaflAEVTLRWZrerCvfe7ZHSMzJ/62EBlho2KFlYKjyNEsPW3JiV7TLSXi3vo8u0gMwIkXSMTw== - dependencies: - aproba "^2.0.0" - npm-registry-fetch "^11.0.0" - -libnpmversion@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/libnpmversion/-/libnpmversion-1.2.1.tgz" - integrity sha512-AA7x5CFgBFN+L4/JWobnY5t4OAHjQuPbAwUYJ7/NtHuyLut5meb+ne/aj0n7PWNiTGCJcRw/W6Zd2LoLT7EZuQ== - dependencies: - "@npmcli/git" "^2.0.7" - "@npmcli/run-script" "^1.8.4" - json-parse-even-better-errors "^2.3.1" - semver "^7.3.5" - stringify-package "^1.0.1" - -libphonenumber-js@^1.10.6: +libphonenumber-js@1.10.6: version "1.10.6" resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.6.tgz#a453efe9d692cc9457abb20a712dec34472a7164" integrity sha512-CIjT100/SmntsUjsLVs2t3ufeN4KdNXUxhD07tH153pdbaCWuAjv0jK/gPuywR3IImB/U/MQM+x9RfhMs5XZiA== @@ -12109,67 +12358,118 @@ libphonenumber-js@^1.10.6: lie@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" - integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4= + integrity sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw== dependencies: immediate "~3.0.5" lilconfig@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25" - integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg== - -lilconfig@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== +lilconfig@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" + integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -linkify-it@^2.0.3: - version "2.2.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" - integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== - dependencies: - uc.micro "^1.0.1" - -lint-staged@^10.0.10: - version "10.5.4" - resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.4.tgz" +lint-staged@10.0.10: + version "10.0.10" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.0.10.tgz#d14d33ee02a31a31ad36cf9aa7973fc156c461b5" + integrity sha512-91vNy3eYStExElLWw1Idva5lghKpFaXh9AJqjcyrJXf7AYZrThi4EhQ+GpmiHdPmJJauKhZMMSzQR1bMB90MtA== dependencies: - chalk "^4.1.0" - cli-truncate "^2.1.0" - commander "^6.2.0" - cosmiconfig "^7.0.0" - debug "^4.2.0" + chalk "^3.0.0" + commander "^4.0.1" + cosmiconfig "^6.0.0" + debug "^4.1.1" dedent "^0.7.0" - enquirer "^2.3.6" - execa "^4.1.0" - listr2 "^3.2.2" - log-symbols "^4.0.0" + execa "^3.4.0" + listr "^0.14.3" + log-symbols "^3.0.0" micromatch "^4.0.2" normalize-path "^3.0.0" please-upgrade-node "^3.2.0" string-argv "0.3.1" stringify-object "^3.3.0" -listr2@^3.2.2: - version "3.7.1" - resolved "https://registry.npmjs.org/listr2/-/listr2-3.7.1.tgz" +listhen@^1.5.5: + version "1.6.0" + resolved "https://registry.yarnpkg.com/listhen/-/listhen-1.6.0.tgz#df26c527c59b87557be4d0408d4a09626bd946c8" + integrity sha512-z0RcEXVX5oTpY1bO02SKoTU/kmZSrFSngNNzHRM6KICR17PTq7ANush6AE6ztGJwJD4RLpBrVHd9GnV51J7s3w== + dependencies: + "@parcel/watcher" "^2.4.0" + "@parcel/watcher-wasm" "2.4.0" + citty "^0.1.5" + clipboardy "^4.0.0" + consola "^3.2.3" + crossws "^0.1.0" + defu "^6.1.4" + get-port-please "^3.1.2" + h3 "^1.10.1" + http-shutdown "^1.2.2" + jiti "^1.21.0" + mlly "^1.5.0" + node-forge "^1.3.1" + pathe "^1.1.2" + std-env "^3.7.0" + ufo "^1.3.2" + untun "^0.1.3" + uqr "^0.1.2" + +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + integrity sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA== + +listr-update-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" + integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA== + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^2.3.0" + strip-ansi "^3.0.1" + +listr-verbose-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" + integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== dependencies: - chalk "^4.1.0" - cli-truncate "^2.1.0" - figures "^3.2.0" - indent-string "^4.0.0" - log-update "^4.0.0" - p-map "^4.0.0" - rxjs "^6.6.7" - through "^2.3.8" - wrap-ansi "^7.0.0" + chalk "^2.4.1" + cli-cursor "^2.1.0" + date-fns "^1.27.2" + figures "^2.0.0" + +listr@^0.14.3: + version "0.14.3" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" + integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== + dependencies: + "@samverschueren/stream-to-observable" "^0.3.0" + is-observable "^1.1.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.5.0" + listr-verbose-renderer "^0.5.0" + p-map "^2.0.0" + rxjs "^6.3.3" + +load-tsconfig@^0.2.3: + version "0.2.5" + resolved "https://registry.yarnpkg.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz#453b8cd8961bfb912dea77eb6c168fe8cca3d3a1" + integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg== -localforage@^1.10.0, localforage@^1.8.1: +localforage@1.10.0, localforage@^1.8.1: version "1.10.0" resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4" integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg== @@ -12178,7 +12478,7 @@ localforage@^1.10.0, localforage@^1.8.1: locate-path@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: p-locate "^3.0.0" @@ -12186,7 +12486,7 @@ locate-path@^3.0.0: locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" @@ -12200,97 +12500,80 @@ locate-path@^6.0.0: lodash-es@^4.17.21: version "4.17.21" - resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== lodash.camelcase@^4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz" - integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= - -lodash.chunk@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz" - integrity sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw= + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== -lodash.escaperegexp@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz" - integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c= +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== lodash.flatmap@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz" + resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" + integrity sha512-/OcpcAGWlrZyoHGeHh3cAoa6nGdX6QYtmzNP84Jqol6UEQQ2gIaU3H+0eICcjcKGl0/XF8LWOujNn9lffsnaOg== lodash.get@^4.4.2: version "4.4.2" - resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz" - -lodash.groupby@^4.6.0: - version "4.6.0" - resolved "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz" - integrity sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E= + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz" - integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= +lodash.isarguments@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== -lodash.isequal@^4.5.0: +lodash.isequal@4.5.0, lodash.isequal@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash.isfunction@^3.0.9: - version "3.0.9" - resolved "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz" - integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== - -lodash.isnil@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz" - integrity sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw= - -lodash.isundefined@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz" - integrity sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g= + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== lodash.mapvalues@^4.6.0: version "4.6.0" - resolved "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz" - integrity sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw= + resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" + integrity sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ== + +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.orderby@^4.6.0: - version "4.6.0" - resolved "https://registry.npmjs.org/lodash.orderby/-/lodash.orderby-4.6.0.tgz" - integrity sha1-5pfwTOXXhSL1TZM4syuBozk+TrM= +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== lodash.topath@^4.5.2: version "4.5.2" - resolved "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz" - integrity sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak= + resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009" + integrity sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg== -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= +lodash.zipobject@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/lodash.zipobject/-/lodash.zipobject-4.1.3.tgz#b399f5aba8ff62a746f6979bf20b214f964dbef8" + integrity sha512-A9SzX4hMKWS25MyalwcOnNoplyHbkNVsjidhTp8ru0Sj23wY9GWBKS8gAIGDSAqeWjIjvE4KBEl24XXAs+v4wQ== -lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: +lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@4.1.0, log-symbols@^4.0.0, log-symbols@^4.1.0: +log-symbols@4.1.0, log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -12298,139 +12581,98 @@ log-symbols@4.1.0, log-symbols@^4.0.0, log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -log-update@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz" +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + integrity sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ== dependencies: - ansi-escapes "^4.3.0" - cli-cursor "^3.1.0" - slice-ansi "^4.0.0" - wrap-ansi "^6.2.0" + chalk "^1.0.0" -loglevel@^1.6.8, loglevel@^1.8.0: - version "1.8.0" - resolved "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz" - integrity sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA== +log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" -long@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" - integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== +log-update@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" + integrity sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg== + dependencies: + ansi-escapes "^3.0.0" + cli-cursor "^2.0.0" + wrap-ansi "^3.0.1" -long@~3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" - integrity sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s= +loglevel@^1.8.0, loglevel@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4" + integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg== + +long@^5.0.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== longest-streak@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/longest-streak/-/longest-streak-3.0.1.tgz" - integrity sha512-cHlYSUpL2s7Fb3394mYxwTYj8niTaNHUCLr0qdiCXQfSjfuA7CKofpX2uSwEfFDQ0EB7JcnMnm+GjbqqoinYYg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4" + integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g== loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lower-case@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== dependencies: tslib "^2.0.3" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -lru_map@^0.3.3: - version "0.3.3" - resolved "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" - integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= - -lunr@^2.3.9: - version "2.3.9" - resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" - integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== - -luxon@^2.4.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-2.5.0.tgz#098090f67d690b247e83c090267a60b1aa8ea96c" - integrity sha512-IDkEPB80Rb6gCAU+FEib0t4FeJ4uVOuX1CQ9GsvU3O+JAGIgu0J7sf1OarXKaKDygTZIoJyU6YdZzTFRu+YR0A== +lru-cache@^10.0.2, lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== lz-string@^1.4.4: version "1.4.4" - resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" + integrity sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ== + +magic-string@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" + integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" make-dir@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" -make-error@^1.1.1: +make-error@1.x, make-error@^1.1.1: version "1.3.6" - resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -make-fetch-happen@^9.0.1, make-fetch-happen@^9.1.0: - version "9.1.0" - resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz" - integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== - dependencies: - agentkeepalive "^4.1.3" - cacache "^15.2.0" - http-cache-semantics "^4.1.0" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - is-lambda "^1.0.1" - lru-cache "^6.0.0" - minipass "^3.1.3" - minipass-collect "^1.0.2" - minipass-fetch "^1.3.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - negotiator "^0.6.2" - promise-retry "^2.0.1" - socks-proxy-agent "^6.0.0" - ssri "^8.0.0" - -makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz" - dependencies: - tmpl "1.0.x" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== dependencies: - object-visit "^1.0.0" + tmpl "1.0.5" markdown-table@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.2.tgz" - integrity sha512-y8j3a5/DkJCmS5x4dMCQL+OR0+2EAq3DOtio1COSHsmW2BGXnNCK3v12hJt1LrUz5iZH5g0LmuYOjDdI+czghA== - -marked@~2.0.3: - version "2.0.7" - resolved "https://registry.yarnpkg.com/marked/-/marked-2.0.7.tgz#bc5b857a09071b48ce82a1f7304913a993d4b7d1" - integrity sha512-BJXxkuIfJchcXOJWTT2DOL+yFWifFv2yGYOUzvXg8Qz610QKw+sHCvTMYwA+qWGhlA2uivBezChZ/pBy1tWdkQ== + version "3.0.3" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.3.tgz#e6331d30e493127e031dd385488b5bd326e4a6bd" + integrity sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw== matchmediaquery@^0.3.0: version "0.3.1" @@ -12441,7 +12683,7 @@ matchmediaquery@^0.3.0: md5.js@^1.3.4: version "1.3.5" - resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" @@ -12449,42 +12691,44 @@ md5.js@^1.3.4: safe-buffer "^5.1.2" mdast-util-definitions@^5.0.0: - version "5.1.0" - resolved "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.0.tgz" - integrity sha512-5hcR7FL2EuZ4q6lLMUK5w4lHT2H3vqL9quPvYZ/Ku5iifrirfMHiGdhxdXMUbUkDmz5I+TYMd7nbaxUhbQkfpQ== + version "5.1.1" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz#2c1d684b28e53f84938bb06317944bee8efa79db" + integrity sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ== dependencies: "@types/mdast" "^3.0.0" "@types/unist" "^2.0.0" - unist-util-visit "^3.0.0" + unist-util-visit "^4.0.0" mdast-util-find-and-replace@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.1.0.tgz" - integrity sha512-1w1jbqAd13oU78QPBf5223+xB+37ecNtQ1JElq2feWols5oEYAl+SgNDnOZipe7NfLemoEt362yUS15/wip4mw== + version "2.2.1" + resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.1.tgz#249901ef43c5f41d6e8a8d446b3b63b17e592d7c" + integrity sha512-SobxkQXFAdd4b5WmEakmkVoh18icjQRxGy5OWTCzgsLRm1Fu/KCtwD1HIQSsmq5ZRjVH0Ehwg6/Fn3xIUk+nKw== dependencies: escape-string-regexp "^5.0.0" unist-util-is "^5.0.0" - unist-util-visit-parents "^4.0.0" + unist-util-visit-parents "^5.0.0" mdast-util-from-markdown@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.0.0.tgz" - integrity sha512-uj2G60sb7z1PNOeElFwCC9b/Se/lFXuLhVKFOAY2EHz/VvgbupTQRNXPoZl7rGpXYL6BNZgcgaybrlSWbo7n/g== + version "1.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.2.0.tgz#84df2924ccc6c995dec1e2368b2b208ad0a76268" + integrity sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q== dependencies: "@types/mdast" "^3.0.0" "@types/unist" "^2.0.0" - mdast-util-to-string "^3.0.0" + decode-named-character-reference "^1.0.0" + mdast-util-to-string "^3.1.0" micromark "^3.0.0" micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-decode-string "^1.0.0" micromark-util-normalize-identifier "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-types "^1.0.0" - parse-entities "^3.0.0" unist-util-stringify-position "^3.0.0" + uvu "^0.5.0" mdast-util-gfm-autolink-literal@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.2.tgz#4032dcbaddaef7d4f2f3768ed830475bb22d3970" integrity sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg== dependencies: "@types/mdast" "^3.0.0" @@ -12494,7 +12738,7 @@ mdast-util-gfm-autolink-literal@^1.0.0: mdast-util-gfm-footnote@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.1.tgz#11d2d40a1a673a399c459e467fa85e00223191fe" integrity sha512-p+PrYlkw9DeCRkTVw1duWqPRHX6Ywh2BNKJQcZbCwAuP/59B0Lk9kakuAd7KbQprVO4GzdW8eS5++A9PUSqIyw== dependencies: "@types/mdast" "^3.0.0" @@ -12502,25 +12746,26 @@ mdast-util-gfm-footnote@^1.0.0: micromark-util-normalize-identifier "^1.0.0" mdast-util-gfm-strikethrough@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.1.tgz" - integrity sha512-zKJbEPe+JP6EUv0mZ0tQUyLQOC+FADt0bARldONot/nefuISkaZFlmVK4tU6JgfyZGrky02m/I6PmehgAgZgqg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.2.tgz#6b4fa4ae37d449ccb988192ac0afbb2710ffcefd" + integrity sha512-T/4DVHXcujH6jx1yqpcAYYwd+z5lAYMw4Ls6yhTfbMMtCt0PHY4gEfhW9+lKsLBtyhUGKRIzcUA2FATVqnvPDA== dependencies: "@types/mdast" "^3.0.0" mdast-util-to-markdown "^1.3.0" mdast-util-gfm-table@^1.0.0: - version "1.0.4" - resolved "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.4.tgz" - integrity sha512-aEuoPwZyP4iIMkf2cLWXxx3EQ6Bmh2yKy9MVCg4i6Sd3cX80dcLEfXO/V4ul3pGH9czBK4kp+FAl+ZHmSUt9/w== + version "1.0.6" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.6.tgz#184e900979fe790745fc3dabf77a4114595fcd7f" + integrity sha512-uHR+fqFq3IvB3Rd4+kzXW8dmpxUhvgCQZep6KdjsLK4O6meK5dYZEayLtIxNus1XO3gfjfcIFe8a7L0HZRGgag== dependencies: + "@types/mdast" "^3.0.0" markdown-table "^3.0.0" mdast-util-from-markdown "^1.0.0" mdast-util-to-markdown "^1.3.0" mdast-util-gfm-task-list-item@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.1.tgz#6f35f09c6e2bcbe88af62fdea02ac199cc802c5c" integrity sha512-KZ4KLmPdABXOsfnM6JHUIjxEvcx2ulk656Z/4Balw071/5qgnhz+H1uGtf2zIGnrnvDC8xR4Fj9uKbjAFGNIeA== dependencies: "@types/mdast" "^3.0.0" @@ -12528,7 +12773,7 @@ mdast-util-gfm-task-list-item@^1.0.0: mdast-util-gfm@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-2.0.1.tgz#16fcf70110ae689a06d77e8f4e346223b64a0ea6" integrity sha512-42yHBbfWIFisaAfV1eixlabbsa6q7vHeSPY+cg+BBjX51M8xhgMacqH9g6TftB/9+YkcI0ooV4ncfrJslzm/RQ== dependencies: mdast-util-from-markdown "^1.0.0" @@ -12540,9 +12785,9 @@ mdast-util-gfm@^2.0.0: mdast-util-to-markdown "^1.0.0" mdast-util-to-hast@^11.0.0: - version "11.2.0" - resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-11.2.0.tgz" - integrity sha512-KSYbg4PA9wk5YwoCZCPxbUAjdYunNN5TqTXoZp/9taRDGQS65cL2fFgKc78l0f3deg4p1LP9xdhmMuUrhAUSZA== + version "11.3.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-11.3.0.tgz#ea9220617a710e80aa5cc3ac7cc9d4bb0440ae7a" + integrity sha512-4o3Cli3hXPmm1LhB+6rqhfsIUBjnKFlIUZvudaermXB+4/KONdd/W4saWWkC+LBLbPMqhFSSTSRgafHsT5fVJw== dependencies: "@types/hast" "^2.0.0" "@types/mdast" "^3.0.0" @@ -12552,12 +12797,12 @@ mdast-util-to-hast@^11.0.0: unist-builder "^3.0.0" unist-util-generated "^2.0.0" unist-util-position "^4.0.0" - unist-util-visit "^3.0.0" + unist-util-visit "^4.0.0" mdast-util-to-markdown@^1.0.0, mdast-util-to-markdown@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.3.0.tgz" - integrity sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA== + version "1.4.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-1.4.0.tgz#bb0153a865dbc022975f403a156fb6399c494ddf" + integrity sha512-IjXARf/O8VGx/pc5SZ7syfydq1DYL9vd92orsG5U0b4GNCmAvXzu+n7sbzfIKrXwB0AVrYk3NV2kXl0AIi9LCA== dependencies: "@types/mdast" "^3.0.0" "@types/unist" "^2.0.0" @@ -12567,57 +12812,63 @@ mdast-util-to-markdown@^1.0.0, mdast-util-to-markdown@^1.3.0: unist-util-visit "^4.0.0" zwitch "^2.0.0" -mdast-util-to-string@^3.0.0: +mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9" integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA== mdurl@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== "memoize-one@>=3.1.1 <6": version "5.2.1" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== -memory-fs@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + is-plain-obj "^2.1.0" merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -methods@^1.1.2, methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +merkletreejs@^0.2.32: + version "0.2.32" + resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.2.32.tgz#cf1c0760e2904e4a1cc269108d6009459fd06223" + integrity sha512-TostQBiwYRIwSE5++jGmacu3ODcKAgqb0Y/pnIohXS7sWxh1gCkSptbmF1a43faehRDpcHf7J/kv0Ml2D/zblQ== + dependencies: + bignumber.js "^9.0.1" + buffer-reverse "^1.0.1" + crypto-js "^3.1.9-1" + treeify "^1.1.0" + web3-utils "^1.3.4" -micromark-core-commonmark@^1.0.0: +merkletreejs@^0.3.11: + version "0.3.11" + resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.3.11.tgz#e0de05c3ca1fd368de05a12cb8efb954ef6fc04f" + integrity sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ== + dependencies: + bignumber.js "^9.0.1" + buffer-reverse "^1.0.1" + crypto-js "^4.2.0" + treeify "^1.1.0" + web3-utils "^1.3.4" + +micromark-core-commonmark@^1.0.0, micromark-core-commonmark@^1.0.1: version "1.0.6" - resolved "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz#edff4c72e5993d93724a3c206970f5a15b0585ad" integrity sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA== dependencies: decode-named-character-reference "^1.0.0" @@ -12637,30 +12888,9 @@ micromark-core-commonmark@^1.0.0: micromark-util-types "^1.0.1" uvu "^0.5.0" -micromark-core-commonmark@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.0.1.tgz" - integrity sha512-vEOw8hcQ3nwHkKKNIyP9wBi8M50zjNajtmI+cCUWcVfJS+v5/3WCh4PLKf7PPRZFUutjzl4ZjlHwBWUKfb/SkA== - dependencies: - micromark-factory-destination "^1.0.0" - micromark-factory-label "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-factory-title "^1.0.0" - micromark-factory-whitespace "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-chunked "^1.0.0" - micromark-util-classify-character "^1.0.0" - micromark-util-html-tag-name "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-subtokenize "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.1" - parse-entities "^3.0.0" - micromark-extension-gfm-autolink-literal@^1.0.0: version "1.0.3" - resolved "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.3.tgz#dc589f9c37eaff31a175bab49f12290edcf96058" integrity sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg== dependencies: micromark-util-character "^1.0.0" @@ -12671,7 +12901,7 @@ micromark-extension-gfm-autolink-literal@^1.0.0: micromark-extension-gfm-footnote@^1.0.0: version "1.0.4" - resolved "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.0.4.tgz#cbfd8873b983e820c494498c6dac0105920818d5" integrity sha512-E/fmPmDqLiMUP8mLJ8NbJWJ4bTw6tS+FEQS8CcuDtZpILuOb2kjLqPEeAePF1djXROHXChM/wPJw0iS4kHCcIg== dependencies: micromark-core-commonmark "^1.0.0" @@ -12685,7 +12915,7 @@ micromark-extension-gfm-footnote@^1.0.0: micromark-extension-gfm-strikethrough@^1.0.0: version "1.0.4" - resolved "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.4.tgz#162232c284ffbedd8c74e59c1525bda217295e18" integrity sha512-/vjHU/lalmjZCT5xt7CcHVJGq8sYRm80z24qAKXzaHzem/xsDYb2yLL+NNVbYvmpLx3O7SYPuGL5pzusL9CLIQ== dependencies: micromark-util-chunked "^1.0.0" @@ -12697,7 +12927,7 @@ micromark-extension-gfm-strikethrough@^1.0.0: micromark-extension-gfm-table@^1.0.0: version "1.0.5" - resolved "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.5.tgz#7b708b728f8dc4d95d486b9e7a2262f9cddbcbb4" integrity sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg== dependencies: micromark-factory-space "^1.0.0" @@ -12708,14 +12938,14 @@ micromark-extension-gfm-table@^1.0.0: micromark-extension-gfm-tagfilter@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.1.tgz#fb2e303f7daf616db428bb6a26e18fda14a90a4d" integrity sha512-Ty6psLAcAjboRa/UKUbbUcwjVAv5plxmpUTy2XC/3nJFL37eHej8jrHrRzkqcpipJliuBH30DTs7+3wqNcQUVA== dependencies: micromark-util-types "^1.0.0" micromark-extension-gfm-task-list-item@^1.0.0: version "1.0.3" - resolved "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.3.tgz#7683641df5d4a09795f353574d7f7f66e47b7fc4" integrity sha512-PpysK2S1Q/5VXi72IIapbi/jliaiOFzv7THH4amwXeYXLq3l1uo8/2Be0Ac1rEwK20MQEsGH2ltAZLNY2KI/0Q== dependencies: micromark-factory-space "^1.0.0" @@ -12726,7 +12956,7 @@ micromark-extension-gfm-task-list-item@^1.0.0: micromark-extension-gfm@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-2.0.1.tgz#40f3209216127a96297c54c67f5edc7ef2d1a2a2" integrity sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA== dependencies: micromark-extension-gfm-autolink-literal "^1.0.0" @@ -12740,7 +12970,7 @@ micromark-extension-gfm@^2.0.0: micromark-factory-destination@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz#fef1cb59ad4997c496f887b6977aa3034a5a277e" integrity sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw== dependencies: micromark-util-character "^1.0.0" @@ -12748,35 +12978,37 @@ micromark-factory-destination@^1.0.0: micromark-util-types "^1.0.0" micromark-factory-label@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.0.0.tgz" - integrity sha512-XWEucVZb+qBCe2jmlOnWr6sWSY6NHx+wtpgYFsm4G+dufOf6tTQRRo0bdO7XSlGPu5fyjpJenth6Ksnc5Mwfww== + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz#6be2551fa8d13542fcbbac478258fb7a20047137" + integrity sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg== dependencies: micromark-util-character "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-types "^1.0.0" + uvu "^0.5.0" micromark-factory-space@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz#cebff49968f2b9616c0fcb239e96685cb9497633" integrity sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew== dependencies: micromark-util-character "^1.0.0" micromark-util-types "^1.0.0" micromark-factory-title@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.0.0.tgz" - integrity sha512-flvC7Gx0dWVWorXuBl09Cr3wB5FTuYec8pMGVySIp2ZlqTcIjN/lFohZcP0EG//krTptm34kozHk7aK/CleCfA== + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz#7e09287c3748ff1693930f176e1c4a328382494f" + integrity sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A== dependencies: micromark-factory-space "^1.0.0" micromark-util-character "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-types "^1.0.0" + uvu "^0.5.0" micromark-factory-whitespace@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz#e991e043ad376c1ba52f4e49858ce0794678621c" integrity sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A== dependencies: micromark-factory-space "^1.0.0" @@ -12786,7 +13018,7 @@ micromark-factory-whitespace@^1.0.0: micromark-util-character@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.1.0.tgz#d97c54d5742a0d9611a68ca0cd4124331f264d86" integrity sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg== dependencies: micromark-util-symbol "^1.0.0" @@ -12794,14 +13026,14 @@ micromark-util-character@^1.0.0: micromark-util-chunked@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz#5b40d83f3d53b84c4c6bce30ed4257e9a4c79d06" integrity sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g== dependencies: micromark-util-symbol "^1.0.0" micromark-util-classify-character@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz#cbd7b447cb79ee6997dd274a46fc4eb806460a20" integrity sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA== dependencies: micromark-util-character "^1.0.0" @@ -12810,7 +13042,7 @@ micromark-util-classify-character@^1.0.0: micromark-util-combine-extensions@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz#91418e1e74fb893e3628b8d496085639124ff3d5" integrity sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA== dependencies: micromark-util-chunked "^1.0.0" @@ -12818,14 +13050,14 @@ micromark-util-combine-extensions@^1.0.0: micromark-util-decode-numeric-character-reference@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz#dcc85f13b5bd93ff8d2868c3dba28039d490b946" integrity sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w== dependencies: micromark-util-symbol "^1.0.0" micromark-util-decode-string@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz#942252ab7a76dec2dbf089cc32505ee2bc3acf02" integrity sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q== dependencies: decode-named-character-reference "^1.0.0" @@ -12834,64 +13066,66 @@ micromark-util-decode-string@^1.0.0: micromark-util-symbol "^1.0.0" micromark-util-encode@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.0.0.tgz" - integrity sha512-cJpFVM768h6zkd8qJ1LNRrITfY4gwFt+tziPcIf71Ui8yFzY9wG3snZQqiWVq93PG4Sw6YOtcNiKJfVIs9qfGg== + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz#2c1c22d3800870ad770ece5686ebca5920353383" + integrity sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA== micromark-util-html-tag-name@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.0.0.tgz" - integrity sha512-NenEKIshW2ZI/ERv9HtFNsrn3llSPZtY337LID/24WeLqMzeZhBEE6BQ0vS2ZBjshm5n40chKtJ3qjAbVV8S0g== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz#eb227118befd51f48858e879b7a419fc0df20497" + integrity sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA== micromark-util-normalize-identifier@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz#4a3539cb8db954bbec5203952bfe8cedadae7828" integrity sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg== dependencies: micromark-util-symbol "^1.0.0" micromark-util-resolve-all@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz#a7c363f49a0162e931960c44f3127ab58f031d88" integrity sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw== dependencies: micromark-util-types "^1.0.0" micromark-util-sanitize-uri@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.0.0.tgz" - integrity sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.1.0.tgz#f12e07a85106b902645e0364feb07cf253a85aee" + integrity sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg== dependencies: micromark-util-character "^1.0.0" micromark-util-encode "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-subtokenize@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.0.tgz" - integrity sha512-EsnG2qscmcN5XhkqQBZni/4oQbLFjz9yk3ZM/P8a3YUjwV6+6On2wehr1ALx0MxK3+XXXLTzuBKHDFeDFYRdgQ== + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz#ff6f1af6ac836f8bfdbf9b02f40431760ad89105" + integrity sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA== dependencies: micromark-util-chunked "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-types "^1.0.0" + uvu "^0.5.0" micromark-util-symbol@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.0.0.tgz" - integrity sha512-NZA01jHRNCt4KlOROn8/bGi6vvpEmlXld7EHcRH+aYWUfL3Wc8JLUNNlqUMKa0hhz6GrpUWsHtzPmKof57v0gQ== + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz#b90344db62042ce454f351cf0bebcc0a6da4920e" + integrity sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ== micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.0.1.tgz" - integrity sha512-UT0ylWEEy80RFYzK9pEaugTqaxoD/j0Y9WhHpSyitxd99zjoQz7JJ+iKuhPAgOW2MiPSUAx+c09dcqokeyaROA== + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.0.2.tgz#f4220fdb319205812f99c40f8c87a9be83eded20" + integrity sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w== micromark@^3.0.0: - version "3.0.5" - resolved "https://registry.npmjs.org/micromark/-/micromark-3.0.5.tgz" - integrity sha512-QfjERBnPw0G9mxhOCkkbRP0n8SX8lIBLrEKeEVceviUukqVMv3hWE4AgNTOK/W6GWqtPvvIHg2Apl3j1Dxm6aQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.1.0.tgz#eeba0fe0ac1c9aaef675157b52c166f125e89f62" + integrity sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA== dependencies: "@types/debug" "^4.0.0" debug "^4.0.0" + decode-named-character-reference "^1.0.0" micromark-core-commonmark "^1.0.1" micromark-factory-space "^1.0.0" micromark-util-character "^1.0.0" @@ -12905,28 +13139,9 @@ micromark@^3.0.0: micromark-util-subtokenize "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-types "^1.0.1" - parse-entities "^3.0.0" - -micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" + uvu "^0.5.0" -micromatch@^4.0.0, micromatch@^4.0.4: +micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -12934,85 +13149,56 @@ micromatch@^4.0.0, micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" -micromatch@^4.0.2: - version "4.0.4" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -microseconds@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" - integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== - -microtime@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/microtime/-/microtime-3.0.0.tgz#d140914bde88aa89b4f9fd2a18620b435af0f39b" - integrity sha512-SirJr7ZL4ow2iWcb54bekS4aWyBQNVcEDBiwAz9D/sTgY59A+uE8UJU15cp5wyZmPBwg/3zf8lyCJ5NUe1nVlQ== +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: - node-addon-api "^1.2.0" - node-gyp-build "^3.8.0" - -mime-db@1.47.0: - version "1.47.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz" - -mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": - version "1.51.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + bn.js "^4.0.0" + brorand "^1.0.1" mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12: - version "2.1.30" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz" - dependencies: - mime-db "1.47.0" - -mime-types@^2.1.34, mime-types@~2.1.19: +mime-types@^2.1.12, mime-types@^2.1.34, mime-types@~2.1.19: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" -mime-types@~2.1.17, mime-types@~2.1.24: - version "2.1.34" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@2.6.0, mime@^2.4.4, mime@^2.4.6: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - mime@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + mimic-fn@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== min-indent@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== +mini-svg-data-uri@^1.2.3: + version "1.4.4" + resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz#8ab0aabcdf8c29ad5693ca595af19dd2ead09939" + integrity sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -13021,202 +13207,146 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" - integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== dependencies: - brace-expansion "^1.1.7" + brace-expansion "^2.0.1" -minimatch@^3.0.0, minimatch@^3.0.4, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - -minipass-collect@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz" - integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== - dependencies: - minipass "^3.0.0" - -minipass-fetch@^1.3.0, minipass-fetch@^1.3.2: - version "1.4.1" - resolved "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz" - integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== - dependencies: - minipass "^3.1.0" - minipass-sized "^1.0.3" - minizlib "^2.0.0" - optionalDependencies: - encoding "^0.1.12" - -minipass-flush@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz" - integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== dependencies: - minipass "^3.0.0" + brace-expansion "^2.0.1" -minipass-json-stream@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz" - integrity sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg== +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: - jsonparse "^1.3.1" - minipass "^3.0.0" + brace-expansion "^2.0.1" -minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: - version "1.2.4" - resolved "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz" - integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== - dependencies: - minipass "^3.0.0" +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== -minipass-sized@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz" - integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== dependencies: - minipass "^3.0.0" + yallist "^4.0.0" -minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: - version "3.1.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" - integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== +minipass@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.0.0.tgz#7cebb0f9fa7d56f0c5b17853cbe28838a8dbbd3b" + integrity sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw== dependencies: yallist "^4.0.0" -minizlib@^2.0.0, minizlib@^2.1.1: +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +minizlib@^2.1.1: version "2.1.2" - resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== dependencies: minipass "^3.0.0" yallist "^4.0.0" -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp-infer-owner@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz" - integrity sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw== - dependencies: - chownr "^2.0.0" - infer-owner "^1.0.4" - mkdirp "^1.0.3" - -mkdirp@^0.5.1: - version "0.5.5" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mkdirp@^0.5.5: +mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: minimist "^1.2.6" -mkdirp@^1.0.3, mkdirp@^1.0.4: +mkdirp@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mocha@^9.1.1: - version "9.2.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" - integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== +mlly@^1.2.0, mlly@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.5.0.tgz#8428a4617d54cc083d3009030ac79739a0e5447a" + integrity sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ== + dependencies: + acorn "^8.11.3" + pathe "^1.1.2" + pkg-types "^1.0.3" + ufo "^1.3.2" + +mocha@10.1.0, mocha@^9.1.4, mocha@^9.2.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.1.0.tgz#dbf1114b7c3f9d0ca5de3133906aea3dfc89ef7a" + integrity sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg== dependencies: - "@ungap/promise-all-settled" "1.1.2" ansi-colors "4.1.1" browser-stdout "1.3.1" chokidar "3.5.3" - debug "4.3.3" + debug "4.3.4" diff "5.0.0" escape-string-regexp "4.0.0" find-up "5.0.0" glob "7.2.0" - growl "1.10.5" he "1.2.0" js-yaml "4.1.0" log-symbols "4.1.0" - minimatch "4.2.1" + minimatch "5.0.1" ms "2.1.3" - nanoid "3.3.1" + nanoid "3.3.3" serialize-javascript "6.0.0" strip-json-comments "3.1.1" supports-color "8.1.1" - which "2.0.2" - workerpool "6.2.0" + workerpool "6.2.1" yargs "16.2.0" yargs-parser "20.2.4" yargs-unparser "2.0.0" modern-normalize@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/modern-normalize/-/modern-normalize-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/modern-normalize/-/modern-normalize-1.1.0.tgz#da8e80140d9221426bd4f725c6e11283d34f90b7" integrity sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA== -mri@^1.1.0: +mri@^1.1.0, mri@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== mrmime@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz" - integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + version "1.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" + integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== ms@2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.2: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1: version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== - dependencies: - dns-packet "^1.3.1" - thunky "^1.0.2" - -multiformats@^9.4.2, multiformats@^9.6.4, multiformats@^9.7.1: - version "9.7.1" - resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.7.1.tgz#ab348e5fd6f8e7fb3fd56033211bda48854e2173" - integrity sha512-TaVmGEBt0fhxiNJMGphBfB+oGvUxFs8KgGvgl8d3C+GWtrFcvXdJ2196eg+dYhmSFClmgFfSfJEklo+SZzdNuw== +multiformats@^9.4.2, multiformats@^9.6.4: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== multistream@^4.1.0: version "4.1.0" @@ -13233,7 +13363,7 @@ mustache@^4.0.0: mute-stream@0.0.8, mute-stream@~0.0.4: version "0.0.8" - resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== mz@^2.7.0: @@ -13245,67 +13375,35 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@^2.12.1, nan@^2.13.2: - version "2.15.0" - resolved "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== - nan@^2.14.0, nan@^2.14.2: - version "2.16.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.16.0.tgz#664f43e45460fb98faf00edca0bb0d7b8dce7916" - integrity sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA== + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== nanoclone@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz" + resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== -nanoid@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" - integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== - -nanoid@^3.1.30: - version "3.3.2" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557" - integrity sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA== - -nanoid@^3.3.1: +nanoid@3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== -nanoid@^3.3.4: +nanoid@^3.3.1, nanoid@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== -nanoid@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.0.tgz#6e144dee117609232c3f415c34b0e550e64999a5" - integrity sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" +napi-wasm@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/napi-wasm/-/napi-wasm-1.1.0.tgz#bbe617823765ae9c1bc12ff5942370eae7b2ba4e" + integrity sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg== natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== near-api-js@^0.44.2: version "0.44.2" @@ -13343,97 +13441,67 @@ near-seed-phrase@^0.2.0: near-hd-key "^1.2.1" tweetnacl "^1.0.2" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -negotiator@^0.6.2: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -neo-async@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -next-router-mock@^0.6.7: +next-router-mock@0.6.7: version "0.6.7" resolved "https://registry.yarnpkg.com/next-router-mock/-/next-router-mock-0.6.7.tgz#8883ed81f245074462e72199fe94002cd85db5e2" integrity sha512-y3yFyTkplpmvCpy1TnOuMTUQDLt2wg9RwTwvg9WcCRko4lqkBYAQM+ph5sqtNpKQ1xngDwzjPjshVBQJvhb/hg== -next-themes@^0.1.1: +next-themes@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.1.1.tgz#122113a458bf1d1be5ffed66778ab924c106f82a" integrity sha512-Iqxt6rhS/KfK/iHJ0tfFjTcdLEAI0AgwFuAFrMwLOPK5e+MI3I+fzyvBoS+VaOS+NldUiazurhgwYhrfV0VXsQ== -next-transpile-modules@^8.0.0: - version "8.0.0" - resolved "https://registry.npmjs.org/next-transpile-modules/-/next-transpile-modules-8.0.0.tgz" - integrity sha512-Q2f2yB0zMJ8KJbIYAeZoIxG6cSfVk813zr6B5HzsLMBVcJ3FaF8lKr7WG66n0KlHCwjLSmf/6EkgI6QQVWHrDw== +next-transpile-modules@9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/next-transpile-modules/-/next-transpile-modules-9.1.0.tgz#dffd2563bf76f8afdb28f0611948f46252ca65ef" + integrity sha512-yzJji65xDqcIqjvx5vPJcs1M+MYQTzLM1pXH/qf8Q88ohx+bwVGDc1AeV+HKr1NwvMCNTpwVPSFI7cA5WdyeWA== dependencies: - enhanced-resolve "^5.7.0" + enhanced-resolve "^5.10.0" escalade "^3.1.1" -next@^12.2.2: - version "12.2.2" - resolved "https://registry.yarnpkg.com/next/-/next-12.2.2.tgz#029bf5e4a18a891ca5d05b189b7cd983fd22c072" - integrity sha512-zAYFY45aBry/PlKONqtlloRFqU/We3zWYdn2NoGvDZkoYUYQSJC8WMcalS5C19MxbCZLUVCX7D7a6gTGgl2yLg== - dependencies: - "@next/env" "12.2.2" - "@swc/helpers" "0.4.2" - caniuse-lite "^1.0.30001332" - postcss "8.4.5" - styled-jsx "5.0.2" - use-sync-external-store "1.1.0" +next@12.3.2: + version "12.3.2" + resolved "https://registry.yarnpkg.com/next/-/next-12.3.2.tgz#3a3356a8d752726128825a8bdf17f2a3b3f861cf" + integrity sha512-orzvvebCwOqaz1eA5ZA0R5dbKxqtJyw7yeig7kDspu6p8OrplfyelzpvMHcDTKscv/l0nn/0l0v3mSsE8w4k7A== + dependencies: + "@next/env" "12.3.2" + "@swc/helpers" "0.4.11" + caniuse-lite "^1.0.30001406" + postcss "8.4.14" + styled-jsx "5.0.7" + use-sync-external-store "1.2.0" optionalDependencies: - "@next/swc-android-arm-eabi" "12.2.2" - "@next/swc-android-arm64" "12.2.2" - "@next/swc-darwin-arm64" "12.2.2" - "@next/swc-darwin-x64" "12.2.2" - "@next/swc-freebsd-x64" "12.2.2" - "@next/swc-linux-arm-gnueabihf" "12.2.2" - "@next/swc-linux-arm64-gnu" "12.2.2" - "@next/swc-linux-arm64-musl" "12.2.2" - "@next/swc-linux-x64-gnu" "12.2.2" - "@next/swc-linux-x64-musl" "12.2.2" - "@next/swc-win32-arm64-msvc" "12.2.2" - "@next/swc-win32-ia32-msvc" "12.2.2" - "@next/swc-win32-x64-msvc" "12.2.2" - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + "@next/swc-android-arm-eabi" "12.3.2" + "@next/swc-android-arm64" "12.3.2" + "@next/swc-darwin-arm64" "12.3.2" + "@next/swc-darwin-x64" "12.3.2" + "@next/swc-freebsd-x64" "12.3.2" + "@next/swc-linux-arm-gnueabihf" "12.3.2" + "@next/swc-linux-arm64-gnu" "12.3.2" + "@next/swc-linux-arm64-musl" "12.3.2" + "@next/swc-linux-x64-gnu" "12.3.2" + "@next/swc-linux-x64-musl" "12.3.2" + "@next/swc-win32-arm64-msvc" "12.3.2" + "@next/swc-win32-ia32-msvc" "12.3.2" + "@next/swc-win32-x64-msvc" "12.3.2" no-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== dependencies: lower-case "^2.0.2" tslib "^2.0.3" -noble-ed25519@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/noble-ed25519/-/noble-ed25519-1.2.6.tgz#a55b75c61da000498abb43ffd81caaa370bfed22" - integrity sha512-zfnWqg9FVMp8CnzUpAjbt1nDXpDjCvxYiCXdnW1mY8zQHw/6twUlkFm14VPdojVzc0kcd+i9zT79+26GcNbsuQ== - -node-addon-api@^1.2.0: - version "1.7.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d" - integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== - node-addon-api@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== -node-domexception@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" - integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== +node-addon-api@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.0.tgz#71f609369379c08e251c558527a107107b5e0fdb" + integrity sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g== node-emoji@^1.11.0: version "1.11.0" @@ -13442,45 +13510,45 @@ node-emoji@^1.11.0: dependencies: lodash "^4.17.21" -node-fetch@2, node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch-native@^1.4.0, node-fetch-native@^1.4.1, node-fetch-native@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.1.tgz#f95c74917d3cebc794cdae0cd2a9c7594aad0cb4" + integrity sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw== + +node-fetch@2.6.1, node-fetch@2.6.7: version "2.6.7" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-fetch@2.6.1: - version "2.6.1" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== - -node-fetch@^3.2.3: - version "3.2.6" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.6.tgz#6d4627181697a9d9674aae0d61548e0d629b31b9" - integrity sha512-LAy/HZnLADOVkVPubaxHDft29booGglPFDr2Hw0J1AercRh01UiVFm++KMDnJeH9sHgNB4hsXPii7Sgym/sTbw== +node-fetch@3.3.2, "node-fetch@npm:@blockworks-foundation/node-fetch@2.6.11": + version "2.6.11" + resolved "https://registry.yarnpkg.com/@blockworks-foundation/node-fetch/-/node-fetch-2.6.11.tgz#fb536ef0e6a960e7b7993f3c1d3b3bba9bdfbc56" + integrity sha512-HeDTxpIypSR4qCoqgUXGr8YL4OG1z7BbV4VhQ9iQs+pt2wV3MtqO+sQk2vXK3WDKu5C6BsbGmWE22BmIrcuOOw== dependencies: - data-uri-to-buffer "^4.0.0" - fetch-blob "^3.1.4" - formdata-polyfill "^4.0.10" + whatwg-url "^5.0.0" -node-forge@^0.10.0: - version "0.10.0" - resolved "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz" - integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== +node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: + version "2.6.12" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" + integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + dependencies: + whatwg-url "^5.0.0" -node-gyp-build@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-3.9.0.tgz#53a350187dd4d5276750da21605d1cb681d09e25" - integrity sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A== +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz" - integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== -node-gyp@^7.1.0, node-gyp@^7.1.2: +node-gyp@^7.1.0: version "7.1.2" - resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae" integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ== dependencies: env-paths "^2.2.0" @@ -13496,233 +13564,70 @@ node-gyp@^7.1.0, node-gyp@^7.1.2: node-int64@^0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-localstorage@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-localstorage/-/node-localstorage-2.2.1.tgz#869723550a4883e426cb391d2df0b563a51c7c1c" - integrity sha512-vv8fJuOUCCvSPjDjBLlMqYMHob4aGjkmrkaE42/mZr0VT+ZAU10jRF8oTnX9+pgU9/vYJ8P7YT3Vd6ajkmzSCw== +node-kraken-api@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/node-kraken-api/-/node-kraken-api-2.2.2.tgz#28bf56eec1f0ffe7e784b2ffa29b360ed98b0e4c" + integrity sha512-f+BZpgT1gD9705hlsRDDGj9m96Psb0Gxu3Td/P2fs0/gFy58YQONrTPiqfYzOBxvpmYnuAMxCRuRmdmkw04eRw== dependencies: - write-file-atomic "^1.1.4" - -node-modules-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz" - -node-releases@^1.1.71: - version "1.1.71" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz" + crc "^4.1.0" + ts-ev "^0.4.0" + ws "^8.5.0" + optionalDependencies: + bufferutil "^4.0.6" + utf-8-validate "^5.0.9" -node-releases@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz" - integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== +node-releases@^2.0.6: + version "2.0.7" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.7.tgz#593edbc7c22860ee4d32d3933cfebdfab0c0e0e5" + integrity sha512-EJ3rzxL9pTWPjk5arA0s0dgXpnyiAbJDE6wHT62g7VsgrgQgmmZ+Ru++M1BFofncWja+Pnn3rEr3fieRySAdKQ== nopt@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== dependencies: abbrev "1" -normalize-package-data@^3.0.0, normalize-package-data@^3.0.2: - version "3.0.3" - resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz" - integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== - dependencies: - hosted-git-info "^4.0.1" - is-core-module "^2.5.0" - semver "^7.3.4" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== normalize-range@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== -npm-audit-report@^2.1.5: - version "2.1.5" - resolved "https://registry.npmjs.org/npm-audit-report/-/npm-audit-report-2.1.5.tgz" - integrity sha512-YB8qOoEmBhUH1UJgh1xFAv7Jg1d+xoNhsDYiFQlEFThEBui0W1vIz2ZK6FVg4WZjwEdl7uBQlm1jy3MUfyHeEw== - dependencies: - chalk "^4.0.0" - -npm-bundled@^1.1.1: - version "1.1.2" - resolved "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz" - integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ== - dependencies: - npm-normalize-package-bin "^1.0.1" - -npm-install-checks@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz" - integrity sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w== - dependencies: - semver "^7.1.1" - -npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: +npm-normalize-package-bin@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== -npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.0, npm-package-arg@^8.1.1, npm-package-arg@^8.1.2, npm-package-arg@^8.1.5: - version "8.1.5" - resolved "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz" - integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q== - dependencies: - hosted-git-info "^4.0.1" - semver "^7.3.4" - validate-npm-package-name "^3.0.0" - -npm-packlist@^2.1.4: - version "2.2.2" - resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-2.2.2.tgz" - integrity sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg== - dependencies: - glob "^7.1.6" - ignore-walk "^3.0.3" - npm-bundled "^1.1.1" - npm-normalize-package-bin "^1.0.1" - -npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.0, npm-pick-manifest@^6.1.1: - version "6.1.1" - resolved "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz" - integrity sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA== - dependencies: - npm-install-checks "^4.0.0" - npm-normalize-package-bin "^1.0.1" - npm-package-arg "^8.1.2" - semver "^7.3.4" - -npm-profile@^5.0.3: - version "5.0.4" - resolved "https://registry.npmjs.org/npm-profile/-/npm-profile-5.0.4.tgz" - integrity sha512-OKtU7yoAEBOnc8zJ+/uo5E4ugPp09sopo+6y1njPp+W99P8DvQon3BJYmpvyK2Bf1+3YV5LN1bvgXRoZ1LUJBA== - dependencies: - npm-registry-fetch "^11.0.0" - -npm-registry-fetch@^11.0.0: - version "11.0.0" - resolved "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz" - integrity sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA== - dependencies: - make-fetch-happen "^9.0.1" - minipass "^3.1.3" - minipass-fetch "^1.3.0" - minipass-json-stream "^1.0.1" - minizlib "^2.0.0" - npm-package-arg "^8.0.0" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" +npm-normalize-package-bin@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.0.tgz#6097436adb4ef09e2628b59a7882576fe53ce485" + integrity sha512-g+DPQSkusnk7HYXr75NtzkIP4+N81i3RPsGFidF3DzHd9MT9wWngmqoeg/fnHFz5MNdtG4w03s+QnhewSLTT2Q== npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: path-key "^3.0.0" -npm-user-validate@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-1.0.1.tgz" - integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw== - -npm@^7.24.1: - version "7.24.2" - resolved "https://registry.npmjs.org/npm/-/npm-7.24.2.tgz" - integrity sha512-120p116CE8VMMZ+hk8IAb1inCPk4Dj3VZw29/n2g6UI77urJKVYb7FZUDW8hY+EBnfsjI/2yrobBgFyzo7YpVQ== - dependencies: - "@isaacs/string-locale-compare" "^1.1.0" - "@npmcli/arborist" "^2.9.0" - "@npmcli/ci-detect" "^1.2.0" - "@npmcli/config" "^2.3.0" - "@npmcli/map-workspaces" "^1.0.4" - "@npmcli/package-json" "^1.0.1" - "@npmcli/run-script" "^1.8.6" - abbrev "~1.1.1" - ansicolors "~0.3.2" - ansistyles "~0.1.3" - archy "~1.0.0" - cacache "^15.3.0" - chalk "^4.1.2" - chownr "^2.0.0" - cli-columns "^3.1.2" - cli-table3 "^0.6.0" - columnify "~1.5.4" - fastest-levenshtein "^1.0.12" - glob "^7.2.0" - graceful-fs "^4.2.8" - hosted-git-info "^4.0.2" - ini "^2.0.0" - init-package-json "^2.0.5" - is-cidr "^4.0.2" - json-parse-even-better-errors "^2.3.1" - libnpmaccess "^4.0.2" - libnpmdiff "^2.0.4" - libnpmexec "^2.0.1" - libnpmfund "^1.1.0" - libnpmhook "^6.0.2" - libnpmorg "^2.0.2" - libnpmpack "^2.0.1" - libnpmpublish "^4.0.1" - libnpmsearch "^3.1.1" - libnpmteam "^2.0.3" - libnpmversion "^1.2.1" - make-fetch-happen "^9.1.0" - minipass "^3.1.3" - minipass-pipeline "^1.2.4" - mkdirp "^1.0.4" - mkdirp-infer-owner "^2.0.0" - ms "^2.1.2" - node-gyp "^7.1.2" - nopt "^5.0.0" - npm-audit-report "^2.1.5" - npm-install-checks "^4.0.0" - npm-package-arg "^8.1.5" - npm-pick-manifest "^6.1.1" - npm-profile "^5.0.3" - npm-registry-fetch "^11.0.0" - npm-user-validate "^1.0.1" - npmlog "^5.0.1" - opener "^1.5.2" - pacote "^11.3.5" - parse-conflict-json "^1.1.1" - qrcode-terminal "^0.12.0" - read "~1.0.7" - read-package-json "^4.1.1" - read-package-json-fast "^2.0.3" - readdir-scoped-modules "^1.1.0" - rimraf "^3.0.2" - semver "^7.3.5" - ssri "^8.0.1" - tar "^6.1.11" - text-table "~0.2.0" - tiny-relative-date "^1.3.0" - treeverse "^1.0.4" - validate-npm-package-name "~3.0.0" - which "^2.0.2" - write-file-atomic "^3.0.3" +npm-run-path@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.2.0.tgz#224cdd22c755560253dd71b83a1ef2f758b2e955" + integrity sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg== + dependencies: + path-key "^4.0.0" npmlog@^4.1.2: version "4.1.2" - resolved "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" @@ -13730,35 +13635,28 @@ npmlog@^4.1.2: gauge "~2.7.3" set-blocking "~2.0.0" -npmlog@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz" - integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== - dependencies: - are-we-there-yet "^2.0.0" - console-control-strings "^1.1.0" - gauge "^3.0.0" - set-blocking "^2.0.0" - num2fraction@^1.2.2: version "1.2.2" - resolved "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + integrity sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg== number-is-nan@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== -numbro@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/numbro/-/numbro-2.3.6.tgz#4bd622ebe59ccbc49dad365c5b9eed200781fa21" - integrity sha512-pxpoTT3hVxQGaOA2RTzXR/muonQNd1K1HPJbWo7QOmxPwiPmoFCFfsG9XXgW3uqjyzezJ0P9IvCPDXUtJexjwg== +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== dependencies: - bignumber.js "^8.1.1" + bn.js "4.11.6" + strip-hex-prefix "1.0.0" -nwsapi@^2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz" +nwsapi@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" + integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== o3@^1.0.3: version "1.0.3" @@ -13769,166 +13667,145 @@ o3@^1.0.3: oauth-sign@~0.9.0: version "0.9.0" - resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-hash@^1.3.1: - version "1.3.1" - resolved "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz" - integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-hash@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== -object-hash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" - integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== - -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.11.0" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== -object-is@^1.0.1: +object-is@^1.0.1, object-is@^1.1.5: version "1.1.5" - resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== +object.assign@^4.1.3, object.assign@^4.1.4, object.assign@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" + call-bind "^1.0.5" + define-properties "^1.2.1" + has-symbols "^1.0.3" object-keys "^1.1.1" -object.entries@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz" - integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - -object.fromentries@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz" - integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== +object.entries@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" + integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" -object.hasown@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz" - integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg== +object.fromentries@^2.0.7, object.fromentries@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== dependencies: - define-properties "^1.1.3" - es-abstract "^1.19.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= +object.groupby@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" + integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== dependencies: - isobject "^3.0.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" -object.values@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz" - integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== +object.values@^1.1.7, object.values@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" + integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" oblivious-set@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.1.1.tgz#d9d38e9491d51f27a5c3ec1681d2ba40aa81e98b" integrity sha512-Oh+8fK09mgGmAshFdH6hSVco6KZmd1tTwNFWj35OvzdmJTMZtAkbn05zar2iG3v6sDs1JLEtOiBGNb6BHwkb2w== -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= +ofetch@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.3.tgz#588cb806a28e5c66c2c47dd8994f9059a036d8c0" + integrity sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg== dependencies: - ee-first "1.1.1" + destr "^2.0.1" + node-fetch-native "^1.4.0" + ufo "^1.3.0" -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== +ohash@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.3.tgz#f12c3c50bfe7271ce3fd1097d42568122ccdcf07" + integrity sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw== -once@1.4.0, once@^1.3.0, once@^1.3.1, once@^1.4.0: +on-exit-leak-free@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" + integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== + dependencies: + mimic-fn "^1.0.0" + onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + opener@^1.5.2: version "1.5.2" - resolved "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== -opn@^5.5.0: - version "5.5.0" - resolved "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz" - integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== - dependencies: - is-wsl "^1.1.0" - optionator@^0.8.1: version "0.8.3" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.6" @@ -13937,16 +13814,17 @@ optionator@^0.8.1: type-check "~0.3.2" word-wrap "~1.2.3" -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== dependencies: deep-is "^0.1.3" fast-levenshtein "^2.0.6" levn "^0.4.1" prelude-ls "^1.2.1" type-check "^0.4.0" - word-wrap "^1.2.3" + word-wrap "^1.2.5" ora@^5.4.1: version "5.4.1" @@ -13963,31 +13841,24 @@ ora@^5.4.1: strip-ansi "^6.0.0" wcwidth "^1.0.1" -original@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" - integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== - dependencies: - url-parse "^1.4.3" - os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= +p-finally@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" -p-limit@^3.0.2: +p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -13996,14 +13867,14 @@ p-limit@^3.0.2: p-locate@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== dependencies: p-limit "^2.0.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" @@ -14017,76 +13888,23 @@ p-locate@^5.0.0: p-map@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" - dependencies: - aggregate-error "^3.0.0" - -p-queue@6.6.2: - version "6.6.2" - resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426" - integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ== - dependencies: - eventemitter3 "^4.0.4" - p-timeout "^3.2.0" - -p-retry@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz" - integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== - dependencies: - retry "^0.12.0" - -p-timeout@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" - integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== - dependencies: - p-finally "^1.0.0" - p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pacote@^11.1.11, pacote@^11.2.6, pacote@^11.3.0, pacote@^11.3.1, pacote@^11.3.5: - version "11.3.5" - resolved "https://registry.npmjs.org/pacote/-/pacote-11.3.5.tgz" - integrity sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg== - dependencies: - "@npmcli/git" "^2.1.0" - "@npmcli/installed-package-contents" "^1.0.6" - "@npmcli/promise-spawn" "^1.2.0" - "@npmcli/run-script" "^1.8.2" - cacache "^15.0.5" - chownr "^2.0.0" - fs-minipass "^2.1.0" - infer-owner "^1.0.4" - minipass "^3.1.3" - mkdirp "^1.0.3" - npm-package-arg "^8.0.1" - npm-packlist "^2.1.4" - npm-pick-manifest "^6.0.0" - npm-registry-fetch "^11.0.0" - promise-retry "^2.0.1" - read-package-json-fast "^2.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.1.0" - -pako@^2.0.3: - version "2.0.4" - resolved "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz" - integrity sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg== +package-json-from-dist@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" + integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== -papaparse@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.3.2.tgz#d1abed498a0ee299f103130a6109720404fbd467" - integrity sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw== +pako@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" + integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== parent-module@^1.0.0: version "1.0.1" @@ -14095,28 +13913,18 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-conflict-json@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-1.1.1.tgz" - integrity sha512-4gySviBiW5TRl7XHvp1agcS7SOe0KZOjC//71dzZVWJrY9hCrgtvl5v3SyIxCZ4fZF47TxD9nfzmxcx76xmbUw== - dependencies: - json-parse-even-better-errors "^2.3.0" - just-diff "^3.0.1" - just-diff-apply "^3.0.0" - -parse-entities@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/parse-entities/-/parse-entities-3.0.0.tgz" - integrity sha512-AJlcIFDNPEP33KyJLguv0xJc83BNvjxwpuUIcetyXUsLpVXAUCePJ5kIoYtEN2R1ac0cYaRu/vk9dVFkewHQhQ== +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== dependencies: - character-entities "^2.0.0" - character-entities-legacy "^2.0.0" - character-reference-invalid "^2.0.0" - is-alphanumerical "^2.0.0" - is-decimal "^2.0.0" - is-hexadecimal "^2.0.0" + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" -parse-json@^5.0.0: +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -14126,82 +13934,67 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= - -parse5@6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= +parse5@^7.0.0, parse5@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" path-exists@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== -path-parse@^1.0.6, path-parse@^1.0.7: +path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-type@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pause-stream@0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= - dependencies: - through "~2.3" +pathe@^1.1.0, pathe@^1.1.1, pathe@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" + integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pbkdf2@^3.0.17, pbkdf2@^3.0.9: +pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -14214,109 +14007,119 @@ pbkdf2@^3.0.17, pbkdf2@^3.0.9: performance-now@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== picocolors@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.0, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pirates@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz" +pino-abstract-transport@v0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz#4b54348d8f73713bfd14e3dc44228739aa13d9c0" + integrity sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ== dependencies: - node-modules-regexp "^1.0.0" + duplexify "^4.1.2" + split2 "^4.0.0" -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" +pino-std-serializers@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1791ccd2539c091ae49ce9993205e2cd5dbba1e2" + integrity sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q== + +pino@7.11.0: + version "7.11.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6" + integrity sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg== + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.0.0" + on-exit-leak-free "^0.2.0" + pino-abstract-transport v0.5.0 + pino-std-serializers "^4.0.0" + process-warning "^1.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.1.0" + safe-stable-stringify "^2.1.0" + sonic-boom "^2.2.1" + thread-stream "^0.15.1" + +pirates@^4.0.1, pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== pkg-dir@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" +pkg-types@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.0.3.tgz#988b42ab19254c01614d13f4f65a2cfc7880f868" + integrity sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A== + dependencies: + jsonc-parser "^3.2.0" + mlly "^1.2.0" + pathe "^1.1.0" + please-upgrade-node@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== dependencies: semver-compare "^1.0.0" -polished@^4.1.3: - version "4.1.4" - resolved "https://registry.npmjs.org/polished/-/polished-4.1.4.tgz" - integrity sha512-Nq5Mbza+Auo7N3sQb1QMFaQiDO+4UexWuSGR7Cjb4Sw11SZIJcrrFtiZ+L0jT9MBsUsxDboHVASbCLbE1rnECg== - dependencies: - "@babel/runtime" "^7.16.7" +pngjs@^3.3.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== -portfinder@^1.0.26: - version "1.0.28" - resolved "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== +polished@^4.1.3, polished@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/polished/-/polished-4.2.2.tgz#2529bb7c3198945373c52e34618c8fe7b1aa84d1" + integrity sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ== dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" + "@babel/runtime" "^7.17.8" -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== postcss-attribute-case-insensitive@^4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" + integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA== dependencies: postcss "^7.0.2" postcss-selector-parser "^6.0.2" postcss-color-functional-notation@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" + integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== dependencies: postcss "^7.0.2" postcss-values-parser "^2.0.0" postcss-color-gray@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" + integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== dependencies: "@csstools/convert-colors" "^1.4.0" postcss "^7.0.5" @@ -14324,14 +14127,16 @@ postcss-color-gray@^5.0.0: postcss-color-hex-alpha@^5.0.3: version "5.0.3" - resolved "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz" + resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" + integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== dependencies: postcss "^7.0.14" postcss-values-parser "^2.0.1" postcss-color-mod-function@^3.0.3: version "3.0.3" - resolved "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" + integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== dependencies: "@csstools/convert-colors" "^1.4.0" postcss "^7.0.2" @@ -14339,101 +14144,105 @@ postcss-color-mod-function@^3.0.3: postcss-color-rebeccapurple@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" + integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== dependencies: postcss "^7.0.2" postcss-values-parser "^2.0.0" postcss-custom-media@^7.0.8: version "7.0.8" - resolved "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz" + resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" + integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== dependencies: postcss "^7.0.14" postcss-custom-properties@^8.0.11: version "8.0.11" - resolved "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" + integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== dependencies: postcss "^7.0.17" postcss-values-parser "^2.0.1" postcss-custom-selectors@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" + integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== dependencies: postcss "^7.0.2" postcss-selector-parser "^5.0.0-rc.3" postcss-dir-pseudo-class@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" + integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== dependencies: postcss "^7.0.2" postcss-selector-parser "^5.0.0-rc.3" postcss-double-position-gradients@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" + integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== dependencies: postcss "^7.0.5" postcss-values-parser "^2.0.0" postcss-env-function@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" + integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== dependencies: postcss "^7.0.2" postcss-values-parser "^2.0.0" postcss-focus-visible@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" + integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== dependencies: postcss "^7.0.2" postcss-focus-within@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" + integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== dependencies: postcss "^7.0.2" postcss-font-variant@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz#42d4c0ab30894f60f98b17561eb5c0321f502641" + integrity sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA== dependencies: postcss "^7.0.2" postcss-gap-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" + integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== dependencies: postcss "^7.0.2" postcss-image-set-function@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" + integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== dependencies: postcss "^7.0.2" postcss-values-parser "^2.0.0" -postcss-import@^14.1.0: - version "14.1.0" - resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0" - integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw== - dependencies: - postcss-value-parser "^4.0.0" - read-cache "^1.0.0" - resolve "^1.1.7" - postcss-initial@^3.0.0: version "3.0.4" - resolved "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.4.tgz" + resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.4.tgz#9d32069a10531fe2ecafa0b6ac750ee0bc7efc53" + integrity sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg== dependencies: postcss "^7.0.2" postcss-js@^3.0.3: version "3.0.3" - resolved "https://registry.npmjs.org/postcss-js/-/postcss-js-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-3.0.3.tgz#2f0bd370a2e8599d45439f6970403b5873abda33" integrity sha512-gWnoWQXKFw65Hk/mi2+WTQTHdPD5UJdDXZmX073EY/B3BWnYjO4F4t0VneTCnCGQ5E5GsCdMkzPaTXwl3r5dJw== dependencies: camelcase-css "^2.0.1" @@ -14448,13 +14257,14 @@ postcss-js@^4.0.0: postcss-lab-function@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" + integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== dependencies: "@csstools/convert-colors" "^1.4.0" postcss "^7.0.2" postcss-values-parser "^2.0.0" -postcss-load-config@^3.1.0, postcss-load-config@^3.1.4: +postcss-load-config@^3.1.0: version "3.1.4" resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855" integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg== @@ -14462,15 +14272,24 @@ postcss-load-config@^3.1.0, postcss-load-config@^3.1.4: lilconfig "^2.0.5" yaml "^1.10.2" +postcss-load-config@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-6.0.1.tgz#6fd7dcd8ae89badcf1b2d644489cbabf83aa8096" + integrity sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g== + dependencies: + lilconfig "^3.1.1" + postcss-logical@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" + integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== dependencies: postcss "^7.0.2" postcss-media-minmax@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" + integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== dependencies: postcss "^7.0.2" @@ -14483,32 +14302,37 @@ postcss-nested@5.0.6: postcss-nesting@^7.0.0: version "7.0.1" - resolved "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz" + resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" + integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== dependencies: postcss "^7.0.2" postcss-overflow-shorthand@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" + integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== dependencies: postcss "^7.0.2" postcss-page-break@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" + integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== dependencies: postcss "^7.0.2" postcss-place@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" + integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== dependencies: postcss "^7.0.2" postcss-values-parser "^2.0.0" -postcss-preset-env@^6.7.0: +postcss-preset-env@6.7.0: version "6.7.0" - resolved "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" + integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg== dependencies: autoprefixer "^9.6.1" browserslist "^4.6.4" @@ -14550,51 +14374,48 @@ postcss-preset-env@^6.7.0: postcss-pseudo-class-any-link@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" + integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== dependencies: postcss "^7.0.2" postcss-selector-parser "^5.0.0-rc.3" postcss-replace-overflow-wrap@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" + integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== dependencies: postcss "^7.0.2" postcss-selector-matches@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" + integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== dependencies: balanced-match "^1.0.0" postcss "^7.0.2" postcss-selector-not@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz#263016eef1cf219e0ade9a913780fc1f48204cbf" + integrity sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ== dependencies: balanced-match "^1.0.0" postcss "^7.0.2" postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: version "5.0.0" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== dependencies: cssesc "^2.0.0" indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^6.0.10: - version "6.0.10" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" - integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9: - version "6.0.9" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" - integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== + version "6.0.11" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc" + integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -14604,37 +14425,21 @@ postcss-value-parser@^3.3.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" + integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== dependencies: flatten "^1.0.2" indexes-of "^1.0.1" uniq "^1.0.1" -postcss@8.4.5: - version "8.4.5" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz" - integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== - dependencies: - nanoid "^3.1.30" - picocolors "^1.0.0" - source-map-js "^1.0.1" - -postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.39" - resolved "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz" - integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== - dependencies: - picocolors "^0.2.1" - source-map "^0.6.1" - -postcss@^8.1.6, postcss@^8.1.8, postcss@^8.3.5, postcss@^8.4.6: +postcss@8.4.12: version "8.4.12" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905" integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg== @@ -14643,7 +14448,7 @@ postcss@^8.1.6, postcss@^8.1.8, postcss@^8.3.5, postcss@^8.4.6: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.12, postcss@^8.4.14: +postcss@8.4.14: version "8.4.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== @@ -14652,116 +14457,125 @@ postcss@^8.4.12, postcss@^8.4.14: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== + dependencies: + picocolors "^0.2.1" + source-map "^0.6.1" + +postcss@^8.1.6, postcss@^8.1.8, postcss@^8.3.5, postcss@^8.4.6: + version "8.4.20" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.20.tgz#64c52f509644cecad8567e949f4081d98349dc56" + integrity sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g== + dependencies: + nanoid "^3.3.4" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +preact@10.4.1: + version "10.4.1" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.1.tgz#9b3ba020547673a231c6cf16f0fbaef0e8863431" + integrity sha512-WKrRpCSwL2t3tpOOGhf2WfTpcmbpxaWtDbdJdKdjd0aEiTkvOmS4NBkG6kzlaAHI9AkQ3iVqbFWM3Ei7mZ4o1Q== + prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prelude-ls@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" - -prettier@^2.0.2: - version "2.2.1" - resolved "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== -prettier@^2.4.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" - integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" -prettier@^2.5.1: - version "2.5.1" - resolved "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz" - integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== +prettier@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" + integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== pretty-format@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== dependencies: "@jest/types" "^26.6.2" ansi-regex "^5.0.0" ansi-styles "^4.0.0" react-is "^17.0.1" -pretty-format@^27.0.0, pretty-format@^27.4.2, pretty-format@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" - integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== +pretty-format@^29.0.0, pretty-format@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.3.1.tgz#1841cac822b02b4da8971dacb03e8a871b4722da" + integrity sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg== dependencies: - ansi-regex "^5.0.1" + "@jest/schemas" "^29.0.0" ansi-styles "^5.0.0" - react-is "^17.0.1" + react-is "^18.0.0" pretty-hrtime@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz" - integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= - -proc-log@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/proc-log/-/proc-log-1.0.0.tgz" - integrity sha512-aCk8AO51s+4JyuYGg3Q/a6gnrlDO09NpVWePtjp7xwphcoQ04x5WAfCyugcsbLooWcMJ87CLkD4+604IckEdhg== + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process-warning@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" + integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== + process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -promise-all-reject-late@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz" - integrity sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw== - -promise-call-limit@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz" - integrity sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q== - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= - promise-retry@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== dependencies: err-code "^2.0.2" retry "^0.12.0" -prompt-sync@^4.1.6: - version "4.2.0" - resolved "https://registry.npmjs.org/prompt-sync/-/prompt-sync-4.2.0.tgz" - integrity sha512-BuEzzc5zptP5LsgV5MZETjDaKSWfchl5U9Luiu8SKp7iZWD5tZalOxvNcZRwv+d2phNFr8xlbxmFNcRKfJOzJw== +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== dependencies: - strip-ansi "^5.0.0" + asap "~2.0.3" + +promptly@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/promptly/-/promptly-3.2.0.tgz#a5517fbbf59bd31c1751d4e1d9bef1714f42b9d8" + integrity sha512-WnR9obtgW+rG4oUV3hSnNGl1pHm3V1H/qD9iJBumGSmVsSC5HpZOLuu8qdMb6yCItGfT7dcRszejr/5P3i9Pug== + dependencies: + read "^1.0.4" prompts@^2.0.1: - version "2.4.1" - resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz" + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== dependencies: kleur "^3.0.3" sisteransi "^1.0.5" -promzard@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz" - integrity sha1-JqXW7ox97kyxIggwWs+5O6OCqe4= - dependencies: - read "1" - -prop-types@^15.0.0, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.0.0, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -14771,19 +14585,19 @@ prop-types@^15.0.0, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, react-is "^16.13.1" property-expr@^2.0.4: - version "2.0.4" - resolved "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz" - integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg== + version "2.0.5" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.5.tgz#278bdb15308ae16af3e3b9640024524f4dc02cb4" + integrity sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA== property-information@^6.0.0: - version "6.0.1" - resolved "https://registry.npmjs.org/property-information/-/property-information-6.0.1.tgz" - integrity sha512-F4WUUAF7fMeF4/JUFHNBWDaKDXi2jbvqBW/y6o5wsf3j19wTZ7S60TmtB5HoBhtgw7NKQRMWuz5vk2PR0CygUg== + version "6.2.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.2.0.tgz#b74f522c31c097b5149e3c3cb8d7f3defd986a1d" + integrity sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg== -protobufjs@^6.10.2, protobufjs@^6.11.3, protobufjs@^6.8.8: - version "6.11.3" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" - integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== +protobufjs@>=7.2.5, protobufjs@^7.2.5, protobufjs@^7.2.6: + version "7.2.6" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.6.tgz#4a0ccd79eb292717aacf07530a07e0ed20278215" + integrity sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -14795,55 +14609,65 @@ protobufjs@^6.10.2, protobufjs@^6.11.3, protobufjs@^6.8.8: "@protobufjs/path" "^1.1.2" "@protobufjs/pool" "^1.1.0" "@protobufjs/utf8" "^1.1.0" - "@types/long" "^4.0.1" "@types/node" ">=13.7.0" - long "^4.0.0" - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" + long "^5.0.0" proxy-from-env@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= +psl@^1.1.28, psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== -ps-tree@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" - integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA== +psyfi-euros-test@0.0.1-rc.33: + version "0.0.1-rc.33" + resolved "https://registry.yarnpkg.com/psyfi-euros-test/-/psyfi-euros-test-0.0.1-rc.33.tgz#23646d3a4284db3f8d5b5ba42999b1c0e2824804" + integrity sha512-vRCz2XzXxdQ1V9QGqxY8L1JWL687Au/FNik9lthO6n+NpfT3un7bvdWkeyyhNljfmhUDDW1zarvcIp/cAFj4VA== dependencies: - event-stream "=3.3.4" + "@project-serum/anchor" "0.23.0" + "@project-serum/common" "^0.0.1-beta.3" + "@project-serum/serum" "^0.13.61" + "@solana/spl-token" "0.1.8" + "@solana/web3.js" "^1.35.1" + psystake-test "0.0.1-rc.8" -psl@^1.1.28, psl@^1.1.33: - version "1.8.0" - resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== +psystake-test@0.0.1-rc.8: + version "0.0.1-rc.8" + resolved "https://registry.yarnpkg.com/psystake-test/-/psystake-test-0.0.1-rc.8.tgz#67ce3c7546c47ac44bd213997fadcee346efe440" + integrity sha512-wng85jJDM8SwVeH/6fUMKBxHiVPl6SwFm6Y1j3fNmhqEINwu1L+kShO3YCIhPN7oK2tox7Fb7tUrXdbk5HQ54g== + dependencies: + "@project-serum/anchor" "^0.23.0" + "@project-serum/common" "^0.0.1-beta.3" + "@project-serum/serum" "^0.13.61" + "@solana/spl-token" "^0.1.8" + "@solana/web3.js" "^1.35.1" + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" pump@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== dependencies: end-of-stream "^1.1.0" once "^1.3.1" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== purgecss@^4.0.3: @@ -14856,75 +14680,64 @@ purgecss@^4.0.3: postcss "^8.3.5" postcss-selector-parser "^6.0.6" -pyth-staking-api@^1.2.17: - version "1.2.17" - resolved "https://registry.yarnpkg.com/pyth-staking-api/-/pyth-staking-api-1.2.17.tgz#c49db878cdd6b074d76ac6bf09f6d7d23b29ae50" - integrity sha512-rcjS9aq9NO1oq1/ynbynKSkGDg1dt1GwPdzb5GlchH5gTtZ9ANsdfM5ZdYZ1DMcLVk8kUaj/n/4u4nZ/98KTYw== - dependencies: - "@project-serum/anchor" "0.24.2" - "@solana/spl-governance" "^0.0.34" - "@solana/spl-token" "^0.1.8" - "@solana/web3.js" "^1.36.0" - encoding "^0.1.13" - pyth-staking-wasm "0.3.2" - ts-node "^10.7.0" - typescript "^4.3.5" - -pyth-staking-wasm@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/pyth-staking-wasm/-/pyth-staking-wasm-0.3.2.tgz#56c67e63797bb9d7cd4a546bdc80d47174ee6940" - integrity sha512-hfUVBJDLZK+HWAH9m1DnPyWUc9d/Nce5Okc5h1OulsoDQ9taAJBgsQr8UACnNXupoTYBlykfwUFTJ6cnxd0FEw== - -qr-code-styling@^1.6.0-rc.1: +qr-code-styling@1.6.0-rc.1: version "1.6.0-rc.1" resolved "https://registry.yarnpkg.com/qr-code-styling/-/qr-code-styling-1.6.0-rc.1.tgz#6c89e185fa50cc9135101085c12ae95b06f1b290" integrity sha512-ModRIiW6oUnsP18QzrRYZSc/CFKFKIdj7pUs57AEVH20ajlglRpN3HukjHk0UbNMTlKGuaYl7Gt6/O5Gg2NU2Q== dependencies: qrcode-generator "^1.4.3" +qr.js@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f" + integrity sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ== + qrcode-generator@^1.4.3: version "1.4.4" resolved "https://registry.yarnpkg.com/qrcode-generator/-/qrcode-generator-1.4.4.tgz#63f771224854759329a99048806a53ed278740e7" integrity sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw== -qrcode-terminal@^0.12.0: - version "0.12.0" - resolved "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz" - integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== - -qs@6.9.3: - version "6.9.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e" - integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw== - -qs@6.9.6: - version "6.9.6" - resolved "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz" - integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== - -qs@^6.10.3: - version "6.10.5" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.5.tgz#974715920a80ff6a262264acd2c7e6c2a53282b4" - integrity sha512-O5RlPh0VFtR78y79rgcgKK4wbAI0C5zGVLztOIdpWX6ep368q5Hv6XRxDvXuZ9q3C6v+e3n8UfZZJw7IIG27eQ== +qrcode.react@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-1.0.1.tgz#2834bb50e5e275ffe5af6906eff15391fe9e38a5" + integrity sha512-8d3Tackk8IRLXTo67Y+c1rpaiXjoz/Dd2HpcMdW//62/x8J1Nbho14Kh8x974t9prsLHN6XqVgcnRiBGFptQmg== dependencies: - side-channel "^1.0.4" + loose-envify "^1.4.0" + prop-types "^15.6.0" + qr.js "0.0.0" -qs@^6.9.4: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== +qrcode@1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83" + integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q== dependencies: - side-channel "^1.0.4" + buffer "^5.4.3" + buffer-alloc "^1.2.0" + buffer-from "^1.1.1" + dijkstrajs "^1.0.1" + isarray "^2.0.1" + pngjs "^3.3.0" + yargs "^13.2.4" qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= +query-string@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" + integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== + dependencies: + decode-uri-component "^0.2.2" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + +querystring@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd" + integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== querystringify@^2.1.1: version "2.2.0" @@ -14933,65 +14746,76 @@ querystringify@^2.1.1: queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + quick-lru@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== +radix3@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/radix3/-/radix3-1.1.0.tgz#9745df67a49c522e94a33d0a93cf743f104b6e0d" + integrity sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A== + +ramda@0.28.0, ramda@^0.28.0: + version "0.28.0" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.28.0.tgz#acd785690100337e8b063cab3470019be427cc97" + integrity sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA== + ramda@^0.27.1: version "0.27.2" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.2.tgz#84463226f7f36dc33592f6f4ed6374c48306c3f1" integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA== -ramda@^0.28.0: - version "0.28.0" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.28.0.tgz#acd785690100337e8b063cab3470019be427cc97" - integrity sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA== +ramda@^0.29.0: + version "0.29.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.1.tgz#408a6165b9555b7ba2fc62555804b6c5a2eca196" + integrity sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA== -randombytes@^2.0.1, randombytes@^2.1.0: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.2: - version "2.4.2" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz" - integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: - bytes "3.1.1" - http-errors "1.8.1" - iconv-lite "0.4.24" - unpipe "1.0.0" + randombytes "^2.0.5" + safe-buffer "^5.1.0" rc-align@^4.0.0: - version "4.0.9" - resolved "https://registry.npmjs.org/rc-align/-/rc-align-4.0.9.tgz" + version "4.0.13" + resolved "https://registry.yarnpkg.com/rc-align/-/rc-align-4.0.13.tgz#5aa1b7b9d20e63f18eb12550cac2eb8d5ef3fe4b" + integrity sha512-l/UwiJllPFVLL/bfDpm0W2ySb1heXeSELnmiMRjXiNp0sboO0z7DnjItXQKS8fNRp6CApzRT1+P6pNWZztbbnA== dependencies: "@babel/runtime" "^7.10.1" classnames "2.x" dom-align "^1.7.0" + lodash "^4.17.21" rc-util "^5.3.0" resize-observer-polyfill "^1.5.1" rc-motion@^2.0.0: - version "2.4.3" - resolved "https://registry.npmjs.org/rc-motion/-/rc-motion-2.4.3.tgz" + version "2.6.2" + resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.6.2.tgz#3d31f97e41fb8e4f91a4a4189b6a98ac63342869" + integrity sha512-4w1FaX3dtV749P8GwfS4fYnFG4Rb9pxvCYPc/b2fw1cmlHJWNNgOFIz7ysiD+eOrzJSvnLJWlNQQncpNMXwwpg== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" - rc-util "^5.2.1" + rc-util "^5.21.0" -rc-slider@^9.7.5: +rc-slider@9.7.5: version "9.7.5" resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-9.7.5.tgz#193141c68e99b1dc3b746daeb6bf852946f5b7f4" integrity sha512-LV/MWcXFjco1epPbdw1JlLXlTgmWpB9/Y/P2yinf8Pg3wElHxA9uajN21lJiWtZjf5SCUekfSP6QMJfDo4t1hg== @@ -15003,60 +14827,69 @@ rc-slider@^9.7.5: shallowequal "^1.1.0" rc-tooltip@^5.0.1: - version "5.1.0" - resolved "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-5.1.0.tgz" + version "5.2.2" + resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-5.2.2.tgz#e5cafa8ecebf78108936a0bcb93c150fa81ac93b" + integrity sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg== dependencies: "@babel/runtime" "^7.11.2" + classnames "^2.3.1" rc-trigger "^5.0.0" rc-trigger@^5.0.0: - version "5.2.5" - resolved "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.2.5.tgz" + version "5.3.4" + resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-5.3.4.tgz#6b4b26e32825677c837d1eb4d7085035eecf9a61" + integrity sha512-mQv+vas0TwKcjAO2izNPkqR4j86OemLRmvL2nOzdP9OWNWA1ivoTt5hzFqYNW9zACwmTezRiN8bttrC7cZzYSw== dependencies: - "@babel/runtime" "^7.11.2" + "@babel/runtime" "^7.18.3" classnames "^2.2.6" rc-align "^4.0.0" rc-motion "^2.0.0" - rc-util "^5.5.0" + rc-util "^5.19.2" -rc-util@^5.16.1, rc-util@^5.2.1, rc-util@^5.3.0, rc-util@^5.5.0: - version "5.20.0" - resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.20.0.tgz#05915902313292cb3f0e8da9401a403be00c3f58" - integrity sha512-sHm129TjpUiJZuHCgX5moead5yag4ukIIZuwkK1SSlFMUceEx64sZNgJZJN7YQ9NJyDpabfJ8310fkcCXeyTog== +rc-util@^5.16.1, rc-util@^5.19.2, rc-util@^5.21.0, rc-util@^5.3.0: + version "5.25.3" + resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.25.3.tgz#7f6a5895e4edc5acdf5f73e90e1c031f3b67257d" + integrity sha512-+M+44T6UdM4iOd4QXRQKQjitOY26vC5pgFPNSo0XsY9OWzpHvy77BI55eL9Q9oDMUHzVuRNzzUkK1RI2W3n+ZQ== dependencies: - "@babel/runtime" "^7.12.5" + "@babel/runtime" "^7.18.3" react-is "^16.12.0" shallowequal "^1.1.0" -react-clientside-effect@^1.2.5: - version "1.2.5" - resolved "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.5.tgz" - integrity sha512-2bL8qFW1TGBHozGGbVeyvnggRpMjibeZM2536AKNENLECutp2yfs44IL8Hmpn8qjFQ2K7A9PnYf3vc7aQq/cPA== +react-async-hook@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/react-async-hook/-/react-async-hook-4.0.0.tgz#1f0467586654e1f33b7433bd98c300a0c5f9b3d0" + integrity sha512-97lgjFkOcHCTYSrsKBpsXg3iVWM0LnzedB749iP76sb3/8Ouu4nHIkCLEOrQWHVYqrYxjF05NN6GHoXWFkB3Kw== + +react-clientside-effect@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz#29f9b14e944a376b03fb650eed2a754dd128ea3a" + integrity sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg== dependencies: "@babel/runtime" "^7.12.13" -react-content-loader@^6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/react-content-loader/-/react-content-loader-6.1.0.tgz" - integrity sha512-S4/+doQrNs0PGDgUYCGGfdFjGax8dMQzYkWcSSxfaUcUjFkbnikWARuX9lWkglocIVhxnn3lxNb6uEWFFUzNUw== +react-content-loader@6.2.1, react-content-loader@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-6.2.1.tgz#8feb733c2d2495002e1b216f13707f2b5f2a8ead" + integrity sha512-6ONbFX+Hi3SHuP66JB8CPvJn372pj+qwltJV0J8z/8MFrq98I1cbFdZuhDWeQXu3CFxiiDTXJn7DFxx2ZvrO7g== react-device-detect@^2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/react-device-detect/-/react-device-detect-2.1.2.tgz" - integrity sha512-N42xttwez3ECgu4KpOL2ICesdfoz8NCBfmc1rH9FRYSjH7NmMyANPSrQ3EvAtJyj/6TzJNhrANSO38iXjCB2Ug== + version "2.2.2" + resolved "https://registry.yarnpkg.com/react-device-detect/-/react-device-detect-2.2.2.tgz#dbabbce798ec359c83f574c3edb24cf1cca641a5" + integrity sha512-zSN1gIAztUekp5qUT/ybHwQ9fmOqVT1psxpSlTn1pe0CO+fnJHKRLOWWac5nKxOxvOpD/w84hk1I+EydrJp7SA== dependencies: - ua-parser-js "^0.7.30" + ua-parser-js "^1.0.2" -react-dom@^17.0.0: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" - integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== +react-dom@16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f" + integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" - scheduler "^0.20.2" + prop-types "^15.6.2" + scheduler "^0.19.1" -react-dom@^18.0.0: +react-dom@18.0.0: version "18.0.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.0.0.tgz#26b88534f8f1dbb80853e1eabe752f24100d8023" integrity sha512-XqX7uzmFo0pUceWFCt7Gff6IyIMzFUn7QMZrbrQfGxtaxXZIcGQzoNpRLE3fQLnS4XzLLPMZX2T9TRcSrasicw== @@ -15064,7 +14897,7 @@ react-dom@^18.0.0: loose-envify "^1.1.0" scheduler "^0.21.0" -react-dropzone@^14.2.2: +react-dropzone@14.2.2: version "14.2.2" resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-14.2.2.tgz#a75a0676055fe9e2cb78578df4dedb4c42b54f98" integrity sha512-5oyGN/B5rNhop2ggUnxztXBQ6q6zii+OMEftPzsxAR2hhpVWz0nAV+3Ktxo2h5bZzdcCKrpd8bfWAVsveIBM+w== @@ -15073,7 +14906,7 @@ react-dropzone@^14.2.2: file-selector "^0.6.0" prop-types "^15.8.1" -react-easy-sort@^1.5.0: +react-easy-sort@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/react-easy-sort/-/react-easy-sort-1.5.0.tgz#66b6983d59ac6e8420683e1fff41d1914857dcc2" integrity sha512-dzVlEr4fa2Z4TzrCIOWsULZeI+7beyh7O2TQPP4m20sB0txniSSk3Ct18qbTtIKfAHJS5+2BTT8KpYcrFrW/Sg== @@ -15081,62 +14914,61 @@ react-easy-sort@^1.5.0: array-move "^3.0.1" tslib "2.0.1" -react-fast-compare@^3.0.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== - react-focus-lock@^2.5.2: - version "2.7.1" - resolved "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.7.1.tgz" - integrity sha512-ImSeVmcrLKNMqzUsIdqOkXwTVltj79OPu43oT8tVun7eIckA4VdM7UmYUFo3H/UC2nRVgagMZGFnAOQEDiDYcA== + version "2.9.2" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.9.2.tgz#a57dfd7c493e5a030d87f161c96ffd082bd920f2" + integrity sha512-5JfrsOKyA5Zn3h958mk7bAcfphr24jPoMoznJ8vaJF6fUrPQ8zrtEd3ILLOK8P5jvGxdMd96OxWNjDzATfR2qw== dependencies: "@babel/runtime" "^7.0.0" - focus-lock "^0.10.1" + focus-lock "^0.11.2" prop-types "^15.6.2" - react-clientside-effect "^1.2.5" - use-callback-ref "^1.2.5" - use-sidecar "^1.0.5" + react-clientside-effect "^1.2.6" + use-callback-ref "^1.3.0" + use-sidecar "^1.1.2" -react-headless-pagination@^0.1.0: +react-headless-pagination@0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/react-headless-pagination/-/react-headless-pagination-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/react-headless-pagination/-/react-headless-pagination-0.1.0.tgz#5a8a7ff68c79466b411dd877b5f16724c472e678" integrity sha512-B+t+9PafVL4M0SYoVwcPelmWvnGzvTijF1BI0iHcq44vXy1brwFi62d8a8GlipIxvvBIYoghmVqTLiFmlElG1A== -react-hook-form@^7.31.3: +react-hook-form@7.31.3: version "7.31.3" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.31.3.tgz#b61bafb9a7435f91695351a7a9f714d8c4df0121" integrity sha512-NVZdCWViIWXXXlQ3jxVQH0NuNfwPf8A/0KvuCxrM9qxtP1qYosfR2ZudarziFrVOC7eTUbWbm1T4OyYCwv9oSQ== -react-icons@^4.3.1: - version "4.3.1" - resolved "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz" - integrity sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ== +react-icons@4.11.0, react-icons@^4.3.1: + version "4.11.0" + resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.11.0.tgz#4b0e31c9bfc919608095cc429c4f1846f4d66c65" + integrity sha512-V+4khzYcE5EBk/BvcuYRq6V/osf11ODUM2J8hg2FDSswRrGvqiYUYPRy4OdrWaQOBj4NcpJfmHZLNaD+VH0TyA== -react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0: +react-intersection-observer@9.5.3: + version "9.5.3" + resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-9.5.3.tgz#f47a31ed3a0359cbbfdb91a53d7470ac2ab7b3c7" + integrity sha512-NJzagSdUPS5rPhaLsHXYeJbsvdpbJwL6yCHtMk91hc0ufQ2BnXis+0QQ9NBh6n9n+Q3OyjR6OQLShYbaNBkThQ== + +react-is@^16.10.2, react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" - resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== react-is@^17.0.0, react-is@^17.0.1: version "17.0.2" - resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -react-lifecycles-compat@^3.0.4: +react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== -react-linkify@^1.0.0-alpha: - version "1.0.0-alpha" - resolved "https://registry.yarnpkg.com/react-linkify/-/react-linkify-1.0.0-alpha.tgz#b391c7b88e3443752fafe76a95ca4434e82e70d5" - integrity sha512-7gcIUvJkAXXttt1fmBK9cwn+1jTa4hbKLGCZ9J1U6EOkyb2/+LKL1Z28d9rtDLMnpvImlNlLPdTPooorl5cpmg== - dependencies: - linkify-it "^2.0.3" - tlds "^1.199.0" - -react-markdown@^7.0.0: +react-markdown@7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/react-markdown/-/react-markdown-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-7.0.0.tgz#66565968e8513af070eeef65abc77e80fc1a9b87" integrity sha512-qdWfKxMgdKF3kHAV5pmcB12fAvytPoTpYwKTO6O/I3HujrK7sKIv6j4RnXVNLrNUh+TaBk+KtqpGzIKslX2rDg== dependencies: "@types/hast" "^2.0.0" @@ -15153,45 +14985,36 @@ react-markdown@^7.0.0: unist-util-visit "^4.0.0" vfile "^5.0.0" -react-media-hook@^0.4.9: - version "0.4.9" - resolved "https://registry.yarnpkg.com/react-media-hook/-/react-media-hook-0.4.9.tgz#7e57092f5800c53787dc9e912ad09e749dfb7bc7" - integrity sha512-FZr/2xA1+23vDJ1IZ794yLqMRRkBoCNOiJATdtTfB5GyVc5djf8FL2qEB/68pSkiNgHdHsmKknMSDr0sC4zBKQ== - -react-native-url-polyfill@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-1.3.0.tgz#c1763de0f2a8c22cc3e959b654c8790622b6ef6a" - integrity sha512-w9JfSkvpqqlix9UjDvJjm1EjSt652zVQ6iwCIj1cVVkwXf4jQhQgTNXY6EVTwuAmUjg6BC6k9RHCBynoLFo3IQ== - dependencies: - whatwg-url-without-unicode "8.0.0-3" - -react-popper@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba" - integrity sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q== +react-modal@^3.12.1: + version "3.16.1" + resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.16.1.tgz#34018528fc206561b1a5467fc3beeaddafb39b2b" + integrity sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg== dependencies: - react-fast-compare "^3.0.1" - warning "^4.0.2" + exenv "^1.2.0" + prop-types "^15.7.2" + react-lifecycles-compat "^3.0.0" + warning "^4.0.3" -react-portal@^4.2.2: +react-portal@4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-4.2.2.tgz#bff1e024147d6041ba8c530ffc99d4c8248f49fa" integrity sha512-vS18idTmevQxyQpnde0Td6ZcUlv+pD8GTyR42n3CHUQq9OHi1C4jDE4ZWEbEsrbrLRhSECYiao58cvocwMtP7Q== dependencies: prop-types "^15.5.8" -react-remove-scroll-bar@^2.1.0: - version "2.2.0" - resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.2.0.tgz" - integrity sha512-UU9ZBP1wdMR8qoUs7owiVcpaPwsQxUDC2lypP6mmixaGlARZa7ZIBx1jcuObLdhMOvCsnZcvetOho0wzPa9PYg== +react-qr-reader@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-qr-reader/-/react-qr-reader-2.2.1.tgz#dc89046d1c1a1da837a683dd970de5926817d55b" + integrity sha512-EL5JEj53u2yAOgtpAKAVBzD/SiKWn0Bl7AZy6ZrSf1lub7xHwtaXe6XSx36Wbhl1VMGmvmrwYMRwO1aSCT2fwA== dependencies: - react-style-singleton "^2.1.0" - tslib "^1.0.0" + jsqr "^1.2.0" + prop-types "^15.7.2" + webrtc-adapter "^7.2.1" react-remove-scroll-bar@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.3.tgz#e291f71b1bb30f5f67f023765b7435f4b2b2cd94" - integrity sha512-i9GMNWwpz8XpUpQ6QlevUtFjHGqnPG4Hxs+wlIJntu/xcsZVEpJcIV71K3ZkqNy2q3GfgvkD7y6t/Sv8ofYSbw== + version "2.3.4" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz#53e272d7a5cb8242990c7f144c44d8bd8ab5afd9" + integrity sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A== dependencies: react-style-singleton "^2.2.1" tslib "^2.0.0" @@ -15207,18 +15030,25 @@ react-remove-scroll@2.5.4: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-remove-scroll@^2.4.3: - version "2.4.3" - resolved "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.4.3.tgz" - integrity sha512-lGWYXfV6jykJwbFpsuPdexKKzp96f3RbvGapDSIdcyGvHb7/eqyn46C7/6h+rUzYar1j5mdU+XECITHXCKBk9Q== +react-remove-scroll@2.5.5, react-remove-scroll@^2.4.3: + version "2.5.5" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" + integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== + dependencies: + react-remove-scroll-bar "^2.3.3" + react-style-singleton "^2.2.1" + tslib "^2.1.0" + use-callback-ref "^1.3.0" + use-sidecar "^1.1.2" + +react-resize-detector@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-7.1.2.tgz#8ef975dd8c3d56f9a5160ac382ef7136dcd2d86c" + integrity sha512-zXnPJ2m8+6oq9Nn8zsep/orts9vQv3elrpA+R8XTcW7DVVUJ9vwDwMXaBtykAYjMnkCIaOoK9vObyR7ZgFNlOw== dependencies: - react-remove-scroll-bar "^2.1.0" - react-style-singleton "^2.1.0" - tslib "^1.0.0" - use-callback-ref "^1.2.3" - use-sidecar "^1.0.1" + lodash "^4.17.21" -react-responsive@^9.0.0-beta.10: +react-responsive@9.0.0-beta.10: version "9.0.0-beta.10" resolved "https://registry.yarnpkg.com/react-responsive/-/react-responsive-9.0.0-beta.10.tgz#892db936da48eb30babf5cb7e31737c7b5677209" integrity sha512-41H8g4FYP46ln16rsHvs9/0ZoZxAPfnNiHET86/5pgS+Vw8fSKfLBuOS2SAquaxOxq7DgPviFoHmybgVvSKCNQ== @@ -15228,14 +15058,20 @@ react-responsive@^9.0.0-beta.10: prop-types "^15.6.1" shallow-equal "^1.2.1" -react-style-singleton@^2.1.0: - version "2.1.1" - resolved "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.1.1.tgz" - integrity sha512-jNRp07Jza6CBqdRKNgGhT3u9umWvils1xsuMOjZlghBDH2MU0PL2WZor4PGYjXpnRCa9DQSlHMs/xnABWOwYbA== +react-slider@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-slider/-/react-slider-2.0.4.tgz#21c656ffabc3bb4481cf6b49e6d647baeda83572" + integrity sha512-sWwQD01n6v+MbeLCYthJGZPc0kzOyhQHyd0bSo0edg+IAxTVQmj3Oy4SBK65eX6gNwS9meUn6Z5sIBUVmwAd9g== dependencies: - get-nonce "^1.0.0" - invariant "^2.2.4" - tslib "^1.0.0" + prop-types "^15.8.1" + +react-smooth@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-2.0.2.tgz#0ef24213628cb13bf4305194a050e1db4302a3a1" + integrity sha512-pgqSp1q8rAGtF1bXQE0m3CHGLNfZZh5oA5o1tsPLXRHnKtkujMIJ8Ws5nO1mTySZf1c4vgwlEk+pHi3Ln6eYLw== + dependencies: + fast-equals "^4.0.3" + react-transition-group "2.9.0" react-style-singleton@^2.2.1: version "2.2.1" @@ -15246,87 +15082,67 @@ react-style-singleton@^2.2.1: invariant "^2.2.4" tslib "^2.0.0" -react-transition-group@^4.4.2: - version "4.4.5" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" - integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== +react-tiny-linkify@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/react-tiny-linkify/-/react-tiny-linkify-1.2.0.tgz#9182750e51f2c7d10103d1d8d0b7b2926671e77f" + integrity sha512-+h9harQ/FKMpb24CLfEE29ITaCvhuaM0pueS47rIRxOw35f3z+35rgsu47ZrUBawcsNnbWax5jZxbouiKUwJGQ== + +react-transition-group@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" + integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg== dependencies: - "@babel/runtime" "^7.5.5" - dom-helpers "^5.0.1" + dom-helpers "^3.4.0" loose-envify "^1.4.0" prop-types "^15.6.2" + react-lifecycles-compat "^3.0.4" react-use-gesture@^9.1.3: version "9.1.3" - resolved "https://registry.npmjs.org/react-use-gesture/-/react-use-gesture-9.1.3.tgz" + resolved "https://registry.yarnpkg.com/react-use-gesture/-/react-use-gesture-9.1.3.tgz#92bd143e4f58e69bd424514a5bfccba2a1d62ec0" integrity sha512-CdqA2SmS/fj3kkS2W8ZU8wjTbVBAIwDWaRprX7OKaj7HlGwBasGEFggmk5qNklknqk9zK/h8D355bEJFTpqEMg== -react-virtualized-auto-sizer@^1.0.6: +react-virtualized-auto-sizer@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz#66c5b1c9278064c5ef1699ed40a29c11518f97ca" integrity sha512-7tQ0BmZqfVF6YYEWcIGuoR3OdYe8I/ZFbNclFlGOC3pMqunkYF/oL30NCjSGl9sMEb17AnzixDz98Kqc3N76HQ== -react-window@^1.8.7: - version "1.8.7" - resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.7.tgz#5e9fd0d23f48f432d7022cdb327219353a15f0d4" - integrity sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA== +react-window@1.8.10: + version "1.8.10" + resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.10.tgz#9e6b08548316814b443f7002b1cf8fd3a1bdde03" + integrity sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg== dependencies: "@babel/runtime" "^7.0.0" memoize-one ">=3.1.1 <6" -react@^17.0.0: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" - integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -react@^18.1.0: - version "18.1.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890" - integrity sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ== +react@16.13.1, react@18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== dependencies: loose-envify "^1.1.0" -read-cache@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" - integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== - dependencies: - pify "^2.3.0" - -read-cmd-shim@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-2.0.0.tgz" - integrity sha512-HJpV9bQpkl6KwjxlJcBoqu9Ba0PQg8TqSNIOrulGt54a0uup0HtevreFHzYzkm0lpnleRdNBzXznKrgxglEHQw== +read-cmd-shim@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz#640a08b473a49043e394ae0c7a34dd822c73b9bb" + integrity sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q== -read-package-json-fast@^2.0.1, read-package-json-fast@^2.0.2, read-package-json-fast@^2.0.3: +read-package-json-fast@^2.0.1: version "2.0.3" - resolved "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz#323ca529630da82cb34b36cc0b996693c98c2b83" integrity sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ== dependencies: json-parse-even-better-errors "^2.3.0" npm-normalize-package-bin "^1.0.1" -read-package-json@^4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/read-package-json/-/read-package-json-4.1.1.tgz" - integrity sha512-P82sbZJ3ldDrWCOSKxJT0r/CXMWR0OR3KRh55SgKo3p91GSIEEC32v3lSHAvO/UcH3/IoL7uqhOFBduAnwdldw== - dependencies: - glob "^7.1.1" - json-parse-even-better-errors "^2.3.0" - normalize-package-data "^3.0.0" - npm-normalize-package-bin "^1.0.0" - -read@1, read@^1.0.7, read@~1.0.1, read@~1.0.7: +read@^1.0.4: version "1.0.7" - resolved "https://registry.npmjs.org/read/-/read-1.0.7.tgz" - integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + integrity sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ== dependencies: mute-stream "~0.0.4" -readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@~2.3.6: +readable-stream@^2.0.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -15339,97 +15155,118 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdir-scoped-modules@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz" - integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== - dependencies: - debuglog "^1.0.1" - dezalgo "^1.0.0" - graceful-fs "^4.1.2" - once "^1.3.0" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" -readline-sync@^1.4.10: - version "1.4.10" - resolved "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz" - integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw== +real-require@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" + integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg== -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= +recharts-scale@^0.4.4: + version "0.4.5" + resolved "https://registry.yarnpkg.com/recharts-scale/-/recharts-scale-0.4.5.tgz#0969271f14e732e642fcc5bd4ab270d6e87dd1d9" + integrity sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w== dependencies: - resolve "^1.1.6" + decimal.js-light "^2.4.1" + +recharts@^2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.4.3.tgz#23b7cd988423449b04a826baa057675b833789b1" + integrity sha512-/hkRHTQShEOKDYd2OlKLIvGA0X9v/XVO/mNeRoDHg0lgFRL2KbGzeqVnStI3mMfORUZ6Hak4JbQ+uDiin1Foqg== + dependencies: + classnames "^2.2.5" + eventemitter3 "^4.0.1" + lodash "^4.17.19" + react-is "^16.10.2" + react-resize-detector "^7.1.2" + react-smooth "^2.0.1" + recharts-scale "^0.4.4" + reduce-css-calc "^2.1.8" + victory-vendor "^36.6.8" + +reconnecting-websocket@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783" + integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng== redent@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== dependencies: indent-string "^4.0.0" strip-indent "^3.0.0" +redis-errors@^1.0.0, redis-errors@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" + integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== + +redis-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" + integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== + dependencies: + redis-errors "^1.0.0" + reduce-css-calc@^2.1.8: version "2.1.8" - resolved "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz#7ef8761a28d614980dc0c982f772c93f7a99de03" integrity sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg== dependencies: css-unit-converter "^1.1.1" postcss-value-parser "^3.3.0" -regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: - version "1.3.1" - resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz" +reflect.getprototypeof@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" + integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.1" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + globalthis "^1.0.3" + which-builtin-type "^1.1.3" + +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + +regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" + integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + call-bind "^1.0.6" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.1" -remark-gfm@^3.0.1: +remark-gfm@3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-3.0.1.tgz#0b180f095e3036545e9dddac0e8df3fa5cfee54f" integrity sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig== dependencies: "@types/mdast" "^3.0.0" @@ -15438,42 +15275,27 @@ remark-gfm@^3.0.1: unified "^10.0.0" remark-parse@^10.0.0: - version "10.0.0" - resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.0.tgz" - integrity sha512-07ei47p2Xl7Bqbn9H2VYQYirnAFJPwdMuypdozWsSbnmrkgA2e2sZLZdnDNrrsxR4onmIzH/J6KXqKxCuqHtPQ== + version "10.0.1" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.1.tgz#6f60ae53edbf0cf38ea223fe643db64d112e0775" + integrity sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw== dependencies: "@types/mdast" "^3.0.0" mdast-util-from-markdown "^1.0.0" unified "^10.0.0" remark-rehype@^9.0.0: - version "9.0.0" - resolved "https://registry.npmjs.org/remark-rehype/-/remark-rehype-9.0.0.tgz" - integrity sha512-SFA+mPWu45ynFPKeT3h5eNNVAYoMp3wizr3KSKh1IQ9L6dLSyD25/df6/vv8EW8ji3O3dnZGdbLQl592Tn+ydg== + version "9.1.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-9.1.0.tgz#e4b5b6e19c125b3780343eb66c3e9b99b0f06a81" + integrity sha512-oLa6YmgAYg19zb0ZrBACh40hpBLteYROaPLhBXzLgjqyHQrN+gVP9N/FJvfzuNNuzCutktkroXEZBrxAxKhh7Q== dependencies: "@types/hast" "^2.0.0" "@types/mdast" "^3.0.0" mdast-util-to-hast "^11.0.0" unified "^10.0.0" -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - request@^2.88.2: version "2.88.2" - resolved "https://registry.npmjs.org/request/-/request-2.88.2.tgz" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== dependencies: aws-sign2 "~0.7.0" @@ -15499,49 +15321,36 @@ request@^2.88.2: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== require-main-filename@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== resize-observer-polyfill@^1.5.1: version "1.5.1" - resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz" - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== resolve-cwd@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== dependencies: resolve-from "^5.0.0" -resolve-dir@^1.0.0, resolve-dir@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz" - integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -15549,86 +15358,72 @@ resolve-from@^4.0.0: resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve.exports@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== -resolve@^1.1.6, resolve@^1.12.0, resolve@^1.20.0, resolve@^1.22.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== +resolve@1.22.8, resolve@^1.12.0, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.4: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: - is-core-module "^2.8.1" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.1.7, resolve@^1.22.1: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== +resolve@^2.0.0-next.5: + version "2.0.0-next.5" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^2.0.0-next.3: - version "2.0.0-next.3" - resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" + onetime "^2.0.0" + signal-exit "^3.0.2" restore-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== dependencies: onetime "^5.1.0" signal-exit "^3.0.2" -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - retry@0.13.1, retry@^0.13.1: version "0.13.1" - resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== retry@^0.12.0: version "0.12.0" - resolved "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz" - integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== reusify@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rgb-regex@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + integrity sha512-gDK5mkALDFER2YLqH6imYvK6g02gpNGM4ILDZ472EwWfXZnC2ZEpoB2ECXTyOVUKuk/bPJZMzwQPBYICzP+D3w== rgba-regex@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= - -rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + integrity sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg== rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" @@ -15639,7 +15434,7 @@ rimraf@^3.0.0, rimraf@^3.0.2: ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" @@ -15657,38 +15452,42 @@ robust-predicates@^3.0.0: resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a" integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g== -rpc-websockets@^7.4.12: - version "7.4.17" - resolved "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.4.17.tgz" - integrity sha512-eolVi/qlXS13viIUH9aqrde902wzSLAai0IjmOZSRefp5I3CSG/vCnD0c0fDSYCWuEyUoRL1BHQA8K1baEUyow== - dependencies: - "@babel/runtime" "^7.11.2" - circular-json "^0.5.9" - eventemitter3 "^4.0.7" - uuid "^8.3.0" - ws "^7.4.5" +rollup@2.78.0: + version "2.78.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.78.0.tgz#00995deae70c0f712ea79ad904d5f6b033209d9e" + integrity sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg== optionalDependencies: - bufferutil "^4.0.1" - utf-8-validate "^5.0.2" + fsevents "~2.3.2" -rpc-websockets@^7.4.2: - version "7.4.16" - resolved "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.4.16.tgz" - integrity sha512-0b7OVhutzwRIaYAtJo5tqtaQTWKfwAsKnaThOSOy+VkhVdleNUgb8eZnWSdWITRZZEigV5uPEIDr5KZe4DBrdQ== +rollup@^4.19.0: + version "4.19.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.19.1.tgz#21d865cd60d4a325172ce8b082e60caccd97b309" + integrity sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw== dependencies: - "@babel/runtime" "^7.11.2" - circular-json "^0.5.9" - eventemitter3 "^4.0.7" - uuid "^8.3.0" - ws "^7.4.5" + "@types/estree" "1.0.5" optionalDependencies: - bufferutil "^4.0.1" - utf-8-validate "^5.0.2" + "@rollup/rollup-android-arm-eabi" "4.19.1" + "@rollup/rollup-android-arm64" "4.19.1" + "@rollup/rollup-darwin-arm64" "4.19.1" + "@rollup/rollup-darwin-x64" "4.19.1" + "@rollup/rollup-linux-arm-gnueabihf" "4.19.1" + "@rollup/rollup-linux-arm-musleabihf" "4.19.1" + "@rollup/rollup-linux-arm64-gnu" "4.19.1" + "@rollup/rollup-linux-arm64-musl" "4.19.1" + "@rollup/rollup-linux-powerpc64le-gnu" "4.19.1" + "@rollup/rollup-linux-riscv64-gnu" "4.19.1" + "@rollup/rollup-linux-s390x-gnu" "4.19.1" + "@rollup/rollup-linux-x64-gnu" "4.19.1" + "@rollup/rollup-linux-x64-musl" "4.19.1" + "@rollup/rollup-win32-arm64-msvc" "4.19.1" + "@rollup/rollup-win32-ia32-msvc" "4.19.1" + "@rollup/rollup-win32-x64-msvc" "4.19.1" + fsevents "~2.3.2" -rpc-websockets@^7.5.0: - version "7.5.0" - resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.5.0.tgz#bbeb87572e66703ff151e50af1658f98098e2748" - integrity sha512-9tIRi1uZGy7YmDjErf1Ax3wtqdSSLIlnmL5OtOzgd5eqPKbsPpwDP5whUDO2LQay3Xp0CcHlcNSGzacNRluBaQ== +rpc-websockets@^7.5.1: + version "7.6.0" + resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.6.0.tgz#d3f4c0dac108ca35566b0e31552c32e58928cd04" + integrity sha512-Jgcs8q6t8Go98dEulww1x7RysgTkzpCMelVxZW4hvuyFtOGpeUz9prpr2KjUa/usqxgFCd9Tu3+yhHEP9GVmiQ== dependencies: "@babel/runtime" "^7.17.2" eventemitter3 "^4.0.7" @@ -15698,6 +15497,13 @@ rpc-websockets@^7.5.0: bufferutil "^4.0.1" utf-8-validate "^5.0.2" +rtcpeerconnection-shim@^1.2.15: + version "1.2.15" + resolved "https://registry.yarnpkg.com/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz#e7cc189a81b435324c4949aa3dfb51888684b243" + integrity sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw== + dependencies: + sdp "^2.6.0" + run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -15705,7 +15511,7 @@ run-async@^2.4.0: run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" @@ -15715,64 +15521,90 @@ rw@1: resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== -rxjs@6, rxjs@^6.6.7: +rxjs@6, rxjs@^6.3.3, rxjs@^6.6.3: version "6.6.7" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== dependencies: tslib "^1.9.0" -rxjs@^7.1.0: - version "7.5.5" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f" - integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw== - dependencies: - tslib "^2.1.0" - rxjs@^7.5.5: - version "7.5.6" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.6.tgz#0446577557862afd6903517ce7cae79ecb9662bc" - integrity sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw== + version "7.8.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4" + integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg== dependencies: tslib "^2.1.0" sade@^1.7.3: version "1.8.1" - resolved "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== dependencies: mri "^1.1.0" -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-array-concat@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" + integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + has-symbols "^1.0.3" + isarray "^2.0.5" -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-json-utils@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/safe-json-utils/-/safe-json-utils-1.1.1.tgz#0e883874467d95ab914c3f511096b89bfb3e63b1" + integrity sha512-SAJWGKDs50tAbiDXLf89PDwt9XYkWyANFWVzn4dTXl5QyI8t2o/bW5/OJl3lvc2WVU4MEpTo9Yz5NVFNsp+OJQ== + +safe-regex-test@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" + integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== dependencies: - ret "~0.1.10" + call-bind "^1.0.6" + es-errors "^1.3.0" + is-regex "^1.1.4" + +safe-stable-stringify@^2.1.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -saxes@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz" +salmon-adapter-sdk@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/salmon-adapter-sdk/-/salmon-adapter-sdk-1.1.1.tgz#d5fdd2d27b1a6c58e38c188c977eeeeface8b20c" + integrity sha512-28ysSzmDjx2AbotxSggqdclh9MCwlPJUldKkCph48oS5Xtwu0QOg8T9ZRHS2Mben4Y8sTq6VvxXznKssCYFBJA== + dependencies: + "@project-serum/sol-wallet-adapter" "^0.2.6" + eventemitter3 "^4.0.7" + +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== dependencies: xmlchars "^2.2.0" -scheduler@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" - integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== +scheduler@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" + integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -15784,20 +15616,16 @@ scheduler@^0.21.0: dependencies: loose-envify "^1.1.0" -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - scrypt-js@3.0.1, scrypt-js@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== +sdp@^2.12.0, sdp@^2.6.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/sdp/-/sdp-2.12.0.tgz#338a106af7560c86e4523f858349680350d53b22" + integrity sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw== + secp256k1@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.0.tgz#28f59f4b01dbee9575f56a47034b7d2e3b3b352d" @@ -15814,64 +15642,27 @@ secp256k1@^3.8.0: secp256k1@^4.0.1, secp256k1@^4.0.2: version "4.0.3" - resolved "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== dependencies: elliptic "^6.5.4" node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= - -selfsigned@^1.10.8: - version "1.10.11" - resolved "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz" - integrity sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA== - dependencies: - node-forge "^0.10.0" - semver-compare@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz" - -semver@^5.5.0: - version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== -semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: - version "7.3.7" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" - integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== - dependencies: - lru-cache "^6.0.0" +semver@7.x, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.6.0: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== -send@0.17.2: - version "0.17.2" - resolved "https://registry.npmjs.org/send/-/send-0.17.2.tgz" - integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "1.8.1" - mime "1.6.0" - ms "2.1.3" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" +semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== serialize-javascript@6.0.0: version "6.0.0" @@ -15880,86 +15671,51 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.14.2: - version "1.14.2" - resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz" - integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.2" - set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== -set-interval-async@1.0.34: - version "1.0.34" - resolved "https://registry.npmjs.org/set-interval-async/-/set-interval-async-1.0.34.tgz" - integrity sha512-wwDVmeXwOaumkZ7FizY0ux8N0fk4KM1Bq7DfBGHxjD/NSSjcvSlj4D6HHIxzu415QngUr0YW97TXl/s1Ou/BHQ== +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== dependencies: - "@babel/runtime" "7.5.0" + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== +set-function-name@^2.0.1, set-function-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== setprototypeof@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sha.js@^2.4.0, sha.js@^2.4.8: +sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: version "2.4.11" - resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" -sha256-uint8array@^0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/sha256-uint8array/-/sha256-uint8array-0.10.3.tgz#322a91413f78f518e0b9c8f8e982cc2e629b59c7" - integrity sha512-SFTs87RfXVulKrhhP6B5/qcFruOKQZaKf6jY9V4PJ7NOG0qIlQP6XL4pQq5xagsuP/Wd55S7tUBJpRajEsDUEQ== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - shallow-equal@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da" @@ -15967,80 +15723,51 @@ shallow-equal@^1.2.1: shallowequal@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" - -shelljs@^0.8.4: - version "0.8.5" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" - integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -shiki@^0.9.3: - version "0.9.15" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.9.15.tgz#2481b46155364f236651319d2c18e329ead6fa44" - integrity sha512-/Y0z9IzhJ8nD9nbceORCqu6NgT9X6I8Fk8c3SICHI5NbZRLdZYFaB233gwct9sU0vvSypyaL/qaKvzyQGJBZSw== - dependencies: - jsonc-parser "^3.0.0" - vscode-oniguruma "^1.6.1" - vscode-textmate "5.2.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" +side-channel@^1.0.4, side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" -signal-exit@^3.0.0, signal-exit@^3.0.3: - version "3.0.6" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^3.0.2: - version "3.0.3" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz" +signal-exit@^4.0.1, signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== simple-swizzle@^0.2.2: version "0.2.2" - resolved "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== dependencies: is-arrayish "^0.3.1" -sinon-chai@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-3.7.0.tgz#cfb7dec1c50990ed18c153f1840721cf13139783" - integrity sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g== - sirv@^1.0.7: version "1.0.19" - resolved "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== dependencies: "@polka/url" "^1.0.0-next.20" @@ -16049,253 +15776,117 @@ sirv@^1.0.7: sisteransi@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== slash@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz" - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -slide@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw== - -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + integrity sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw== snake-case@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== dependencies: dot-case "^3.0.4" tslib "^2.0.3" -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -socket.io-client@^4.5.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.5.1.tgz#cab8da71976a300d3090414e28c2203a47884d84" - integrity sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA== +socket.io-client@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.5.4.tgz#d3cde8a06a6250041ba7390f08d2468ccebc5ac9" + integrity sha512-ZpKteoA06RzkD32IbqILZ+Cnst4xewU7ZYK12aS1mzHftFFjpoMz69IuhP/nL25pJfao/amoPI527KnuhFm01g== dependencies: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.2" - engine.io-client "~6.2.1" - socket.io-parser "~4.2.0" + engine.io-client "~6.2.3" + socket.io-parser "~4.2.1" -socket.io-parser@~4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.0.tgz#3f01e5bc525d94aa52a97ed5cbc12e229bbc4d6b" - integrity sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng== +socket.io-parser@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.1.tgz#01c96efa11ded938dcb21cbe590c26af5eff65e5" + integrity sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g== dependencies: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" -sockjs-client@^1.5.0: - version "1.5.2" - resolved "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.2.tgz" - integrity sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ== - dependencies: - debug "^3.2.6" - eventsource "^1.0.7" - faye-websocket "^0.11.3" - inherits "^2.0.4" - json3 "^3.3.3" - url-parse "^1.5.3" - -sockjs@^0.3.21: - version "0.3.24" - resolved "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz" - integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== - dependencies: - faye-websocket "^0.11.3" - uuid "^8.3.2" - websocket-driver "^0.7.4" - -socks-proxy-agent@^6.0.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.0.tgz#f6b5229cc0cbd6f2f202d9695f09d871e951c85e" - integrity sha512-wWqJhjb32Q6GsrUqzuFkukxb/zzide5quXYcMVpIjxalDBBYy2nqKCFQ/9+Ie4dvOYSQdOk3hUlZSdzZOd3zMQ== - dependencies: - agent-base "^6.0.2" - debug "^4.3.3" - socks "^2.6.2" - -socks@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a" - integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== +sonic-boom@^2.2.1: + version "2.8.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611" + integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg== dependencies: - ip "^1.1.5" - smart-buffer "^4.2.0" + atomic-sleep "^1.0.0" -source-map-js@^1.0.1, source-map-js@^1.0.2: +source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - source-map-resolve@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== dependencies: atob "^2.1.2" decode-uri-component "^0.2.0" +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@^0.5.6: - version "0.5.19" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz" + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== +source-map@0.8.0-beta.0: + version "0.8.0-beta.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" + integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== + dependencies: + whatwg-url "^7.0.0" -source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: +source-map@^0.5.7: version "0.5.7" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.3: - version "0.7.3" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz" - space-separated-tokens@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz" - integrity sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw== - -spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.11" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" - integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" + version "2.0.2" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" + integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= - dependencies: - through "2" +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== sshpk@^1.7.0: version "1.17.0" @@ -16312,52 +15903,34 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -ssri@^8.0.0, ssri@^8.0.1: - version "8.0.1" - resolved "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz" - integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== - dependencies: - minipass "^3.1.1" - stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== dependencies: escape-string-regexp "^2.0.0" -start-server-and-test@^1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.14.0.tgz#c57f04f73eac15dd51733b551d775b40837fdde3" - integrity sha512-on5ELuxO2K0t8EmNj9MtVlFqwBMxfWOhu4U7uZD1xccVpFlOQKR93CSe0u98iQzfNxRyaNTb/CdadbNllplTsw== - dependencies: - bluebird "3.7.2" - check-more-types "2.24.0" - debug "4.3.2" - execa "5.1.1" - lazy-ass "1.6.0" - ps-tree "1.2.0" - wait-on "6.0.0" - -static-eval@2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.2.tgz#2d1759306b1befa688938454c546b7871f806a42" - integrity sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg== +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== dependencies: - escodegen "^1.8.1" + type-fest "^0.7.1" -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" +standard-as-callback@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" + integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: +"statuses@>= 1.5.0 < 2": version "1.5.0" - resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +std-env@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" + integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== stream-browserify@^3.0.0: version "3.0.0" @@ -16367,61 +15940,60 @@ stream-browserify@^3.0.0: inherits "~2.0.4" readable-stream "^3.5.0" -stream-chunker@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/stream-chunker/-/stream-chunker-1.2.8.tgz#eb3af2c8aee5256cde76f0a1fea86348336d04f7" - integrity sha512-1j0PRZxgxJ8pPRyLlFu6Eer2imfhx1f++644xu/ZGRReDanv4frTSTWwNidtZOHJKwi86ue2KOWHFyikkQWN8w== - dependencies: - through2 "~2.0.0" - -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= - dependencies: - duplexer "~0.1.1" +stream-shift@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== -stream-transform@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/stream-transform/-/stream-transform-3.2.0.tgz#5b94300c09f4db30d682f5b3bad97c3c8aac81d1" - integrity sha512-M22v88wNknyJiIyHYoiIYI5RPl/R7tkf92j1YNkmrbe5XRGHW0jW8n458j1njOrR4Edcj8bwbpSV0iLIWon1hg== +stream-transform@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/stream-transform/-/stream-transform-3.2.1.tgz#4c8cbdd3e4fa7254c770ef34a962cec68349fcb0" + integrity sha512-ApK+WTJ5bCOf0A2tlec1qhvr8bGEBM/sgXXB7mysdCYgZJO5DZeaV3h3G+g0HnAQ372P5IhiGqnW29zoLOfTzQ== + +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== string-argv@0.3.1: version "0.3.1" - resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" + integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== string-length@^4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== dependencies: char-regex "^1.0.2" strip-ansi "^6.0.0" string-similarity@^4.0.3: version "4.0.4" - resolved "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz" - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" + resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" + integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^2.0.0: +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" @@ -16429,117 +16001,161 @@ string-width@^2.0.0: string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: emoji-regex "^7.0.1" is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string.prototype.matchall@^4.0.6: - version "4.0.6" - resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz" - integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg== +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string.prototype.matchall@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" + integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.7" + regexp.prototype.flags "^1.5.2" + set-function-name "^2.0.2" + side-channel "^1.0.6" + +string.prototype.repeat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" + integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== dependencies: - call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.19.1" - get-intrinsic "^1.1.1" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - regexp.prototype.flags "^1.3.1" - side-channel "^1.0.4" + es-abstract "^1.17.5" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== +string.prototype.trim@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" + integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-object-atoms "^1.0.0" -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== +string.prototype.trimend@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" + integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" stringify-object@^3.3.0: version "3.3.0" - resolved "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== dependencies: get-own-enumerable-property-symbols "^3.0.0" is-obj "^1.0.1" is-regexp "^1.0.0" -stringify-package@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz" - integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg== +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== dependencies: ansi-regex "^3.0.0" strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== dependencies: - ansi-regex "^5.0.1" + ansi-regex "^6.0.1" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-bom@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== + dependencies: + is-hex-prefixed "1.0.0" + strip-indent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" @@ -16547,7 +16163,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -16560,9 +16176,9 @@ style-to-object@^0.3.0: inline-style-parser "0.1.1" styled-components@^5.3.1: - version "5.3.5" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.5.tgz#a750a398d01f1ca73af16a241dec3da6deae5ec4" - integrity sha512-ndETJ9RKaaL6q41B69WudeqLzOpY1A/ET/glXkNZ2T7dPjPqpPCXXQjDFYZWwNnE5co0wX+gTCqx9mfxTmSIPg== + version "5.3.11" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.11.tgz#9fda7bf1108e39bf3f3e612fcc18170dedcd57a8" + integrity sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/traverse" "^7.4.5" @@ -16575,72 +16191,51 @@ styled-components@^5.3.1: shallowequal "^1.1.0" supports-color "^5.5.0" -styled-jsx@5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.2.tgz#ff230fd593b737e9e68b630a694d460425478729" - integrity sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ== - -stylis@4.0.13: - version "4.0.13" - resolved "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz" - integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== +styled-jsx@5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.7.tgz#be44afc53771b983769ac654d355ca8d019dff48" + integrity sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA== -superagent@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-6.1.0.tgz#09f08807bc41108ef164cfb4be293cebd480f4a6" - integrity sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg== - dependencies: - component-emitter "^1.3.0" - cookiejar "^2.1.2" - debug "^4.1.1" - fast-safe-stringify "^2.0.7" - form-data "^3.0.0" - formidable "^1.2.2" - methods "^1.1.2" - mime "^2.4.6" - qs "^6.9.4" - readable-stream "^3.6.0" - semver "^7.3.2" +stylis@4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.3.tgz#fd2fbe79f5fed17c55269e16ed8da14c84d069f7" + integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA== -superagent@^7.1.3: - version "7.1.6" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-7.1.6.tgz#64f303ed4e4aba1e9da319f134107a54cacdc9c6" - integrity sha512-gZkVCQR1gy/oUXr+kxJMLDjla434KmSOKbx5iGD30Ql+AkJQ/YlPKECJy2nhqOsHLjGHzoDTXNSjhnvWhzKk7g== +sucrase@^3.35.0: + version "3.35.0" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" + integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== dependencies: - component-emitter "^1.3.0" - cookiejar "^2.1.3" - debug "^4.3.4" - fast-safe-stringify "^2.1.1" - form-data "^4.0.0" - formidable "^2.0.1" - methods "^1.1.2" - mime "2.6.0" - qs "^6.10.3" - readable-stream "^3.6.0" - semver "^7.3.7" + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "^10.3.10" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" superstruct@0.8.3: version "0.8.3" - resolved "https://registry.npmjs.org/superstruct/-/superstruct-0.8.3.tgz" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.8.3.tgz#fb4d8901aca3bf9f79afab1bbab7a7f335cc4ef2" integrity sha512-LbtbFpktW1FcwxVIJlxdk7bCyBq/GzOx2FSFLRLTUhWIA1gHkYPIl3aXRG5mBdGZtnPNT6t+4eEcLDCMOuBHww== dependencies: kind-of "^6.0.2" tiny-invariant "^1.0.6" +superstruct@1.0.4, superstruct@^1.0.3, superstruct@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" + integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== + superstruct@^0.14.2: version "0.14.2" - resolved "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.14.2.tgz#0dbcdf3d83676588828f1cf5ed35cda02f59025b" integrity sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ== -superstruct@^0.15.2: - version "0.15.3" - resolved "https://registry.npmjs.org/superstruct/-/superstruct-0.15.3.tgz" - integrity sha512-wilec1Rg3FtKuRjRyCt70g5W29YUEuaLnybdVQUI+VQ7m0bw8k7TzrRv5iYmo6IpjLVrwxP5t3RgjAVqhYh4Fg== - -superstruct@^0.15.4: - version "0.15.4" - resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.15.4.tgz#e3381dd84ca07e704e19f69eda74eee1a5efb1f9" - integrity sha512-eOoMeSbP9ZJChNOm/9RYjE+F36rYR966AAqeG3xhQB02j2sfAUXDp4EQ/7bAOqnlJnuFDB8yvOu50SocvKpUEw== +superstruct@^0.15.2, superstruct@^0.15.4: + version "0.15.5" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.15.5.tgz#0f0a8d3ce31313f0d84c6096cd4fa1bfdedc9dab" + integrity sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ== supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" @@ -16649,50 +16244,99 @@ supports-color@8.1.1, supports-color@^8.0.0: dependencies: has-flag "^4.0.0" +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.0.0, supports-color@^7.1.0: +supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" -supports-hyperlinks@^2.0.0: - version "2.2.0" - resolved "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz" - dependencies: - has-flag "^4.0.0" - supports-color "^7.0.0" - supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -swr@^1.3.0: +swr@1.3.0, swr@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/swr/-/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8" integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw== +swr@^2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/swr/-/swr-2.2.5.tgz#063eea0e9939f947227d5ca760cc53696f46446b" + integrity sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg== + dependencies: + client-only "^0.0.1" + use-sync-external-store "^1.2.0" + +symbol-observable@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== + symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -tailwindcss@^2.2.7: +synckit@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.1.tgz#febbfbb6649979450131f64735aa3f6c14575c88" + integrity sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A== + dependencies: + "@pkgr/core" "^0.1.0" + tslib "^2.6.2" + +system-architecture@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/system-architecture/-/system-architecture-0.1.0.tgz#71012b3ac141427d97c67c56bc7921af6bff122d" + integrity sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA== + +tailwind-merge@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-1.6.0.tgz#dd652005544aa0b04628e69688b7108265f0d441" + integrity sha512-lfpys05uZMcVGIbgrrM/HlQGYKiPIcUhs76H1VrXo0gerpYkoLk4zjQTppdyAcBcmpzlzXJw7X0JniUKOr2hkg== + +tailwindcss@3.0.23: + version "3.0.23" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10" + integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA== + dependencies: + arg "^5.0.1" + chalk "^4.1.2" + chokidar "^3.5.3" + color-name "^1.1.4" + cosmiconfig "^7.0.1" + detective "^5.2.0" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.2.11" + glob-parent "^6.0.2" + is-glob "^4.0.3" + normalize-path "^3.0.0" + object-hash "^2.2.0" + postcss "^8.4.6" + postcss-js "^4.0.0" + postcss-load-config "^3.1.0" + postcss-nested "5.0.6" + postcss-selector-parser "^6.0.9" + postcss-value-parser "^4.2.0" + quick-lru "^5.1.1" + resolve "^1.22.0" + +tailwindcss@^2.1.0, tailwindcss@^2.2.7: version "2.2.19" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-2.2.19.tgz#540e464832cd462bb9649c1484b0a38315c2653c" integrity sha512-6Ui7JSVtXadtTUo2NtkBBacobzWiQYVjYW0ZnKaP9S1ZCKQ0w7KVNz+YSDI/j7O7KCMHbOkz94ZMQhbT9pOqjw== @@ -16730,88 +16374,27 @@ tailwindcss@^2.2.7: resolve "^1.20.0" tmp "^0.2.1" -tailwindcss@^3.0.15: - version "3.1.7" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.1.7.tgz#ce99425f30a74e01457a2e6a724463b0df3159ac" - integrity sha512-r7mgumZ3k0InfVPpGWcX8X/Ut4xBfv+1O/+C73ar/m01LxGVzWvPxF/w6xIUPEztrCoz7axfx0SMdh8FH8ZvRQ== - dependencies: - arg "^5.0.2" - chokidar "^3.5.3" - color-name "^1.1.4" - detective "^5.2.1" - didyoumean "^1.2.2" - dlv "^1.1.3" - fast-glob "^3.2.11" - glob-parent "^6.0.2" - is-glob "^4.0.3" - lilconfig "^2.0.6" - normalize-path "^3.0.0" - object-hash "^3.0.0" - picocolors "^1.0.0" - postcss "^8.4.14" - postcss-import "^14.1.0" - postcss-js "^4.0.0" - postcss-load-config "^3.1.4" - postcss-nested "5.0.6" - postcss-selector-parser "^6.0.10" - postcss-value-parser "^4.2.0" - quick-lru "^5.1.1" - resolve "^1.22.1" - -tailwindcss@^3.0.23: - version "3.0.23" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10" - integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA== - dependencies: - arg "^5.0.1" - chalk "^4.1.2" - chokidar "^3.5.3" - color-name "^1.1.4" - cosmiconfig "^7.0.1" - detective "^5.2.0" - didyoumean "^1.2.2" - dlv "^1.1.3" - fast-glob "^3.2.11" - glob-parent "^6.0.2" - is-glob "^4.0.3" - normalize-path "^3.0.0" - object-hash "^2.2.0" - postcss "^8.4.6" - postcss-js "^4.0.0" - postcss-load-config "^3.1.0" - postcss-nested "5.0.6" - postcss-selector-parser "^6.0.9" - postcss-value-parser "^4.2.0" - quick-lru "^5.1.1" - resolve "^1.22.0" - tapable@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar@^6.0.2, tar@^6.1.0, tar@^6.1.11: - version "6.1.11" - resolved "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz" - integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== +tar@^6.0.2: + version "6.1.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b" + integrity sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" - minipass "^3.0.0" + minipass "^4.0.0" minizlib "^2.1.1" mkdirp "^1.0.3" yallist "^4.0.0" -terminal-link@^2.0.0: - version "2.1.1" - resolved "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz" - dependencies: - ansi-escapes "^4.2.1" - supports-hyperlinks "^2.0.0" - test-exclude@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== dependencies: "@istanbuljs/schema" "^0.1.2" glob "^7.1.4" @@ -16819,92 +16402,66 @@ test-exclude@^6.0.0: text-encoding-utf-8@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== -text-table@^0.2.0, text-table@~0.2.0: +text-table@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== thenify-all@^1.0.0: version "1.6.0" - resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" - integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.1" - resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== dependencies: any-promise "^1.0.0" -throat@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz" - integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== - -through2@~2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== +thread-stream@^0.15.1: + version "0.15.2" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.15.2.tgz#fb95ad87d2f1e28f07116eb23d85aba3bc0425f4" + integrity sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA== dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" + real-require "^0.1.0" -through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1: +"through@>=2.2.7 <3", through@^2.3.6: version "2.3.8" - resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== +timezones-ical-library@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/timezones-ical-library/-/timezones-ical-library-1.8.2.tgz#33a96db1f2bcce87d5e00ee64f263b9925c37719" + integrity sha512-0bbCp+xXtTUOcBo7bAGkzK5yMiNnY/FmJblTlnkGcqW5O+SChvWNtvsOX9WqbU5/8sT+Nl/MKQ7c9qafIkUstA== timsort@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz" - -tiny-invariant@^1.0.6, tiny-invariant@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" - integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== - -tiny-relative-date@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz" - integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A== + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + integrity sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A== -tiny-secp256k1@^1.1.3: - version "1.1.6" - resolved "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz" - integrity sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA== - dependencies: - bindings "^1.3.0" - bn.js "^4.11.8" - create-hmac "^1.1.7" - elliptic "^6.4.0" - nan "^2.13.2" +tiny-invariant@^1.0.6, tiny-invariant@^1.2.0, tiny-invariant@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" + integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== tiny-warning@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== tippy.js@^6.3.1: - version "6.3.1" - resolved "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.1.tgz" - integrity sha512-JnFncCq+rF1dTURupoJ4yPie5Cof978inW6/4S6kmWV7LL9YOSEVMifED3KdrVPEG+Z/TFH2CDNJcQEfaeuQww== + version "6.3.7" + resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c" + integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ== dependencies: - "@popperjs/core" "^2.8.3" - -tlds@^1.199.0: - version "1.231.0" - resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.231.0.tgz#93880175cd0a06fdf7b5b5b9bcadff9d94813e39" - integrity sha512-L7UQwueHSkGxZHQBXHVmXW64oi+uqNtzFt2x6Ssk7NVnpIbw16CRs4eb/jmKOZ9t2JnqZ/b3Cfvo97lnXqKrhw== + "@popperjs/core" "^2.9.0" tmp-promise@^3.0.2: version "3.0.3" @@ -16922,125 +16479,145 @@ tmp@^0.0.33: tmp@^0.2.0, tmp@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== dependencies: rimraf "^3.0.0" -tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz" +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - toformat@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/toformat/-/toformat-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/toformat/-/toformat-2.0.0.tgz#7a043fd2dfbe9021a4e36e508835ba32056739d8" integrity sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ== toggle-selection@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" - integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= + integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ== toidentifier@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== toml@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== toposort@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz" - integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= + resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" + integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg== totalist@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== -tough-cookie@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz" +tough-cookie@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" + integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== dependencies: psl "^1.1.33" punycode "^2.1.1" - universalify "^0.1.2" + universalify "^0.2.0" + url-parse "^1.5.3" tough-cookie@~2.5.0: version "2.5.0" - resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: psl "^1.1.28" punycode "^2.1.1" -tr46@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz" +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA== + dependencies: + punycode "^2.1.0" + +tr46@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" + integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== dependencies: punycode "^2.1.1" tr46@~0.0.3: version "0.0.3" - resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== traverse-chain@~0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz" - integrity sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE= + resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" + integrity sha512-up6Yvai4PYKhpNp5PkYtx50m3KbwQrqDwbuZP/ItyL64YEWHAvH6Md83LFLV/GRSk/BoUVwwgUzX6SOQSbsfAg== -treeverse@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/treeverse/-/treeverse-1.0.4.tgz" - integrity sha512-whw60l7r+8ZU8Tu/Uc2yxtc4ZTZbR/PF3u1IPNKGQ6p8EICLb3Z2lAgoqw9bqYd8IkgnsaOcLzYHFckjqNsf0g== +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + +treeify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" + integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== trough@^2.0.0: - version "2.0.2" - resolved "https://registry.npmjs.org/trough/-/trough-2.0.2.tgz" - integrity sha512-FnHq5sTMxC0sk957wHDzRnemFnNBvt/gSY99HzK8F7UP5WAbvP70yX5bd7CjEQkN+TjdxwI7g7lJ6podqrG2/w== + version "2.1.0" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" + integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== + +ts-api-utils@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" + integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== + +ts-ev@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/ts-ev/-/ts-ev-0.4.0.tgz#b30bbab35bd57516efba7ab89b6417424a1ebf0e" + integrity sha512-rLX6QdkC1/jA9sS4y9/DxHABTcOussp33J90h+TxHmya9CWvbGc9uLqdM4c/N4pNRmSdtq9zqhz7sB9KcN1NFQ== -ts-loader@^9.3.1: +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + +ts-jest@29.0.3: + version "29.0.3" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.0.3.tgz#63ea93c5401ab73595440733cefdba31fcf9cb77" + integrity sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.1" + lodash.memoize "4.x" + make-error "1.x" + semver "7.x" + yargs-parser "^21.0.1" + +ts-loader@9.3.1: version "9.3.1" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.3.1.tgz#fe25cca56e3e71c1087fe48dc67f4df8c59b22d4" integrity sha512-OkyShkcZTsTwyS3Kt7a4rsT/t2qvEVQuKCTg4LJmpj9fhFR7ukGdZwV6Qq3tRUkqcXtfGpPR7+hFKHCG/0d3Lw== @@ -17050,7 +16627,25 @@ ts-loader@^9.3.1: micromatch "^4.0.0" semver "^7.3.4" -ts-node@^10.5.0, ts-node@^10.7.0, ts-node@^10.9.1: +ts-mocha@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-8.0.0.tgz#962d0fa12eeb6468aa1a6b594bb3bbc818da3ef0" + integrity sha512-Kou1yxTlubLnD5C3unlCVO7nh0HERTezjoVhVw/M5S1SqoUec0WgllQvPk3vzPMc6by8m6xD1uR1yRf8lnVUbA== + dependencies: + ts-node "7.0.1" + optionalDependencies: + tsconfig-paths "^3.5.0" + +ts-mocha@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-9.0.2.tgz#c1ef0248874d04a0f26dd9bd8d88e617a8d82ab1" + integrity sha512-WyQjvnzwrrubl0JT7EC1yWmNpcsU3fOuBFfdps30zbmFBgKniSaSOyZMZx+Wq7kytUs5CY+pEbSYEbGfIKnXTw== + dependencies: + ts-node "7.0.1" + optionalDependencies: + tsconfig-paths "^3.5.0" + +ts-node@10.9.1, ts-node@^10.7.0: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== @@ -17069,35 +16664,26 @@ ts-node@^10.5.0, ts-node@^10.7.0, ts-node@^10.9.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -ts-poet@^4.5.0: - version "4.10.0" - resolved "https://registry.npmjs.org/ts-poet/-/ts-poet-4.10.0.tgz" - integrity sha512-V5xzt+LDMVtxWvK12WVwHhGHTA//CeoPdWOqka0mMjlRqq7RPKYSfWEnzJdMmhNbd34BwZuZpip4mm+nqEcbQA== - dependencies: - lodash "^4.17.15" - prettier "^2.5.1" - -ts-proto-descriptors@1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-1.6.0.tgz" - integrity sha512-Vrhue2Ti99us/o76mGy28nF3W/Uanl1/8detyJw2yyRwiBC5yxy+hEZqQ/ZX2PbZ1vyCpJ51A9L4PnCCnkBMTQ== +ts-node@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" + integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== dependencies: - long "^4.0.0" - protobufjs "^6.8.8" + arrify "^1.0.0" + buffer-from "^1.1.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.6" + yn "^2.0.0" -ts-proto@^1.79.0: - version "1.107.0" - resolved "https://registry.npmjs.org/ts-proto/-/ts-proto-1.107.0.tgz" - integrity sha512-g9/x0Uh/gov5gG0w/0ulNV2W6RXmBYc12Z3pSLbMKMDvrmEOAvYCbPl8qxAiu9DCNh6gY7asO9aVrP6+2QNWCA== - dependencies: - "@types/object-hash" "^1.3.0" - dataloader "^1.4.0" - object-hash "^1.3.1" - protobufjs "^6.8.8" - ts-poet "^4.5.0" - ts-proto-descriptors "1.6.0" +ts-toolbelt@^6.15.1: + version "6.15.5" + resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz#cb3b43ed725cb63644782c64fbcad7d8f28c0a83" + integrity sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A== -tsconfig-paths@^3.14.1: +tsconfig-paths@3.14.1: version "3.14.1" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== @@ -17107,51 +16693,96 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" - integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== +tsconfig-paths@^3.15.0, tsconfig-paths@^3.5.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" -tslib@^1.0.0, tslib@^1.11.1, tslib@^1.7.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@1.14.1, tslib@^1.9.0: version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.3, tslib@^2.3.0, tslib@^2.3.1: - version "2.3.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== +tslib@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" + integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== -tslib@^2.1.0, tslib@^2.4.0: +tslib@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + +tsup@^8.1.0: + version "8.2.3" + resolved "https://registry.yarnpkg.com/tsup/-/tsup-8.2.3.tgz#4a1ff2962a4d7c8265fea661b0dd9668de58916d" + integrity sha512-6YNT44oUfXRbZuSMNmN36GzwPPIlD2wBccY7looM2fkTcxkf2NEmwr3OZuDZoySklnrIG4hoEtzy8yUXYOqNcg== + dependencies: + bundle-require "^5.0.0" + cac "^6.7.14" + chokidar "^3.6.0" + consola "^3.2.3" + debug "^4.3.5" + esbuild "^0.23.0" + execa "^5.1.1" + globby "^11.1.0" + joycon "^3.1.1" + picocolors "^1.0.1" + postcss-load-config "^6.0.1" + resolve-from "^5.0.0" + rollup "^4.19.0" + source-map "0.8.0-beta.0" + sucrase "^3.35.0" + tree-kill "^1.2.2" tunnel-agent@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" -tweetnacl@1.0.3, tweetnacl@1.x.x, tweetnacl@^1.0.0, tweetnacl@^1.0.1, tweetnacl@^1.0.2, tweetnacl@^1.0.3: +tweetnacl@1.0.3, tweetnacl@1.x.x, tweetnacl@^1.0.1, tweetnacl@^1.0.2, tweetnacl@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" - resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +twin.macro@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/twin.macro/-/twin.macro-2.4.0.tgz#ec78a7ce844d94f6a6001be233a8903c2dd523da" + integrity sha512-1iRIn/cKvsyGkZclyeRKVP+UaDIqCPcQrT5nLjIB+4ZxumY3CRRA1Q3QYBu3Mpo2+HrnjThJcJk9iurpa05XQg== + dependencies: + "@babel/parser" "^7.12.5" + autoprefixer "^10.2.5" + babel-plugin-macros "^2.8.0" + chalk "^4.1.0" + clean-set "^1.1.1" + color "^3.1.3" + dset "^2.0.1" + lodash.flatmap "^4.5.0" + lodash.get "^4.4.2" + lodash.merge "^4.6.2" + postcss "^8.1.8" + string-similarity "^4.0.3" + tailwindcss "^2.1.0" + timsort "^0.3.0" -twin.macro@^2.4.0, twin.macro@^2.8.2: +twin.macro@^2.8.2: version "2.8.2" resolved "https://registry.yarnpkg.com/twin.macro/-/twin.macro-2.8.2.tgz#7f1344b4b1c3811da93a62fa204fe08999df7a75" integrity sha512-2Vg09mp+nA70AWUedJ8WRgB2me3buq7JGbOnjHnFnNaBzomVu5k7lJ9YGpByIlre+UYr7QRhtlj7+IUKxvCrUA== @@ -17174,137 +16805,149 @@ twin.macro@^2.4.0, twin.macro@^2.8.2: type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" type-check@~0.3.2: version "0.3.2" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== dependencies: prelude-ls "~1.1.2" -type-detect@4.0.8: +type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" - resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" - type-fest@^0.21.3: version "0.21.3" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== +typed-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" + integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== dependencies: - is-typedarray "^1.0.0" - -typedoc-default-themes@^0.12.10: - version "0.12.10" - resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.12.10.tgz#614c4222fe642657f37693ea62cad4dafeddf843" - integrity sha512-fIS001cAYHkyQPidWXmHuhs8usjP5XVJjWB8oZGqkTowZaz3v7g3KDZeeqE82FBrmkAnIBOY3jgy7lnPnqATbA== - -typedoc-plugin-missing-exports@^0.22.6: - version "0.22.6" - resolved "https://registry.yarnpkg.com/typedoc-plugin-missing-exports/-/typedoc-plugin-missing-exports-0.22.6.tgz#7467c60f1cd26507124103f0b9bca271d5aa8d71" - integrity sha512-1uguGQqa+c5f33nWS3v1mm0uAx4Ii1lw4Kx2zQksmYFKNEWTmrmMXbMNBoBg4wu0p4dFCNC7JIWPoRzpNS6pFA== + call-bind "^1.0.7" + es-errors "^1.3.0" + is-typed-array "^1.1.13" -typedoc@^0.20.36: - version "0.20.37" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.20.37.tgz#9b9417149cb815e3d569fc300b5d2c6e4e6c5d93" - integrity sha512-9+qDhdc4X00qTNOtii6QX2z7ndAeWVOso7w3MPSoSJdXlVhpwPfm1yEp4ooKuWA9fiQILR8FKkyjmeqa13hBbw== +typed-array-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" + integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== dependencies: - colors "^1.4.0" - fs-extra "^9.1.0" - handlebars "^4.7.7" - lodash "^4.17.21" - lunr "^2.3.9" - marked "~2.0.3" - minimatch "^3.0.0" - progress "^2.0.3" - shelljs "^0.8.4" - shiki "^0.9.3" - typedoc-default-themes "^0.12.10" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" -typeforce@^1.11.5: - version "1.18.0" - resolved "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz" - integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== +typed-array-byte-offset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" + integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" -typescript@^4.1.2, typescript@^4.5.4: - version "4.5.5" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz" - integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== +typed-array-length@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" + integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" -typescript@^4.2.4: - version "4.6.2" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz" - integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== +typescript-collections@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/typescript-collections/-/typescript-collections-1.3.3.tgz#62d50d93c018c094d425eabee649f00ec5cc0fea" + integrity sha512-7sI4e/bZijOzyURng88oOFZCISQPTHozfE2sUu5AviFYk5QV7fYGb6YiDl+vKjF/pICA354JImBImL9XJWUvdQ== -typescript@^4.3.5, typescript@^4.6.2: - version "4.6.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" - integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== +typescript@5.5.4: + version "5.5.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" + integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== -typescript@^4.5.5, typescript@^4.6.3: - version "4.6.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" - integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== +typescript@^4.1.2, typescript@^4.3.5, typescript@^4.5.5, typescript@^4.6.2, typescript@^4.8.2: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== u3@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/u3/-/u3-0.1.1.tgz#5f52044f42ee76cd8de33148829e14528494b73b" integrity sha512-+J5D5ir763y+Am/QY6hXNRlwljIeRMZMGs0cT6qqZVVzzT3X3nFPXVyPOFRMOR4kupB0T8JnCdpWdp6Q/iXn3w== -ua-parser-js@^0.7.30: - version "0.7.31" - resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz" - integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ== +ua-parser-js@^0.7.18: + version "0.7.32" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.32.tgz#cd8c639cdca949e30fa68c44b7813ef13e36d211" + integrity sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw== -uc.micro@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" - integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== +ua-parser-js@^1.0.2: + version "1.0.32" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.32.tgz#786bf17df97de159d5b1c9d5e8e9e89806f8a030" + integrity sha512-dXVsz3M4j+5tTiovFVyVqssXBu5HM47//YSOeZ9fQkdDKkfzv2v3PP1jmH6FUyPW+yCSn7aBVK1fGGKNhowdDA== -uglify-js@^3.1.4: - version "3.15.4" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.4.tgz#fa95c257e88f85614915b906204b9623d4fa340d" - integrity sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA== +ufo@^1.3.0, ufo@^1.3.1, ufo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.2.tgz#c7d719d0628a1c80c006d2240e0d169f6e3c0496" + integrity sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA== -uint8arrays@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.0.tgz#8186b8eafce68f28bd29bd29d683a311778901e2" - integrity sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog== +uint8arrays@^3.0.0, uint8arrays@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" + integrity sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg== dependencies: multiformats "^9.4.2" -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -underscore@1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" - integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== +uncrypto@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b" + integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +unenv@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/unenv/-/unenv-1.9.0.tgz#469502ae85be1bd3a6aa60f810972b1a904ca312" + integrity sha512-QKnFNznRxmbOF1hDgzpqrlIf6NC5sbZ2OJ+5Wl3OX8uM+LUJXbj4TXvLJCtwbPTmbMHCLIz6JLKNinNsMShK9g== + dependencies: + consola "^3.2.3" + defu "^6.1.3" + mime "^3.0.0" + node-fetch-native "^1.6.1" + pathe "^1.1.1" unfetch@^4.2.0: version "4.2.0" @@ -17312,9 +16955,9 @@ unfetch@^4.2.0: integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== unified@^10.0.0: - version "10.1.0" - resolved "https://registry.npmjs.org/unified/-/unified-10.1.0.tgz" - integrity sha512-4U3ru/BRXYYhKbwXV6lU6bufLikoAavTwev89H5UxY8enDFaAT2VXmIXYNm6hb5oHPng/EXr77PVyDFcptbk5g== + version "10.1.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" + integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== dependencies: "@types/unist" "^2.0.0" bail "^2.0.0" @@ -17324,105 +16967,67 @@ unified@^10.0.0: trough "^2.0.0" vfile "^5.0.0" -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - uniq@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz" - -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA== unist-builder@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04" integrity sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ== dependencies: "@types/unist" "^2.0.0" unist-util-generated@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113" integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw== unist-util-is@^5.0.0: version "5.1.1" - resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.1.1.tgz" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ== unist-util-position@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.1.tgz" - integrity sha512-mgy/zI9fQ2HlbOtTdr2w9lhVaiFUHWQnZrFF2EUoVOqtAUdzqMtNiD99qA5a1IcjWVR8O6aVYE9u7Z2z1v0SQA== - -unist-util-stringify-position@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.0.tgz" - integrity sha512-SdfAl8fsDclywZpfMDTVDxA2V7LjtRDTOFd44wUJamgl6OlVngsqWjxvermMYf60elWHbxhuRCZml7AnuXCaSA== - dependencies: - "@types/unist" "^2.0.0" - -unist-util-visit-parents@^4.0.0: - version "4.1.1" - resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz" - integrity sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw== + version "4.0.3" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.3.tgz#5290547b014f6222dff95c48d5c3c13a88fadd07" + integrity sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ== dependencies: "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" -unist-util-visit-parents@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.0.0.tgz" - integrity sha512-CVaLOYPM/EaFTYMytbaju3Tw4QI3DHnHFnL358FkEu0hZOzSm/hqBdVwOQDR60jF5ZzhB1tlZlRH0ll/yekZIQ== +unist-util-stringify-position@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz#5c6aa07c90b1deffd9153be170dce628a869a447" + integrity sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg== dependencies: "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" -unist-util-visit@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-3.1.0.tgz" - integrity sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA== +unist-util-visit-parents@^5.0.0, unist-util-visit-parents@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz#868f353e6fce6bf8fa875b251b0f4fec3be709bb" + integrity sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw== dependencies: "@types/unist" "^2.0.0" unist-util-is "^5.0.0" - unist-util-visit-parents "^4.0.0" unist-util-visit@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.0.0.tgz" - integrity sha512-3HWTvrtU10/E7qgPznBfiOyG0TXj9W8c1GSfaI8L9GkaG1pLePiQPZ7E35a0R3ToQ/zcy4Im6aZ9WBgOTnv1MQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.1.tgz#1c4842d70bd3df6cc545276f5164f933390a9aad" + integrity sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg== dependencies: "@types/unist" "^2.0.0" unist-util-is "^5.0.0" - unist-util-visit-parents "^5.0.0" + unist-util-visit-parents "^5.1.1" -universalify@^0.1.0, universalify@^0.1.2: - version "0.1.2" - resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== universalify@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== unload@^2.3.1: @@ -17433,41 +17038,58 @@ unload@^2.3.1: "@babel/runtime" "^7.6.2" detect-node "2.1.0" -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - unstated-next@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/unstated-next/-/unstated-next-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/unstated-next/-/unstated-next-1.1.0.tgz#7bb4911a12fdf3cc8ad3eb11a0b315e4a8685ea8" integrity sha512-AAn47ZncPvgBGOvMcn8tSRxsrqwf2VdAPxLASTuLJvZt4rhKfDvUkmYZLGfclImSfTVMv7tF4ynaVxin0JjDCA== -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== +unstorage@^1.9.0: + version "1.10.1" + resolved "https://registry.yarnpkg.com/unstorage/-/unstorage-1.10.1.tgz#bf8cc00a406e40a6293e893da9807057d95875b0" + integrity sha512-rWQvLRfZNBpF+x8D3/gda5nUCQL2PgXy2jNG4U7/Rc9BGEv9+CAJd0YyGCROUBKs9v49Hg8huw3aih5Bf5TAVw== + dependencies: + anymatch "^3.1.3" + chokidar "^3.5.3" + destr "^2.0.2" + h3 "^1.8.2" + ioredis "^5.3.2" + listhen "^1.5.5" + lru-cache "^10.0.2" + mri "^1.2.0" + node-fetch-native "^1.4.1" + ofetch "^1.3.3" + ufo "^1.3.1" + +untun@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/untun/-/untun-0.1.3.tgz#5d10dee37a3a5737ff03d158be877dae0a0e58a6" + integrity sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ== + dependencies: + citty "^0.1.5" + consola "^3.2.3" + pathe "^1.1.1" + +update-browserslist-db@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uqr@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/uqr/-/uqr-0.1.2.tgz#5c6cd5dcff9581f9bb35b982cb89e2c483a41d7d" + integrity sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA== uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-parse@^1.4.3: +url-parse@^1.5.3: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== @@ -17475,26 +17097,13 @@ url-parse@^1.4.3: querystringify "^2.1.1" requires-port "^1.0.0" -url-parse@^1.5.3: - version "1.5.4" - resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.4.tgz" - integrity sha512-ITeAByWWoqutFClc/lRZnFplgXgEZr3WJ6XngMM/N9DMIm4K8zXPCZ1Jdu0rERwO84w1WC5wkle2ubwTA4NTBg== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= +urql@3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/urql/-/urql-3.0.3.tgz#275631f487558354e090d9ffc4ea2030bd56c34a" + integrity sha512-aVUAMRLdc5AOk239DxgXt6ZxTl/fEmjr7oyU5OGo8uvpqu42FkeJErzd2qBzhAQ3DyusoZIbqbBLPlnKo/yy2A== dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use-callback-ref@^1.2.3, use-callback-ref@^1.2.5: - version "1.2.5" - resolved "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz" - integrity sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg== + "@urql/core" "^3.0.3" + wonka "^6.0.0" use-callback-ref@^1.3.0: version "1.3.0" @@ -17508,14 +17117,6 @@ use-isomorphic-layout-effect@^1.1.1: resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== -use-sidecar@^1.0.1, use-sidecar@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.5.tgz" - integrity sha512-k9jnrjYNwN6xYLj1iaGhonDghfvmeTmYjAiGvOr7clwKfPjMXJf4/HOr7oT5tJwYafgp2tG2l3eZEOfoELiMcA== - dependencies: - detect-node-es "^1.1.0" - tslib "^1.9.3" - use-sidecar@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" @@ -17524,59 +17125,58 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" -use-sync-external-store@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.1.0.tgz#3343c3fe7f7e404db70f8c687adf5c1652d34e82" - integrity sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ== - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== +use-sync-external-store@1.2.0, use-sync-external-store@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== -utf-8-validate@^5.0.2: - version "5.0.8" - resolved "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.8.tgz" - integrity sha512-k4dW/Qja1BYDl2qD4tOMB9PFVha/UJtxTc1cXYOe3WwA/2m0Yn4qB7wLMpJyLJ/7DR0XnTut3HsCSzDT4ZvKgA== +utf-8-validate@^5.0.2, utf-8-validate@^5.0.9: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== dependencies: node-gyp-build "^4.3.0" +utf8@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util@^0.12.0, util@^0.12.4: - version "0.12.4" - resolved "https://registry.npmjs.org/util/-/util-0.12.4.tgz" - integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== dependencies: inherits "^2.0.3" is-arguments "^1.0.4" is-generator-function "^1.0.7" is-typed-array "^1.1.3" - safe-buffer "^5.1.2" which-typed-array "^1.1.2" -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - uuid@^3.3.2: version "3.4.0" - resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.3.0, uuid@^8.3.2: +uuid@^8.3.2: version "8.3.2" - resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.0, uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + uvu@^0.5.0: - version "0.5.3" - resolved "https://registry.npmjs.org/uvu/-/uvu-0.5.3.tgz" - integrity sha512-brFwqA3FXzilmtnIyJ+CxdkInkY/i4ErvP7uV0DnUVxQcQ55reuHphorpF+tZoVHK2MniZ/VJzI7zJQoc9T9Yw== + version "0.5.6" + resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" + integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== dependencies: dequal "^2.0.0" diff "^5.0.0" @@ -17588,157 +17188,126 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -v8-compile-cache@^2.0.3: - version "2.3.0" - resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" - -v8-to-istanbul@^8.1.0: - version "8.1.0" - resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz" - integrity sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA== +v8-to-istanbul@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" + integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== dependencies: + "@jridgewell/trace-mapping" "^0.3.12" "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" - source-map "^0.7.3" - -validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz" - integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= - dependencies: - builtins "^1.0.3" - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= verror@1.10.0: version "1.10.0" - resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" vfile-message@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-3.0.2.tgz" - integrity sha512-UUjZYIOg9lDRwwiBAuezLIsu9KlXntdxwG+nXnjuQAHvBpcX3x0eN8h+I7TkY5nkCXj+cWVp4ZqebtGBvok8ww== + version "3.1.3" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.3.tgz#1360c27a99234bebf7bddbbbca67807115e6b0dd" + integrity sha512-0yaU+rj2gKAyEk12ffdSbBfjnnj+b1zqTBv3OQCTn8yEB02bsPizwdBPrLJjHnK+cU9EMMcUnNv938XcZIkmdA== dependencies: "@types/unist" "^2.0.0" unist-util-stringify-position "^3.0.0" vfile@^5.0.0: - version "5.1.0" - resolved "https://registry.npmjs.org/vfile/-/vfile-5.1.0.tgz" - integrity sha512-4o7/DJjEaFPYSh0ckv5kcYkJTHQgCKdL8ozMM1jLAxO9ox95IzveDPXCZp08HamdWq8JXTkClDvfAKaeLQeKtg== + version "5.3.6" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.6.tgz#61b2e70690cc835a5d0d0fd135beae74e5a39546" + integrity sha512-ADBsmerdGBs2WYckrLBEmuETSPyTD4TuLxTrw0DvjirxW1ra4ZwkbzG8ndsv3Q57smvHxo677MHaQrY9yxH8cA== dependencies: "@types/unist" "^2.0.0" is-buffer "^2.0.0" unist-util-stringify-position "^3.0.0" vfile-message "^3.0.0" -vscode-oniguruma@^1.6.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz#aeb9771a2f1dbfc9083c8a7fdd9cccaa3f386607" - integrity sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA== - -vscode-textmate@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" - integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== - -w3c-hr-time@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz" - dependencies: - browser-process-hrtime "^1.0.0" - -w3c-xmlserializer@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz" - dependencies: - xml-name-validator "^3.0.0" - -wait-for-event@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/wait-for-event/-/wait-for-event-2.0.1.tgz" - integrity sha512-CuUBvs/TnLfmgJvCVTXDU8yl3DyTilEzMYUe7mlGWtiQU1gndKT/lvdaUatG4AVwq+3heXugYTILZDOm4etc2Q== +victory-vendor@^36.6.8: + version "36.6.8" + resolved "https://registry.yarnpkg.com/victory-vendor/-/victory-vendor-36.6.8.tgz#5a1c555ca99a39fdb66a6c959c8426eb834893a2" + integrity sha512-H3kyQ+2zgjMPvbPqAl7Vwm2FD5dU7/4bCTQakFQnpIsfDljeOMDojRsrmJfwh4oAlNnWhpAf+mbAoLh8u7dwyQ== + dependencies: + "@types/d3-array" "^3.0.3" + "@types/d3-ease" "^3.0.0" + "@types/d3-interpolate" "^3.0.1" + "@types/d3-scale" "^4.0.2" + "@types/d3-shape" "^3.1.0" + "@types/d3-time" "^3.0.0" + "@types/d3-timer" "^3.0.0" + d3-array "^3.1.6" + d3-ease "^3.0.1" + d3-interpolate "^3.0.1" + d3-scale "^4.0.2" + d3-shape "^3.1.0" + d3-time "^3.0.0" + d3-timer "^3.0.1" + +vlq@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-2.0.4.tgz#6057b85729245b9829e3cc7755f95b228d4fe041" + integrity sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA== -wait-on@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.0.tgz#7e9bf8e3d7fe2daecbb7a570ac8ca41e9311c7e7" - integrity sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw== +w3c-xmlserializer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073" + integrity sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw== dependencies: - axios "^0.21.1" - joi "^17.4.0" - lodash "^4.17.21" - minimist "^1.2.5" - rxjs "^7.1.0" + xml-name-validator "^4.0.0" -walk-up-path@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz" - integrity sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg== - -walker@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz" +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== dependencies: - makeerror "1.0.x" + makeerror "1.0.12" -warning@^4.0.2, warning@^4.0.3: +warning@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== dependencies: loose-envify "^1.0.0" -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -wcwidth@^1.0.0, wcwidth@^1.0.1: +wcwidth@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== dependencies: defaults "^1.0.3" -web-streams-polyfill@^3.0.3: - version "3.2.1" - resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" - integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== +web3-utils@^1.3.4: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578" + integrity sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg== + dependencies: + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" webidl-conversions@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== -webidl-conversions@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz" +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webidl-conversions@^6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz" +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== webpack-bundle-analyzer@4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.3.0.tgz#2f3c0ca9041d5ee47fa418693cf56b4a518b578b" integrity sha512-J3TPm54bPARx6QG8z4cKBszahnUglcv70+N+8gUqv2I5KOFHJbzBiLx+pAp606so0X004fxM7hqRu10MLjJifA== dependencies: acorn "^8.0.4" @@ -17751,129 +17320,64 @@ webpack-bundle-analyzer@4.3.0: sirv "^1.0.7" ws "^7.3.1" -webpack-dev-middleware@^3.7.2: - version "3.7.3" - resolved "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz" - integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== - dependencies: - memory-fs "^0.4.1" - mime "^2.4.4" - mkdirp "^0.5.1" - range-parser "^1.2.1" - webpack-log "^2.0.0" - -webpack-dev-server@^3.11.2: - version "3.11.3" - resolved "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz" - integrity sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA== - dependencies: - ansi-html-community "0.0.8" - bonjour "^3.5.0" - chokidar "^2.1.8" - compression "^1.7.4" - connect-history-api-fallback "^1.6.0" - debug "^4.1.1" - del "^4.1.1" - express "^4.17.1" - html-entities "^1.3.1" - http-proxy-middleware "0.19.1" - import-local "^2.0.0" - internal-ip "^4.3.0" - ip "^1.1.5" - is-absolute-url "^3.0.3" - killable "^1.0.1" - loglevel "^1.6.8" - opn "^5.5.0" - p-retry "^3.0.1" - portfinder "^1.0.26" - schema-utils "^1.0.0" - selfsigned "^1.10.8" - semver "^6.3.0" - serve-index "^1.9.1" - sockjs "^0.3.21" - sockjs-client "^1.5.0" - spdy "^4.0.2" - strip-ansi "^3.0.1" - supports-color "^6.1.0" - url "^0.11.0" - webpack-dev-middleware "^3.7.2" - webpack-log "^2.0.0" - ws "^6.2.1" - yargs "^13.3.2" - -webpack-log@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz" - integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== - dependencies: - ansi-colors "^3.0.0" - uuid "^3.3.2" - -webpack-merge@^5.8.0: - version "5.8.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" - integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== - dependencies: - clone-deep "^4.0.1" - wildcard "^2.0.0" +"webpack-sources@^2.0.0 || ^3.0.0": + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -websocket-driver@>=0.5.1, websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== +webrtc-adapter@^7.2.1: + version "7.7.1" + resolved "https://registry.yarnpkg.com/webrtc-adapter/-/webrtc-adapter-7.7.1.tgz#b2c227a6144983b35057df67bd984a7d4bfd17f1" + integrity sha512-TbrbBmiQBL9n0/5bvDdORc6ZfRY/Z7JnEj+EYOD1ghseZdpJ+nF2yx14k3LgQKc7JZnG7HAcL+zHnY25So9d7A== dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + rtcpeerconnection-shim "^1.2.15" + sdp "^2.12.0" -whatwg-encoding@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz" +whatwg-encoding@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" + integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== dependencies: - iconv-lite "0.4.24" + iconv-lite "0.6.3" whatwg-fetch@^3.4.1: version "3.6.2" - resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== -whatwg-mimetype@^2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz" +whatwg-mimetype@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" + integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== -whatwg-url-without-unicode@8.0.0-3: - version "8.0.0-3" - resolved "https://registry.yarnpkg.com/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz#ab6df4bf6caaa6c85a59f6e82c026151d4bb376b" - integrity sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig== +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== dependencies: - buffer "^5.4.3" - punycode "^2.1.1" - webidl-conversions "^5.0.0" + tr46 "^3.0.0" + webidl-conversions "^7.0.0" whatwg-url@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" -whatwg-url@^8.0.0, whatwg-url@^8.5.0: - version "8.5.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.5.0.tgz" +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== dependencies: - lodash "^4.7.0" - tr46 "^2.0.2" - webidl-conversions "^6.1.0" + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" which-boxed-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== dependencies: is-bigint "^1.0.1" @@ -17882,195 +17386,204 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-builtin-type@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.4.tgz#592796260602fc3514a1b5ee7fa29319b72380c3" + integrity sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w== + dependencies: + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" + is-async-function "^2.0.0" + is-date-object "^1.0.5" + is-finalizationregistry "^1.0.2" + is-generator-function "^1.0.10" + is-regex "^1.1.4" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.2" + which-typed-array "^1.1.15" + +which-collection@^1.0.1, which-collection@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== + dependencies: + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" + which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== -which-typed-array@^1.1.2: - version "1.1.7" - resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz" - integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw== +which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2, which-typed-array@^1.1.8: + version "1.1.15" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.7" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" -which@2.0.2, which@^2.0.1, which@^2.0.2: +which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -which@^1.2.14, which@^1.2.9: - version "1.3.1" - resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.0, wide-align@^1.1.2: +wide-align@^1.1.0: version "1.1.5" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: string-width "^1.0.2 || 2 || 3 || 4" -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - -wif@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz" - integrity sha1-CNP1IFbGZnkplyb63g1DKudLRwQ= - dependencies: - bs58check "<3.0.0" +wonka@^6.0.0, wonka@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/wonka/-/wonka-6.1.2.tgz#2c66fa5b26a12f002a03619b988258313d0b5352" + integrity sha512-zNrXPMccg/7OEp9tSfFkMgTvhhowqasiSHdJ3eCZolXxVTV/aT6HUTofoZk9gwRbGoFey/Nss3JaZKUMKMbofg== -wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== +word-wrap@^1.2.5, word-wrap@~1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" -workerpool@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" - integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== +wrap-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" + integrity sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" wrap-ansi@^5.1.0: version "5.1.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== dependencies: ansi-styles "^3.2.0" string-width "^3.0.0" strip-ansi "^5.0.0" -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" wrappy@1: version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^1.1.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" - integrity sha512-SdrHoC/yVBPpV0Xq/mUZQIpW2sWXAShb/V4pomcJXh92RuaO+f3UTWItiR3Px+pLnV2PvC2/bfn5cwr5X6Vfxw== +write-file-atomic@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== dependencies: - graceful-fs "^4.1.11" imurmurhash "^0.1.4" - slide "^1.1.5" + signal-exit "^3.0.7" -write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== +write-file-atomic@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.0.tgz#54303f117e109bf3d540261125c8ea5a7320fab0" + integrity sha512-R7NYMnHSlV42K54lwY9lvW6MnSm1HSJqZL3xiSgi9E7//FYaI74r2G0rd+/X6VAMkHEdzxQaU5HUOXWUz5kA/w== dependencies: imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" + signal-exit "^3.0.7" ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== -ws@^6.2.1: - version "6.2.2" - resolved "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz" - integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw== - dependencies: - async-limiter "~1.0.0" - -ws@^7.3.1: - version "7.5.7" - resolved "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz" - integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== -ws@^7.4.5, ws@^7.4.6: - version "7.5.6" - resolved "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz" - integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== +ws@^7.2.0, ws@^7.3.1, ws@^7.4.0, ws@^7.5.1, ws@^7.5.10: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== -ws@^8.5.0: - version "8.8.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" - integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA== +ws@^8.11.0, ws@^8.18.0, ws@^8.5.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== ws@~8.2.3: version "8.2.3" resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== -xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz" +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== xmlchars@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== xmlhttprequest-ssl@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67" integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== -xtend@^4.0.2, xtend@~4.0.1: +xtend@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^4.0.0: version "4.0.3" - resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: version "1.10.2" - resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yaml@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.0.tgz#c6165a721cf8000e91c36490a41d7be25176cf5d" + integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw== yargs-parser@20.2.4: version "20.2.4" @@ -18079,7 +17592,7 @@ yargs-parser@20.2.4: yargs-parser@^13.1.2: version "13.1.2" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" @@ -18087,13 +17600,13 @@ yargs-parser@^13.1.2: yargs-parser@^20.2.2: version "20.2.9" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-parser@^21.0.0: - version "21.0.0" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz" - integrity sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA== +yargs-parser@^21.0.1, yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs-unparser@2.0.0: version "2.0.0" @@ -18118,9 +17631,9 @@ yargs@16.2.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^13.3.2: +yargs@^13.2.4: version "13.3.2" - resolved "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: cliui "^5.0.0" @@ -18134,32 +17647,47 @@ yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@^17.0.1: - version "17.3.1" - resolved "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz" - integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== +yargs@^17.3.1, yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: - cliui "^7.0.2" + cliui "^8.0.1" escalade "^3.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^21.0.0" + yargs-parser "^21.1.1" + +yarn-deduplicate@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/yarn-deduplicate/-/yarn-deduplicate-6.0.0.tgz#91bc0b7b374efe24796606df2c6b00eabb5aab62" + integrity sha512-HjGVvuy10hetOuXeexXXT77V+6FfgS+NiW3FsmQD88yfF2kBqTpChvMglyKUlQ0xXEcI77VJazll5qKKBl3ssw== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + commander "^9.4.0" + semver "^7.3.7" + tslib "^2.4.0" yn@3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" + integrity sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -yup@^0.32.11: +yup@0.32.11: version "0.32.11" - resolved "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5" integrity sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg== dependencies: "@babel/runtime" "^7.15.4" @@ -18170,12 +17698,24 @@ yup@^0.32.11: property-expr "^2.0.4" toposort "^2.0.2" -zustand@^3.7.2: +zod-error@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/zod-error/-/zod-error-1.5.0.tgz#bfdc20532746d564c88c51bd36267d6b7d9b9a5d" + integrity sha512-zzopKZ/skI9iXpqCEPj+iLCKl9b88E43ehcU+sbRoHuwGd9F1IDVGQ70TyO6kmfiRL1g4IXkjsXK+g1gLYl4WQ== + dependencies: + zod "^3.20.2" + +zod@^3.20.2, zod@^3.22.2: + version "3.22.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" + integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== + +zustand@3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.7.2.tgz#7b44c4f4a5bfd7a8296a3957b13e1c346f42514d" integrity sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA== zwitch@^2.0.0: - version "2.0.2" - resolved "https://registry.npmjs.org/zwitch/-/zwitch-2.0.2.tgz" - integrity sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA== + version "2.0.4" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" + integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==