tests: Remove `auction-house` submodule and host it natively (#2654)

This commit is contained in:
acheron 2023-10-09 13:50:40 +02:00 committed by GitHub
parent 5e7fb44518
commit 267c4ceab7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 3006 additions and 11 deletions

View File

@ -419,9 +419,9 @@ jobs:
path: tests/ido-pool
# - cmd: cd tests/cfo && anchor run test-with-build && cd deps/stake && git checkout Cargo.lock && cd ../swap && git checkout Cargo.lock
# path: tests/cfo
- cmd: cd tests/auction-house && yarn --frozen-lockfile && anchor test --skip-lint && git checkout Cargo.lock
- cmd: cd tests/auction-house && anchor test --skip-lint
path: tests/auction-house
- cmd: cd tests/floats && yarn --frozen-lockfile && anchor test --skip-lint && npx tsc --noEmit
- cmd: cd tests/floats && anchor test --skip-lint && npx tsc --noEmit
path: tests/floats
- cmd: cd tests/safety-checks && anchor run test
path: tests/safety-checks

4
.gitmodules vendored
View File

@ -12,7 +12,3 @@
path = tests/cfo/deps/stake
url = https://github.com/project-serum/stake.git
branch = armani/cfo
[submodule "tests/auction-house"]
path = tests/auction-house
url = https://github.com/armaniferrante/auction-house
branch = armani/pda

@ -1 +0,0 @@
Subproject commit 93021530dfcd75b903cc3a3ef1c4b464c456d9c9

View File

@ -0,0 +1,22 @@
[features]
seeds = true
[programs.localnet]
auction_house = "hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk"
[programs.devnet]
auction_house = "hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk"
[programs.mainnet]
auction_house = "hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk"
[provider]
cluster = "localnet"
wallet = "~/.config/solana/id.json"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
[[test.genesis]]
address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
program = "./prebuilt-programs/metaplex_token_metadata.so"

View File

@ -0,0 +1,4 @@
[workspace]
members = [
"programs/*"
]

View File

@ -0,0 +1,12 @@
// Migrations are an early feature. Currently, they're nothing more than this
// single deploy script that's invoked from the CLI, injecting a provider
// configured from the workspace's Anchor.toml.
const anchor = require("@coral-xyz/anchor");
module.exports = async function (provider) {
// Configure client to use the provider.
anchor.setProvider(provider);
// Add your deploy script here.
};

View File

@ -0,0 +1,22 @@
{
"name": "auction-house",
"version": "0.28.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {
"url": "https://github.com/coral-xyz/anchor/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/coral-xyz/anchor.git"
},
"engines": {
"node": ">=17"
},
"scripts": {
"test": "anchor test --skip-lint"
},
"dependencies": {
"@metaplex/js": "^4.4.1"
}
}

View File

@ -0,0 +1,24 @@
[package]
name = "auction-house"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib", "lib"]
name = "auction_house"
[features]
no-entrypoint = []
no-idl = []
cpi = ["no-entrypoint"]
default = []
[dependencies]
anchor-lang = { path = "../../../../lang" }
anchor-spl = { path = "../../../../spl", features = ["metadata"] }
spl-token = { version = "3.2", features = ["no-entrypoint"] }
spl-associated-token-account = { version = "1.1.1", features = ["no-entrypoint"] }
thiserror = "1.0"
arrayref = "0.3.6"

View File

@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,478 @@
use {
crate::{AuctionHouse, ErrorCode},
anchor_lang::{
prelude::*,
solana_program::{
program::invoke_signed,
program_option::COption,
program_pack::{IsInitialized, Pack},
system_instruction,
},
},
anchor_spl::{
metadata::mpl_token_metadata,
token::{Mint, Token, TokenAccount},
},
arrayref::array_ref,
spl_associated_token_account::get_associated_token_address,
spl_token::{instruction::initialize_account2, state::Account},
std::{convert::TryInto, slice::Iter},
};
pub fn assert_is_ata(ata: &AccountInfo, wallet: &Pubkey, mint: &Pubkey) -> Result<Account> {
assert_owned_by(ata, &spl_token::id())?;
let ata_account: Account = assert_initialized(ata)?;
assert_keys_equal(ata_account.owner, *wallet)?;
assert_keys_equal(get_associated_token_address(wallet, mint), *ata.key)?;
Ok(ata_account)
}
pub fn make_ata<'a>(
ata: AccountInfo<'a>,
wallet: AccountInfo<'a>,
mint: AccountInfo<'a>,
fee_payer: AccountInfo<'a>,
ata_program: AccountInfo<'a>,
token_program: AccountInfo<'a>,
system_program: AccountInfo<'a>,
fee_payer_seeds: &[&[u8]],
) -> Result<()> {
let seeds: &[&[&[u8]]];
let as_arr = [fee_payer_seeds];
if fee_payer_seeds.len() > 0 {
seeds = &as_arr;
} else {
seeds = &[];
}
invoke_signed(
&spl_associated_token_account::create_associated_token_account(
&fee_payer.key,
&wallet.key,
&mint.key,
),
&[
ata,
wallet,
mint,
fee_payer,
ata_program,
system_program,
token_program,
],
seeds,
)?;
Ok(())
}
pub fn assert_metadata_valid<'a>(
metadata: &UncheckedAccount,
token_account: &anchor_lang::accounts::account::Account<'a, TokenAccount>,
) -> Result<()> {
assert_derivation(
&mpl_token_metadata::ID,
&metadata.to_account_info(),
&[
b"metadata",
mpl_token_metadata::ID.as_ref(),
token_account.mint.as_ref(),
],
)?;
if metadata.data_is_empty() {
return err!(ErrorCode::MetadataDoesntExist);
}
Ok(())
}
pub fn get_fee_payer<'a, 'b>(
authority: &AccountInfo,
auction_house: &anchor_lang::accounts::account::Account<AuctionHouse>,
wallet: AccountInfo<'a>,
auction_house_fee_account: AccountInfo<'a>,
auction_house_seeds: &'b [&'b [u8]],
) -> Result<(AccountInfo<'a>, &'b [&'b [u8]])> {
let mut seeds: &[&[u8]] = &[];
let fee_payer: AccountInfo;
if authority.to_account_info().is_signer {
seeds = auction_house_seeds;
fee_payer = auction_house_fee_account;
} else if wallet.is_signer {
if auction_house.requires_sign_off {
return err!(ErrorCode::CannotTakeThisActionWithoutAuctionHouseSignOff);
}
fee_payer = wallet
} else {
return err!(ErrorCode::NoPayerPresent);
};
Ok((fee_payer, &seeds))
}
pub fn assert_valid_delegation(
src_account: &AccountInfo,
dst_account: &AccountInfo,
src_wallet: &AccountInfo,
dst_wallet: &AccountInfo,
transfer_authority: &AccountInfo,
mint: &anchor_lang::accounts::account::Account<Mint>,
paysize: u64,
) -> Result<()> {
match Account::unpack(&src_account.data.borrow()) {
Ok(token_account) => {
// Ensure that the delegated amount is exactly equal to the maker_size
msg!(
"Delegate {}",
token_account.delegate.unwrap_or(*src_wallet.key)
);
msg!("Delegated Amount {}", token_account.delegated_amount);
if token_account.delegated_amount != paysize {
return Err(ProgramError::InvalidAccountData.into());
}
// Ensure that authority is the delegate of this token account
msg!("Authority key matches");
if token_account.delegate != COption::Some(*transfer_authority.key) {
return Err(ProgramError::InvalidAccountData.into());
}
msg!("Delegate matches");
assert_is_ata(src_account, src_wallet.key, &mint.key())?;
assert_is_ata(dst_account, dst_wallet.key, &mint.key())?;
msg!("ATAs match")
}
Err(_) => {
if mint.key() != spl_token::native_mint::id() {
return err!(ErrorCode::ExpectedSolAccount);
}
if !src_wallet.is_signer {
return err!(ErrorCode::SOLWalletMustSign);
}
assert_keys_equal(*src_wallet.key, src_account.key())?;
assert_keys_equal(*dst_wallet.key, dst_account.key())?;
}
}
Ok(())
}
pub fn assert_keys_equal(key1: Pubkey, key2: Pubkey) -> Result<()> {
if key1 != key2 {
err!(ErrorCode::PublicKeyMismatch)
} else {
Ok(())
}
}
pub fn assert_initialized<T: Pack + IsInitialized>(account_info: &AccountInfo) -> Result<T> {
let account: T = T::unpack_unchecked(&account_info.data.borrow())?;
if !account.is_initialized() {
err!(ErrorCode::UninitializedAccount)
} else {
Ok(account)
}
}
pub fn assert_owned_by(account: &AccountInfo, owner: &Pubkey) -> Result<()> {
if account.owner != owner {
err!(ErrorCode::IncorrectOwner)
} else {
Ok(())
}
}
#[allow(clippy::too_many_arguments)]
pub fn pay_auction_house_fees<'a>(
auction_house: &anchor_lang::accounts::account::Account<'a, AuctionHouse>,
auction_house_treasury: &AccountInfo<'a>,
escrow_payment_account: &AccountInfo<'a>,
token_program: &AccountInfo<'a>,
system_program: &AccountInfo<'a>,
signer_seeds: &[&[u8]],
size: u64,
is_native: bool,
) -> Result<u64> {
let fees = auction_house.seller_fee_basis_points;
let total_fee = (fees as u128)
.checked_mul(size as u128)
.ok_or(error!(ErrorCode::NumericalOverflow))?
.checked_div(10000)
.ok_or(error!(ErrorCode::NumericalOverflow))? as u64;
if !is_native {
invoke_signed(
&spl_token::instruction::transfer(
token_program.key,
&escrow_payment_account.key,
&auction_house_treasury.key,
&auction_house.key(),
&[],
total_fee,
)?,
&[
escrow_payment_account.clone(),
auction_house_treasury.clone(),
token_program.clone(),
auction_house.to_account_info(),
],
&[signer_seeds],
)?;
} else {
invoke_signed(
&system_instruction::transfer(
&escrow_payment_account.key,
auction_house_treasury.key,
total_fee,
),
&[
escrow_payment_account.clone(),
auction_house_treasury.clone(),
system_program.clone(),
],
&[signer_seeds],
)?;
}
Ok(total_fee)
}
pub fn create_program_token_account_if_not_present<'a>(
payment_account: &UncheckedAccount<'a>,
system_program: &Program<'a, System>,
fee_payer: &AccountInfo<'a>,
token_program: &Program<'a, Token>,
treasury_mint: &anchor_lang::accounts::account::Account<'a, Mint>,
owner: &AccountInfo<'a>,
rent: &Sysvar<'a, Rent>,
signer_seeds: &[&[u8]],
fee_seeds: &[&[u8]],
is_native: bool,
) -> Result<()> {
if !is_native && payment_account.data_is_empty() {
create_or_allocate_account_raw(
*token_program.key,
&payment_account.to_account_info(),
&rent.to_account_info(),
&system_program,
&fee_payer,
spl_token::state::Account::LEN,
fee_seeds,
signer_seeds,
)?;
invoke_signed(
&initialize_account2(
&token_program.key,
&payment_account.key(),
&treasury_mint.key(),
&owner.key(),
)
.unwrap(),
&[
token_program.to_account_info(),
treasury_mint.to_account_info(),
payment_account.to_account_info(),
rent.to_account_info(),
owner.clone(),
],
&[&signer_seeds],
)?;
msg!("Passes");
}
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub fn pay_creator_fees<'a>(
remaining_accounts: &mut Iter<AccountInfo<'a>>,
metadata_info: &AccountInfo<'a>,
escrow_payment_account: &AccountInfo<'a>,
payment_account_owner: &AccountInfo<'a>,
fee_payer: &AccountInfo<'a>,
treasury_mint: &AccountInfo<'a>,
ata_program: &AccountInfo<'a>,
token_program: &AccountInfo<'a>,
system_program: &AccountInfo<'a>,
signer_seeds: &[&[u8]],
fee_payer_seeds: &[&[u8]],
size: u64,
is_native: bool,
) -> Result<u64> {
let metadata =
mpl_token_metadata::accounts::Metadata::from_bytes(*metadata_info.data.borrow())?;
let fees = metadata.seller_fee_basis_points;
let total_fee = (fees as u128)
.checked_mul(size as u128)
.ok_or(error!(ErrorCode::NumericalOverflow))?
.checked_div(10000)
.ok_or(error!(ErrorCode::NumericalOverflow))? as u64;
let mut remaining_fee = total_fee;
let remaining_size = size
.checked_sub(total_fee)
.ok_or(error!(ErrorCode::NumericalOverflow))?;
match metadata.creators {
Some(creators) => {
for creator in creators {
let pct = creator.share as u128;
let creator_fee =
pct.checked_mul(total_fee as u128)
.ok_or(error!(ErrorCode::NumericalOverflow))?
.checked_div(100)
.ok_or(error!(ErrorCode::NumericalOverflow))? as u64;
remaining_fee = remaining_fee
.checked_sub(creator_fee)
.ok_or(error!(ErrorCode::NumericalOverflow))?;
let current_creator_info = next_account_info(remaining_accounts)?;
assert_keys_equal(creator.address, *current_creator_info.key)?;
if !is_native {
let current_creator_token_account_info = next_account_info(remaining_accounts)?;
if current_creator_token_account_info.data_is_empty() {
make_ata(
current_creator_token_account_info.to_account_info(),
current_creator_info.to_account_info(),
treasury_mint.to_account_info(),
fee_payer.to_account_info(),
ata_program.to_account_info(),
token_program.to_account_info(),
system_program.to_account_info(),
fee_payer_seeds,
)?;
}
assert_is_ata(
current_creator_token_account_info,
current_creator_info.key,
&treasury_mint.key(),
)?;
if creator_fee > 0 {
invoke_signed(
&spl_token::instruction::transfer(
token_program.key,
&escrow_payment_account.key,
current_creator_token_account_info.key,
payment_account_owner.key,
&[],
creator_fee,
)?,
&[
escrow_payment_account.clone(),
current_creator_token_account_info.clone(),
token_program.clone(),
payment_account_owner.clone(),
],
&[signer_seeds],
)?;
}
} else if creator_fee > 0 {
invoke_signed(
&system_instruction::transfer(
&escrow_payment_account.key,
current_creator_info.key,
creator_fee,
),
&[
escrow_payment_account.clone(),
current_creator_info.clone(),
system_program.clone(),
],
&[signer_seeds],
)?;
}
}
}
None => {
msg!("No creators found in metadata");
}
}
// Any dust is returned to the party posting the NFT
Ok(remaining_size
.checked_add(remaining_fee)
.ok_or(error!(ErrorCode::NumericalOverflow))?)
}
/// Cheap method to just grab mint Pubkey from token account, instead of deserializing entire thing
pub fn get_mint_from_token_account(token_account_info: &AccountInfo) -> Result<Pubkey> {
// TokeAccount layout: mint(32), owner(32), ...
let data = token_account_info.try_borrow_data()?;
let mint_data = array_ref![data, 0, 32];
Ok(Pubkey::new_from_array(*mint_data))
}
/// Cheap method to just grab delegate Pubkey from token account, instead of deserializing entire thing
pub fn get_delegate_from_token_account(token_account_info: &AccountInfo) -> Result<Option<Pubkey>> {
// TokeAccount layout: mint(32), owner(32), ...
let data = token_account_info.try_borrow_data()?;
let key_data = array_ref![data, 76, 32];
let coption_data = u32::from_le_bytes(*array_ref![data, 72, 4]);
if coption_data == 0 {
Ok(None)
} else {
Ok(Some(Pubkey::new_from_array(*key_data)))
}
}
/// Create account almost from scratch, lifted from
/// https://github.com/solana-labs/solana-program-library/blob/7d4873c61721aca25464d42cc5ef651a7923ca79/associated-token-account/program/src/processor.rs#L51-L98
#[inline(always)]
pub fn create_or_allocate_account_raw<'a>(
program_id: Pubkey,
new_account_info: &AccountInfo<'a>,
rent_sysvar_info: &AccountInfo<'a>,
system_program_info: &AccountInfo<'a>,
payer_info: &AccountInfo<'a>,
size: usize,
signer_seeds: &[&[u8]],
new_acct_seeds: &[&[u8]],
) -> Result<()> {
let rent = &Rent::from_account_info(rent_sysvar_info)?;
let required_lamports = rent
.minimum_balance(size)
.max(1)
.saturating_sub(new_account_info.lamports());
if required_lamports > 0 {
msg!("Transfer {} lamports to the new account", required_lamports);
let seeds: &[&[&[u8]]];
let as_arr = [signer_seeds];
if signer_seeds.len() > 0 {
seeds = &as_arr;
} else {
seeds = &[];
}
invoke_signed(
&system_instruction::transfer(&payer_info.key, new_account_info.key, required_lamports),
&[
payer_info.clone(),
new_account_info.clone(),
system_program_info.clone(),
],
seeds,
)?;
}
let accounts = &[new_account_info.clone(), system_program_info.clone()];
msg!("Allocate space for the account {}", new_account_info.key);
invoke_signed(
&system_instruction::allocate(new_account_info.key, size.try_into().unwrap()),
accounts,
&[&new_acct_seeds],
)?;
msg!("Assign the account to the owning program");
invoke_signed(
&system_instruction::assign(new_account_info.key, &program_id),
accounts,
&[&new_acct_seeds],
)?;
msg!("Completed assignation!");
Ok(())
}
pub fn assert_derivation(program_id: &Pubkey, account: &AccountInfo, path: &[&[u8]]) -> Result<u8> {
let (key, bump) = Pubkey::find_program_address(&path, program_id);
if key != *account.key {
return err!(ErrorCode::DerivedKeyInvalid);
}
Ok(bump)
}

View File

@ -0,0 +1,436 @@
import {
AnchorProvider,
Program,
Wallet,
BN,
getProvider,
setProvider,
} from "@coral-xyz/anchor";
import {
Transaction,
Keypair,
PublicKey,
SystemProgram,
} from "@solana/web3.js";
import { u64, Token, TOKEN_PROGRAM_ID } from "@solana/spl-token";
import * as metaplex from "@metaplex/js";
import * as assert from "assert";
import { IDL, AuctionHouse } from "../target/types/auction_house";
const MetadataDataData = metaplex.programs.metadata.MetadataDataData;
const CreateMetadata = metaplex.programs.metadata.CreateMetadata;
const TOKEN_METADATA_PROGRAM_ID = new PublicKey(
"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
);
const AUCTION_HOUSE_PROGRAM_ID = new PublicKey(
"hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk"
);
// Mint address for native SOL token accounts.
//
// The program uses this when one wants to pay with native SOL vs an SPL token.
const NATIVE_SOL_MINT = new PublicKey(
"So11111111111111111111111111111111111111112"
);
describe("auction-house", () => {
setProvider(AnchorProvider.env());
// @ts-ignore
const wallet = getProvider().wallet as Wallet;
// Clients.
let authorityClient: Program<AuctionHouse>; // Reprents the exchange authority.
let sellerClient: Program<AuctionHouse>; // Represents the seller.
let buyerClient: Program<AuctionHouse>; // Represents the buyer.
let nftMintClient: Token; // Represents the NFT to be traded.
// Seeds constants.
const PREFIX = Buffer.from("auction_house");
const FEE_PAYER = Buffer.from("fee_payer");
const TREASURY = Buffer.from("treasury");
// Constant accounts.
const authorityKeypair = wallet.payer;
const authority = wallet.publicKey;
const feeWithdrawalDestination = authority;
const treasuryWithdrawalDestination = authority;
const treasuryWithdrawalDestinationOwner = authority;
const treasuryMint = NATIVE_SOL_MINT;
const tokenProgram = TOKEN_PROGRAM_ID;
// Uninitialized constant accounts.
let metadata: PublicKey;
let auctionHouse: PublicKey;
let auctionHouseFeeAccount: PublicKey;
// Buyer specific vars.
const buyerWallet = Keypair.generate();
let buyerTokenAccount: PublicKey;
// Seller specific vars.
const sellerWallet = Keypair.generate();
let sellerTokenAccount: PublicKey;
it("Creates an NFT mint", async () => {
// Create the mint.
nftMintClient = await Token.createMint(
getProvider().connection,
authorityKeypair,
authority,
null,
6,
tokenProgram
);
// Create the metadata.
const [_metadata] = await PublicKey.findProgramAddress(
[
Buffer.from("metadata"),
TOKEN_METADATA_PROGRAM_ID.toBuffer(),
nftMintClient.publicKey.toBuffer(),
],
TOKEN_METADATA_PROGRAM_ID
);
metadata = _metadata;
const tx = new CreateMetadata(
{ feePayer: authority },
{
metadata,
metadataData: new MetadataDataData({
name: "test-nft",
symbol: "TEST",
uri: "https://nothing.com",
sellerFeeBasisPoints: 1,
creators: null,
}),
updateAuthority: authority,
mint: nftMintClient.publicKey,
mintAuthority: authority,
}
);
await getProvider().sendAndConfirm(tx);
});
it("Creates token accounts for the NFT", async () => {
// Create token accounts for the mint.
buyerTokenAccount = await nftMintClient.createAssociatedTokenAccount(
buyerWallet.publicKey
);
sellerTokenAccount = await nftMintClient.createAssociatedTokenAccount(
sellerWallet.publicKey
);
// Initialize the seller's account with a single token.
await nftMintClient.mintTo(sellerTokenAccount, authority, [], 1);
});
it("Creates auction house program clients representing the buyer and seller", async () => {
authorityClient = new Program<AuctionHouse>(
IDL,
AUCTION_HOUSE_PROGRAM_ID,
getProvider()
);
sellerClient = new Program<AuctionHouse>(
IDL,
AUCTION_HOUSE_PROGRAM_ID,
new AnchorProvider(
getProvider().connection,
new Wallet(sellerWallet),
AnchorProvider.defaultOptions()
)
);
buyerClient = new Program<AuctionHouse>(
IDL,
AUCTION_HOUSE_PROGRAM_ID,
new AnchorProvider(
getProvider().connection,
new Wallet(buyerWallet),
AnchorProvider.defaultOptions()
)
);
});
it("Initializes constants", async () => {
const [_auctionHouse] = await PublicKey.findProgramAddress(
[PREFIX, authority.toBuffer(), treasuryMint.toBuffer()],
AUCTION_HOUSE_PROGRAM_ID
);
const [_auctionHouseFeeAccount] = await PublicKey.findProgramAddress(
[PREFIX, _auctionHouse.toBuffer(), FEE_PAYER],
AUCTION_HOUSE_PROGRAM_ID
);
auctionHouse = _auctionHouse;
auctionHouseFeeAccount = _auctionHouseFeeAccount;
});
it("Funds the buyer with lamports so that it can bid", async () => {
const tx = new Transaction();
tx.add(
SystemProgram.transfer({
fromPubkey: authority,
toPubkey: buyerWallet.publicKey,
lamports: 20 * 10 ** 9,
})
);
tx.add(
SystemProgram.transfer({
fromPubkey: authority,
toPubkey: sellerWallet.publicKey,
lamports: 20 * 10 ** 9,
})
);
tx.add(
SystemProgram.transfer({
fromPubkey: authority,
toPubkey: auctionHouseFeeAccount,
lamports: 100 * 10 ** 9,
})
);
const txSig = await getProvider().sendAndConfirm(tx);
console.log("fund buyer:", txSig);
});
it("Creates an auction house", async () => {
const sellerFeeBasisPoints = 1;
const requiresSignOff = true;
const canChangeSalePrice = true;
const txSig = await authorityClient.methods
.createAuctionHouse(
sellerFeeBasisPoints,
requiresSignOff,
canChangeSalePrice
)
.accounts({
treasuryMint,
authority,
feeWithdrawalDestination,
treasuryWithdrawalDestination,
treasuryWithdrawalDestinationOwner,
})
.rpc();
console.log("createAuctionHouse:", txSig);
});
it("Deposits into an escrow account", async () => {
const amount = new BN(10 * 10 ** 9);
const txSig = await buyerClient.methods
.deposit(amount)
.accounts({
paymentAccount: buyerWallet.publicKey,
transferAuthority: buyerWallet.publicKey,
treasuryMint,
authority,
})
.signers([authorityKeypair])
.rpc();
console.log("deposit:", txSig);
});
it("Withdraws from an escrow account", async () => {
const amount = new BN(10 * 10 ** 9);
const txSig = await buyerClient.methods
.withdraw(amount)
.accounts({
wallet: buyerWallet.publicKey,
receiptAccount: buyerWallet.publicKey,
treasuryMint,
authority,
})
.signers([authorityKeypair])
.rpc();
console.log("withdraw:", txSig);
});
it("Posts an offer", async () => {
const buyerPrice = new u64(2 * 10 ** 9);
const tokenSize = new u64(1);
const txSig = await sellerClient.methods
.sell(buyerPrice, tokenSize)
.accounts({
wallet: sellerWallet.publicKey,
tokenAccount: sellerTokenAccount,
metadata,
authority,
treasuryMint,
})
.signers([authorityKeypair])
.rpc();
console.log("sell:", txSig);
});
it("Cancels an offer", async () => {
const buyerPrice = new u64(2 * 10 ** 9);
const tokenSize = new u64(1);
const txSig = await sellerClient.methods
.cancel(buyerPrice, tokenSize)
.accounts({
wallet: sellerWallet.publicKey,
tokenAccount: sellerTokenAccount,
authority,
treasuryMint,
})
.signers([authorityKeypair])
.rpc();
console.log("cancel:", txSig);
});
it("Posts an offer (again)", async () => {
const buyerPrice = new u64(2 * 10 ** 9);
const tokenSize = new u64(1);
const txSig = await sellerClient.methods
.sell(buyerPrice, tokenSize)
.accounts({
wallet: sellerWallet.publicKey,
tokenAccount: sellerTokenAccount,
metadata,
authority,
treasuryMint,
})
.signers([authorityKeypair])
.rpc();
console.log("sell:", txSig);
});
it("Posts a bid", async () => {
const buyerPrice = new u64(2 * 10 ** 9);
const tokenSize = new u64(1);
const txSig = await buyerClient.methods
.buy(buyerPrice, tokenSize)
.accounts({
wallet: buyerWallet.publicKey,
paymentAccount: buyerWallet.publicKey,
transferAuthority: buyerWallet.publicKey,
treasuryMint,
tokenAccount: sellerTokenAccount,
metadata,
authority,
})
.signers([authorityKeypair])
.rpc();
console.log("buy:", txSig);
});
it("Executes a trade", async () => {
const [buyerEscrow] = await PublicKey.findProgramAddress(
[PREFIX, auctionHouse.toBuffer(), buyerWallet.publicKey.toBuffer()],
AUCTION_HOUSE_PROGRAM_ID
);
const [auctionHouseTreasury] = await PublicKey.findProgramAddress(
[PREFIX, auctionHouse.toBuffer(), TREASURY],
AUCTION_HOUSE_PROGRAM_ID
);
const airdropSig = await authorityClient.provider.connection.requestAirdrop(
auctionHouseTreasury,
890880
);
await authorityClient.provider.connection.confirmTransaction(airdropSig);
// Before state.
const beforeEscrowState =
await authorityClient.provider.connection.getAccountInfo(buyerEscrow);
const beforeSeller =
await authorityClient.provider.connection.getAccountInfo(
sellerWallet.publicKey
);
// Execute trade.
const buyerPrice = new u64(2 * 10 ** 9);
const tokenSize = new u64(1);
const txSig = await authorityClient.methods
.executeSale(buyerPrice, tokenSize)
.accounts({
buyer: buyerWallet.publicKey,
seller: sellerWallet.publicKey,
tokenAccount: sellerTokenAccount,
tokenMint: nftMintClient.publicKey,
metadata,
treasuryMint,
escrowPaymentAccount: buyerEscrow,
sellerPaymentReceiptAccount: sellerWallet.publicKey,
buyerReceiptTokenAccount: buyerTokenAccount,
authority,
})
.rpc();
console.log("executeSale:", txSig);
// After state.
const afterEscrowState =
await authorityClient.provider.connection.getAccountInfo(buyerEscrow);
const afterSeller =
await authorityClient.provider.connection.getAccountInfo(
sellerWallet.publicKey
);
// Assertions.
assert.ok(afterEscrowState === null);
assert.ok(beforeEscrowState.lamports === 2 * 10 ** 9);
assert.ok(1999800000.0 === afterSeller.lamports - beforeSeller.lamports); // 1bp fee.
});
it("Withdraws from the fee account", async () => {
const txSig = await authorityClient.methods
.withdrawFromFee(new u64(1))
.accounts({
authority,
treasuryMint,
feeWithdrawalDestination,
})
.rpc();
console.log("withdrawFromFee:", txSig);
});
it("Withdraws from the treasury account", async () => {
const txSig = await authorityClient.methods
.withdrawFromTreasury(new u64(1))
.accounts({
treasuryMint,
authority,
treasuryWithdrawalDestination,
})
.rpc();
console.log("txSig:", txSig);
});
it("Updates an auction house", async () => {
const sellerFeeBasisPoints = 2;
const requiresSignOff = true;
const canChangeSalePrice = null;
const tx = new Transaction();
tx.add(
await authorityClient.methods
.updateAuctionHouse(
sellerFeeBasisPoints,
requiresSignOff,
canChangeSalePrice
)
.accounts({
treasuryMint,
payer: authority,
authority,
newAuthority: authority,
feeWithdrawalDestination,
treasuryWithdrawalDestination,
treasuryWithdrawalDestinationOwner,
})
.instruction()
);
const txSig = await authorityClient.provider.sendAndConfirm(tx);
console.log("updateAuctionHouse:", txSig);
const newAh = await authorityClient.account.auctionHouse.fetch(
auctionHouse
);
assert.ok(newAh.sellerFeeBasisPoints === 2);
});
});

View File

@ -0,0 +1,11 @@
{
"compilerOptions": {
"types": ["mocha", "node"],
"lib": ["es2020"],
"module": "commonjs",
"target": "es6",
"esModuleInterop": true,
"skipLibCheck": true,
"strict": true
}
}

View File

@ -8,6 +8,7 @@
"workspaces": [
"anchor-cli-account",
"anchor-cli-idl",
"auction-house",
"bench",
"cashiers-check",
"cfo",

View File

@ -16,11 +16,107 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.22.6":
version "7.23.1"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.1.tgz#72741dc4d413338a91dcb044a86f3c0bc402646d"
integrity sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==
dependencies:
regenerator-runtime "^0.14.0"
"@metaplex-foundation/mpl-auction@^0.0.2":
version "0.0.2"
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-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.31.0"
bs58 "^4.0.1"
"@metaplex-foundation/mpl-metaplex@^0.0.5":
version "0.0.5"
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"
"@metaplex-foundation/mpl-core" "^0.0.2"
"@metaplex-foundation/mpl-token-metadata" "^0.0.2"
"@metaplex-foundation/mpl-token-vault" "^0.0.2"
"@solana/spl-token" "^0.1.8"
"@solana/web3.js" "^1.31.0"
"@metaplex-foundation/mpl-token-metadata@^0.0.2":
version "0.0.2"
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@^1.1.0":
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/mpl-core" "^0.0.2"
"@solana/spl-token" "^0.1.8"
"@solana/web3.js" "^1.31.0"
"@metaplex-foundation/mpl-token-vault@^0.0.2":
version "0.0.2"
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"
"@solana/spl-token" "^0.1.8"
"@solana/web3.js" "^1.31.0"
"@metaplex/js@^4.4.1":
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" "^1.1.0"
"@metaplex-foundation/mpl-token-vault" "^0.0.2"
"@solana/spl-token" "^0.1.8"
"@solana/web3.js" "^1.30.2"
"@types/bs58" "^4.0.1"
axios "^0.25.0"
bn.js "^5.2.0"
borsh "^0.4.0"
bs58 "^4.0.1"
buffer "^6.0.3"
crypto-hash "^1.3.0"
form-data "^4.0.0"
"@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/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/hashes@1.3.2", "@noble/hashes@^1.3.1":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39"
integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==
"@noble/hashes@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183"
@ -119,6 +215,27 @@
rpc-websockets "^7.5.0"
superstruct "^0.14.2"
"@solana/web3.js@^1.30.2", "@solana/web3.js@^1.31.0":
version "1.87.1"
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.87.1.tgz#da376cebbc4cc97ece0cb028d799163ea147f299"
integrity sha512-E8Y9bNlZ8TQlhOvCx1b7jG+TjA4SJLVwufmIk1+tcQctUhK5HiB1Q8ljd4yQDkFlk6OOeAlAeqvW0YntWJU94Q==
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.2.1"
borsh "^0.7.0"
bs58 "^4.0.1"
buffer "6.0.3"
fast-stable-stringify "^1.0.0"
jayson "^4.1.0"
node-fetch "^2.6.12"
rpc-websockets "^7.5.1"
superstruct "^0.14.2"
"@solana/web3.js@^1.68.0":
version "1.70.0"
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.70.0.tgz#14ad207f431861397db85921aad8df4e8374e7c8"
@ -140,6 +257,13 @@
rpc-websockets "^7.5.0"
superstruct "^0.14.2"
"@types/bn.js@^4.11.5":
version "4.11.6"
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c"
integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==
dependencies:
"@types/node" "*"
"@types/bn.js@^5.1.1":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682"
@ -147,6 +271,13 @@
dependencies:
"@types/node" "*"
"@types/bs58@^4.0.1":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/bs58/-/bs58-4.0.2.tgz#2f266fb45d19aab4028a9488e7941aa39a537e9a"
integrity sha512-ytn3FpvB9LRQGxK2vMHD12tgmUhx7TUTbA8A2VbhDVC0eqzgfvoU1rYBOeCl7hJDtTMaOg/Sl9xIOQhkY0G4uw==
dependencies:
base-x "^3.0.6"
"@types/chai@^4.3.0":
version "4.3.0"
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc"
@ -228,6 +359,13 @@ JSONStream@^1.3.5:
jsonparse "^1.2.0"
through ">=2.2.7 <3"
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"
ansi-colors@4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
@ -268,12 +406,24 @@ assertion-error@^1.1.0:
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
axios@^0.25.0:
version "0.25.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a"
integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==
dependencies:
follow-redirects "^1.14.7"
balanced-match@^1.0.0:
version "1.0.2"
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.2, base-x@^3.0.6:
version "3.0.9"
resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320"
integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==
@ -309,11 +459,21 @@ bn.js@^5.0.0, bn.js@^5.1.0, bn.js@^5.1.2:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
bn.js@^5.2.0:
bn.js@^5.2.0, 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==
borsh@^0.4.0:
version "0.4.0"
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"
bn.js "^5.0.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"
@ -375,7 +535,7 @@ buffer@6.0.1:
base64-js "^1.3.1"
ieee754 "^1.2.1"
buffer@6.0.3, buffer@~6.0.3:
buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
@ -461,6 +621,13 @@ color-name@~1.1.4:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
commander@^2.20.3:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@ -507,6 +674,11 @@ delay@^5.0.0:
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.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
diff@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
@ -604,6 +776,20 @@ flat@^5.0.2:
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
follow-redirects@^1.14.7:
version "1.15.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==
form-data@^4.0.0:
version "4.0.0"
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"
combined-stream "^1.0.8"
mime-types "^2.1.12"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@ -658,6 +844,13 @@ he@1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
humanize-ms@^1.2.1:
version "1.2.1"
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"
ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
@ -746,6 +939,24 @@ jayson@^3.4.4:
uuid "^3.4.0"
ws "^7.4.5"
jayson@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.0.tgz#60dc946a85197317f2b1439d672a8b0a99cea2f9"
integrity sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==
dependencies:
"@types/connect" "^3.4.33"
"@types/node" "^12.12.54"
"@types/ws" "^7.4.4"
JSONStream "^1.3.5"
commander "^2.20.3"
delay "^5.0.0"
es6-promisify "^5.0.0"
eyes "^0.1.8"
isomorphic-ws "^4.0.1"
json-stringify-safe "^5.0.1"
uuid "^8.3.2"
ws "^7.4.5"
js-sha256@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966"
@ -812,6 +1023,18 @@ make-error@^1.1.1:
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
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.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"
minimatch@4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4"
@ -907,7 +1130,7 @@ ms@2.1.2:
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.1.3, ms@^2.0.0:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@ -937,6 +1160,13 @@ node-fetch@2:
dependencies:
whatwg-url "^5.0.0"
node-fetch@^2.6.12:
version "2.7.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
dependencies:
whatwg-url "^5.0.0"
node-gyp-build@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
@ -1017,6 +1247,11 @@ regenerator-runtime@^0.13.4:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
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==
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@ -1035,6 +1270,19 @@ rpc-websockets@^7.5.0:
bufferutil "^4.0.1"
utf-8-validate "^5.0.2"
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"
uuid "^8.3.2"
ws "^8.5.0"
optionalDependencies:
bufferutil "^4.0.1"
utf-8-validate "^5.0.2"
safe-buffer@^5.0.1, safe-buffer@^5.1.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"