solotto 1.0.2 → 1.0.4

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.
package/README.md CHANGED
@@ -18,6 +18,7 @@ A JavaScript SDK for interacting with the Solotto on-chain lottery program on So
18
18
  - [Initialize](#initialize)
19
19
  - [RandomDraw](#randomdraw)
20
20
  - [LockLottery](#locklottery)
21
+ - [ClaimExpired](#claimexpired)
21
22
  - [Lottery](#lottery-api)
22
23
  - [BuyTickets](#buytickets)
23
24
  - [ClaimTicket](#claimticket)
@@ -198,6 +199,24 @@ await manager.LockLottery(authority, lotteryId, 1);
198
199
 
199
200
  ---
200
201
 
202
+ #### ClaimExpired
203
+
204
+ Reclaims the prize pool funds from an expired lottery where the winner did not claim in time. Only callable by the lottery authority.
205
+
206
+ ```js
207
+ const result = await manager.ClaimExpired(authority, lotteryId, encoded);
208
+ ```
209
+
210
+ | Parameter | Type | Default | Description |
211
+ |---|---|---|---|
212
+ | `authority` | `Keypair` | — | The lottery authority keypair. |
213
+ | `lotteryId` | `String` | — | The lottery ID. |
214
+ | `encoded` | `Boolean` | `false` | If `true`, returns encoded transaction. |
215
+
216
+ **Returns:** Updated lottery state object on finalization, or the transaction object when encoded.
217
+
218
+ ---
219
+
201
220
  ### Lottery API
202
221
 
203
222
  #### BuyTickets
@@ -282,12 +301,14 @@ const state = await lottery.GetLottery(authority, lotteryId, fees);
282
301
  ticketPrice: 100000000, // Ticket price in lamports
283
302
  totalTickets: 42, // Total tickets sold
284
303
  winnerTicketNumber: 17, // Winning ticket number (0/null if not drawn)
285
- winnerAddress: "Pubkey...", // Winner's public key (null if not drawn)
304
+ winnerAddress: "Pubkey...", // Winner's public key as string (null if not drawn)
286
305
  isActive: true, // Whether the lottery is active
287
306
  prizePoolBalance: 3780000000, // Prize pool in lamports (after fees if fees=true)
288
307
  drawInitiated: false, // Whether a draw has been initiated
289
308
  prizePoolAddress: "Pubkey...", // Prize pool PDA
290
309
  lotteryAddress: "Pubkey...", // Lottery PDA
310
+ release: "Pubkey...", // Release address (lottery PDA)
311
+ releaseTime: null, // Unix timestamp when unclaimed prizes can be released (null if not set)
291
312
  }
292
313
  ```
293
314
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solotto",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Solana lottery client",
5
5
  "type": "module",
6
6
  "types": "./solotto.d.ts",
package/solotto.d.ts CHANGED
@@ -62,7 +62,7 @@ declare module "solotto" {
62
62
  totalTickets: number;
63
63
  /** Winning ticket number, or `0`/`null` if not yet drawn. */
64
64
  winnerTicketNumber: number | null;
65
- /** Winner's public key, or `null` if not yet drawn. */
65
+ /** Winner's public key as a base-58 string, or `null` if not yet drawn. */
66
66
  winnerAddress: string | null;
67
67
  /** Whether the lottery is currently active. */
68
68
  isActive: boolean;
@@ -74,6 +74,10 @@ declare module "solotto" {
74
74
  prizePoolAddress: string;
75
75
  /** Lottery PDA as a base-58 string. */
76
76
  lotteryAddress: string;
77
+ /** Release address (lottery PDA) as a base-58 string. */
78
+ release: string;
79
+ /** Unix timestamp when unclaimed prizes can be released, or `null` if not set. */
80
+ releaseTime: number | null;
77
81
  }
78
82
 
79
83
  // ── Ticket State ──────────────────────────────────────────────────────
@@ -321,5 +325,17 @@ declare module "solotto" {
321
325
  lockState: 0 | 1,
322
326
  encoded?: boolean
323
327
  ): Promise<LotteryState | string | TxResult | undefined>;
328
+
329
+ /**
330
+ * Reclaim prize pool funds from an expired lottery where the winner did not claim in time.
331
+ * @param authority - The lottery authority keypair.
332
+ * @param lotteryId - Lottery numeric identifier.
333
+ * @param encoded - If `true`, return a base64-encoded transaction.
334
+ */
335
+ ClaimExpired(
336
+ authority: Keypair,
337
+ lotteryId: number,
338
+ encoded?: boolean
339
+ ): Promise<LotteryState | string | TxResult | undefined>;
324
340
  }
325
- }
341
+ }
package/solotto.js CHANGED
@@ -10,9 +10,10 @@ import {EventEmitter} from 'events';
10
10
  const INSTRUCTIONS = {
11
11
  INITIALIZE_LOTTERY: 0,
12
12
  BUY_TICKET: 1,
13
- ENTROPY: 2,
13
+ DRAW_WINNER: 2,
14
14
  CLAIM_PRIZE: 3,
15
15
  LOCK_LOTTERY: 4,
16
+ RELEASE_EXPIRED: 5,
16
17
  };
17
18
 
18
19
  class LotteryNetwork {
@@ -496,12 +497,16 @@ class Lottery extends EventEmitter {
496
497
  offset += 8;
497
498
  return val;
498
499
  });
500
+
499
501
  // 6. winner_address: Option<Pubkey> (1 + 32 bytes)
500
- const winnerAddress = readOption(() => {
501
- const val = buffer.slice(offset, offset + 32);
502
- offset += 32;
503
- return val;
504
- });
502
+ let winnerAddress = null;
503
+ try{
504
+ winnerAddress = readOption(() => {
505
+ const val = buffer.slice(offset, offset + 32);
506
+ offset += 32;
507
+ return new PublicKey(val).toString();
508
+ });
509
+ }catch{}
505
510
  // 7. is_active: bool (1 byte)
506
511
  const isActive = buffer.readUInt8(offset) === 1;
507
512
  offset += 1;
@@ -510,6 +515,15 @@ class Lottery extends EventEmitter {
510
515
  offset += 8;
511
516
  const drawInitiated = buffer.readUInt8(offset) === 1;
512
517
  offset += 1;
518
+ // 9. draw_timestamp: Option<u64> (1 + 8 bytes)
519
+ let releaseTime = null;
520
+ try{
521
+ releaseTime = readOption(() => {
522
+ const val = buffer.readBigUInt64LE(offset);
523
+ offset += 8;
524
+ return Number(releaseTime);
525
+ });
526
+ }catch{}
513
527
  const prizePoolAddress = await this.DerivePrizePoolPDA();
514
528
  const lotteryAddress = await this.DeriveLotteryPDA(new PublicKey(auth), lotteryId);
515
529
  let prizePoolBalance = prizePool;
@@ -526,6 +540,8 @@ class Lottery extends EventEmitter {
526
540
  drawInitiated,
527
541
  prizePoolAddress: prizePoolAddress[0].toString(),
528
542
  lotteryAddress: lotteryAddress[0].toString(),
543
+ release: lotteryAddress[0].toString(),
544
+ releaseTime,
529
545
  };
530
546
  };
531
547
 
@@ -625,7 +641,7 @@ class LotteryManager {
625
641
  try{
626
642
  async function randomnessData() {
627
643
  const buffer = Buffer.alloc(1);
628
- buffer.writeUInt8(INSTRUCTIONS.ENTROPY, 0);
644
+ buffer.writeUInt8(INSTRUCTIONS.DRAW_WINNER, 0);
629
645
  return buffer;
630
646
  }
631
647
  const lottery = new Lottery(this.connection, false, this.program);
@@ -635,8 +651,7 @@ class LotteryManager {
635
651
  const keys = [
636
652
  { pubkey: authority.publicKey, isSigner: true, isWritable: false },
637
653
  { pubkey: lotteryPDA, isSigner: false, isWritable: true },
638
- { pubkey: SYSVAR_RECENT_BLOCKHASHES_PUBKEY, isSigner: false, isWritable: false },
639
- { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false },
654
+ { pubkey: SYSVAR_SLOT_HASHES_PUBKEY, isSigner: false, isWritable: false },
640
655
  { pubkey: prizePoolPDA, isSigner: false, isWritable: true },
641
656
  { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
642
657
  ];
@@ -737,6 +752,66 @@ class LotteryManager {
737
752
  }
738
753
  }
739
754
 
755
+ /**
756
+ * @param {Keypair} authority - Keypair
757
+ * @param {String} lotteryId - The lottery id
758
+ * @param {Boolean} encoded - true returns encoded transaction
759
+ */
760
+ async ClaimExpired(authority, lotteryId, encoded = false) {
761
+ try{
762
+ async function expiredData() {
763
+ const buffer = Buffer.alloc(1); // 1 byte discriminator + 1 bytes lock status
764
+ buffer.writeUInt8(INSTRUCTIONS.RELEASE_EXPIRED, 0); // lock discriminator
765
+ return buffer;
766
+ }
767
+ const lottery = new Lottery(this.connection, false, this.program);
768
+ const network = new LotteryNetwork(this.connection);
769
+ const [lotteryPDA] = await lottery.DeriveLotteryPDA(authority.publicKey, lotteryId);
770
+ const LOTTO = await lottery.GetLottery(authority, lotteryId);
771
+ const keys = [
772
+ { pubkey: authority.publicKey, isSigner: true, isWritable: true },
773
+ { pubkey: lotteryPDA, isSigner: false, isWritable: true },
774
+ { pubkey: new PublicKey(LOTTO.prizePoolAddress), isSigner: false, isWritable: true },
775
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
776
+ ];
777
+ const ix = new TransactionInstruction({programId: this.program, keys, data: await expiredData()});
778
+ const _tx_ = {};
779
+ _tx_.account = authority.publicKey.toString(); // string : required
780
+ _tx_.instructions = [ix]; // array : required
781
+ _tx_.signers = false; // array : default false
782
+ _tx_.table = false; // array : default false
783
+ _tx_.tolerance = 1.2; // int : default 1.1
784
+ _tx_.compute = true; // bool : default true
785
+ _tx_.fees = true; // bool : default true
786
+ _tx_.priority = "Low"; // string : default Low
787
+ _tx_.memo = false;
788
+ if(encoded){
789
+ _tx_.serialize = true;
790
+ _tx_.encode = true;
791
+ }
792
+ else{
793
+ _tx_.serialize = false;
794
+ _tx_.encode = false;
795
+ }
796
+ const tx = await network.Tx(_tx_); // build the tx
797
+ if(tx.status !== "ok"){return tx;}
798
+ if(authority.secretKey && !encoded){
799
+ tx.transaction.sign([authority]);
800
+ const sig = await network.Send(tx.transaction);
801
+ console.log("Signature:", sig);
802
+ const status = await network.Status(sig);
803
+ if(status == "finalized"){
804
+ return await lottery.GetLottery({publicKey: authority.publicKey}, lotteryId, false);
805
+ }
806
+ else{return status;}
807
+ }
808
+ else{return tx;}
809
+ }
810
+ catch (error) {
811
+ console.log(error);
812
+ }
813
+ }
814
+
740
815
  }
741
816
 
742
817
  export {