@triadxyz/poseidons-protocol 0.4.3 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,9 @@ const chest_1 = __importDefault(require("./chest"));
17
17
  const wheel_1 = __importDefault(require("./wheel"));
18
18
  const sendVersionedTransaction_1 = __importDefault(require("../utils/sendVersionedTransaction"));
19
19
  const pda_1 = require("../utils/pda");
20
+ const getTokenBalance_1 = require("../utils/getTokenBalance");
21
+ const constants_1 = require("../utils/constants");
22
+ const swap_1 = require("../utils/swap");
20
23
  class Game {
21
24
  constructor(program, rpcOptions) {
22
25
  this.program = program;
@@ -33,8 +36,39 @@ class Game {
33
36
  addSpin({ users, refer }) {
34
37
  return __awaiter(this, void 0, void 0, function* () {
35
38
  const ixs = [];
39
+ const addressLookupTableAccounts = [];
36
40
  for (const user of users) {
37
41
  const userPDA = (0, pda_1.getUserPDA)(user.user);
42
+ const userSolBalance = yield (0, getTokenBalance_1.getBalanceSol)(user.user.toBase58(), this.program.provider.connection);
43
+ const totalCost = user.spins * 0.0015;
44
+ const feeBuffer = Math.max(totalCost * 0.1, 0.0001);
45
+ const totalCostWithFees = totalCost + feeBuffer;
46
+ if (userSolBalance !== undefined && userSolBalance < totalCostWithFees) {
47
+ const solNeeded = totalCostWithFees - userSolBalance;
48
+ const solPrice = yield (0, swap_1.getPrice)(constants_1.SOL_MINT.toString());
49
+ const usdcNeeded = solNeeded * solPrice * 1.05;
50
+ const userUsdcBalance = yield (0, getTokenBalance_1.getTokenBalance)(constants_1.USDC_MINT.toString(), user.user.toBase58(), this.program.provider.connection);
51
+ if (userUsdcBalance < usdcNeeded) {
52
+ throw new Error(`The user does not have enough USDC. Necessary: ${usdcNeeded.toFixed(2)} USDC, Available: ${userUsdcBalance.toFixed(2)} USDC`);
53
+ }
54
+ const { swapIxs, closeAccountIxs, addressLookupTableAccounts: swapAddressLookupTableAccounts, outAmount, setupInstructions } = yield (0, swap_1.swap)({
55
+ connection: this.program.provider.connection,
56
+ wallet: user.user.toBase58(),
57
+ inToken: constants_1.USDC_MINT.toString(),
58
+ outToken: constants_1.SOL_MINT.toString(),
59
+ amount: usdcNeeded,
60
+ payer: this.rpcOptions.payer.toBase58()
61
+ });
62
+ if (swapIxs.length === 0) {
63
+ return;
64
+ }
65
+ ixs.push(...setupInstructions);
66
+ ixs.push(...swapIxs);
67
+ if (closeAccountIxs && closeAccountIxs.length > 0) {
68
+ ixs.push(...closeAccountIxs);
69
+ }
70
+ addressLookupTableAccounts.push(...swapAddressLookupTableAccounts);
71
+ }
38
72
  try {
39
73
  yield this.program.account.user.fetch(userPDA, this.rpcOptions.commitment);
40
74
  }
@@ -55,7 +89,7 @@ class Game {
55
89
  })
56
90
  .instruction());
57
91
  }
58
- return (0, sendVersionedTransaction_1.default)(this.program, ixs, this.rpcOptions);
92
+ return (0, sendVersionedTransaction_1.default)(this.program, ixs, this.rpcOptions, addressLookupTableAccounts);
59
93
  });
60
94
  }
61
95
  }
@@ -44,10 +44,13 @@ export default class Wheel {
44
44
  * @param available - The available quantity of the prize
45
45
  * @returns The transaction signature or versioned transaction
46
46
  */
47
- addWheelPrize({ id, available }: {
47
+ addWheelPrize(prizes: {
48
48
  id: number;
49
49
  available: number;
50
- }): Promise<string | import("@solana/web3.js").VersionedTransaction>;
50
+ rangeMin: number;
51
+ rangeMax: number;
52
+ wheelId: number;
53
+ }[]): Promise<string | import("@solana/web3.js").VersionedTransaction>;
51
54
  /**
52
55
  * Spin a wheel
53
56
  * @param id - The id of the wheel
@@ -81,20 +81,23 @@ class Wheel {
81
81
  * @param available - The available quantity of the prize
82
82
  * @returns The transaction signature or versioned transaction
83
83
  */
84
- addWheelPrize({ id, available }) {
84
+ addWheelPrize(prizes) {
85
85
  return __awaiter(this, void 0, void 0, function* () {
86
- const ixs = [
87
- yield this.program.methods
86
+ const ixs = [];
87
+ for (const prize of prizes) {
88
+ ixs.push(yield this.program.methods
88
89
  .addWheelPrize({
89
- id,
90
- available: new anchor_1.BN(available)
90
+ id: prize.id,
91
+ available: new anchor_1.BN(prize.available),
92
+ rangeMin: new anchor_1.BN(prize.rangeMin),
93
+ rangeMax: new anchor_1.BN(prize.rangeMax)
91
94
  })
92
95
  .accounts({
93
96
  signer: this.program.provider.publicKey,
94
- wheel: (0, pda_1.getWheelPDA)(0)
97
+ wheel: (0, pda_1.getWheelPDA)(prize.wheelId)
95
98
  })
96
- .instruction()
97
- ];
99
+ .instruction());
100
+ }
98
101
  return (0, sendVersionedTransaction_1.default)(this.program, ixs, this.rpcOptions);
99
102
  });
100
103
  }
@@ -1116,6 +1116,14 @@
1116
1116
  {
1117
1117
  "name": "available",
1118
1118
  "type": "u64"
1119
+ },
1120
+ {
1121
+ "name": "range_min",
1122
+ "type": "u64"
1123
+ },
1124
+ {
1125
+ "name": "range_max",
1126
+ "type": "u64"
1119
1127
  }
1120
1128
  ]
1121
1129
  }
@@ -1802,6 +1810,10 @@
1802
1810
  "name": "wheel_id",
1803
1811
  "type": "u8"
1804
1812
  },
1813
+ {
1814
+ "name": "spins",
1815
+ "type": "u64"
1816
+ },
1805
1817
  {
1806
1818
  "name": "timestamp",
1807
1819
  "type": "i64"
@@ -56,6 +56,7 @@ export type Wheel = {
56
56
  address: string;
57
57
  id: number;
58
58
  name: string;
59
+ cost: number;
59
60
  count: number;
60
61
  isActive: boolean;
61
62
  prizes: Prize[];
@@ -1407,6 +1407,14 @@ export type PoseidonsProtocol = {
1407
1407
  {
1408
1408
  name: 'available';
1409
1409
  type: 'u64';
1410
+ },
1411
+ {
1412
+ name: 'rangeMin';
1413
+ type: 'u64';
1414
+ },
1415
+ {
1416
+ name: 'rangeMax';
1417
+ type: 'u64';
1410
1418
  }
1411
1419
  ];
1412
1420
  };
@@ -2093,6 +2101,10 @@ export type PoseidonsProtocol = {
2093
2101
  name: 'wheelId';
2094
2102
  type: 'u8';
2095
2103
  },
2104
+ {
2105
+ name: 'spins';
2106
+ type: 'u64';
2107
+ },
2096
2108
  {
2097
2109
  name: 'timestamp';
2098
2110
  type: 'i64';
@@ -1,3 +1,5 @@
1
1
  import { PublicKey } from '@solana/web3.js';
2
+ export declare const SOL_MINT: PublicKey;
2
3
  export declare const POSEIDON_VAULT_PROGRAM_ID: PublicKey;
3
4
  export declare const CORE_POSEIDON_COLLECTION: PublicKey;
5
+ export declare const USDC_MINT: PublicKey;
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CORE_POSEIDON_COLLECTION = exports.POSEIDON_VAULT_PROGRAM_ID = void 0;
3
+ exports.USDC_MINT = exports.CORE_POSEIDON_COLLECTION = exports.POSEIDON_VAULT_PROGRAM_ID = exports.SOL_MINT = void 0;
4
4
  const web3_js_1 = require("@solana/web3.js");
5
+ exports.SOL_MINT = new web3_js_1.PublicKey('So11111111111111111111111111111111111111112');
5
6
  exports.POSEIDON_VAULT_PROGRAM_ID = new web3_js_1.PublicKey('E65MHJjJT2ihTLgMfHdWtsNYMA6iJsCjraf7UrxU2sDP');
6
7
  exports.CORE_POSEIDON_COLLECTION = new web3_js_1.PublicKey('69CLccefLRmvDSAJP7Er632dvn878qkpdcnvq5ZUspSm');
8
+ exports.USDC_MINT = new web3_js_1.PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
@@ -0,0 +1,3 @@
1
+ import type { Connection } from '@solana/web3.js';
2
+ export declare function getTokenBalance(tokenAddress: string, wallet: string, connection: Connection): Promise<number>;
3
+ export declare function getBalanceSol(wallet: string, connection: Connection): Promise<number | undefined>;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getBalanceSol = exports.getTokenBalance = void 0;
13
+ const spl_token_1 = require("@solana/spl-token");
14
+ const web3_js_1 = require("@solana/web3.js");
15
+ const formatBigNumber = (number, decimals = 6) => Number(number.toString()) / Math.pow(10, decimals);
16
+ function getTokenBalance(tokenAddress, wallet, connection) {
17
+ return __awaiter(this, void 0, void 0, function* () {
18
+ if (!wallet)
19
+ return 0;
20
+ try {
21
+ const token = yield (0, spl_token_1.getAssociatedTokenAddress)(new web3_js_1.PublicKey(tokenAddress), new web3_js_1.PublicKey(wallet));
22
+ const mint = yield (0, spl_token_1.getMint)(connection, new web3_js_1.PublicKey(tokenAddress));
23
+ const account = yield (0, spl_token_1.getAccount)(connection, token);
24
+ const formattedAmount = formatBigNumber(account.amount, mint.decimals);
25
+ return formattedAmount;
26
+ }
27
+ catch (error) {
28
+ return 0;
29
+ }
30
+ });
31
+ }
32
+ exports.getTokenBalance = getTokenBalance;
33
+ function getBalanceSol(wallet, connection) {
34
+ return __awaiter(this, void 0, void 0, function* () {
35
+ if (!wallet)
36
+ return;
37
+ try {
38
+ const balanceSol = yield connection.getBalance(new web3_js_1.PublicKey(wallet));
39
+ const amountInSol = balanceSol / web3_js_1.LAMPORTS_PER_SOL;
40
+ return amountInSol;
41
+ }
42
+ catch (error) {
43
+ /* empty */
44
+ }
45
+ });
46
+ }
47
+ exports.getBalanceSol = getBalanceSol;
@@ -77,6 +77,7 @@ const formatWheel = (account, address) => {
77
77
  id: account.id,
78
78
  name: account.name,
79
79
  count: account.count.toNumber(),
80
+ cost: account.cost.toNumber(),
80
81
  isActive: account.isActive,
81
82
  prizes: account.prizes.map((prize) => ({
82
83
  id: prize.id,
@@ -0,0 +1,16 @@
1
+ import { AddressLookupTableAccount, Connection, TransactionInstruction } from '@solana/web3.js';
2
+ export declare const swap: ({ connection, wallet, inToken, outToken, amount, payer }: {
3
+ connection: Connection;
4
+ wallet: string;
5
+ inToken: string;
6
+ outToken: string;
7
+ amount: number;
8
+ payer: string;
9
+ }) => Promise<{
10
+ swapIxs: TransactionInstruction[];
11
+ closeAccountIxs: TransactionInstruction[];
12
+ addressLookupTableAccounts: AddressLookupTableAccount[];
13
+ setupInstructions: any[];
14
+ outAmount: any;
15
+ }>;
16
+ export declare const getPrice: (token: string) => Promise<any>;
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.getPrice = exports.swap = void 0;
16
+ const axios_1 = __importDefault(require("axios"));
17
+ const web3_js_1 = require("@solana/web3.js");
18
+ const spl_token_1 = require("@solana/spl-token");
19
+ const pda_1 = require("./pda");
20
+ const constants_1 = require("./constants");
21
+ const swap = ({ connection, wallet, inToken, outToken, amount, payer }) => __awaiter(void 0, void 0, void 0, function* () {
22
+ try {
23
+ const token = TOKENS[inToken];
24
+ if (!token) {
25
+ throw new Error('Token not found');
26
+ }
27
+ const formattedAmountIn = Math.round(amount * Math.pow(10, token.decimals));
28
+ const quoteResponse = yield axios_1.default.get(`https://lite-api.jup.ag/swap/v1/quote?inputMint=${inToken}&outputMint=${outToken}&amount=${formattedAmountIn}&slippageBps=20&onlyDirectRoutes=true&platformFeeBps=60`);
29
+ const { data: quoteData } = quoteResponse;
30
+ const swapResponse = yield axios_1.default.post('https://lite-api.jup.ag/swap/v1/swap-instructions', {
31
+ quoteResponse: quoteData,
32
+ userPublicKey: wallet,
33
+ payer,
34
+ feeAccount: inToken === constants_1.USDC_MINT.toString() ? getFeeAccount() : undefined,
35
+ wrapAndUnwrapSol: false
36
+ });
37
+ const { setupInstructions, swapInstruction, addressLookupTableAddresses } = swapResponse.data;
38
+ const swapIxs = [
39
+ deserializeInstruction(swapInstruction)
40
+ ];
41
+ const closeAccountIxs = [];
42
+ if (outToken === constants_1.SOL_MINT.toString()) {
43
+ const wsolATA = (0, pda_1.getTokenATA)(new web3_js_1.PublicKey(wallet), constants_1.SOL_MINT, spl_token_1.TOKEN_PROGRAM_ID);
44
+ closeAccountIxs.push((0, spl_token_1.createCloseAccountInstruction)(wsolATA, new web3_js_1.PublicKey(wallet), new web3_js_1.PublicKey(wallet), [], spl_token_1.TOKEN_PROGRAM_ID));
45
+ }
46
+ return {
47
+ swapIxs,
48
+ closeAccountIxs,
49
+ addressLookupTableAccounts: yield getAddressLookupTableAccounts(connection, addressLookupTableAddresses),
50
+ setupInstructions: setupInstructions.length > 0
51
+ ? [...setupInstructions.map(deserializeInstruction)]
52
+ : [],
53
+ outAmount: quoteData.otherAmountThreshold
54
+ };
55
+ }
56
+ catch (error) {
57
+ throw error;
58
+ }
59
+ });
60
+ exports.swap = swap;
61
+ const getPrice = (token) => __awaiter(void 0, void 0, void 0, function* () {
62
+ var _a, _b;
63
+ const response = yield axios_1.default.get(`https://lite-api.jup.ag/price/v3?ids=${token}`);
64
+ return (_b = (_a = response.data[token]) === null || _a === void 0 ? void 0 : _a.usdPrice) !== null && _b !== void 0 ? _b : 0;
65
+ });
66
+ exports.getPrice = getPrice;
67
+ const deserializeInstruction = (instruction) => {
68
+ return new web3_js_1.TransactionInstruction({
69
+ programId: new web3_js_1.PublicKey(instruction.programId),
70
+ keys: instruction.accounts.map((key) => ({
71
+ pubkey: new web3_js_1.PublicKey(key.pubkey),
72
+ isSigner: key.isSigner,
73
+ isWritable: key.isWritable
74
+ })),
75
+ data: Buffer.from(instruction.data, 'base64')
76
+ });
77
+ };
78
+ const getAddressLookupTableAccounts = (connection, keys) => __awaiter(void 0, void 0, void 0, function* () {
79
+ const addressLookupTableAccountInfos = yield connection.getMultipleAccountsInfo(keys.map((key) => new web3_js_1.PublicKey(key)));
80
+ return addressLookupTableAccountInfos.reduce((acc, accountInfo, index) => {
81
+ const addressLookupTableAddress = keys[index];
82
+ if (accountInfo) {
83
+ const addressLookupTableAccount = new web3_js_1.AddressLookupTableAccount({
84
+ key: new web3_js_1.PublicKey(addressLookupTableAddress),
85
+ state: web3_js_1.AddressLookupTableAccount.deserialize(new Uint8Array(accountInfo.data))
86
+ });
87
+ acc.push(addressLookupTableAccount);
88
+ }
89
+ return acc;
90
+ }, new Array());
91
+ });
92
+ const TOKENS = {
93
+ So11111111111111111111111111111111111111112: {
94
+ mint: 'So11111111111111111111111111111111111111112',
95
+ decimals: 9
96
+ },
97
+ EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: {
98
+ mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
99
+ decimals: 6
100
+ },
101
+ t3DohmswhKk94PPbPYwA6ZKACyY3y5kbcqeQerAJjmV: {
102
+ mint: 't3DohmswhKk94PPbPYwA6ZKACyY3y5kbcqeQerAJjmV',
103
+ decimals: 6
104
+ }
105
+ };
106
+ const getFeeAccount = () => {
107
+ return (0, pda_1.getTokenATA)(new web3_js_1.PublicKey('Hk1r2NUL4LbUhx1agg1w44tyZiNr72mbeLsg6suF5MA4'), constants_1.USDC_MINT, spl_token_1.TOKEN_PROGRAM_ID);
108
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@triadxyz/poseidons-protocol",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -30,9 +30,9 @@
30
30
  "bs58": "6.0.0"
31
31
  },
32
32
  "devDependencies": {
33
+ "@types/bn.js": "^5.1.0",
33
34
  "@typescript-eslint/eslint-plugin": "6.7.3",
34
35
  "@typescript-eslint/parser": "6.7.3",
35
- "@types/bn.js": "^5.1.0",
36
36
  "eslint": "8.50.0",
37
37
  "eslint-config-prettier": "9.0.0",
38
38
  "eslint-plugin-prettier": "5.0.0",