@atomiqlabs/chain-solana 11.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.
- package/dist/solana/SolanaChainType.d.ts +2 -1
- package/dist/solana/chain/SolanaChainInterface.d.ts +8 -1
- package/dist/solana/chain/SolanaChainInterface.js +13 -0
- package/dist/solana/chain/modules/SolanaEvents.d.ts +45 -2
- package/dist/solana/chain/modules/SolanaEvents.js +167 -2
- package/dist/solana/chain/modules/SolanaTransactions.js +17 -26
- package/dist/solana/events/SolanaChainEventsBrowser.d.ts +1 -11
- package/dist/solana/events/SolanaChainEventsBrowser.js +1 -23
- package/dist/solana/program/modules/SolanaProgramEvents.d.ts +3 -9
- package/dist/solana/program/modules/SolanaProgramEvents.js +38 -27
- package/dist/solana/swaps/SolanaSwapData.d.ts +13 -1
- package/dist/solana/swaps/SolanaSwapData.js +25 -0
- package/dist/solana/swaps/SolanaSwapProgram.d.ts +26 -4
- package/dist/solana/swaps/SolanaSwapProgram.js +116 -19
- package/dist/solana/wallet/SolanaSigner.d.ts +1 -0
- package/dist/solana/wallet/SolanaSigner.js +1 -0
- package/package.json +2 -2
- package/src/solana/SolanaChainType.ts +2 -0
- package/src/solana/chain/SolanaChainInterface.ts +19 -1
- package/src/solana/chain/modules/SolanaEvents.ts +199 -5
- package/src/solana/chain/modules/SolanaTransactions.ts +17 -22
- package/src/solana/events/SolanaChainEventsBrowser.ts +4 -51
- package/src/solana/program/modules/SolanaProgramEvents.ts +44 -29
- package/src/solana/swaps/SolanaSwapData.ts +52 -1
- package/src/solana/swaps/SolanaSwapProgram.ts +172 -20
- package/src/solana/wallet/SolanaSigner.ts +1 -0
|
@@ -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,11 +37,14 @@ 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);
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
const MAX_PARALLEL_COMMIT_STATUS_CHECKS = 5;
|
|
47
|
+
|
|
44
48
|
export class SolanaSwapProgram
|
|
45
49
|
extends SolanaProgramBase<SwapProgram>
|
|
46
50
|
implements SwapContract<
|
|
@@ -269,21 +273,19 @@ export class SolanaSwapProgram
|
|
|
269
273
|
}
|
|
270
274
|
|
|
271
275
|
//Check if paid or what
|
|
272
|
-
const status: SwapNotCommitedState | SwapExpiredState | SwapPaidState = await this.Events.findInEvents(escrowStateKey, async (event,
|
|
276
|
+
const status: SwapNotCommitedState | SwapExpiredState | SwapPaidState = await this.Events.findInEvents(escrowStateKey, async (event, tx) => {
|
|
273
277
|
if(event.name==="ClaimEvent") {
|
|
274
278
|
const paymentHash = Buffer.from(event.data.hash).toString("hex");
|
|
275
279
|
if(paymentHash!==data.paymentHash) return null;
|
|
276
280
|
if(!event.data.sequence.eq(data.sequence)) return null;
|
|
277
281
|
return {
|
|
278
282
|
type: SwapCommitStateType.PAID,
|
|
279
|
-
getClaimTxId: () => Promise.resolve(
|
|
283
|
+
getClaimTxId: () => Promise.resolve(tx.transaction.signatures[0]),
|
|
280
284
|
getClaimResult: () => Promise.resolve(Buffer.from(event.data.secret).toString("hex")),
|
|
281
|
-
getTxBlock:
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
};
|
|
286
|
-
}
|
|
285
|
+
getTxBlock: () => Promise.resolve({
|
|
286
|
+
blockHeight: tx.slot,
|
|
287
|
+
blockTime: tx.blockTime
|
|
288
|
+
})
|
|
287
289
|
}
|
|
288
290
|
}
|
|
289
291
|
if(event.name==="RefundEvent") {
|
|
@@ -292,13 +294,11 @@ export class SolanaSwapProgram
|
|
|
292
294
|
if(!event.data.sequence.eq(data.sequence)) return null;
|
|
293
295
|
return {
|
|
294
296
|
type: isExpired ? SwapCommitStateType.EXPIRED : SwapCommitStateType.NOT_COMMITED,
|
|
295
|
-
getRefundTxId: () => Promise.resolve(
|
|
296
|
-
getTxBlock:
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
};
|
|
301
|
-
}
|
|
297
|
+
getRefundTxId: () => Promise.resolve(tx.transaction.signatures[0]),
|
|
298
|
+
getTxBlock: () => Promise.resolve({
|
|
299
|
+
blockHeight: tx.slot,
|
|
300
|
+
blockTime: tx.blockTime
|
|
301
|
+
})
|
|
302
302
|
};
|
|
303
303
|
}
|
|
304
304
|
});
|
|
@@ -308,6 +308,26 @@ export class SolanaSwapProgram
|
|
|
308
308
|
return {type: SwapCommitStateType.NOT_COMMITED};
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
async getCommitStatuses(request: { signer: string; swapData: SolanaSwapData }[]): Promise<{
|
|
312
|
+
[p: string]: SwapCommitState
|
|
313
|
+
}> {
|
|
314
|
+
const result: {
|
|
315
|
+
[p: string]: SwapCommitState
|
|
316
|
+
} = {};
|
|
317
|
+
let promises: Promise<void>[] = [];
|
|
318
|
+
for(let {signer, swapData} of request) {
|
|
319
|
+
promises.push(this.getCommitStatus(signer, swapData).then(val => {
|
|
320
|
+
result[swapData.getEscrowHash()] = val;
|
|
321
|
+
}));
|
|
322
|
+
if(promises.length>=MAX_PARALLEL_COMMIT_STATUS_CHECKS) {
|
|
323
|
+
await Promise.all(promises);
|
|
324
|
+
promises = [];
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
await Promise.all(promises);
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
|
|
311
331
|
/**
|
|
312
332
|
* Checks the status of the specific payment hash
|
|
313
333
|
*
|
|
@@ -358,6 +378,138 @@ export class SolanaSwapProgram
|
|
|
358
378
|
return SolanaSwapData.fromEscrowState(account);
|
|
359
379
|
}
|
|
360
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
|
+
|
|
361
513
|
////////////////////////////////////////////
|
|
362
514
|
//// Swap data initializer
|
|
363
515
|
createSwapData(
|
|
@@ -662,28 +814,28 @@ export class SolanaSwapProgram
|
|
|
662
814
|
/**
|
|
663
815
|
* Get the estimated solana fee of the commit transaction
|
|
664
816
|
*/
|
|
665
|
-
getCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
817
|
+
getCommitFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
666
818
|
return this.Init.getInitFee(swapData, feeRate);
|
|
667
819
|
}
|
|
668
820
|
|
|
669
821
|
/**
|
|
670
822
|
* Get the estimated solana fee of the commit transaction, without any deposits
|
|
671
823
|
*/
|
|
672
|
-
getRawCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
824
|
+
getRawCommitFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
673
825
|
return this.Init.getRawInitFee(swapData, feeRate);
|
|
674
826
|
}
|
|
675
827
|
|
|
676
828
|
/**
|
|
677
829
|
* Get the estimated solana transaction fee of the refund transaction
|
|
678
830
|
*/
|
|
679
|
-
getRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
831
|
+
getRefundFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
680
832
|
return this.Refund.getRefundFee(swapData, feeRate);
|
|
681
833
|
}
|
|
682
834
|
|
|
683
835
|
/**
|
|
684
836
|
* Get the estimated solana transaction fee of the refund transaction
|
|
685
837
|
*/
|
|
686
|
-
getRawRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
838
|
+
getRawRefundFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
687
839
|
return this.Refund.getRawRefundFee(swapData, feeRate);
|
|
688
840
|
}
|
|
689
841
|
|