@atomiqlabs/chain-solana 13.3.0 → 13.5.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/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/solana/SolanaChainType.d.ts +1 -1
- package/dist/solana/SolanaChains.d.ts +5 -2
- package/dist/solana/SolanaChains.js +25 -13
- package/dist/solana/SolanaInitializer.d.ts +30 -4
- package/dist/solana/SolanaInitializer.js +105 -15
- package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +4 -2
- package/dist/solana/btcrelay/SolanaBtcRelay.js +7 -1
- package/dist/solana/chain/SolanaAction.d.ts +1 -1
- package/dist/solana/chain/SolanaAction.js +2 -2
- package/dist/solana/chain/SolanaChainInterface.d.ts +6 -1
- package/dist/solana/chain/SolanaChainInterface.js +30 -0
- package/dist/solana/events/SolanaChainEvents.d.ts +5 -1
- package/dist/solana/events/SolanaChainEvents.js +16 -6
- package/dist/solana/events/SolanaChainEventsBrowser.d.ts +39 -16
- package/dist/solana/events/SolanaChainEventsBrowser.js +96 -61
- package/dist/solana/swaps/SolanaSwapData.d.ts +50 -5
- package/dist/solana/swaps/SolanaSwapData.js +52 -8
- package/dist/solana/swaps/SolanaSwapModule.d.ts +4 -3
- package/dist/solana/swaps/SolanaSwapProgram.d.ts +12 -6
- package/dist/solana/swaps/SolanaSwapProgram.js +73 -47
- package/dist/solana/swaps/modules/SwapClaim.js +2 -0
- package/dist/solana/swaps/modules/SwapInit.d.ts +10 -5
- package/dist/solana/swaps/modules/SwapInit.js +222 -85
- package/dist/solana/swaps/modules/SwapRefund.d.ts +8 -2
- package/dist/solana/swaps/modules/SwapRefund.js +38 -22
- package/dist/solana/swaps/v1/programIdl.json +945 -0
- package/dist/solana/swaps/v1/programTypes.d.ts +943 -0
- package/dist/solana/swaps/v1/programTypes.js +945 -0
- package/dist/solana/swaps/v2/programIdl.json +952 -0
- package/dist/solana/swaps/v2/programTypes.d.ts +950 -0
- package/dist/solana/swaps/v2/programTypes.js +952 -0
- package/package.json +2 -2
- package/src/index.ts +2 -2
- package/src/solana/SolanaChainType.ts +2 -2
- package/src/solana/SolanaChains.ts +29 -14
- package/src/solana/SolanaInitializer.ts +147 -25
- package/src/solana/btcrelay/SolanaBtcRelay.ts +10 -2
- package/src/solana/chain/SolanaAction.ts +2 -2
- package/src/solana/chain/SolanaChainInterface.ts +35 -1
- package/src/solana/events/SolanaChainEvents.ts +22 -11
- package/src/solana/events/SolanaChainEventsBrowser.ts +110 -67
- package/src/solana/swaps/SolanaSwapData.ts +95 -11
- package/src/solana/swaps/SolanaSwapModule.ts +5 -3
- package/src/solana/swaps/SolanaSwapProgram.ts +87 -43
- package/src/solana/swaps/modules/SolanaLpVault.ts +2 -2
- package/src/solana/swaps/modules/SwapClaim.ts +3 -1
- package/src/solana/swaps/modules/SwapInit.ts +227 -99
- package/src/solana/swaps/modules/SwapRefund.ts +38 -20
- package/src/solana/swaps/v2/programIdl.json +952 -0
- package/src/solana/swaps/v2/programTypes.ts +1899 -0
- /package/src/solana/swaps/{programIdl.json → v1/programIdl.json} +0 -0
- /package/src/solana/swaps/{programTypes.ts → v1/programTypes.ts} +0 -0
|
@@ -4,7 +4,7 @@ import { IdlEvents } from "@coral-xyz/anchor";
|
|
|
4
4
|
import { SolanaSwapProgram } from "../swaps/SolanaSwapProgram";
|
|
5
5
|
import { Connection } from "@solana/web3.js";
|
|
6
6
|
import { InstructionWithAccounts, ProgramEvent } from "../program/modules/SolanaProgramEvents";
|
|
7
|
-
import { SwapProgram } from "../swaps/programTypes";
|
|
7
|
+
import { SwapProgram } from "../swaps/v1/programTypes";
|
|
8
8
|
/**
|
|
9
9
|
* Parsed event payload grouped by originating transaction metadata.
|
|
10
10
|
*
|
|
@@ -17,11 +17,11 @@ export type EventObject = {
|
|
|
17
17
|
signature: string;
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Legacy current cursor of Solana event listener state.
|
|
21
21
|
*
|
|
22
22
|
* @category Events
|
|
23
23
|
*/
|
|
24
|
-
export type
|
|
24
|
+
export type SolanaLegacyEventListenerState = {
|
|
25
25
|
/**
|
|
26
26
|
* Last processed transaction's signature
|
|
27
27
|
*/
|
|
@@ -31,6 +31,14 @@ export type SolanaEventListenerState = {
|
|
|
31
31
|
*/
|
|
32
32
|
slot: number;
|
|
33
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* Current cursor of Solana event listener state.
|
|
36
|
+
*
|
|
37
|
+
* @category Events
|
|
38
|
+
*/
|
|
39
|
+
export type SolanaEventListenerState = {
|
|
40
|
+
[version: string]: SolanaLegacyEventListenerState | null;
|
|
41
|
+
};
|
|
34
42
|
/**
|
|
35
43
|
* Solana on-chain event handler for front-end systems without access to fs, uses pure WS to subscribe, might lose
|
|
36
44
|
* out on some events if the network is unreliable, front-end systems should take this into consideration and not
|
|
@@ -38,7 +46,7 @@ export type SolanaEventListenerState = {
|
|
|
38
46
|
*
|
|
39
47
|
* @category Events
|
|
40
48
|
*/
|
|
41
|
-
export declare class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapData, SolanaEventListenerState> {
|
|
49
|
+
export declare class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapData, SolanaLegacyEventListenerState | SolanaEventListenerState> {
|
|
42
50
|
/**
|
|
43
51
|
* @internal
|
|
44
52
|
*/
|
|
@@ -50,11 +58,17 @@ export declare class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapD
|
|
|
50
58
|
/**
|
|
51
59
|
* @internal
|
|
52
60
|
*/
|
|
53
|
-
protected readonly
|
|
61
|
+
protected readonly contractVersions: {
|
|
62
|
+
[version: string]: {
|
|
63
|
+
swapContract: SolanaSwapProgram;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
54
66
|
/**
|
|
55
67
|
* @internal
|
|
56
68
|
*/
|
|
57
|
-
protected eventListeners:
|
|
69
|
+
protected eventListeners: {
|
|
70
|
+
[version: string]: number[];
|
|
71
|
+
};
|
|
58
72
|
/**
|
|
59
73
|
* @internal
|
|
60
74
|
*/
|
|
@@ -62,21 +76,24 @@ export declare class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapD
|
|
|
62
76
|
debug: (msg: string, ...args: any[]) => false | void;
|
|
63
77
|
info: (msg: string, ...args: any[]) => false | void;
|
|
64
78
|
warn: (msg: string, ...args: any[]) => false | void;
|
|
65
|
-
error: (msg: string, ...args: any[]) => false | void;
|
|
66
|
-
* @internal
|
|
67
|
-
*/
|
|
79
|
+
error: (msg: string, ...args: any[]) => false | void;
|
|
68
80
|
};
|
|
69
81
|
private readonly logFetchLimit;
|
|
70
82
|
private signaturesProcessing;
|
|
71
83
|
private processedSignatures;
|
|
72
84
|
private processedSignaturesIndex;
|
|
73
|
-
constructor(connection: Connection,
|
|
85
|
+
constructor(connection: Connection, contractVersions: SolanaSwapProgram | {
|
|
86
|
+
[version: string]: {
|
|
87
|
+
swapContract: SolanaSwapProgram;
|
|
88
|
+
};
|
|
89
|
+
}, logFetchLimit?: number);
|
|
74
90
|
private addProcessedSignature;
|
|
75
91
|
private isSignatureProcessed;
|
|
76
92
|
/**
|
|
77
93
|
* Parses EventObject from the transaction
|
|
78
94
|
*
|
|
79
95
|
* @param transaction
|
|
96
|
+
* @param version
|
|
80
97
|
* @private
|
|
81
98
|
* @returns {EventObject} parsed event object
|
|
82
99
|
*/
|
|
@@ -85,6 +102,7 @@ export declare class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapD
|
|
|
85
102
|
* Fetches transaction from the RPC, parses it to even object & processes it through event handler
|
|
86
103
|
*
|
|
87
104
|
* @param signature
|
|
105
|
+
* @param version
|
|
88
106
|
* @private
|
|
89
107
|
* @returns {boolean} whether the operation was successful
|
|
90
108
|
*/
|
|
@@ -101,6 +119,7 @@ export declare class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapD
|
|
|
101
119
|
*
|
|
102
120
|
* @param eventObject
|
|
103
121
|
* @param txoHash
|
|
122
|
+
* @param version
|
|
104
123
|
* @private
|
|
105
124
|
* @returns {() => Promise<SolanaSwapData>} getter to be passed to InitializeEvent constructor
|
|
106
125
|
*/
|
|
@@ -108,30 +127,32 @@ export declare class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapD
|
|
|
108
127
|
/**
|
|
109
128
|
* @internal
|
|
110
129
|
*/
|
|
111
|
-
protected parseInitializeEvent(data: IdlEvents<SwapProgram>["InitializeEvent"], eventObject: EventObject): InitializeEvent<SolanaSwapData>;
|
|
130
|
+
protected parseInitializeEvent(data: IdlEvents<SwapProgram>["InitializeEvent"], eventObject: EventObject, version: string): InitializeEvent<SolanaSwapData>;
|
|
112
131
|
/**
|
|
113
132
|
* @internal
|
|
114
133
|
*/
|
|
115
|
-
protected parseRefundEvent(data: IdlEvents<SwapProgram>["RefundEvent"]): RefundEvent<SolanaSwapData>;
|
|
134
|
+
protected parseRefundEvent(data: IdlEvents<SwapProgram>["RefundEvent"], version: string): RefundEvent<SolanaSwapData>;
|
|
116
135
|
/**
|
|
117
136
|
* @internal
|
|
118
137
|
*/
|
|
119
|
-
protected parseClaimEvent(data: IdlEvents<SwapProgram>["ClaimEvent"]): ClaimEvent<SolanaSwapData>;
|
|
138
|
+
protected parseClaimEvent(data: IdlEvents<SwapProgram>["ClaimEvent"], version: string): ClaimEvent<SolanaSwapData>;
|
|
120
139
|
/**
|
|
121
140
|
* Processes event as received from the chain, parses it & calls event listeners
|
|
122
141
|
*
|
|
123
142
|
* @param eventObject
|
|
143
|
+
* @param version
|
|
124
144
|
* @internal
|
|
125
145
|
*/
|
|
126
|
-
protected processEvent(eventObject: EventObject): Promise<void>;
|
|
146
|
+
protected processEvent(eventObject: EventObject, version: string): Promise<void>;
|
|
127
147
|
/**
|
|
128
148
|
* Returns websocket event handler for specific event type
|
|
129
149
|
*
|
|
130
150
|
* @param name
|
|
151
|
+
* @param version
|
|
131
152
|
* @internal
|
|
132
153
|
* @returns event handler to be passed to program's addEventListener function
|
|
133
154
|
*/
|
|
134
|
-
protected getWsEventHandler<E extends "InitializeEvent" | "RefundEvent" | "ClaimEvent">(name: E): (data: IdlEvents<SwapProgram>[E], slotNumber: number, signature: string) => void;
|
|
155
|
+
protected getWsEventHandler<E extends "InitializeEvent" | "RefundEvent" | "ClaimEvent">(name: E, version: string): (data: IdlEvents<SwapProgram>[E], slotNumber: number, signature: string) => void;
|
|
135
156
|
/**
|
|
136
157
|
* Sets up event handlers listening for swap events over websocket
|
|
137
158
|
*
|
|
@@ -142,6 +163,7 @@ export declare class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapD
|
|
|
142
163
|
* Gets all the new signatures from the last processed signature
|
|
143
164
|
*
|
|
144
165
|
* @param lastProcessedSignature
|
|
166
|
+
* @param version
|
|
145
167
|
* @private
|
|
146
168
|
*/
|
|
147
169
|
private getNewSignatures;
|
|
@@ -155,6 +177,7 @@ export declare class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapD
|
|
|
155
177
|
* Processes signatures, fetches transactions & processes event through event handlers
|
|
156
178
|
*
|
|
157
179
|
* @param signatures
|
|
180
|
+
* @param version
|
|
158
181
|
* @private
|
|
159
182
|
* @returns {Promise<{signature: string, slot: number}>} latest processed transaction signature and slot height
|
|
160
183
|
*/
|
|
@@ -162,7 +185,7 @@ export declare class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapD
|
|
|
162
185
|
/**
|
|
163
186
|
* @inheritDoc
|
|
164
187
|
*/
|
|
165
|
-
poll(lastSignature?: SolanaEventListenerState): Promise<SolanaEventListenerState
|
|
188
|
+
poll(lastSignature?: SolanaLegacyEventListenerState | SolanaEventListenerState): Promise<SolanaEventListenerState>;
|
|
166
189
|
/**
|
|
167
190
|
* @inheritDoc
|
|
168
191
|
*/
|
|
@@ -3,11 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SolanaChainEventsBrowser = void 0;
|
|
4
4
|
const base_1 = require("@atomiqlabs/base");
|
|
5
5
|
const SolanaSwapData_1 = require("../swaps/SolanaSwapData");
|
|
6
|
+
const SolanaSwapProgram_1 = require("../swaps/SolanaSwapProgram");
|
|
6
7
|
const Utils_1 = require("../../utils/Utils");
|
|
7
8
|
const SwapTypeEnum_1 = require("../swaps/SwapTypeEnum");
|
|
8
9
|
const buffer_1 = require("buffer");
|
|
9
10
|
const LOG_FETCH_LIMIT = 500;
|
|
10
|
-
const PROCESSED_SIGNATURES_BACKLOG =
|
|
11
|
+
const PROCESSED_SIGNATURES_BACKLOG = 500;
|
|
12
|
+
function toNewEventListenerState(obj) {
|
|
13
|
+
if (obj == null)
|
|
14
|
+
return undefined;
|
|
15
|
+
if (obj.slot != null || obj.signature != null)
|
|
16
|
+
return { "v1": obj };
|
|
17
|
+
return obj;
|
|
18
|
+
}
|
|
11
19
|
/**
|
|
12
20
|
* Solana on-chain event handler for front-end systems without access to fs, uses pure WS to subscribe, might lose
|
|
13
21
|
* out on some events if the network is unreliable, front-end systems should take this into consideration and not
|
|
@@ -16,7 +24,7 @@ const PROCESSED_SIGNATURES_BACKLOG = 100;
|
|
|
16
24
|
* @category Events
|
|
17
25
|
*/
|
|
18
26
|
class SolanaChainEventsBrowser {
|
|
19
|
-
constructor(connection,
|
|
27
|
+
constructor(connection, contractVersions, logFetchLimit) {
|
|
20
28
|
/**
|
|
21
29
|
* @internal
|
|
22
30
|
*/
|
|
@@ -24,7 +32,7 @@ class SolanaChainEventsBrowser {
|
|
|
24
32
|
/**
|
|
25
33
|
* @internal
|
|
26
34
|
*/
|
|
27
|
-
this.eventListeners =
|
|
35
|
+
this.eventListeners = {};
|
|
28
36
|
/**
|
|
29
37
|
* @internal
|
|
30
38
|
*/
|
|
@@ -33,33 +41,39 @@ class SolanaChainEventsBrowser {
|
|
|
33
41
|
this.processedSignatures = [];
|
|
34
42
|
this.processedSignaturesIndex = 0;
|
|
35
43
|
this.connection = connection;
|
|
36
|
-
|
|
44
|
+
if (contractVersions instanceof SolanaSwapProgram_1.SolanaSwapProgram) {
|
|
45
|
+
this.contractVersions = { [contractVersions.version]: { swapContract: contractVersions } };
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this.contractVersions = contractVersions;
|
|
49
|
+
}
|
|
37
50
|
this.logFetchLimit = logFetchLimit ?? LOG_FETCH_LIMIT;
|
|
38
51
|
}
|
|
39
|
-
addProcessedSignature(signature) {
|
|
40
|
-
this.processedSignatures[this.processedSignaturesIndex] = signature;
|
|
52
|
+
addProcessedSignature(signature, version) {
|
|
53
|
+
this.processedSignatures[this.processedSignaturesIndex] = signature + "-" + version;
|
|
41
54
|
this.processedSignaturesIndex += 1;
|
|
42
55
|
if (this.processedSignaturesIndex >= PROCESSED_SIGNATURES_BACKLOG)
|
|
43
56
|
this.processedSignaturesIndex = 0;
|
|
44
57
|
}
|
|
45
|
-
isSignatureProcessed(signature) {
|
|
46
|
-
return this.processedSignatures.includes(signature);
|
|
58
|
+
isSignatureProcessed(signature, version) {
|
|
59
|
+
return this.processedSignatures.includes(signature + "-" + version);
|
|
47
60
|
}
|
|
48
61
|
/**
|
|
49
62
|
* Parses EventObject from the transaction
|
|
50
63
|
*
|
|
51
64
|
* @param transaction
|
|
65
|
+
* @param version
|
|
52
66
|
* @private
|
|
53
67
|
* @returns {EventObject} parsed event object
|
|
54
68
|
*/
|
|
55
|
-
getEventObjectFromTransaction(transaction) {
|
|
69
|
+
getEventObjectFromTransaction(transaction, version) {
|
|
56
70
|
const signature = transaction.transaction.signatures[0];
|
|
57
71
|
if (transaction.meta == null)
|
|
58
72
|
throw new Error(`Transaction 'meta' not found for Solana tx: ${signature}`);
|
|
59
73
|
if (transaction.meta.err != null || transaction.meta.logMessages == null)
|
|
60
74
|
return null;
|
|
61
|
-
const instructions = this.
|
|
62
|
-
const events = this.
|
|
75
|
+
const instructions = this.contractVersions[version].swapContract._Events.decodeInstructions(transaction.transaction.message);
|
|
76
|
+
const events = this.contractVersions[version].swapContract._Events.parseLogs(transaction.meta.logMessages);
|
|
63
77
|
return {
|
|
64
78
|
instructions,
|
|
65
79
|
events,
|
|
@@ -71,10 +85,11 @@ class SolanaChainEventsBrowser {
|
|
|
71
85
|
* Fetches transaction from the RPC, parses it to even object & processes it through event handler
|
|
72
86
|
*
|
|
73
87
|
* @param signature
|
|
88
|
+
* @param version
|
|
74
89
|
* @private
|
|
75
90
|
* @returns {boolean} whether the operation was successful
|
|
76
91
|
*/
|
|
77
|
-
async fetchTxAndProcessEvent(signature) {
|
|
92
|
+
async fetchTxAndProcessEvent(signature, version) {
|
|
78
93
|
try {
|
|
79
94
|
const transaction = await this.connection.getParsedTransaction(signature, {
|
|
80
95
|
commitment: "confirmed",
|
|
@@ -82,10 +97,10 @@ class SolanaChainEventsBrowser {
|
|
|
82
97
|
});
|
|
83
98
|
if (transaction == null)
|
|
84
99
|
return false;
|
|
85
|
-
const eventObject = this.getEventObjectFromTransaction(transaction);
|
|
100
|
+
const eventObject = this.getEventObjectFromTransaction(transaction, version);
|
|
86
101
|
if (eventObject == null)
|
|
87
102
|
return true;
|
|
88
|
-
await this.processEvent(eventObject);
|
|
103
|
+
await this.processEvent(eventObject, version);
|
|
89
104
|
return true;
|
|
90
105
|
}
|
|
91
106
|
catch (e) {
|
|
@@ -99,7 +114,7 @@ class SolanaChainEventsBrowser {
|
|
|
99
114
|
* @private
|
|
100
115
|
* @returns {Promise<(InstructionWithAccounts<SwapProgram> | null)[] | null>} array of parsed instructions
|
|
101
116
|
*/
|
|
102
|
-
async getTransactionInstructions(signature) {
|
|
117
|
+
async getTransactionInstructions(signature, version) {
|
|
103
118
|
const transaction = await (0, Utils_1.tryWithRetries)(async () => {
|
|
104
119
|
const res = await this.connection.getParsedTransaction(signature, {
|
|
105
120
|
commitment: "confirmed",
|
|
@@ -113,20 +128,21 @@ class SolanaChainEventsBrowser {
|
|
|
113
128
|
throw new Error("Transaction 'meta' not found!");
|
|
114
129
|
if (transaction.meta.err != null)
|
|
115
130
|
return null;
|
|
116
|
-
return this.
|
|
131
|
+
return this.contractVersions[version].swapContract._Events.decodeInstructions(transaction.transaction.message);
|
|
117
132
|
}
|
|
118
133
|
/**
|
|
119
134
|
* Returns async getter for fetching on-demand initialize event swap data
|
|
120
135
|
*
|
|
121
136
|
* @param eventObject
|
|
122
137
|
* @param txoHash
|
|
138
|
+
* @param version
|
|
123
139
|
* @private
|
|
124
140
|
* @returns {() => Promise<SolanaSwapData>} getter to be passed to InitializeEvent constructor
|
|
125
141
|
*/
|
|
126
|
-
getSwapDataGetter(eventObject, txoHash) {
|
|
142
|
+
getSwapDataGetter(eventObject, txoHash, version) {
|
|
127
143
|
return async () => {
|
|
128
144
|
if (eventObject.instructions == null) {
|
|
129
|
-
const ixs = await this.getTransactionInstructions(eventObject.signature);
|
|
145
|
+
const ixs = await this.getTransactionInstructions(eventObject.signature, version);
|
|
130
146
|
if (ixs == null)
|
|
131
147
|
return null;
|
|
132
148
|
eventObject.instructions = ixs;
|
|
@@ -134,59 +150,60 @@ class SolanaChainEventsBrowser {
|
|
|
134
150
|
const initIx = eventObject.instructions.find(ix => ix != null && (ix.name === "offererInitializePayIn" || ix.name === "offererInitialize"));
|
|
135
151
|
if (initIx == null)
|
|
136
152
|
return null;
|
|
137
|
-
return SolanaSwapData_1.SolanaSwapData.fromInstruction(this.
|
|
153
|
+
return SolanaSwapData_1.SolanaSwapData.fromInstruction(this.contractVersions[version].swapContract.program.programId, version, initIx, txoHash);
|
|
138
154
|
};
|
|
139
155
|
}
|
|
140
156
|
/**
|
|
141
157
|
* @internal
|
|
142
158
|
*/
|
|
143
|
-
parseInitializeEvent(data, eventObject) {
|
|
159
|
+
parseInitializeEvent(data, eventObject, version) {
|
|
144
160
|
const paymentHash = buffer_1.Buffer.from(data.hash).toString("hex");
|
|
145
161
|
const txoHash = buffer_1.Buffer.from(data.txoHash).toString("hex");
|
|
146
162
|
const escrowHash = (0, Utils_1.toEscrowHash)(paymentHash, data.sequence);
|
|
147
163
|
this.logger.debug("InitializeEvent paymentHash: " + paymentHash + " sequence: " + data.sequence.toString(10) +
|
|
148
164
|
" txoHash: " + txoHash + " escrowHash: " + escrowHash);
|
|
149
|
-
return new base_1.InitializeEvent(escrowHash, SwapTypeEnum_1.SwapTypeEnum.toChainSwapType(data.kind), (0, Utils_1.onceAsync)(this.getSwapDataGetter(eventObject, txoHash)));
|
|
165
|
+
return new base_1.InitializeEvent(escrowHash, SwapTypeEnum_1.SwapTypeEnum.toChainSwapType(data.kind), (0, Utils_1.onceAsync)(this.getSwapDataGetter(eventObject, txoHash, version)), version);
|
|
150
166
|
}
|
|
151
167
|
/**
|
|
152
168
|
* @internal
|
|
153
169
|
*/
|
|
154
|
-
parseRefundEvent(data) {
|
|
170
|
+
parseRefundEvent(data, version) {
|
|
155
171
|
const paymentHash = buffer_1.Buffer.from(data.hash).toString("hex");
|
|
156
172
|
const escrowHash = (0, Utils_1.toEscrowHash)(paymentHash, data.sequence);
|
|
157
173
|
this.logger.debug("RefundEvent paymentHash: " + paymentHash + " sequence: " + data.sequence.toString(10) +
|
|
158
174
|
" escrowHash: " + escrowHash);
|
|
159
|
-
return new base_1.RefundEvent(escrowHash);
|
|
175
|
+
return new base_1.RefundEvent(escrowHash, version);
|
|
160
176
|
}
|
|
161
177
|
/**
|
|
162
178
|
* @internal
|
|
163
179
|
*/
|
|
164
|
-
parseClaimEvent(data) {
|
|
180
|
+
parseClaimEvent(data, version) {
|
|
165
181
|
const secret = buffer_1.Buffer.from(data.secret).toString("hex");
|
|
166
182
|
const paymentHash = buffer_1.Buffer.from(data.hash).toString("hex");
|
|
167
183
|
const escrowHash = (0, Utils_1.toEscrowHash)(paymentHash, data.sequence);
|
|
168
184
|
this.logger.debug("ClaimEvent paymentHash: " + paymentHash + " sequence: " + data.sequence.toString(10) +
|
|
169
185
|
" secret: " + secret + " escrowHash: " + escrowHash);
|
|
170
|
-
return new base_1.ClaimEvent(escrowHash, secret);
|
|
186
|
+
return new base_1.ClaimEvent(escrowHash, secret, version);
|
|
171
187
|
}
|
|
172
188
|
/**
|
|
173
189
|
* Processes event as received from the chain, parses it & calls event listeners
|
|
174
190
|
*
|
|
175
191
|
* @param eventObject
|
|
192
|
+
* @param version
|
|
176
193
|
* @internal
|
|
177
194
|
*/
|
|
178
|
-
async processEvent(eventObject) {
|
|
195
|
+
async processEvent(eventObject, version) {
|
|
179
196
|
let parsedEvents = eventObject.events.map(event => {
|
|
180
197
|
let parsedEvent;
|
|
181
198
|
switch (event.name) {
|
|
182
199
|
case "ClaimEvent":
|
|
183
|
-
parsedEvent = this.parseClaimEvent(event.data);
|
|
200
|
+
parsedEvent = this.parseClaimEvent(event.data, version);
|
|
184
201
|
break;
|
|
185
202
|
case "RefundEvent":
|
|
186
|
-
parsedEvent = this.parseRefundEvent(event.data);
|
|
203
|
+
parsedEvent = this.parseRefundEvent(event.data, version);
|
|
187
204
|
break;
|
|
188
205
|
case "InitializeEvent":
|
|
189
|
-
parsedEvent = this.parseInitializeEvent(event.data, eventObject);
|
|
206
|
+
parsedEvent = this.parseInitializeEvent(event.data, eventObject, version);
|
|
190
207
|
break;
|
|
191
208
|
}
|
|
192
209
|
if (parsedEvent == null)
|
|
@@ -206,21 +223,22 @@ class SolanaChainEventsBrowser {
|
|
|
206
223
|
* Returns websocket event handler for specific event type
|
|
207
224
|
*
|
|
208
225
|
* @param name
|
|
226
|
+
* @param version
|
|
209
227
|
* @internal
|
|
210
228
|
* @returns event handler to be passed to program's addEventListener function
|
|
211
229
|
*/
|
|
212
|
-
getWsEventHandler(name) {
|
|
230
|
+
getWsEventHandler(name, version) {
|
|
213
231
|
return (data, slotNumber, signature) => {
|
|
214
|
-
if (this.signaturesProcessing[signature] != null)
|
|
232
|
+
if (this.signaturesProcessing[signature + "-" + version] != null)
|
|
215
233
|
return;
|
|
216
|
-
if (this.isSignatureProcessed(signature))
|
|
234
|
+
if (this.isSignatureProcessed(signature, version))
|
|
217
235
|
return;
|
|
218
236
|
this.logger.debug("getWsEventHandler(" + name + "): Process signature: ", signature);
|
|
219
|
-
this.signaturesProcessing[signature] = this.processEvent({
|
|
237
|
+
this.signaturesProcessing[signature + "-" + version] = this.processEvent({
|
|
220
238
|
events: [{ name, data: data }],
|
|
221
239
|
blockTime: Math.floor(Date.now() / 1000),
|
|
222
240
|
signature
|
|
223
|
-
}).then(() => true).catch(e => {
|
|
241
|
+
}, version).then(() => true).catch(e => {
|
|
224
242
|
this.logger.error("getWsEventHandler(" + name + "): Error processing signature: " + signature, e);
|
|
225
243
|
return false;
|
|
226
244
|
});
|
|
@@ -232,23 +250,28 @@ class SolanaChainEventsBrowser {
|
|
|
232
250
|
* @internal
|
|
233
251
|
*/
|
|
234
252
|
setupWebsocket() {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
253
|
+
var _a;
|
|
254
|
+
for (let version in this.contractVersions) {
|
|
255
|
+
const program = this.contractVersions[version].swapContract.program;
|
|
256
|
+
const eventListeners = (_a = this.eventListeners)[version] ?? (_a[version] = []);
|
|
257
|
+
eventListeners.push(program.addEventListener("InitializeEvent", this.getWsEventHandler("InitializeEvent", version)));
|
|
258
|
+
eventListeners.push(program.addEventListener("ClaimEvent", this.getWsEventHandler("ClaimEvent", version)));
|
|
259
|
+
eventListeners.push(program.addEventListener("RefundEvent", this.getWsEventHandler("RefundEvent", version)));
|
|
260
|
+
}
|
|
239
261
|
}
|
|
240
262
|
/**
|
|
241
263
|
* Gets all the new signatures from the last processed signature
|
|
242
264
|
*
|
|
243
265
|
* @param lastProcessedSignature
|
|
266
|
+
* @param version
|
|
244
267
|
* @private
|
|
245
268
|
*/
|
|
246
|
-
async getNewSignatures(lastProcessedSignature) {
|
|
269
|
+
async getNewSignatures(lastProcessedSignature, version) {
|
|
247
270
|
let signatures = [];
|
|
248
271
|
let fetched = null;
|
|
249
272
|
while (fetched == null || fetched.length === this.logFetchLimit) {
|
|
250
273
|
if (signatures.length === 0) {
|
|
251
|
-
fetched = await this.connection.getSignaturesForAddress(this.
|
|
274
|
+
fetched = await this.connection.getSignaturesForAddress(this.contractVersions[version].swapContract.program.programId, {
|
|
252
275
|
until: lastProcessedSignature.signature,
|
|
253
276
|
limit: this.logFetchLimit
|
|
254
277
|
}, "confirmed");
|
|
@@ -259,7 +282,7 @@ class SolanaChainEventsBrowser {
|
|
|
259
282
|
}
|
|
260
283
|
}
|
|
261
284
|
else {
|
|
262
|
-
fetched = await this.connection.getSignaturesForAddress(this.
|
|
285
|
+
fetched = await this.connection.getSignaturesForAddress(this.contractVersions[version].swapContract.program.programId, {
|
|
263
286
|
before: signatures[signatures.length - 1].signature,
|
|
264
287
|
until: lastProcessedSignature.signature,
|
|
265
288
|
limit: this.logFetchLimit
|
|
@@ -274,8 +297,8 @@ class SolanaChainEventsBrowser {
|
|
|
274
297
|
*
|
|
275
298
|
* @private
|
|
276
299
|
*/
|
|
277
|
-
async getFirstSignature() {
|
|
278
|
-
return await this.connection.getSignaturesForAddress(this.
|
|
300
|
+
async getFirstSignature(version) {
|
|
301
|
+
return await this.connection.getSignaturesForAddress(this.contractVersions[version].swapContract.program.programId, {
|
|
279
302
|
limit: 1
|
|
280
303
|
}, "confirmed");
|
|
281
304
|
}
|
|
@@ -283,34 +306,35 @@ class SolanaChainEventsBrowser {
|
|
|
283
306
|
* Processes signatures, fetches transactions & processes event through event handlers
|
|
284
307
|
*
|
|
285
308
|
* @param signatures
|
|
309
|
+
* @param version
|
|
286
310
|
* @private
|
|
287
311
|
* @returns {Promise<{signature: string, slot: number}>} latest processed transaction signature and slot height
|
|
288
312
|
*/
|
|
289
|
-
async processSignatures(signatures) {
|
|
313
|
+
async processSignatures(signatures, version) {
|
|
290
314
|
let lastSuccessfulSignature = null;
|
|
291
315
|
try {
|
|
292
316
|
for (let i = signatures.length - 1; i >= 0; i--) {
|
|
293
317
|
const txSignature = signatures[i];
|
|
294
318
|
//Check if signature is already being processed by the
|
|
295
|
-
const signaturePromise = this.signaturesProcessing[txSignature.signature];
|
|
319
|
+
const signaturePromise = this.signaturesProcessing[txSignature.signature + "-" + version];
|
|
296
320
|
if (signaturePromise != null) {
|
|
297
321
|
const result = await signaturePromise;
|
|
298
|
-
delete this.signaturesProcessing[txSignature.signature];
|
|
322
|
+
delete this.signaturesProcessing[txSignature.signature + "-" + version];
|
|
299
323
|
if (result) {
|
|
300
324
|
lastSuccessfulSignature = txSignature;
|
|
301
|
-
this.addProcessedSignature(txSignature.signature);
|
|
325
|
+
this.addProcessedSignature(txSignature.signature, version);
|
|
302
326
|
continue;
|
|
303
327
|
}
|
|
304
328
|
}
|
|
305
329
|
this.logger.debug("processSignatures(): Process signature: ", txSignature);
|
|
306
|
-
const processPromise = this.fetchTxAndProcessEvent(txSignature.signature);
|
|
307
|
-
this.signaturesProcessing[txSignature.signature] = processPromise;
|
|
330
|
+
const processPromise = this.fetchTxAndProcessEvent(txSignature.signature, version);
|
|
331
|
+
this.signaturesProcessing[txSignature.signature + "-" + version] = processPromise;
|
|
308
332
|
const result = await processPromise;
|
|
309
333
|
if (!result)
|
|
310
334
|
throw new Error("Failed to process signature: " + txSignature);
|
|
311
335
|
lastSuccessfulSignature = txSignature;
|
|
312
|
-
this.addProcessedSignature(txSignature.signature);
|
|
313
|
-
delete this.signaturesProcessing[txSignature.signature];
|
|
336
|
+
this.addProcessedSignature(txSignature.signature, version);
|
|
337
|
+
delete this.signaturesProcessing[txSignature.signature + "-" + version];
|
|
314
338
|
}
|
|
315
339
|
}
|
|
316
340
|
catch (e) {
|
|
@@ -322,13 +346,22 @@ class SolanaChainEventsBrowser {
|
|
|
322
346
|
* @inheritDoc
|
|
323
347
|
*/
|
|
324
348
|
async poll(lastSignature) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
349
|
+
const _lastSignature = toNewEventListenerState(lastSignature);
|
|
350
|
+
const result = {};
|
|
351
|
+
for (let version in this.contractVersions) {
|
|
352
|
+
const lastSignature = _lastSignature?.[version];
|
|
353
|
+
let signatures = lastSignature == null
|
|
354
|
+
? await this.getFirstSignature(version)
|
|
355
|
+
: await this.getNewSignatures(lastSignature, version);
|
|
356
|
+
if (signatures == null) {
|
|
357
|
+
result[version] = lastSignature ?? null;
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
let lastSuccessfulSignature = await this.processSignatures(signatures, version);
|
|
361
|
+
result[version] = lastSuccessfulSignature ?? lastSignature ?? null;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return result;
|
|
332
365
|
}
|
|
333
366
|
/**
|
|
334
367
|
* @inheritDoc
|
|
@@ -343,10 +376,12 @@ class SolanaChainEventsBrowser {
|
|
|
343
376
|
* @inheritDoc
|
|
344
377
|
*/
|
|
345
378
|
async stop() {
|
|
346
|
-
for (let
|
|
347
|
-
|
|
379
|
+
for (let version in this.eventListeners) {
|
|
380
|
+
for (let num of this.eventListeners[version]) {
|
|
381
|
+
await this.contractVersions[version].swapContract.program.removeEventListener(num);
|
|
382
|
+
}
|
|
348
383
|
}
|
|
349
|
-
this.eventListeners =
|
|
384
|
+
this.eventListeners = {};
|
|
350
385
|
}
|
|
351
386
|
/**
|
|
352
387
|
* @inheritDoc
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { PublicKey } from "@solana/web3.js";
|
|
2
2
|
import * as BN from "bn.js";
|
|
3
3
|
import { ChainSwapType, SwapData } from "@atomiqlabs/base";
|
|
4
|
-
import { SwapProgram } from "./programTypes";
|
|
4
|
+
import { SwapProgram } from "./v1/programTypes";
|
|
5
5
|
import { IdlAccounts, IdlTypes } from "@coral-xyz/anchor";
|
|
6
6
|
import { Serialized } from "../../utils/Utils";
|
|
7
7
|
import { SingleInstructionWithAccounts } from "../program/modules/SolanaProgramEvents";
|
|
8
|
-
|
|
8
|
+
import { SwapProgramV2 } from "./v2/programTypes";
|
|
9
|
+
export type InitInstruction = SingleInstructionWithAccounts<SwapProgram["instructions"][2 | 3] | SwapProgramV2["instructions"][2 | 3], SwapProgram>;
|
|
9
10
|
export type SolanaSwapDataCtorArgs = {
|
|
10
11
|
programId: PublicKey;
|
|
12
|
+
version: "v1" | "v2";
|
|
11
13
|
offerer: PublicKey;
|
|
12
14
|
claimer: PublicKey;
|
|
13
15
|
token: PublicKey;
|
|
@@ -25,6 +27,7 @@ export type SolanaSwapDataCtorArgs = {
|
|
|
25
27
|
securityDeposit: BN;
|
|
26
28
|
claimerBounty: BN;
|
|
27
29
|
txoHash?: string;
|
|
30
|
+
offererInitializer?: boolean;
|
|
28
31
|
};
|
|
29
32
|
export declare function isSerializedData(obj: any): obj is ({
|
|
30
33
|
type: "sol";
|
|
@@ -39,6 +42,10 @@ export declare class SolanaSwapData extends SwapData {
|
|
|
39
42
|
* Program ID for which this swap data was created
|
|
40
43
|
*/
|
|
41
44
|
programId: PublicKey;
|
|
45
|
+
/**
|
|
46
|
+
* Program version for which this swap was created
|
|
47
|
+
*/
|
|
48
|
+
version: "v1" | "v2";
|
|
42
49
|
/**
|
|
43
50
|
* Offerer address funding the swap.
|
|
44
51
|
*/
|
|
@@ -107,6 +114,10 @@ export declare class SolanaSwapData extends SwapData {
|
|
|
107
114
|
* Optional txo hash hint.
|
|
108
115
|
*/
|
|
109
116
|
txoHash?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Optional flag whether the offerer is the initializer for V2 swap data
|
|
119
|
+
*/
|
|
120
|
+
offererInitializer?: boolean;
|
|
110
121
|
/**
|
|
111
122
|
* Creates swap data from structured constructor arguments.
|
|
112
123
|
*
|
|
@@ -232,7 +243,7 @@ export declare class SolanaSwapData extends SwapData {
|
|
|
232
243
|
*
|
|
233
244
|
* @param account Escrow account data fetched from chain
|
|
234
245
|
*/
|
|
235
|
-
correctPDA(account: IdlAccounts<SwapProgram>["escrowState"]): boolean;
|
|
246
|
+
correctPDA(account: IdlAccounts<SwapProgram | SwapProgramV2>["escrowState"]): boolean;
|
|
236
247
|
/**
|
|
237
248
|
* @inheritDoc
|
|
238
249
|
*/
|
|
@@ -241,18 +252,20 @@ export declare class SolanaSwapData extends SwapData {
|
|
|
241
252
|
* Converts initialize instruction data into {@link SolanaSwapData}.
|
|
242
253
|
*
|
|
243
254
|
* @param programId
|
|
255
|
+
* @param version
|
|
244
256
|
* @param initIx Decoded initialize instruction
|
|
245
257
|
* @param txoHash Parsed txo hash hint from initialize event
|
|
246
258
|
* @returns Converted and parsed swap data
|
|
247
259
|
*/
|
|
248
|
-
static fromInstruction(programId: PublicKey, initIx: InitInstruction, txoHash: string): SolanaSwapData;
|
|
260
|
+
static fromInstruction(programId: PublicKey, version: "v1" | "v2", initIx: InitInstruction, txoHash: string): SolanaSwapData;
|
|
249
261
|
/**
|
|
250
262
|
* Deserializes swap data from an on-chain escrow account state.
|
|
251
263
|
*
|
|
252
264
|
* @param programId
|
|
265
|
+
* @param version
|
|
253
266
|
* @param account Escrow account state as returned by Anchor
|
|
254
267
|
*/
|
|
255
|
-
static fromEscrowState(programId: PublicKey, account: IdlAccounts<SwapProgram>["escrowState"]): SolanaSwapData;
|
|
268
|
+
static fromEscrowState(programId: PublicKey, version: "v1" | "v2", account: IdlAccounts<SwapProgram | SwapProgramV2>["escrowState"]): SolanaSwapData;
|
|
256
269
|
/**
|
|
257
270
|
* Converts abstract swap type to Solana program kind discriminator.
|
|
258
271
|
*
|
|
@@ -286,3 +299,35 @@ export declare class SolanaSwapData extends SwapData {
|
|
|
286
299
|
*/
|
|
287
300
|
getEscrowStruct(): any;
|
|
288
301
|
}
|
|
302
|
+
export declare class SolanaSwapDataV1 extends SolanaSwapData {
|
|
303
|
+
/**
|
|
304
|
+
* Creates swap data from structured constructor arguments.
|
|
305
|
+
*
|
|
306
|
+
* @param args Swap data fields
|
|
307
|
+
*/
|
|
308
|
+
constructor(args: SolanaSwapDataCtorArgs);
|
|
309
|
+
/**
|
|
310
|
+
* Deserializes swap data from serialized storage representation.
|
|
311
|
+
*
|
|
312
|
+
* @param data Serialized swap data from {@link SolanaSwapData.serialize}
|
|
313
|
+
*/
|
|
314
|
+
constructor(data: {
|
|
315
|
+
type: "sol";
|
|
316
|
+
} & Serialized<SolanaSwapData>);
|
|
317
|
+
}
|
|
318
|
+
export declare class SolanaSwapDataV2 extends SolanaSwapData {
|
|
319
|
+
/**
|
|
320
|
+
* Creates swap data from structured constructor arguments.
|
|
321
|
+
*
|
|
322
|
+
* @param args Swap data fields
|
|
323
|
+
*/
|
|
324
|
+
constructor(args: SolanaSwapDataCtorArgs);
|
|
325
|
+
/**
|
|
326
|
+
* Deserializes swap data from serialized storage representation.
|
|
327
|
+
*
|
|
328
|
+
* @param data Serialized swap data from {@link SolanaSwapData.serialize}
|
|
329
|
+
*/
|
|
330
|
+
constructor(data: {
|
|
331
|
+
type: "sol";
|
|
332
|
+
} & Serialized<SolanaSwapData>);
|
|
333
|
+
}
|