@project-serum/anchor#web3 TypeScript Examples
The following examples show how to use
@project-serum/anchor#web3.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utilities.spec.ts From jet-engine with GNU Affero General Public License v3.0 | 7 votes |
describe("TokenAmount", () => {
let t: TokenAmount
test("properly instantiates", () => {
t = new TokenAmount(new BN(10), 6, web3.PublicKey.default)
})
test("sets the proper mint address", () => {
expect(t.mint.equals(web3.PublicKey.default)).toBeTruthy()
})
test("sets the correct token amount", () => {
// 6 decimals
expect(t.tokens).toStrictEqual(10 / 1e6)
})
})
Example #2
Source File: accounts.ts From metaplex with Apache License 2.0 | 6 votes |
getMetadata = async (
mint: anchor.web3.PublicKey,
): Promise<anchor.web3.PublicKey> => {
return (
await anchor.web3.PublicKey.findProgramAddress(
[
Buffer.from('metadata'),
TOKEN_METADATA_PROGRAM_ID.toBuffer(),
mint.toBuffer(),
],
TOKEN_METADATA_PROGRAM_ID,
)
)[0];
}
Example #3
Source File: serum.ts From psyoptions with Apache License 2.0 | 6 votes |
async function setupMarket({
provider,
program,
baseMint,
quoteMint,
marketLoader,
optionMarket,
}: {
provider: Provider;
program: Program<PsyAmerican>;
optionMarket: OptionMarketV2;
baseMint: PublicKey;
quoteMint: PublicKey;
marketLoader: MarketLoader;
}): Promise<
[
MarketProxy,
anchor.web3.PublicKey | anchor.BN,
anchor.web3.PublicKey,
number
]
> {
const {
serumMarketKey: marketAPublicKey,
vaultOwner,
marketAuthority,
marketAuthorityBump,
} = await listMarket({
provider,
program,
quoteMint: quoteMint,
dexProgramId: DEX_PID,
feeRateBps: 0,
optionMarket,
});
const MARKET_A_USDC = await marketLoader(marketAPublicKey as PublicKey);
return [MARKET_A_USDC, vaultOwner, marketAuthority, marketAuthorityBump];
}
Example #4
Source File: accounts.ts From metaplex with Apache License 2.0 | 6 votes |
export async function loadCandyProgram(
walletKeyPair: Keypair,
env: string,
customRpcUrl?: string,
) {
if (customRpcUrl) console.log('USING CUSTOM URL', customRpcUrl);
// @ts-ignore
const solConnection = new anchor.web3.Connection(
//@ts-ignore
customRpcUrl || getCluster(env),
);
const walletWrapper = new anchor.Wallet(walletKeyPair);
const provider = new anchor.Provider(solConnection, walletWrapper, {
preflightCommitment: 'recent',
});
const idl = await anchor.Program.fetchIdl(CANDY_MACHINE_PROGRAM_ID, provider);
const program = new anchor.Program(idl, CANDY_MACHINE_PROGRAM_ID, provider);
log.debug('program id from anchor', program.programId.toBase58());
return program;
}
Example #5
Source File: get-metadata.ts From candy-machine-v2 with MIT License | 6 votes |
getMetadata = async (
program: Program<Idl>,
candyMachineId: web3.PublicKey
) => {
const state: any = await program.account.candyMachine.fetch(candyMachineId);
const itemsAvailable = state.data.itemsAvailable.toNumber();
const itemsRedeemed = state.itemsRedeemed.toNumber();
const itemsRemaining = itemsAvailable - itemsRedeemed;
return {
id: candyMachineId,
program,
state: {
itemsAvailable,
itemsRedeemed,
itemsRemaining,
isSoldOut: itemsRemaining === 0,
isActive:
state.data.goLiveDate.toNumber() < new Date().getTime() / 1000 &&
(state.endSettings
? state.endSettings.endSettingType.date
? state.endSettings.number.toNumber() > new Date().getTime() / 1000
: itemsRedeemed < state.endSettings.number.toNumber()
: true),
goLiveDate: state.data.goLiveDate,
treasury: state.wallet,
tokenMint: state.tokenMint,
gatekeeper: state.data.gatekeeper,
endSettings: state.data.endSettings,
whitelistMintSettings: state.data.whitelistMintSettings,
hiddenSettings: state.data.hiddenSettings,
price: state.data.price,
},
};
}
Example #6
Source File: auction-house-cli.ts From metaplex with Apache License 2.0 | 6 votes |
export async function getAuctionHouseFromOpts(
auctionHouse: any,
walletKeyPair: any,
tMintKey: any,
) {
let auctionHouseKey;
if (auctionHouse) {
auctionHouseKey = new web3.PublicKey(auctionHouse);
} else {
log.info(
'No auction house explicitly passed in, assuming you are creator on it and deriving key...',
);
auctionHouseKey = (
await getAuctionHouse(walletKeyPair.publicKey, tMintKey)
)[0];
}
return auctionHouseKey;
}
Example #7
Source File: helpers.ts From candy-machine-v2 with MIT License | 5 votes |
CANDY_MACHINE_PROGRAM = new web3.PublicKey(
"cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ"
)
Example #8
Source File: token-entangler-cli.ts From metaplex with Apache License 2.0 | 5 votes |
programCommand('update_entanglement')
.option(
'-ep, --entangled-pair <string>',
'Optional. Overrides mint arguments.',
)
.option('-na, --new-authority <string>', 'Authority, defaults to keypair')
.option('-p, --price <string>', 'Price for a swap')
.option(
'-pet, --pays-every-time <string>',
'If true, the user must pay the swapping fee each swap',
)
.option(
'-ma, --mint-a <string>',
'Mint a. You do not even need to own this token to create this entanglement.',
)
.option(
'-mb, --mint-b <string>',
'Mint b. This token will be removed from your token account right now.',
)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.action(async (directory, cmd) => {
const {
keypair,
env,
price,
paysEveryTime,
mintA,
mintB,
entangledPair,
newAuthority,
} = cmd.opts();
const walletKeyPair = loadWalletKey(keypair);
const anchorProgram = await loadTokenEntanglementProgream(
walletKeyPair,
env,
);
const epKey = await getEpKeyFromArgs(
anchorProgram,
mintA ? new web3.PublicKey(mintA) : null,
mintB ? new web3.PublicKey(mintB) : null,
entangledPair,
);
const epObj = await anchorProgram.account.entangledPair.fetch(epKey);
//@ts-ignore
const authorityKey = new web3.PublicKey(
newAuthority ? newAuthority : epObj.authority,
);
const priceAdjusted = price
? new BN(
await getPriceWithMantissa(
parseFloat(price),
//@ts-ignore
epObj.treasuryMint,
walletKeyPair,
anchorProgram,
),
)
: //@ts-ignore
epObj.price;
await anchorProgram.rpc.updateEntangledPair(
priceAdjusted,
paysEveryTime == 'true',
{
accounts: {
newAuthority: authorityKey,
//@ts-ignore
authority: epObj.authority,
entangledPair: epKey,
},
},
);
log.info('Updated entanglement', epKey.toBase58());
});
Example #9
Source File: helpers.ts From candy-machine-v2 with MIT License | 5 votes |
TOKEN_METADATA_PROGRAM_ID = new web3.PublicKey(
"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
)
Example #10
Source File: auction-house-cli.ts From metaplex with Apache License 2.0 | 5 votes |
programCommand('show_escrow')
.option('-ah, --auction-house <string>', 'Specific auction house')
.option(
'-w, --wallet <string>',
'Specific wallet owner of escrow. If not present, we use your keypair.',
)
.action(async (directory, cmd) => {
const { keypair, env, auctionHouse, wallet } = cmd.opts();
const otherWallet = wallet ? new web3.PublicKey(wallet) : null;
const walletKeyPair = loadWalletKey(keypair);
const anchorProgram = await loadAuctionHouseProgram(walletKeyPair, env);
const auctionHouseKey = new web3.PublicKey(auctionHouse);
const auctionHouseObj = await anchorProgram.account.auctionHouse.fetch(
auctionHouseKey,
);
if (!otherWallet) {
log.info('No --wallet passed in, defaulting to keypair');
}
const escrow = (
await getAuctionHouseBuyerEscrow(
auctionHouseKey,
otherWallet || walletKeyPair.publicKey,
)
)[0];
const amount = await getTokenAmount(
anchorProgram,
escrow,
//@ts-ignore
auctionHouseObj.treasuryMint,
);
log.info(
otherWallet.toBase58() || walletKeyPair.publicKey.toBase58(),
'Balance:',
amount,
);
});
Example #11
Source File: newOrder.ts From psyoptions with Apache License 2.0 | 4 votes |
describe("cpi_examples newOrder", () => {
const program = anchor.workspace.CpiExamples as Program<CpiExamples>;
const provider = program.provider;
const americanOptionsProgram = anchor.workspace
.PsyAmerican as Program<PsyAmerican>;
const payer = web3.Keypair.fromSecretKey(
Buffer.from(
JSON.parse(
require("fs").readFileSync(process.env.ANCHOR_WALLET, {
encoding: "utf-8",
})
)
)
);
const wallet = payer;
const mintAuthority = anchor.web3.Keypair.generate();
let underlyingToken: Token, usdcToken: Token, optionToken: Token;
// Global PsyOptions variables
let optionMarket: OptionMarketV2;
// Global DEX variables
let marketProxy: MarketProxy,
marketAuthority: anchor.web3.PublicKey,
marketAuthorityBump: number,
usdcMint: anchor.web3.PublicKey,
usdcMintInfo: MintInfo,
referral: anchor.web3.PublicKey,
openOrders: PublicKey,
openOrdersBump: number,
vault: anchor.web3.PublicKey,
vaultBumpSeed: number,
vaultAuthority: anchor.web3.PublicKey,
vaultAuthBump: number;
before(async () => {
// Setup - Create an OptionMarket
const {
optionMarket: newOptionMarket,
remainingAccounts,
instructions,
} = await initSetup(
provider,
wallet,
mintAuthority,
americanOptionsProgram
);
optionMarket = newOptionMarket;
await initOptionMarket(
americanOptionsProgram,
wallet,
optionMarket,
remainingAccounts,
instructions
);
[usdcMint] = await createMintAndVault(
provider,
new anchor.BN("1000000000000000000"),
undefined,
6
);
// Initialize a permissioned Serum Market
({ marketAuthority, marketAuthorityBump } = await getMarketAndAuthorityInfo(
americanOptionsProgram,
optionMarket,
DEX_PID,
usdcMint
));
// Setup - Create a Serum market for the OptionMarket's option tokens
({ marketA: marketProxy } = await initMarket(
provider,
americanOptionsProgram,
marketLoader(provider, program, optionMarket.key, marketAuthorityBump),
optionMarket,
usdcMint
));
// Set the token variables for use in later tests
underlyingToken = new Token(
provider.connection,
optionMarket.underlyingAssetMint,
TOKEN_PROGRAM_ID,
wallet
);
optionToken = new Token(
provider.connection,
optionMarket.optionMint,
TOKEN_PROGRAM_ID,
wallet
);
usdcToken = new Token(
provider.connection,
usdcMint,
TOKEN_PROGRAM_ID,
wallet
);
referral = await usdcToken.createAssociatedTokenAccount(FEE_OWNER_KEY);
});
describe("cpi_examples initNewOrderVault", () => {
it("should create a USDC vault owned by the program", async () => {
// Generate a PDA for the USDC vault
[vault, vaultBumpSeed] = await anchor.web3.PublicKey.findProgramAddress(
[usdcToken.publicKey.toBuffer(), textEncoder.encode("vault")],
program.programId
);
[vaultAuthority, vaultAuthBump] =
await anchor.web3.PublicKey.findProgramAddress(
[vault.toBuffer(), textEncoder.encode("vaultAuthority")],
program.programId
);
try {
await program.rpc.initNewOrderVault({
accounts: {
authority: wallet.publicKey,
usdcMint: usdcMint,
vault,
vaultAuthority,
tokenProgram: TOKEN_PROGRAM_ID,
rent: SYSVAR_RENT_PUBKEY,
systemProgram: SystemProgram.programId,
},
});
} catch (err) {
console.log((err as Error).toString());
throw err;
}
// validate that the vault was initialized and owned by the program
const vaultAcct = await usdcToken.getAccountInfo(vault);
assert.ok(vaultAcct.owner.equals(vaultAuthority));
});
});
describe("place newOrder", () => {
before(async () => {
// Vault is already initialized because these tests run sequentially
// transfer USDC to that vault so it can place an order
usdcMintInfo = await usdcToken.getMintInfo();
await usdcToken.mintTo(
vault,
wallet.publicKey,
[],
new u64(10_000_000 * usdcMintInfo.decimals)
);
// Get the open orders account that needs to be optionally created
[openOrders, openOrdersBump] = await PublicKey.findProgramAddress(
[
openOrdersSeed,
marketProxy.dexProgramId.toBuffer(),
marketProxy.market.address.toBuffer(),
// NOTE: For other developers, this should be changed to be the User or Vault that has the authority over the account.
vaultAuthority.toBuffer(),
],
americanOptionsProgram.programId
);
});
it("should create an open orders account and place an order on the Serum market", async () => {
// test the vault contains USDC
const vaultAcct = await usdcToken.getAccountInfo(vault);
assert.equal(
vaultAcct.amount.toString(),
new u64(10_000_000 * usdcMintInfo.decimals).toString()
);
// test the order book is blank
let bids = await marketProxy.market.loadBids(provider.connection);
let l2 = await bids.getL2(3);
assert.equal(l2.length, 0);
const price = 1;
const size = 22;
// Run placeOrder instruction for vault
try {
await program.rpc.placeOrder(
vaultAuthBump,
openOrdersBump,
marketAuthorityBump,
Side.Bid, // Side
marketProxy.market.priceNumberToLots(price), // liimit_price
marketProxy.market.baseSizeNumberToLots(size), // max_coin_qty
OrderType.PostOnly, // order_type
new anchor.BN(999), // client_order_id
SelfTradeBehavior.AbortTransaction, // self_trade_behavior
new anchor.BN(65535), // limit - no idea what this is
new anchor.BN(
// @ts-ignore: serum
marketProxy.market._decoded.quoteLotSize.toNumber()
).mul(
marketProxy.market
.baseSizeNumberToLots(size)
.mul(marketProxy.market.priceNumberToLots(price))
), // max_native_pc_qty_including_fees - no idea what exactly this is
{
accounts: {
userAuthority: wallet.publicKey,
psyAmericanProgram: americanOptionsProgram.programId,
dexProgram: DEX_PID,
openOrders,
market: marketProxy.market.address,
psyMarketAuthority: marketAuthority,
vault,
vaultAuthority,
// @ts-ignore: Dumb serum stuff
requestQueue: marketProxy.market._decoded.requestQueue,
// @ts-ignore: Dumb serum stuff
eventQueue: marketProxy.market._decoded.eventQueue,
marketBids: marketProxy.market.bidsAddress,
marketAsks: marketProxy.market.asksAddress,
// @ts-ignore: Dumb serum stuff
coinVault: marketProxy.market._decoded.baseVault,
// @ts-ignore: Dumb serum stuff
pcVault: marketProxy.market._decoded.quoteVault,
systemProgram: SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
rent: SYSVAR_RENT_PUBKEY,
},
}
);
} catch (err) {
console.log("*** error", (err as Error).toString());
throw err;
}
// Test that a new open orders account was created
const openOrdersAcct = await OpenOrders.load(
provider.connection,
openOrders,
DEX_PID
);
assert.ok(openOrdersAcct.owner.equals(openOrders));
// test that the order book contains the new order.
bids = await marketProxy.market.loadBids(provider.connection);
l2 = await bids.getL2(3);
assert.equal(l2.length, 1);
assert.equal(l2[0][0], price);
assert.equal(l2[0][1], size);
});
describe("Open orders account exists", () => {
it("should place the order without fail", async () => {
// Test that the open orders account already exists
const openOrdersAcct = await OpenOrders.load(
provider.connection,
openOrders,
DEX_PID
);
assert.ok(openOrdersAcct.owner.equals(openOrders));
// test that the order book contains the new order.
let bids = await marketProxy.market.loadBids(provider.connection);
let l2 = await bids.getL2(3);
assert.equal(l2.length, 1);
const price = 2;
const size = 1;
// Run placeOrder instruction for vault
try {
await program.rpc.placeOrder(
vaultAuthBump,
openOrdersBump,
marketAuthorityBump,
Side.Bid, // Side
marketProxy.market.priceNumberToLots(price), // liimit_price
marketProxy.market.baseSizeNumberToLots(size), // max_coin_qty
OrderType.PostOnly, // order_type
new anchor.BN(998), // client_order_id
SelfTradeBehavior.AbortTransaction, // self_trade_behavior
new anchor.BN(65535), // limit
new anchor.BN(
// @ts-ignore: serum
marketProxy.market._decoded.quoteLotSize.toNumber()
).mul(
marketProxy.market
.baseSizeNumberToLots(size)
.mul(marketProxy.market.priceNumberToLots(price))
), // max_native_pc_qty_including_fees
{
accounts: {
userAuthority: wallet.publicKey,
psyAmericanProgram: americanOptionsProgram.programId,
dexProgram: DEX_PID,
openOrders,
market: marketProxy.market.address,
psyMarketAuthority: marketAuthority,
vault,
vaultAuthority,
// @ts-ignore: Dumb serum stuff
requestQueue: marketProxy.market._decoded.requestQueue,
// @ts-ignore: Dumb serum stuff
eventQueue: marketProxy.market._decoded.eventQueue,
marketBids: marketProxy.market.bidsAddress,
marketAsks: marketProxy.market.asksAddress,
// @ts-ignore: Dumb serum stuff
coinVault: marketProxy.market._decoded.baseVault,
// @ts-ignore: Dumb serum stuff
pcVault: marketProxy.market._decoded.quoteVault,
systemProgram: SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
rent: SYSVAR_RENT_PUBKEY,
},
}
);
} catch (err) {
console.log("*** error", (err as Error).toString());
throw err;
}
bids = await marketProxy.market.loadBids(provider.connection);
l2 = await bids.getL2(3);
assert.equal(l2.length, 2);
});
});
});
});
Example #12
Source File: auction-house-cli.ts From metaplex with Apache License 2.0 | 4 votes |
programCommand('execute_sale')
.option('-ah, --auction-house <string>', 'Specific auction house')
.option(
'-ak, --auction-house-keypair <string>',
'If this auction house requires sign off, pass in keypair for it',
)
.option(
'-aks, --auction-house-signs',
'If you want to simulate the auction house executing the sale without another signer',
)
.option('-b, --buy-price <string>', 'Price you wish to sell for')
.option('-m, --mint <string>', 'Mint of the token to purchase')
.option('-t, --token-size <string>', 'Amount of tokens you want to sell')
.option('-bw, --buyer-wallet <string>', 'Buyer wallet')
.option('-sw, --seller-wallet <string>', 'Buyer wallet')
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.action(async (directory, cmd) => {
const {
keypair,
env,
auctionHouse,
auctionHouseKeypair,
buyPrice,
mint,
tokenSize,
auctionHouseSigns,
buyerWallet,
sellerWallet,
} = cmd.opts();
const auctionHouseKey = new web3.PublicKey(auctionHouse);
const walletKeyPair = loadWalletKey(keypair);
const mintKey = new web3.PublicKey(mint);
const auctionHouseKeypairLoaded = auctionHouseKeypair
? loadWalletKey(auctionHouseKeypair)
: null;
const anchorProgram = await loadAuctionHouseProgram(
auctionHouseSigns ? auctionHouseKeypairLoaded : walletKeyPair,
env,
);
const auctionHouseObj = await anchorProgram.account.auctionHouse.fetch(
auctionHouseKey,
);
const buyerWalletKey = new web3.PublicKey(buyerWallet);
const sellerWalletKey = new web3.PublicKey(sellerWallet);
//@ts-ignore
const isNative = auctionHouseObj.treasuryMint.equals(WRAPPED_SOL_MINT);
const buyPriceAdjusted = new BN(
await getPriceWithMantissa(
buyPrice,
//@ts-ignore
auctionHouseObj.treasuryMint,
walletKeyPair,
anchorProgram,
),
);
const tokenSizeAdjusted = new BN(
await getPriceWithMantissa(
tokenSize,
mintKey,
walletKeyPair,
anchorProgram,
),
);
const tokenAccountKey = (await getAtaForMint(mintKey, sellerWalletKey))[0];
const buyerTradeState = (
await getAuctionHouseTradeState(
auctionHouseKey,
buyerWalletKey,
tokenAccountKey,
//@ts-ignore
auctionHouseObj.treasuryMint,
mintKey,
tokenSizeAdjusted,
buyPriceAdjusted,
)
)[0];
const sellerTradeState = (
await getAuctionHouseTradeState(
auctionHouseKey,
sellerWalletKey,
tokenAccountKey,
//@ts-ignore
auctionHouseObj.treasuryMint,
mintKey,
tokenSizeAdjusted,
buyPriceAdjusted,
)
)[0];
const [freeTradeState, freeTradeStateBump] =
await getAuctionHouseTradeState(
auctionHouseKey,
sellerWalletKey,
tokenAccountKey,
//@ts-ignore
auctionHouseObj.treasuryMint,
mintKey,
tokenSizeAdjusted,
new BN(0),
);
const [escrowPaymentAccount, bump] = await getAuctionHouseBuyerEscrow(
auctionHouseKey,
buyerWalletKey,
);
const [programAsSigner, programAsSignerBump] =
await getAuctionHouseProgramAsSigner();
const metadata = await getMetadata(mintKey);
const metadataObj = await anchorProgram.provider.connection.getAccountInfo(
metadata,
);
const metadataDecoded: Metadata = decodeMetadata(
Buffer.from(metadataObj.data),
);
const remainingAccounts = [];
for (let i = 0; i < metadataDecoded.data.creators.length; i++) {
remainingAccounts.push({
pubkey: new web3.PublicKey(metadataDecoded.data.creators[i].address),
isWritable: true,
isSigner: false,
});
if (!isNative) {
remainingAccounts.push({
pubkey: (
await getAtaForMint(
//@ts-ignore
auctionHouseObj.treasuryMint,
remainingAccounts[remainingAccounts.length - 1].pubkey,
)
)[0],
isWritable: true,
isSigner: false,
});
}
}
const signers = [];
//@ts-ignore
const tMint: web3.PublicKey = auctionHouseObj.treasuryMint;
const instruction = await anchorProgram.instruction.executeSale(
bump,
freeTradeStateBump,
programAsSignerBump,
buyPriceAdjusted,
tokenSizeAdjusted,
{
accounts: {
buyer: buyerWalletKey,
seller: sellerWalletKey,
metadata,
tokenAccount: tokenAccountKey,
tokenMint: mintKey,
escrowPaymentAccount,
treasuryMint: tMint,
sellerPaymentReceiptAccount: isNative
? sellerWalletKey
: (
await getAtaForMint(tMint, sellerWalletKey)
)[0],
buyerReceiptTokenAccount: (
await getAtaForMint(mintKey, buyerWalletKey)
)[0],
//@ts-ignore
authority: auctionHouseObj.authority,
auctionHouse: auctionHouseKey,
//@ts-ignore
auctionHouseFeeAccount: auctionHouseObj.auctionHouseFeeAccount,
//@ts-ignore
auctionHouseTreasury: auctionHouseObj.auctionHouseTreasury,
sellerTradeState,
buyerTradeState,
tokenProgram: TOKEN_PROGRAM_ID,
systemProgram: web3.SystemProgram.programId,
ataProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
programAsSigner,
rent: web3.SYSVAR_RENT_PUBKEY,
freeTradeState,
},
remainingAccounts,
signers,
},
);
if (auctionHouseKeypairLoaded) {
signers.push(auctionHouseKeypairLoaded);
instruction.keys
.filter(k => k.pubkey.equals(auctionHouseKeypairLoaded.publicKey))
.map(k => (k.isSigner = true));
}
if (!auctionHouseSigns) {
instruction.keys
.filter(k => k.pubkey.equals(walletKeyPair.publicKey))
.map(k => (k.isSigner = true));
}
await sendTransactionWithRetryWithKeypair(
anchorProgram.provider.connection,
auctionHouseSigns ? auctionHouseKeypairLoaded : walletKeyPair,
[instruction],
signers,
'max',
);
log.info(
'Accepted',
tokenSize,
mint,
'sale from wallet',
sellerWalletKey.toBase58(),
'to',
buyerWalletKey.toBase58(),
'for',
buyPrice,
'from your account with Auction House',
auctionHouse,
);
});
Example #13
Source File: famine.spec.ts From quarry with GNU Affero General Public License v3.0 | 4 votes |
describe("Famine", () => {
let sdk: QuarrySDK;
let provider: Provider;
let mintWrapper: MintWrapper;
let mine: MineWrapper;
before("Initialize SDK", () => {
sdk = makeSDK();
provider = sdk.provider;
mintWrapper = sdk.mintWrapper;
mine = sdk.mine;
});
const stakeAmount = 1_000_000000;
let stakedMintAuthority: web3.Keypair;
let stakeTokenMint: web3.PublicKey;
let stakeToken: Token;
let rewardsMint: web3.PublicKey;
let token: Token;
let mintWrapperKey: web3.PublicKey;
let hardCap: TokenAmount;
beforeEach("Initialize rewards and stake mint", async () => {
await doesNotReject(async () => {
stakedMintAuthority = web3.Keypair.generate();
stakeTokenMint = await createMint(
provider,
stakedMintAuthority.publicKey,
DEFAULT_DECIMALS
);
});
stakeToken = Token.fromMint(stakeTokenMint, DEFAULT_DECIMALS, {
name: "stake token",
});
const rewardsMintKP = web3.Keypair.generate();
rewardsMint = rewardsMintKP.publicKey;
token = Token.fromMint(rewardsMint, DEFAULT_DECIMALS);
hardCap = TokenAmount.parse(token, DEFAULT_HARD_CAP.toString());
const { tx, mintWrapper: wrapperKey } = await mintWrapper.newWrapper({
hardcap: hardCap.toU64(),
tokenMint: rewardsMint,
});
await expectTX(
await createInitMintInstructions({
provider,
mintKP: rewardsMintKP,
decimals: DEFAULT_DECIMALS,
mintAuthority: wrapperKey,
freezeAuthority: wrapperKey,
})
).to.be.fulfilled;
mintWrapperKey = wrapperKey;
await expectTX(tx, "Initialize mint").to.be.fulfilled;
});
let rewarderWrapper: RewarderWrapper;
const dailyRewardsRate = new BN(1_000_000 * DEFAULT_DECIMALS);
const annualRewardsRate = dailyRewardsRate.mul(new BN(365));
beforeEach("Set up rewarder and minter", async () => {
const { tx, key: rewarder } = await mine.createRewarder({
mintWrapper: mintWrapperKey,
authority: provider.wallet.publicKey,
});
await expectTX(tx, "Create new rewarder").to.be.fulfilled;
rewarderWrapper = await mine.loadRewarderWrapper(rewarder);
// Set annual rewards rate
await expectTX(
rewarderWrapper.setAnnualRewards({
newAnnualRate: annualRewardsRate,
}),
"Set annual rewards rate"
).to.be.fulfilled;
// whitelist rewarder
await expectTX(
mintWrapper.newMinterWithAllowance(
mintWrapperKey,
rewarder,
new u64(100_000_000_000000)
),
"Minter add"
).to.be.fulfilled;
});
let quarryWrapper: QuarryWrapper;
beforeEach("Set up quarry and miner", async () => {
const { quarry, tx: tx1 } = await rewarderWrapper.createQuarry({
token: stakeToken,
});
await expectTX(tx1, "Create new quarry").to.be.fulfilled;
quarryWrapper = await QuarryWrapper.load({
sdk,
token: stakeToken,
key: quarry,
});
// mint test tokens
await newUserStakeTokenAccount(
sdk,
quarryWrapper,
stakeToken,
stakedMintAuthority,
stakeAmount
);
await expectTX(
quarryWrapper.setRewardsShare(new u64(100)),
"Set rewards share"
).to.be.fulfilled;
const { tx: tx2 } = await quarryWrapper.createMiner();
await expectTX(tx2, "Create new miner").to.be.fulfilled;
});
it("Stake and claim after famine", async () => {
const famine = new BN(Date.now() / 1000 - 5); // Rewards stopped 5 seconds ago
await expectTX(quarryWrapper.setFamine(famine), "Set famine").to.be
.fulfilled;
const minerActions = await quarryWrapper.getMinerActions(
provider.wallet.publicKey
);
await expectTX(
minerActions.stake(new TokenAmount(stakeToken, stakeAmount)),
"Stake into the quarry"
).to.be.fulfilled;
// Sleep for 5 seconds
await sleep(5000);
const tx = await minerActions.claim();
await expectTX(tx, "Claim from the quarry").to.be.fulfilled;
const rewardsTokenAccount = await getATAAddress({
mint: rewardsMint,
owner: provider.wallet.publicKey,
});
const rewardsTokenAccountInfo = await getTokenAccount(
provider,
rewardsTokenAccount
);
expect(rewardsTokenAccountInfo.amount.toString()).to.equal(ZERO.toString());
});
it("Stake before famine and claim after famine", async () => {
const minerActions = await quarryWrapper.getMinerActions(
provider.wallet.publicKey
);
const rewardsDuration = 5; // 5 seconds
const famine = new BN(Date.now() / 1_000 + rewardsDuration);
await expectTX(
minerActions
.stake(new TokenAmount(stakeToken, stakeAmount))
.combine(quarryWrapper.setFamine(famine)),
"Set famine then stake tokens"
).to.be.fulfilled;
// Sleep for 8 seconds
await sleep(8_000);
const tx = await minerActions.claim();
const claimSent = await tx.send();
await expectTX(claimSent, "Claim from the quarry").to.be.fulfilled;
const receipt = await claimSent.wait();
receipt.printLogs();
const claimEvent = QUARRY_CODERS.Mine.parseProgramLogEvents(
receipt.response.meta?.logMessages ?? []
).find((ev) => ev.name === "ClaimEvent");
invariant(
claimEvent && claimEvent.name === "ClaimEvent",
"claim event not found"
);
const expectedRewards = dailyRewardsRate
.div(new BN(86400))
.mul(new BN(rewardsDuration))
.add(new BN(2)); // error epsilon
expect(claimEvent.data.amount.toString()).to.be.oneOf([
expectedRewards.toString(),
"416", // XXX: Figure out this flaky case
]);
console.log("Claiming again after 5 seconds ...");
// Sleep for 5 seconds
await sleep(5_000);
const claim2 = await minerActions.claim();
const claim2Sent = await claim2.send();
await expectTX(claim2Sent, "Claim again from the quarry").to.be.fulfilled;
const claim2Receipt = await claim2Sent.wait();
claim2Receipt.printLogs();
const claim2Event = QUARRY_CODERS.Mine.parseProgramLogEvents(
claim2Receipt.response.meta?.logMessages ?? []
)[0];
expect(claim2Event).to.be.undefined; // No claim event
});
});
Example #14
Source File: auction-house-cli.ts From metaplex with Apache License 2.0 | 4 votes |
programCommand('update_auction_house')
.option(
'-tm, --treasury-mint <string>',
'Mint address of treasury used during creation. If not used, default to SOL. Ignored if providing -ah arg',
)
.option(
'-ah, --auction-house <string>',
'Specific auction house(if not provided, we assume you are asking for your own)',
)
.option(
'-a, --new-authority <string>',
'New authority of auction house - defaults to current authority',
)
.option('-f, --force', 'Cannot set authority without this flag being set.')
.option(
'-sfbp, --seller-fee-basis-points <string>',
'Auction house cut of each txn, 10000 = 100%',
)
.option(
'-ccsp, --can-change-sale-price <string>',
'if true, and user initially places item for sale for 0, then AH can make new sell prices without consent(off chain price matching). Should only be used in concert with requires-sign-off, so AH is controlling every txn hitting the system.',
)
.option(
'-rso, --requires-sign-off <string>',
'if true, no txn can occur against this Auction House without AH authority as signer. Good if you are doing all txns through a pass-through GCP or something.',
)
.option(
'-twd, --treasury-withdrawal-destination <string>',
'if you wish to empty the treasury account, this is where it will land, default is your keypair. Pass in a wallet, not an ATA - ATA will be made for you if not present.',
)
.option(
'-fwd, --fee-withdrawal-destination <string>',
'if you wish to empty the fee paying account, this is where it will land, default is your keypair',
)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.action(async (directory, cmd) => {
const {
keypair,
env,
sellerFeeBasisPoints,
canChangeSalePrice,
requiresSignOff,
treasuryWithdrawalDestination,
feeWithdrawalDestination,
treasuryMint,
auctionHouse,
newAuthority,
force,
} = cmd.opts();
const walletKeyPair = loadWalletKey(keypair);
const anchorProgram = await loadAuctionHouseProgram(walletKeyPair, env);
let tMintKey: web3.PublicKey;
if (!treasuryMint) {
log.info('No treasury mint detected, using SOL.');
tMintKey = WRAPPED_SOL_MINT;
} else {
tMintKey = new web3.PublicKey(treasuryMint);
}
const auctionHouseKey = await getAuctionHouseFromOpts(
auctionHouse,
walletKeyPair,
tMintKey,
);
const auctionHouseObj = await anchorProgram.account.auctionHouse.fetch(
auctionHouseKey,
);
//@ts-ignore
tMintKey = auctionHouseObj.treasuryMint;
let twdKey: web3.PublicKey, fwdKey: web3.PublicKey;
if (!treasuryWithdrawalDestination) {
log.info('No treasury withdrawal dest detected, using original value');
twdKey = tMintKey.equals(WRAPPED_SOL_MINT)
? //@ts-ignore
auctionHouseObj.treasuryWithdrawalDestination
: deserializeAccount(
Buffer.from(
(
await anchorProgram.provider.connection.getAccountInfo(
//@ts-ignore
auctionHouseObj.treasuryWithdrawalDestination,
)
).data,
),
).owner;
} else {
twdKey = new web3.PublicKey(treasuryWithdrawalDestination);
}
if (!feeWithdrawalDestination) {
log.info('No fee withdrawal dest detected, using original value');
//@ts-ignore
fwdKey = auctionHouseObj.feeWithdrawalDestination;
} else {
fwdKey = new web3.PublicKey(feeWithdrawalDestination);
}
const twdAta = tMintKey.equals(WRAPPED_SOL_MINT)
? twdKey
: (await getAtaForMint(tMintKey, twdKey))[0];
let sfbp;
if (sellerFeeBasisPoints != undefined && sellerFeeBasisPoints != null) {
sfbp = parseInt(sellerFeeBasisPoints);
} else {
log.info('No sfbp passed in, using original value');
//@ts-ignore
sfbp = auctionHouseObj.sellerFeeBasisPoints;
}
let newAuth;
if (newAuthority != undefined && newAuthority != null) {
if (!force) {
throw Error(
'Cannot change authority without additional force flag. Are you sure you want to do this?',
);
}
newAuth = newAuthority;
} else {
log.info('No authority passed in, using original value');
//@ts-ignore
newAuth = auctionHouseObj.authority;
}
let ccsp;
if (canChangeSalePrice != undefined && canChangeSalePrice != null) {
ccsp = canChangeSalePrice == 'true';
} else {
log.info('No can change sale price passed in, using original value');
//@ts-ignore
ccsp = auctionHouseObj.canChangeSalePrice;
}
let rso;
if (requiresSignOff != undefined && requiresSignOff != null) {
rso = requiresSignOff == 'true';
} else {
log.info('No requires sign off passed in, using original value');
//@ts-ignore
rso = auctionHouseObj.requiresSignOff;
}
await anchorProgram.rpc.updateAuctionHouse(sfbp, rso, ccsp, {
accounts: {
treasuryMint: tMintKey,
payer: walletKeyPair.publicKey,
authority: walletKeyPair.publicKey,
// extra safety here even though newAuth should be right
//@ts-ignore
newAuthority: force ? newAuth : auctionHouseObj.authority,
feeWithdrawalDestination: fwdKey,
treasuryWithdrawalDestination: twdAta,
treasuryWithdrawalDestinationOwner: twdKey,
auctionHouse: auctionHouseKey,
//@ts-ignore
auctionHouseFeeAccount: auctionHouseObj.feePayer,
//@ts-ignore
auctionHouseTreasury: auctionHouseObj.treasury,
tokenProgram: TOKEN_PROGRAM_ID,
systemProgram: web3.SystemProgram.programId,
ataProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
rent: web3.SYSVAR_RENT_PUBKEY,
},
});
log.info('Updated auction house', auctionHouseKey.toBase58());
});