@atomiqlabs/chain-solana 12.0.0 → 12.0.6

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.
@@ -1,6 +1,7 @@
1
- import {SolanaSwapData} from "./SolanaSwapData";
1
+ import {SolanaSwapData, InitInstruction} from "./SolanaSwapData";
2
2
  import {IdlAccounts} from "@coral-xyz/anchor";
3
3
  import {
4
+ ParsedTransactionWithMeta,
4
5
  PublicKey,
5
6
  } from "@solana/web3.js";
6
7
  import {sha256} from "@noble/hashes/sha2";
@@ -36,6 +37,7 @@ import {SolanaSigner} from "../wallet/SolanaSigner";
36
37
  import {fromClaimHash, toBN, toClaimHash, toEscrowHash} from "../../utils/Utils";
37
38
  import {SolanaTokens} from "../chain/modules/SolanaTokens";
38
39
  import * as BN from "bn.js";
40
+ import {ProgramEvent} from "../program/modules/SolanaProgramEvents";
39
41
 
40
42
  function toPublicKeyOrNull(str: string | null): PublicKey | null {
41
43
  return str==null ? null : new PublicKey(str);
@@ -271,21 +273,19 @@ export class SolanaSwapProgram
271
273
  }
272
274
 
273
275
  //Check if paid or what
274
- const status: SwapNotCommitedState | SwapExpiredState | SwapPaidState = await this.Events.findInEvents(escrowStateKey, async (event, info) => {
276
+ const status: SwapNotCommitedState | SwapExpiredState | SwapPaidState = await this.Events.findInEvents(escrowStateKey, async (event, tx) => {
275
277
  if(event.name==="ClaimEvent") {
276
278
  const paymentHash = Buffer.from(event.data.hash).toString("hex");
277
279
  if(paymentHash!==data.paymentHash) return null;
278
280
  if(!event.data.sequence.eq(data.sequence)) return null;
279
281
  return {
280
282
  type: SwapCommitStateType.PAID,
281
- getClaimTxId: () => Promise.resolve(info.signature),
283
+ getClaimTxId: () => Promise.resolve(tx.transaction.signatures[0]),
282
284
  getClaimResult: () => Promise.resolve(Buffer.from(event.data.secret).toString("hex")),
283
- getTxBlock: async () => {
284
- return {
285
- blockHeight: (await this.Chain.Blocks.getParsedBlock(info.slot)).blockHeight,
286
- blockTime: info.blockTime
287
- };
288
- }
285
+ getTxBlock: () => Promise.resolve({
286
+ blockHeight: tx.slot,
287
+ blockTime: tx.blockTime
288
+ })
289
289
  }
290
290
  }
291
291
  if(event.name==="RefundEvent") {
@@ -294,13 +294,11 @@ export class SolanaSwapProgram
294
294
  if(!event.data.sequence.eq(data.sequence)) return null;
295
295
  return {
296
296
  type: isExpired ? SwapCommitStateType.EXPIRED : SwapCommitStateType.NOT_COMMITED,
297
- getRefundTxId: () => Promise.resolve(info.signature),
298
- getTxBlock: async () => {
299
- return {
300
- blockHeight: (await this.Chain.Blocks.getParsedBlock(info.slot)).blockHeight,
301
- blockTime: info.blockTime
302
- };
303
- }
297
+ getRefundTxId: () => Promise.resolve(tx.transaction.signatures[0]),
298
+ getTxBlock: () => Promise.resolve({
299
+ blockHeight: tx.slot,
300
+ blockTime: tx.blockTime
301
+ })
304
302
  };
305
303
  }
306
304
  });
@@ -380,6 +378,138 @@ export class SolanaSwapProgram
380
378
  return SolanaSwapData.fromEscrowState(account);
381
379
  }
382
380
 
381
+ async getHistoricalSwaps(signer: string, startBlockheight?: number): Promise<{
382
+ swaps: {
383
+ [escrowHash: string]: {
384
+ init?: {
385
+ data: SolanaSwapData,
386
+ getInitTxId: () => Promise<string>,
387
+ getTxBlock: () => Promise<{
388
+ blockTime: number,
389
+ blockHeight: number
390
+ }>
391
+ },
392
+ state: SwapCommitState
393
+ }
394
+ },
395
+ latestBlockheight: number
396
+ }> {
397
+ let latestBlockheight: number;
398
+
399
+ const events: {event: ProgramEvent<SwapProgram>, tx: ParsedTransactionWithMeta}[] = [];
400
+
401
+ await this.Events.findInEvents(new PublicKey(signer), async (event, tx) => {
402
+ if(latestBlockheight==null) latestBlockheight = tx.slot;
403
+ events.push({event, tx});
404
+ }, undefined, undefined, startBlockheight);
405
+
406
+ const swapsOpened: {[escrowHash: string]: {
407
+ data: SolanaSwapData,
408
+ getInitTxId: () => Promise<string>,
409
+ getTxBlock: () => Promise<{
410
+ blockTime: number,
411
+ blockHeight: number
412
+ }>
413
+ }} = {};
414
+ const resultingSwaps: {
415
+ [escrowHash: string]: {
416
+ init?: {
417
+ data: SolanaSwapData,
418
+ getInitTxId: () => Promise<string>,
419
+ getTxBlock: () => Promise<{
420
+ blockTime: number,
421
+ blockHeight: number
422
+ }>
423
+ },
424
+ state: SwapCommitState
425
+ }
426
+ } = {};
427
+
428
+ events.reverse();
429
+ for(let {event, tx} of events) {
430
+ const txSignature = tx.transaction.signatures[0];
431
+ const paymentHash: string = Buffer.from(event.data.hash).toString("hex");
432
+ const escrowHash = toEscrowHash(paymentHash, event.data.sequence);
433
+
434
+ if(event.name==="InitializeEvent") {
435
+ //Parse swap data from initialize event
436
+ const txoHash: string = Buffer.from(event.data.txoHash).toString("hex");
437
+ const instructions = this.Events.decodeInstructions(tx.transaction.message);
438
+ if(instructions == null) {
439
+ this.logger.warn(`getHistoricalSwaps(): Skipping tx ${txSignature} because cannot parse instructions!`);
440
+ continue;
441
+ }
442
+
443
+ const initIx = instructions.find(
444
+ ix => ix!=null && (ix.name === "offererInitializePayIn" || ix.name === "offererInitialize")
445
+ ) as InitInstruction;
446
+ if(initIx == null) {
447
+ this.logger.warn(`getHistoricalSwaps(): Skipping tx ${txSignature} because cannot init instruction not found!`);
448
+ continue;
449
+ }
450
+
451
+ swapsOpened[escrowHash] = {
452
+ data: SolanaSwapData.fromInstruction(initIx, txoHash),
453
+ getInitTxId: () => Promise.resolve(txSignature),
454
+ getTxBlock: () => Promise.resolve({
455
+ blockHeight: tx.slot,
456
+ blockTime: tx.blockTime
457
+ })
458
+ };
459
+ }
460
+
461
+ if(event.name==="ClaimEvent") {
462
+ const foundSwapData = swapsOpened[escrowHash];
463
+ delete swapsOpened[escrowHash];
464
+ resultingSwaps[escrowHash] = {
465
+ init: foundSwapData,
466
+ state: {
467
+ type: SwapCommitStateType.PAID,
468
+ getClaimTxId: () => Promise.resolve(txSignature),
469
+ getClaimResult: () => Promise.resolve(Buffer.from(event.data.secret).toString("hex")),
470
+ getTxBlock: () => Promise.resolve({
471
+ blockHeight: tx.slot,
472
+ blockTime: tx.blockTime
473
+ })
474
+ }
475
+ }
476
+ }
477
+
478
+ if(event.name==="RefundEvent") {
479
+ const foundSwapData = swapsOpened[escrowHash];
480
+ delete swapsOpened[escrowHash];
481
+ const isExpired = foundSwapData!=null && await this.isExpired(signer, foundSwapData.data);
482
+ resultingSwaps[escrowHash] = {
483
+ init: foundSwapData,
484
+ state: {
485
+ type: isExpired ? SwapCommitStateType.EXPIRED : SwapCommitStateType.NOT_COMMITED,
486
+ getRefundTxId: () => Promise.resolve(txSignature),
487
+ getTxBlock: () => Promise.resolve({
488
+ blockHeight: tx.slot,
489
+ blockTime: tx.blockTime
490
+ })
491
+ }
492
+ }
493
+ }
494
+ }
495
+
496
+ for(let escrowHash in swapsOpened) {
497
+ const foundSwapData = swapsOpened[escrowHash];
498
+ const isExpired = await this.isExpired(signer, foundSwapData.data);
499
+ resultingSwaps[escrowHash] = {
500
+ init: foundSwapData,
501
+ state: foundSwapData.data.isOfferer(signer) && isExpired
502
+ ? {type: SwapCommitStateType.REFUNDABLE}
503
+ : {type: SwapCommitStateType.COMMITED}
504
+ }
505
+ }
506
+
507
+ return {
508
+ swaps: resultingSwaps,
509
+ latestBlockheight
510
+ }
511
+ }
512
+
383
513
  ////////////////////////////////////////////
384
514
  //// Swap data initializer
385
515
  createSwapData(