mirror of https://github.com/certusone/oyster.git
Finish auction actions out
This commit is contained in:
parent
87bb0870c6
commit
41b7393d00
|
@ -0,0 +1,538 @@
|
||||||
|
import {
|
||||||
|
PublicKey,
|
||||||
|
SystemProgram,
|
||||||
|
SYSVAR_CLOCK_PUBKEY,
|
||||||
|
SYSVAR_RENT_PUBKEY,
|
||||||
|
TransactionInstruction,
|
||||||
|
} from '@solana/web3.js';
|
||||||
|
import { programIds } from '../utils/ids';
|
||||||
|
import { deserializeBorsh } from './../utils/borsh';
|
||||||
|
import { serialize } from 'borsh';
|
||||||
|
import BN from 'bn.js';
|
||||||
|
|
||||||
|
export const AUCTION_PREFIX = 'auction';
|
||||||
|
|
||||||
|
export enum AuctionState {
|
||||||
|
Created = 0,
|
||||||
|
Started,
|
||||||
|
Ended,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum BidStateType {
|
||||||
|
EnglishAuction = 0,
|
||||||
|
OpenEdition = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Bid {
|
||||||
|
key: PublicKey;
|
||||||
|
amount: BN;
|
||||||
|
constructor(args: { key: PublicKey; amount: BN }) {
|
||||||
|
this.key = args.key;
|
||||||
|
this.amount = args.amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BidState {
|
||||||
|
type: BidStateType;
|
||||||
|
bids?: Bid[];
|
||||||
|
max?: BN;
|
||||||
|
|
||||||
|
constructor(args: { type: BidStateType; bids?: Bid[]; max?: BN }) {
|
||||||
|
this.type = args.type;
|
||||||
|
this.bids = args.bids;
|
||||||
|
this.max = args.max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BASE_AUCTION_DATA_SIZE = 32 + 32 + 32 + 8 + 8 + 1 + 9 + 9 + 9 + 9;
|
||||||
|
|
||||||
|
export class AuctionData {
|
||||||
|
/// Pubkey of the authority with permission to modify this auction.
|
||||||
|
authority: PublicKey;
|
||||||
|
/// Pubkey of the resource being bid on.
|
||||||
|
resource: PublicKey;
|
||||||
|
/// Token mint for the SPL token being used to bid
|
||||||
|
tokenMint: PublicKey;
|
||||||
|
/// The state the auction is in, whether it has started or ended.
|
||||||
|
state: AuctionState;
|
||||||
|
/// Auction Bids, each user may have one bid open at a time.
|
||||||
|
bidState: BidState;
|
||||||
|
/// The time the last bid was placed, used to keep track of auction timing.
|
||||||
|
lastBid?: BN;
|
||||||
|
/// Slot time the auction was officially ended by.
|
||||||
|
endedAt?: BN;
|
||||||
|
/// End time is the cut-off point that the auction is forced to end by.
|
||||||
|
endAuctionAt?: BN;
|
||||||
|
/// Gap time is the amount of time in slots after the previous bid at which the auction ends.
|
||||||
|
endAuctionGap?: BN;
|
||||||
|
|
||||||
|
constructor(args: {
|
||||||
|
authority: PublicKey;
|
||||||
|
resource: PublicKey;
|
||||||
|
tokenMint: PublicKey;
|
||||||
|
state: AuctionState;
|
||||||
|
bidState: BidState;
|
||||||
|
lastBid?: BN;
|
||||||
|
endedAt?: BN;
|
||||||
|
endAuctionAt?: BN;
|
||||||
|
endAuctionGap?: BN;
|
||||||
|
}) {
|
||||||
|
this.authority = args.authority;
|
||||||
|
this.resource = args.resource;
|
||||||
|
this.tokenMint = args.tokenMint;
|
||||||
|
this.state = args.state;
|
||||||
|
this.bidState = args.bidState;
|
||||||
|
this.lastBid = args.lastBid;
|
||||||
|
this.endedAt = args.endedAt;
|
||||||
|
this.endAuctionAt = args.endAuctionAt;
|
||||||
|
this.endAuctionGap = args.endAuctionGap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BidderMetadata {
|
||||||
|
// Relationship with the bidder who's metadata this covers.
|
||||||
|
bidderPubkey: PublicKey;
|
||||||
|
// Relationship with the auction this bid was placed on.
|
||||||
|
auctionPubkey: PublicKey;
|
||||||
|
// Amount that the user bid.
|
||||||
|
lastBid: BN;
|
||||||
|
// Tracks the last time this user bid.
|
||||||
|
lastBidTimestamp: BN;
|
||||||
|
// Whether the last bid the user made was cancelled. This should also be enough to know if the
|
||||||
|
// user is a winner, as if cancelled it implies previous bids were also cancelled.
|
||||||
|
cancelled: boolean;
|
||||||
|
constructor(args: {
|
||||||
|
bidderPubkey: PublicKey;
|
||||||
|
auctionPubkey: PublicKey;
|
||||||
|
lastBid: BN;
|
||||||
|
lastBidTimestamp: BN;
|
||||||
|
cancelled: boolean;
|
||||||
|
}) {
|
||||||
|
this.bidderPubkey = args.bidderPubkey;
|
||||||
|
this.auctionPubkey = args.auctionPubkey;
|
||||||
|
this.lastBid = args.lastBid;
|
||||||
|
this.lastBidTimestamp = args.lastBidTimestamp;
|
||||||
|
this.cancelled = args.cancelled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BidderPot {
|
||||||
|
/// Points at actual pot that is a token account
|
||||||
|
bidderPot: PublicKey;
|
||||||
|
constructor(args: { bidderPot: PublicKey }) {
|
||||||
|
this.bidderPot = args.bidderPot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum WinnerLimitType {
|
||||||
|
Unlimited = 0,
|
||||||
|
Capped = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class WinnerLimit {
|
||||||
|
type: WinnerLimitType;
|
||||||
|
usize?: BN;
|
||||||
|
constructor(args: { type: WinnerLimitType; usize?: BN }) {
|
||||||
|
this.type = args.type;
|
||||||
|
this.usize = args.usize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CreateAuctionArgs {
|
||||||
|
instruction: number = 0;
|
||||||
|
/// How many winners are allowed for this auction. See AuctionData.
|
||||||
|
winners: WinnerLimit;
|
||||||
|
/// The resource being auctioned. See AuctionData.
|
||||||
|
resource: PublicKey;
|
||||||
|
/// End time is the cut-off point that the auction is forced to end by. See AuctionData.
|
||||||
|
endAuctionAt?: BN;
|
||||||
|
/// Gap time is how much time after the previous bid where the auction ends. See AuctionData.
|
||||||
|
endAuctionGap?: BN;
|
||||||
|
/// Token mint for the SPL token used for bidding.
|
||||||
|
tokenMint: PublicKey;
|
||||||
|
/// Authority
|
||||||
|
authority: PublicKey;
|
||||||
|
|
||||||
|
constructor(args: {
|
||||||
|
winners: WinnerLimit;
|
||||||
|
resource: PublicKey;
|
||||||
|
endAuctionAt?: BN;
|
||||||
|
endAuctionGap?: BN;
|
||||||
|
tokenMint: PublicKey;
|
||||||
|
authority: PublicKey;
|
||||||
|
}) {
|
||||||
|
this.winners = args.winners;
|
||||||
|
this.resource = args.resource;
|
||||||
|
this.endAuctionAt = args.endAuctionAt;
|
||||||
|
this.endAuctionGap = args.endAuctionGap;
|
||||||
|
this.tokenMint = args.tokenMint;
|
||||||
|
this.authority = args.authority;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StartAuctionArgs {
|
||||||
|
instruction: number = 1;
|
||||||
|
resource: PublicKey;
|
||||||
|
|
||||||
|
constructor(args: { resource: PublicKey }) {
|
||||||
|
this.resource = args.resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PlaceBidArgs {
|
||||||
|
instruction: number = 2;
|
||||||
|
resource: PublicKey;
|
||||||
|
amount: BN;
|
||||||
|
|
||||||
|
constructor(args: { resource: PublicKey; amount: BN }) {
|
||||||
|
this.resource = args.resource;
|
||||||
|
this.amount = args.amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AUCTION_SCHEMA = new Map<any, any>([
|
||||||
|
[
|
||||||
|
CreateAuctionArgs,
|
||||||
|
{
|
||||||
|
kind: 'struct',
|
||||||
|
fields: [
|
||||||
|
['instruction', 'u8'],
|
||||||
|
['winnerLimitType', 'u8'],
|
||||||
|
['usize', { kind: 'option', type: 'u64' }],
|
||||||
|
['resource', 'pubkey'],
|
||||||
|
['endAuctionAt', { kind: 'option', type: 'u64' }],
|
||||||
|
['endAuctionGap', { kind: 'option', type: 'u64' }],
|
||||||
|
['tokenMint', 'pubkey'],
|
||||||
|
['authority', 'pubkey'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
StartAuctionArgs,
|
||||||
|
{
|
||||||
|
kind: 'struct',
|
||||||
|
fields: [
|
||||||
|
['instruction', 'u8'],
|
||||||
|
['resource', 'pubkey'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
PlaceBidArgs,
|
||||||
|
{
|
||||||
|
kind: 'struct',
|
||||||
|
fields: [
|
||||||
|
['instruction', 'u8'],
|
||||||
|
['resource', 'pubkey'],
|
||||||
|
['amount', 'u64'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
AuctionData,
|
||||||
|
{
|
||||||
|
kind: 'struct',
|
||||||
|
fields: [
|
||||||
|
['authority', 'pubkey'],
|
||||||
|
['resource', 'pubkey'],
|
||||||
|
['tokenMint', 'pubkey'],
|
||||||
|
['state', 'u8'],
|
||||||
|
['bidState', 'BidState'],
|
||||||
|
['lastBid', { kind: 'option', type: 'u64' }],
|
||||||
|
['endedAt', { kind: 'option', type: 'u64' }],
|
||||||
|
['endAuctionAt', { kind: 'option', type: 'u64' }],
|
||||||
|
['endAuctionGap', { kind: 'option', type: 'u64' }],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
BidState,
|
||||||
|
{
|
||||||
|
kind: 'struct',
|
||||||
|
fields: [
|
||||||
|
['type', 'u8'],
|
||||||
|
['bids', { kind: 'option', type: { kind: 'vec', type: 'Bid' } }],
|
||||||
|
['max', { kind: 'option', type: 'u64' }],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Bid,
|
||||||
|
{
|
||||||
|
kind: 'struct',
|
||||||
|
fields: [
|
||||||
|
['key', 'pubkey'],
|
||||||
|
['amount', 'u64'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
BidderMetadata,
|
||||||
|
{
|
||||||
|
kind: 'struct',
|
||||||
|
fields: [
|
||||||
|
['bidderPubkey', 'pubkey'],
|
||||||
|
['auctionPubkey', 'pubkey'],
|
||||||
|
['lastBid', 'u64'],
|
||||||
|
['lastBidTimestamp', 'u64'],
|
||||||
|
['cancelled', 'u8'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
BidderPot,
|
||||||
|
{
|
||||||
|
kind: 'struct',
|
||||||
|
fields: [['bidderPot', 'pubkey']],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const decodeAuctionData = (buffer: Buffer) => {
|
||||||
|
return deserializeBorsh(AUCTION_SCHEMA, AuctionData, buffer) as AuctionData;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function createAuction(
|
||||||
|
winners: WinnerLimit,
|
||||||
|
resource: PublicKey,
|
||||||
|
endAuctionAt: BN | undefined,
|
||||||
|
endAuctionGap: BN | undefined,
|
||||||
|
tokenMint: PublicKey,
|
||||||
|
authority: PublicKey,
|
||||||
|
creator: PublicKey,
|
||||||
|
instructions: TransactionInstruction[],
|
||||||
|
) {
|
||||||
|
const auctionProgramId = programIds().auction;
|
||||||
|
|
||||||
|
const data = Buffer.from(
|
||||||
|
serialize(
|
||||||
|
AUCTION_SCHEMA,
|
||||||
|
new CreateAuctionArgs({
|
||||||
|
winners,
|
||||||
|
resource,
|
||||||
|
endAuctionAt,
|
||||||
|
endAuctionGap,
|
||||||
|
tokenMint,
|
||||||
|
authority,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const auctionKey: PublicKey = (
|
||||||
|
await PublicKey.findProgramAddress(
|
||||||
|
[
|
||||||
|
Buffer.from(AUCTION_PREFIX),
|
||||||
|
auctionProgramId.toBuffer(),
|
||||||
|
resource.toBuffer(),
|
||||||
|
],
|
||||||
|
auctionProgramId,
|
||||||
|
)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
const keys = [
|
||||||
|
{
|
||||||
|
pubkey: creator,
|
||||||
|
isSigner: true,
|
||||||
|
isWritable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: auctionKey,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: SYSVAR_RENT_PUBKEY,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
instructions.push(
|
||||||
|
new TransactionInstruction({
|
||||||
|
keys,
|
||||||
|
programId: auctionProgramId,
|
||||||
|
data: data,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function startAuction(
|
||||||
|
resource: PublicKey,
|
||||||
|
creator: PublicKey,
|
||||||
|
instructions: TransactionInstruction[],
|
||||||
|
) {
|
||||||
|
const auctionProgramId = programIds().auction;
|
||||||
|
|
||||||
|
const data = Buffer.from(
|
||||||
|
serialize(
|
||||||
|
AUCTION_SCHEMA,
|
||||||
|
new StartAuctionArgs({
|
||||||
|
resource,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const auctionKey: PublicKey = (
|
||||||
|
await PublicKey.findProgramAddress(
|
||||||
|
[
|
||||||
|
Buffer.from(AUCTION_PREFIX),
|
||||||
|
auctionProgramId.toBuffer(),
|
||||||
|
resource.toBuffer(),
|
||||||
|
],
|
||||||
|
auctionProgramId,
|
||||||
|
)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
const keys = [
|
||||||
|
{
|
||||||
|
pubkey: creator,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: auctionKey,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: SYSVAR_CLOCK_PUBKEY,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
instructions.push(
|
||||||
|
new TransactionInstruction({
|
||||||
|
keys,
|
||||||
|
programId: auctionProgramId,
|
||||||
|
data: data,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function placeBid(
|
||||||
|
bidderPubkey: PublicKey,
|
||||||
|
bidderPotTokenPubkey: PublicKey,
|
||||||
|
tokenMintPubkey: PublicKey,
|
||||||
|
transferAuthority: PublicKey,
|
||||||
|
payer: PublicKey,
|
||||||
|
resource: PublicKey,
|
||||||
|
amount: BN,
|
||||||
|
instructions: TransactionInstruction[],
|
||||||
|
) {
|
||||||
|
const auctionProgramId = programIds().auction;
|
||||||
|
|
||||||
|
const data = Buffer.from(
|
||||||
|
serialize(
|
||||||
|
AUCTION_SCHEMA,
|
||||||
|
new PlaceBidArgs({
|
||||||
|
resource,
|
||||||
|
amount,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const auctionKey: PublicKey = (
|
||||||
|
await PublicKey.findProgramAddress(
|
||||||
|
[
|
||||||
|
Buffer.from(AUCTION_PREFIX),
|
||||||
|
auctionProgramId.toBuffer(),
|
||||||
|
resource.toBuffer(),
|
||||||
|
],
|
||||||
|
auctionProgramId,
|
||||||
|
)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
const bidderPotKey: PublicKey = (
|
||||||
|
await PublicKey.findProgramAddress(
|
||||||
|
[
|
||||||
|
Buffer.from(AUCTION_PREFIX),
|
||||||
|
auctionProgramId.toBuffer(),
|
||||||
|
auctionKey.toBuffer(),
|
||||||
|
bidderPubkey.toBuffer(),
|
||||||
|
],
|
||||||
|
auctionProgramId,
|
||||||
|
)
|
||||||
|
)[0];
|
||||||
|
const bidderMetaKey: PublicKey = (
|
||||||
|
await PublicKey.findProgramAddress(
|
||||||
|
[
|
||||||
|
Buffer.from(AUCTION_PREFIX),
|
||||||
|
auctionProgramId.toBuffer(),
|
||||||
|
auctionKey.toBuffer(),
|
||||||
|
bidderPubkey.toBuffer(),
|
||||||
|
Buffer.from('metadata'),
|
||||||
|
],
|
||||||
|
auctionProgramId,
|
||||||
|
)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
const keys = [
|
||||||
|
{
|
||||||
|
pubkey: bidderPubkey,
|
||||||
|
isSigner: true,
|
||||||
|
isWritable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: bidderPotKey,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: bidderPotTokenPubkey,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: bidderMetaKey,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: auctionKey,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
pubkey: tokenMintPubkey,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: transferAuthority,
|
||||||
|
isSigner: true,
|
||||||
|
isWritable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: payer,
|
||||||
|
isSigner: true,
|
||||||
|
isWritable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: SYSVAR_CLOCK_PUBKEY,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: SYSVAR_RENT_PUBKEY,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: SystemProgram.programId,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pubkey: programIds().token,
|
||||||
|
isSigner: false,
|
||||||
|
isWritable: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
instructions.push(
|
||||||
|
new TransactionInstruction({
|
||||||
|
keys,
|
||||||
|
programId: auctionProgramId,
|
||||||
|
data: data,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
export * from './account';
|
export * from './account';
|
||||||
export * from './metadata';
|
export * from './metadata';
|
||||||
export * from './vault';
|
export * from './vault';
|
||||||
|
export * from './auction';
|
||||||
|
|
|
@ -30,6 +30,14 @@ export const VAULT_ID = new PublicKey(
|
||||||
'94wRaYAQdC2gYF76AUTYSugNJ3rAC4EimjAMPwM7uYry',
|
'94wRaYAQdC2gYF76AUTYSugNJ3rAC4EimjAMPwM7uYry',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const AUCTION_ID = new PublicKey(
|
||||||
|
'C9nHkL6BfGx9M9MyYrJqAD5hPsGJd1fHpp1uAJA6vTCn',
|
||||||
|
);
|
||||||
|
|
||||||
|
export const METAPLEX_ID = new PublicKey(
|
||||||
|
'EPtpKdKW8qciGVd1UFyGjgbBHTbSAyvbY61h9uQGVgeu',
|
||||||
|
);
|
||||||
|
|
||||||
export let SYSTEM = new PublicKey('11111111111111111111111111111111');
|
export let SYSTEM = new PublicKey('11111111111111111111111111111111');
|
||||||
|
|
||||||
let WORMHOLE_BRIDGE: {
|
let WORMHOLE_BRIDGE: {
|
||||||
|
@ -171,5 +179,7 @@ export const programIds = () => {
|
||||||
metadata: METADATA_PROGRAM_ID,
|
metadata: METADATA_PROGRAM_ID,
|
||||||
memo: MEMO_ID,
|
memo: MEMO_ID,
|
||||||
vault: VAULT_ID,
|
vault: VAULT_ID,
|
||||||
|
auction: AUCTION_ID,
|
||||||
|
metaplex: METAPLEX_ID,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,27 +4,20 @@ import {
|
||||||
PublicKey,
|
PublicKey,
|
||||||
TransactionInstruction,
|
TransactionInstruction,
|
||||||
} from '@solana/web3.js';
|
} from '@solana/web3.js';
|
||||||
import { contexts, utils, actions, models } from '@oyster/common';
|
import { utils, actions, models } from '@oyster/common';
|
||||||
|
|
||||||
import { AccountLayout } from '@solana/spl-token';
|
import { AccountLayout } from '@solana/spl-token';
|
||||||
import BN from 'bn.js';
|
import BN from 'bn.js';
|
||||||
const {
|
const { createTokenAccount, addTokenToInactiveVault, VAULT_PREFIX } = actions;
|
||||||
createTokenAccount,
|
|
||||||
activateVault,
|
|
||||||
addTokenToInactiveVault,
|
|
||||||
VAULT_PREFIX,
|
|
||||||
} = actions;
|
|
||||||
const { approve } = models;
|
const { approve } = models;
|
||||||
|
|
||||||
const BATCH_SIZE = 4;
|
const BATCH_SIZE = 4;
|
||||||
// This command batches out adding tokens to a vault using a prefilled payer account, and then activates
|
// This command batches out adding tokens to a vault using a prefilled payer account, and then activates and combines
|
||||||
// the vault for use. It issues a series of transaction instructions and signers for the sendTransactions batch.
|
// the vault for use. It issues a series of transaction instructions and signers for the sendTransactions batch.
|
||||||
export async function addTokensToVault(
|
export async function addTokensToVault(
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
wallet: any,
|
wallet: any,
|
||||||
vault: PublicKey,
|
vault: PublicKey,
|
||||||
fractionMint: PublicKey,
|
|
||||||
fractionTreasury: PublicKey,
|
|
||||||
nfts: { tokenAccount: PublicKey; tokenMint: PublicKey; amount: BN }[],
|
nfts: { tokenAccount: PublicKey; tokenMint: PublicKey; amount: BN }[],
|
||||||
): Promise<{
|
): Promise<{
|
||||||
instructions: Array<TransactionInstruction[]>;
|
instructions: Array<TransactionInstruction[]>;
|
||||||
|
@ -50,7 +43,8 @@ export async function addTokensToVault(
|
||||||
|
|
||||||
let currSigners: Account[] = [];
|
let currSigners: Account[] = [];
|
||||||
let currInstructions: TransactionInstruction[] = [];
|
let currInstructions: TransactionInstruction[] = [];
|
||||||
nfts.forEach(nft => {
|
for (let i = 0; i < nfts.length; i++) {
|
||||||
|
let nft = nfts[i];
|
||||||
const newStoreAccount = createTokenAccount(
|
const newStoreAccount = createTokenAccount(
|
||||||
currInstructions,
|
currInstructions,
|
||||||
wallet.publicKey,
|
wallet.publicKey,
|
||||||
|
@ -70,13 +64,13 @@ export async function addTokensToVault(
|
||||||
|
|
||||||
currSigners.push(transferAuthority);
|
currSigners.push(transferAuthority);
|
||||||
|
|
||||||
addTokenToInactiveVault(
|
await addTokenToInactiveVault(
|
||||||
nft.amount,
|
nft.amount,
|
||||||
nft.tokenMint,
|
nft.tokenMint,
|
||||||
nft.tokenAccount,
|
nft.tokenAccount,
|
||||||
newStoreAccount,
|
newStoreAccount,
|
||||||
vault,
|
vault,
|
||||||
vaultAuthority,
|
wallet.publicKey,
|
||||||
wallet.publicKey,
|
wallet.publicKey,
|
||||||
transferAuthority.publicKey,
|
transferAuthority.publicKey,
|
||||||
currInstructions,
|
currInstructions,
|
||||||
|
@ -89,19 +83,7 @@ export async function addTokensToVault(
|
||||||
currSigners = [];
|
currSigners = [];
|
||||||
currInstructions = [];
|
currInstructions = [];
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
currSigners = [];
|
|
||||||
currInstructions = [];
|
|
||||||
|
|
||||||
activateVault(
|
|
||||||
new BN(0),
|
|
||||||
vault,
|
|
||||||
fractionMint,
|
|
||||||
fractionTreasury,
|
|
||||||
vaultAuthority,
|
|
||||||
currInstructions,
|
|
||||||
);
|
|
||||||
|
|
||||||
signers.push(currSigners);
|
signers.push(currSigners);
|
||||||
instructions.push(currInstructions);
|
instructions.push(currInstructions);
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
import {
|
||||||
|
Account,
|
||||||
|
Connection,
|
||||||
|
PublicKey,
|
||||||
|
TransactionInstruction,
|
||||||
|
} from '@solana/web3.js';
|
||||||
|
import { utils, actions, models } from '@oyster/common';
|
||||||
|
|
||||||
|
import { AccountLayout } from '@solana/spl-token';
|
||||||
|
import BN from 'bn.js';
|
||||||
|
import { METAPLEX_PREFIX } from '../models/metaplex';
|
||||||
|
const {
|
||||||
|
createTokenAccount,
|
||||||
|
activateVault,
|
||||||
|
combineVault,
|
||||||
|
VAULT_PREFIX,
|
||||||
|
AUCTION_PREFIX,
|
||||||
|
} = actions;
|
||||||
|
const { approve } = models;
|
||||||
|
|
||||||
|
// This command "closes" the vault, by activating & combining it in one go, handing it over to the auction manager
|
||||||
|
// authority (that may or may not exist yet.)
|
||||||
|
export async function closeVault(
|
||||||
|
connection: Connection,
|
||||||
|
wallet: any,
|
||||||
|
vault: PublicKey,
|
||||||
|
fractionMint: PublicKey,
|
||||||
|
fractionTreasury: PublicKey,
|
||||||
|
redeemTreasury: PublicKey,
|
||||||
|
priceMint: PublicKey,
|
||||||
|
externalPriceAccount: PublicKey,
|
||||||
|
): Promise<{
|
||||||
|
instructions: TransactionInstruction[];
|
||||||
|
signers: Account[];
|
||||||
|
}> {
|
||||||
|
const PROGRAM_IDS = utils.programIds();
|
||||||
|
|
||||||
|
const accountRentExempt = await connection.getMinimumBalanceForRentExemption(
|
||||||
|
AccountLayout.span,
|
||||||
|
);
|
||||||
|
let signers: Account[] = [];
|
||||||
|
let instructions: TransactionInstruction[] = [];
|
||||||
|
const vaultAuthority = (
|
||||||
|
await PublicKey.findProgramAddress(
|
||||||
|
[Buffer.from(VAULT_PREFIX), PROGRAM_IDS.vault.toBuffer()],
|
||||||
|
PROGRAM_IDS.vault,
|
||||||
|
)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
const auctionKey: PublicKey = (
|
||||||
|
await PublicKey.findProgramAddress(
|
||||||
|
[
|
||||||
|
Buffer.from(AUCTION_PREFIX),
|
||||||
|
PROGRAM_IDS.auction.toBuffer(),
|
||||||
|
vault.toBuffer(),
|
||||||
|
],
|
||||||
|
PROGRAM_IDS.auction,
|
||||||
|
)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
const auctionManagerKey: PublicKey = (
|
||||||
|
await PublicKey.findProgramAddress(
|
||||||
|
[Buffer.from(METAPLEX_PREFIX), auctionKey.toBuffer()],
|
||||||
|
PROGRAM_IDS.metaplex,
|
||||||
|
)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
await activateVault(
|
||||||
|
new BN(0),
|
||||||
|
vault,
|
||||||
|
fractionMint,
|
||||||
|
fractionTreasury,
|
||||||
|
vaultAuthority,
|
||||||
|
instructions,
|
||||||
|
);
|
||||||
|
|
||||||
|
const outstandingShareAccount = createTokenAccount(
|
||||||
|
instructions,
|
||||||
|
wallet.publicKey,
|
||||||
|
accountRentExempt,
|
||||||
|
fractionMint,
|
||||||
|
wallet.publicKey,
|
||||||
|
signers,
|
||||||
|
);
|
||||||
|
|
||||||
|
const payingTokenAccount = createTokenAccount(
|
||||||
|
instructions,
|
||||||
|
wallet.publicKey,
|
||||||
|
accountRentExempt,
|
||||||
|
priceMint,
|
||||||
|
wallet.publicKey,
|
||||||
|
signers,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Shouldn't need to pay anything since we activated vault with 0 shares, but we still
|
||||||
|
// need this setup anyway.
|
||||||
|
const transferAuthority = approve(
|
||||||
|
instructions,
|
||||||
|
[],
|
||||||
|
payingTokenAccount,
|
||||||
|
wallet.publicKey,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
signers.push(transferAuthority);
|
||||||
|
|
||||||
|
await combineVault(
|
||||||
|
vault,
|
||||||
|
outstandingShareAccount,
|
||||||
|
payingTokenAccount,
|
||||||
|
fractionMint,
|
||||||
|
fractionTreasury,
|
||||||
|
redeemTreasury,
|
||||||
|
auctionManagerKey,
|
||||||
|
wallet.publicKey,
|
||||||
|
transferAuthority.publicKey,
|
||||||
|
externalPriceAccount,
|
||||||
|
instructions,
|
||||||
|
);
|
||||||
|
|
||||||
|
return { instructions, signers };
|
||||||
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
export * from './nft';
|
export * from './nft';
|
||||||
export * from './createVault';
|
export * from './createVault';
|
||||||
export * from './auction';
|
export * from './createAuction';
|
||||||
|
|
|
@ -9,6 +9,8 @@ export * from './redeemMasterEditionBid';
|
||||||
export * from './redeemOpenEditionBid';
|
export * from './redeemOpenEditionBid';
|
||||||
export * from './startAuction';
|
export * from './startAuction';
|
||||||
export * from './validateSafetyDepositBox';
|
export * from './validateSafetyDepositBox';
|
||||||
|
|
||||||
|
export const METAPLEX_PREFIX = 'metaplex';
|
||||||
export class AuctionManager {
|
export class AuctionManager {
|
||||||
key: number = 0;
|
key: number = 0;
|
||||||
authority?: PublicKey;
|
authority?: PublicKey;
|
||||||
|
|
Loading…
Reference in New Issue