UNPKG

@coral-xyz/soulbound

Version:
611 lines 29.3 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import * as anchor from "@coral-xyz/anchor"; import { Program } from "@coral-xyz/anchor"; import { PublicKey, SystemProgram, ComputeBudgetProgram, Transaction, SYSVAR_INSTRUCTIONS_PUBKEY, } from "@solana/web3.js"; import { getAssociatedTokenAddress, getAccount, TOKEN_PROGRAM_ID, } from "@solana/spl-token"; import { IDL as SoulBoundIdl, } from "./_idls/soulBoundAuthority"; import { IDL as CardinalStakePoolIdl, } from "./_idls/cardinalStakePool"; import { IDL as CardinalRewardDistributorIdl, } from "./_idls/cardinalRewardDistributor"; const BN = anchor.BN; export function createStakeApi(PROVIDER) { // // Mainnet stake constants. // const STAKE_POOL = new PublicKey("7xmGGtuNNvjKLDwbYWBYGPpAjRqftJnrTyzSRK92yku8"); //const STAKE_POOL_IDENTIFIER = new PublicKey( //"E43L3VCJcDqN4pPhhPBiQjSr5A9cBJreTdMDVhWxXVCZ" //); const REWARD_DISTRIBUTOR = new PublicKey("6DBnpqRm1szSz25dD1aWEmYzgGoMB59Y1GMv2gtWUSM4"); const GOLD_MINT = new PublicKey("5QPAPkBvd2B7RQ6DBGvCxGdAcyWitdvRAP58CdvBiuf7"); // // Program ids. // const SOUL_BOUND_PROGRAM_ID = new PublicKey("7DkjPwuKxvz6Viiawtbmb4CqnMKP6eGb1WqYas1airUS"); const CARDINAL_REWARD_DISTRIBUTOR_PROGRAM_ID = new PublicKey("H2yQahQ7eQH8HXXPtJSJn8MURRFEWVesTd8PsracXp1S"); const CARDINAL_STAKE_POOL_PROGRAM_ID = new PublicKey("2gvBmibwtBnbkLExmgsijKy6hGXJneou8X6hkyWQvYnF"); const TOKEN_METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"); // // Misc program constants. // const AUTHORIZATION_RULES_PROGRAM_ID = new PublicKey("auth9SigNpDKz4sJJ1DfCTuZrZNSAgh9sFD3rboVmgg"); const AUTHORIZATION_RULES = new PublicKey("eBJLFYPxJmMGKuFwpDWkzxZeUrad92kZRC5BJLpzyT9"); // // Stake program clients. // const SOUL_BOUND_PROGRAM = new Program(SoulBoundIdl, SOUL_BOUND_PROGRAM_ID, PROVIDER); const REWARD_DISTRIBUTOR_PROGRAM = new Program(CardinalRewardDistributorIdl, CARDINAL_REWARD_DISTRIBUTOR_PROGRAM_ID, PROVIDER); const STAKE_POOL_PROGRAM = new Program(CardinalStakePoolIdl, CARDINAL_STAKE_POOL_PROGRAM_ID, PROVIDER); function stake({ user, nft, stakePool = STAKE_POOL, rewardDistributor = REWARD_DISTRIBUTOR, stakePoolProgram = STAKE_POOL_PROGRAM, rewardDistributorProgram = REWARD_DISTRIBUTOR_PROGRAM, }) { return __awaiter(this, void 0, void 0, function* () { const tx = new Transaction(); tx.add(ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000, })); tx.add(yield stakeInstruction({ user, nft, stakePool, rewardDistributor, stakePoolProgram, rewardDistributorProgram, })); // @ts-ignore return yield window.xnft.solana.send(tx); }); } function stakeInstruction({ user, nft, stakePool = STAKE_POOL, rewardDistributor = REWARD_DISTRIBUTOR, stakePoolProgram = STAKE_POOL_PROGRAM, rewardDistributorProgram = REWARD_DISTRIBUTOR_PROGRAM, }) { return __awaiter(this, void 0, void 0, function* () { const stakeEntry = PublicKey.findProgramAddressSync([ Buffer.from("stake-entry"), stakePool.toBuffer(), nft.mintAddress.toBuffer(), getStakeSeed(1, user).toBuffer(), ], stakePoolProgram.programId)[0]; const rewardEntry = PublicKey.findProgramAddressSync([ Buffer.from("reward-entry"), rewardDistributor.toBuffer(), stakeEntry.toBuffer(), ], rewardDistributorProgram.programId)[0]; const ata = yield anchor.utils.token.associatedAddress({ mint: nft.mintAddress, owner: user, }); const tokenRecord = PublicKey.findProgramAddressSync([ Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nft.mintAddress.toBuffer(), Buffer.from("token_record"), ata.toBuffer(), ], TOKEN_METADATA_PROGRAM_ID)[0]; const masterEditionAddress = PublicKey.findProgramAddressSync([ Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nft.mintAddress.toBuffer(), Buffer.from("edition"), ], TOKEN_METADATA_PROGRAM_ID)[0]; return yield stakePoolProgram.methods .stakeProgrammable(new BN(1)) .accounts({ stakeEntry, rewardEntry, rewardDistributor, stakePool, originalMint: nft.mintAddress, user, userOriginalMintTokenAccount: ata, userOriginalMintTokenRecord: tokenRecord, mintMetadata: nft.metadataAddress, mintEdition: masterEditionAddress, authorizationRules: AUTHORIZATION_RULES, sysvarInstructions: SYSVAR_INSTRUCTIONS_PUBKEY, tokenProgram: TOKEN_PROGRAM_ID, tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, authorizationRulesProgram: AUTHORIZATION_RULES_PROGRAM_ID, rewardDistributorProgram: rewardDistributorProgram.programId, systemProgram: SystemProgram.programId, }) .instruction(); }); } function unstake({ user, nft, stakePool = STAKE_POOL, stakePoolProgram = STAKE_POOL_PROGRAM, options, }) { return __awaiter(this, void 0, void 0, function* () { const tx = new Transaction(); tx.add(...(yield claimAndUnstakeInstructions({ user, nft, stakePool, stakePoolProgram, }))); // @ts-ignore return yield window.xnft.solana.send(tx, undefined, options); }); } function claimAndUnstakeInstructions({ user, nft, stakePool = STAKE_POOL, stakePoolProgram = STAKE_POOL_PROGRAM, }) { return __awaiter(this, void 0, void 0, function* () { const ixs = yield claimRewardInstruction({ user, nft, }); ixs.push(yield unstakeInstruction({ user, nft, stakePool, stakePoolProgram, })); return ixs; }); } function unstakeInstruction({ user, nft, stakePool = STAKE_POOL, stakePoolProgram = STAKE_POOL_PROGRAM, }) { return __awaiter(this, void 0, void 0, function* () { const stakeEntry = PublicKey.findProgramAddressSync([ Buffer.from("stake-entry"), stakePool.toBuffer(), nft.mintAddress.toBuffer(), getStakeSeed(1, user).toBuffer(), ], stakePoolProgram.programId)[0]; const ata = yield anchor.utils.token.associatedAddress({ mint: nft.mintAddress, owner: user, }); const tokenRecord = PublicKey.findProgramAddressSync([ Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nft.mintAddress.toBuffer(), Buffer.from("token_record"), ata.toBuffer(), ], TOKEN_METADATA_PROGRAM_ID)[0]; const masterEditionAddress = PublicKey.findProgramAddressSync([ Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), nft.mintAddress.toBuffer(), Buffer.from("edition"), ], TOKEN_METADATA_PROGRAM_ID)[0]; return yield stakePoolProgram.methods .unstakeProgrammable() .accounts({ stakeEntry, stakePool, originalMint: nft.mintAddress, user, userOriginalMintTokenAccount: ata, userOriginalMintTokenRecord: tokenRecord, mintMetadata: nft.metadataAddress, mintEdition: masterEditionAddress, authorizationRules: AUTHORIZATION_RULES, sysvarInstructions: SYSVAR_INSTRUCTIONS_PUBKEY, tokenProgram: TOKEN_PROGRAM_ID, tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, authorizationRulesProgram: AUTHORIZATION_RULES_PROGRAM_ID, systemProgram: SystemProgram.programId, }) .instruction(); }); } function isStaked({ user, nft, stakePool = STAKE_POOL, stakePoolProgram = STAKE_POOL_PROGRAM, }) { return __awaiter(this, void 0, void 0, function* () { try { const stakeEntry = yield fetchStakeEntry({ user, nft, stakePool, stakePoolProgram, }); return stakeEntry.lastStaker.equals(user); } catch (err) { // If throws, then the account probably doesn't exist. return false; } }); } const fetchStakeEntry = ({ user, nft, stakePool = STAKE_POOL, stakePoolProgram = STAKE_POOL_PROGRAM, }) => __awaiter(this, void 0, void 0, function* () { const stakeEntry = yield stakeEntryAddress({ user, nft, stakePool, stakePoolProgram, }); return yield stakePoolProgram.account.stakeEntry.fetch(stakeEntry); }); const stakeEntryAddress = ({ user, nft, stakePool = STAKE_POOL, stakePoolProgram = STAKE_POOL_PROGRAM, }) => __awaiter(this, void 0, void 0, function* () { const stakeEntry = PublicKey.findProgramAddressSync([ Buffer.from("stake-entry"), stakePool.toBuffer(), nft.mintAddress.toBuffer(), getStakeSeed(1, user).toBuffer(), ], stakePoolProgram.programId)[0]; return stakeEntry; }); const fetchRewardEntry = ({ user, nft, stakePool = STAKE_POOL, rewardDistributor = REWARD_DISTRIBUTOR, stakePoolProgram = STAKE_POOL_PROGRAM, rewardDistributorProgram = REWARD_DISTRIBUTOR_PROGRAM, }) => __awaiter(this, void 0, void 0, function* () { const stakeEntry = PublicKey.findProgramAddressSync([ Buffer.from("stake-entry"), stakePool.toBuffer(), nft.mintAddress.toBuffer(), getStakeSeed(1, user).toBuffer(), ], stakePoolProgram.programId)[0]; const rewardEntry = PublicKey.findProgramAddressSync([ Buffer.from("reward-entry"), rewardDistributor.toBuffer(), stakeEntry.toBuffer(), ], rewardDistributorProgram.programId)[0]; const rewardEntryAccount = yield rewardDistributorProgram.account.rewardEntry.fetch(rewardEntry); return rewardEntryAccount; }); const rewardEntryAddress = ({ user, nft, stakePool = STAKE_POOL, rewardDistributor = REWARD_DISTRIBUTOR, stakePoolProgram = STAKE_POOL_PROGRAM, rewardDistributorProgram = REWARD_DISTRIBUTOR_PROGRAM, }) => __awaiter(this, void 0, void 0, function* () { const stakeEntry = yield stakeEntryAddress({ user, nft, stakePool, stakePoolProgram, }); const rewardEntry = PublicKey.findProgramAddressSync([ Buffer.from("reward-entry"), rewardDistributor.toBuffer(), stakeEntry.toBuffer(), ], rewardDistributorProgram.programId)[0]; return rewardEntry; }); function claimRewardInstruction({ user, nft, stakePool = STAKE_POOL, rewardDistributor = REWARD_DISTRIBUTOR, goldMint = GOLD_MINT, soulboundProgram = SOUL_BOUND_PROGRAM, stakePoolProgram = STAKE_POOL_PROGRAM, rewardDistributorProgram = REWARD_DISTRIBUTOR_PROGRAM, }) { return __awaiter(this, void 0, void 0, function* () { const [sbaUser] = PublicKey.findProgramAddressSync([Buffer.from("sba-scoped-user"), user.toBuffer()], soulboundProgram.programId); const scopedSbaUserAuthority = PublicKey.findProgramAddressSync([ Buffer.from("sba-scoped-user-nft-program"), user.toBuffer(), nft.mintAddress.toBuffer(), rewardDistributorProgram.programId.toBuffer(), ], soulboundProgram.programId)[0]; const stakeEntry = PublicKey.findProgramAddressSync([ Buffer.from("stake-entry"), stakePool.toBuffer(), nft.mintAddress.toBuffer(), getStakeSeed(1, user).toBuffer(), ], stakePoolProgram.programId)[0]; const rewardEntry = PublicKey.findProgramAddressSync([ Buffer.from("reward-entry"), rewardDistributor.toBuffer(), stakeEntry.toBuffer(), ], rewardDistributorProgram.programId)[0]; const userRewardMintTokenAccount = yield getAssociatedTokenAddress(goldMint, scopedSbaUserAuthority, true); let { data, keys } = yield rewardDistributorProgram.methods .claimRewards() .accounts({ rewardEntry, rewardDistributor, stakeEntry, stakePool, originalMint: nft.mintAddress, rewardMint: goldMint, userRewardMintTokenAccount, authority: scopedSbaUserAuthority, user, }) .instruction(); // Need to set the signer on the PDA to false so that we can serialize // the transaction without error. The CPI in the program will flip this // back to true before signging with PDA seeds. keys = keys.map((k) => { return Object.assign(Object.assign({}, k), { isSigner: k.pubkey.equals(scopedSbaUserAuthority) ? false : k.isSigner }); }); const nftToken = yield getAssociatedTokenAddress(nft.mintAddress, user); // // If this is the first time using the soulbound program, then we need // to initialize the user account. // const soulboundInitInstructions = yield (() => __awaiter(this, void 0, void 0, function* () { // If the soul bound authority user is already created, do nothing. if (yield isSoulBoundAuthorityUserInitialized(user, soulboundProgram)) { return []; } // If the soulbound authority user is not yet created, then we // need to create it before claiming a reward. else { __cached = null; // Wipe cache. return [ yield soulboundProgram.methods .createSbaUser() .accounts({ sba: sbaUser, authority: user, payer: user, }) .instruction(), ]; } }))(); const claimIx = yield soulboundProgram.methods .executeTxScopedUserNftProgram(data) .accounts({ sbaUser, nftToken, nftMint: nft.mintAddress, authority: user, delegate: PublicKey.default, authorityOrDelegate: user, scopedAuthority: scopedSbaUserAuthority, program: rewardDistributorProgram.programId, }) .remainingAccounts(keys) .instruction(); const updateIx = yield stakePoolProgram.methods .updateTotalStakeSeconds() .accounts({ stakeEntry, lastStaker: user, }) .instruction(); return soulboundInitInstructions.concat([updateIx, claimIx]); }); } // Should invoke this method on load to slightly speed things up. // // Note this account can only be created; it can't be removed. let __cached = null; function isSoulBoundAuthorityUserInitialized(user, soulboundProgram = SOUL_BOUND_PROGRAM) { return __awaiter(this, void 0, void 0, function* () { const [sbaUser] = PublicKey.findProgramAddressSync([Buffer.from("sba-scoped-user"), user.toBuffer()], soulboundProgram.programId); if (__cached !== null) { return __cached; } try { yield soulboundProgram.account.soulBoundAuthorityUser.fetch(sbaUser); __cached = true; return true; } catch (_a) { __cached = false; return false; } }); } function readGoldPoints({ user, nft, goldMint = GOLD_MINT, stakePool = STAKE_POOL, rewardDistributor = REWARD_DISTRIBUTOR, soulboundProgram = SOUL_BOUND_PROGRAM, stakePoolProgram = STAKE_POOL_PROGRAM, rewardDistributorProgram = REWARD_DISTRIBUTOR_PROGRAM, accounts, }) { return __awaiter(this, void 0, void 0, function* () { const unclaimed = yield (() => __awaiter(this, void 0, void 0, function* () { try { return yield readUnclaimedGoldPoints({ user, nft, stakePool, rewardDistributor, stakePoolProgram, rewardDistributorProgram, accounts, }); } catch (_a) { return new BN(0); } }))(); const claimed = yield (() => __awaiter(this, void 0, void 0, function* () { try { return yield readClaimedGoldPoints({ user, nft, goldMint, soulboundProgram, rewardDistributorProgram, accounts, }); } catch (_b) { return new BN(0); } }))(); const native = unclaimed.add(claimed); const decimals = 0; return native.toNumber() / Math.pow(10, decimals); }); } // Unclaimed gold points are calculated client side. // // Rant: Would be nice if the contract just had a view function so that // we don't have to redo this logic in typescript land, but such is life. function readUnclaimedGoldPoints({ user, nft, stakePool = STAKE_POOL, rewardDistributor = REWARD_DISTRIBUTOR, stakePoolProgram = STAKE_POOL_PROGRAM, rewardDistributorProgram = REWARD_DISTRIBUTOR_PROGRAM, accounts, }) { return __awaiter(this, void 0, void 0, function* () { const stakeEntryAcc = accounts ? accounts.stakeEntry : yield fetchStakeEntry({ user, nft, stakePool, stakePoolProgram, }); const rewardEntryAcc = accounts ? accounts.rewardEntry : yield fetchRewardEntry({ user, nft: nft, stakePool, rewardDistributor, stakePoolProgram, rewardDistributorProgram, }); // This means the staker unstaked. if (stakeEntryAcc.lastStaker.equals(PublicKey.default)) { return new BN(0); } if (stakeEntryAcc.amount.eq(new BN(0))) { return new BN(0); } const totalStakeSeconds = stakeEntryAcc.totalStakeSeconds.add(stakeEntryAcc.amount.eq(new BN(0)) ? new BN(0) : new BN(Date.now() / 1000).sub(stakeEntryAcc.lastUpdatedAt)); const rewardSecondsReceived = rewardEntryAcc.rewardSecondsReceived; const rewardDistributorAcc = accounts ? accounts.rewardDistributor : yield rewardDistributorProgram.account.rewardDistributor.fetch(rewardDistributor); const rewardAmountToReceive = totalStakeSeconds .sub(rewardSecondsReceived) .div(rewardDistributorAcc.rewardDurationSeconds) .mul(rewardDistributorAcc.rewardAmount) .mul(new BN(1)) .div(new BN(10).pow(new BN(rewardDistributorAcc.multiplierDecimals))); return rewardAmountToReceive; }); } // Points swept into the soulbound token account. These are soulbound to the // user and nft (combinatino) and automatically swept during unstaking. function readClaimedGoldPoints({ user, nft, goldMint = GOLD_MINT, soulboundProgram = SOUL_BOUND_PROGRAM, rewardDistributorProgram = REWARD_DISTRIBUTOR_PROGRAM, accounts, }) { return __awaiter(this, void 0, void 0, function* () { const userRewardMintTokenAccount = yield goldPointsAddress({ user, nft, goldMint, soulboundProgram, rewardDistributorProgram, }); const claimedAmount = yield (() => __awaiter(this, void 0, void 0, function* () { try { const rewardTokenAccount = accounts ? accounts.goldTokenAccount : yield getAccount(soulboundProgram.provider.connection, userRewardMintTokenAccount); return new BN(rewardTokenAccount.amount.toString()); } catch (_a) { return new BN(0); } }))(); return claimedAmount; }); } function goldPointsAddress({ user, nft, goldMint = GOLD_MINT, soulboundProgram = SOUL_BOUND_PROGRAM, rewardDistributorProgram = REWARD_DISTRIBUTOR_PROGRAM, }) { return __awaiter(this, void 0, void 0, function* () { const scopedSbaUserAuthority = PublicKey.findProgramAddressSync([ Buffer.from("sba-scoped-user-nft-program"), user.toBuffer(), nft.mintAddress.toBuffer(), rewardDistributorProgram.programId.toBuffer(), ], soulboundProgram.programId)[0]; const userRewardMintTokenAccount = yield getAssociatedTokenAddress(goldMint, scopedSbaUserAuthority, true); return userRewardMintTokenAccount; }); } function transferRewards({ amount, fromUser, // fromUser should be the client payer/signer. fromNft, toNft, goldMint = GOLD_MINT, stakePool = STAKE_POOL, rewardDistributor = REWARD_DISTRIBUTOR, soulboundProgram = SOUL_BOUND_PROGRAM, stakePoolProgram = STAKE_POOL_PROGRAM, rewardDistributorProgram = REWARD_DISTRIBUTOR_PROGRAM, }) { return __awaiter(this, void 0, void 0, function* () { const toUser = fromUser; // Transfers only allowed between same wallet. const [fromSbaUser] = PublicKey.findProgramAddressSync([Buffer.from("sba-scoped-user"), fromUser.toBuffer()], soulboundProgram.programId); const fromScopedSbaUserAuthority = PublicKey.findProgramAddressSync([ Buffer.from("sba-scoped-user-nft-program"), fromUser.toBuffer(), fromNft.mintAddress.toBuffer(), rewardDistributorProgram.programId.toBuffer(), ], soulboundProgram.programId)[0]; const fromStakeEntry = PublicKey.findProgramAddressSync([ Buffer.from("stake-entry"), stakePool.toBuffer(), fromNft.mintAddress.toBuffer(), getStakeSeed(1, fromUser).toBuffer(), ], stakePoolProgram.programId)[0]; const fromRewardEntry = PublicKey.findProgramAddressSync([ Buffer.from("reward-entry"), rewardDistributor.toBuffer(), fromStakeEntry.toBuffer(), ], rewardDistributorProgram.programId)[0]; const fromScopedSbaUserAuthorityAta = yield getAssociatedTokenAddress(goldMint, fromScopedSbaUserAuthority, true); const toScopedSbaUserAuthority = PublicKey.findProgramAddressSync([ Buffer.from("sba-scoped-user-nft-program"), toUser.toBuffer(), toNft.mintAddress.toBuffer(), rewardDistributorProgram.programId.toBuffer(), ], soulboundProgram.programId)[0]; const toStakeEntry = PublicKey.findProgramAddressSync([ Buffer.from("stake-entry"), stakePool.toBuffer(), toNft.mintAddress.toBuffer(), getStakeSeed(1, toUser).toBuffer(), ], stakePoolProgram.programId)[0]; const toRewardEntry = PublicKey.findProgramAddressSync([ Buffer.from("reward-entry"), rewardDistributor.toBuffer(), toStakeEntry.toBuffer(), ], rewardDistributorProgram.programId)[0]; const toScopedSbaUserAuthorityAta = yield getAssociatedTokenAddress(goldMint, toScopedSbaUserAuthority, true); const fromNftToken = yield getAssociatedTokenAddress(fromNft.mintAddress, fromUser); let { data, keys } = yield rewardDistributorProgram.methods .transferRewards(amount !== null && amount !== void 0 ? amount : null) .accounts({ rewardEntryA: fromRewardEntry, rewardEntryB: toRewardEntry, stakeEntryA: fromStakeEntry, stakeEntryB: toStakeEntry, rewardDistributor, stakePool, originalMintA: fromNft.mintAddress, originalMintB: toNft.mintAddress, rewardMint: goldMint, user: fromUser, userRewardMintTokenAccountA: fromScopedSbaUserAuthorityAta, userRewardMintTokenAccountB: toScopedSbaUserAuthorityAta, authorityA: fromScopedSbaUserAuthority, authorityB: toScopedSbaUserAuthority, }) .instruction(); // Need to set the signer on the PDA to false so that we can serialize // the transaction without error. The CPI in the program will flip this // back to true before signging with PDA seeds. keys = keys.map((k) => { return Object.assign(Object.assign({}, k), { isSigner: k.pubkey.equals(fromScopedSbaUserAuthority) ? false : k.isSigner }); }); const tx = yield soulboundProgram.methods .executeTxScopedUserNftProgram(data) .accounts({ sbaUser: fromSbaUser, nftToken: fromNftToken, nftMint: fromNft.mintAddress, authority: fromUser, delegate: PublicKey.default, authorityOrDelegate: fromUser, scopedAuthority: fromScopedSbaUserAuthority, program: rewardDistributorProgram.programId, }) .remainingAccounts(keys) .transaction(); // @ts-ignore return yield window.xnft.solana.send(tx); }); } // Supply is the token supply of the nft mint. function getStakeSeed(supply, user) { if (supply > 1) { return user; } else { return PublicKey.default; } } return { stake, stakeInstruction, unstake, unstakeInstruction, claimAndUnstakeInstructions, isStaked, isSoulBoundAuthorityUserInitialized, readGoldPoints, readUnclaimedGoldPoints, readClaimedGoldPoints, transferRewards, anchor: { soulbound: SOUL_BOUND_PROGRAM, rewardDistributor: REWARD_DISTRIBUTOR_PROGRAM, stakePool: STAKE_POOL_PROGRAM, }, constants: { REWARD_DISTRIBUTOR, }, rewardEntryAddress, stakeEntryAddress, goldPointsAddress, }; } //# sourceMappingURL=index.js.map