@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.
Files changed (54) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.js +2 -2
  3. package/dist/solana/SolanaChainType.d.ts +1 -1
  4. package/dist/solana/SolanaChains.d.ts +5 -2
  5. package/dist/solana/SolanaChains.js +25 -13
  6. package/dist/solana/SolanaInitializer.d.ts +30 -4
  7. package/dist/solana/SolanaInitializer.js +105 -15
  8. package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +4 -2
  9. package/dist/solana/btcrelay/SolanaBtcRelay.js +7 -1
  10. package/dist/solana/chain/SolanaAction.d.ts +1 -1
  11. package/dist/solana/chain/SolanaAction.js +2 -2
  12. package/dist/solana/chain/SolanaChainInterface.d.ts +6 -1
  13. package/dist/solana/chain/SolanaChainInterface.js +30 -0
  14. package/dist/solana/events/SolanaChainEvents.d.ts +5 -1
  15. package/dist/solana/events/SolanaChainEvents.js +16 -6
  16. package/dist/solana/events/SolanaChainEventsBrowser.d.ts +39 -16
  17. package/dist/solana/events/SolanaChainEventsBrowser.js +96 -61
  18. package/dist/solana/swaps/SolanaSwapData.d.ts +50 -5
  19. package/dist/solana/swaps/SolanaSwapData.js +52 -8
  20. package/dist/solana/swaps/SolanaSwapModule.d.ts +4 -3
  21. package/dist/solana/swaps/SolanaSwapProgram.d.ts +12 -6
  22. package/dist/solana/swaps/SolanaSwapProgram.js +73 -47
  23. package/dist/solana/swaps/modules/SwapClaim.js +2 -0
  24. package/dist/solana/swaps/modules/SwapInit.d.ts +10 -5
  25. package/dist/solana/swaps/modules/SwapInit.js +222 -85
  26. package/dist/solana/swaps/modules/SwapRefund.d.ts +8 -2
  27. package/dist/solana/swaps/modules/SwapRefund.js +38 -22
  28. package/dist/solana/swaps/v1/programIdl.json +945 -0
  29. package/dist/solana/swaps/v1/programTypes.d.ts +943 -0
  30. package/dist/solana/swaps/v1/programTypes.js +945 -0
  31. package/dist/solana/swaps/v2/programIdl.json +952 -0
  32. package/dist/solana/swaps/v2/programTypes.d.ts +950 -0
  33. package/dist/solana/swaps/v2/programTypes.js +952 -0
  34. package/package.json +2 -2
  35. package/src/index.ts +2 -2
  36. package/src/solana/SolanaChainType.ts +2 -2
  37. package/src/solana/SolanaChains.ts +29 -14
  38. package/src/solana/SolanaInitializer.ts +147 -25
  39. package/src/solana/btcrelay/SolanaBtcRelay.ts +10 -2
  40. package/src/solana/chain/SolanaAction.ts +2 -2
  41. package/src/solana/chain/SolanaChainInterface.ts +35 -1
  42. package/src/solana/events/SolanaChainEvents.ts +22 -11
  43. package/src/solana/events/SolanaChainEventsBrowser.ts +110 -67
  44. package/src/solana/swaps/SolanaSwapData.ts +95 -11
  45. package/src/solana/swaps/SolanaSwapModule.ts +5 -3
  46. package/src/solana/swaps/SolanaSwapProgram.ts +87 -43
  47. package/src/solana/swaps/modules/SolanaLpVault.ts +2 -2
  48. package/src/solana/swaps/modules/SwapClaim.ts +3 -1
  49. package/src/solana/swaps/modules/SwapInit.ts +227 -99
  50. package/src/solana/swaps/modules/SwapRefund.ts +38 -20
  51. package/src/solana/swaps/v2/programIdl.json +952 -0
  52. package/src/solana/swaps/v2/programTypes.ts +1899 -0
  53. /package/src/solana/swaps/{programIdl.json → v1/programIdl.json} +0 -0
  54. /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
- * Current cursor of Solana event listener state.
20
+ * Legacy current cursor of Solana event listener state.
21
21
  *
22
22
  * @category Events
23
23
  */
24
- export type SolanaEventListenerState = {
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 solanaSwapProgram: SolanaSwapProgram;
61
+ protected readonly contractVersions: {
62
+ [version: string]: {
63
+ swapContract: SolanaSwapProgram;
64
+ };
65
+ };
54
66
  /**
55
67
  * @internal
56
68
  */
57
- protected eventListeners: number[];
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, solanaSwapContract: SolanaSwapProgram, logFetchLimit?: number);
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 | null>;
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 = 100;
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, solanaSwapContract, logFetchLimit) {
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
- this.solanaSwapProgram = solanaSwapContract;
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.solanaSwapProgram._Events.decodeInstructions(transaction.transaction.message);
62
- const events = this.solanaSwapProgram._Events.parseLogs(transaction.meta.logMessages);
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.solanaSwapProgram._Events.decodeInstructions(transaction.transaction.message);
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.solanaSwapProgram.program.programId, initIx, txoHash);
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
- const program = this.solanaSwapProgram.program;
236
- this.eventListeners.push(program.addEventListener("InitializeEvent", this.getWsEventHandler("InitializeEvent")));
237
- this.eventListeners.push(program.addEventListener("ClaimEvent", this.getWsEventHandler("ClaimEvent")));
238
- this.eventListeners.push(program.addEventListener("RefundEvent", this.getWsEventHandler("RefundEvent")));
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.solanaSwapProgram.program.programId, {
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.solanaSwapProgram.program.programId, {
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.solanaSwapProgram.program.programId, {
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
- let signatures = lastSignature == null
326
- ? await this.getFirstSignature()
327
- : await this.getNewSignatures(lastSignature);
328
- if (signatures == null)
329
- return lastSignature ?? null;
330
- let lastSuccessfulSignature = await this.processSignatures(signatures);
331
- return lastSuccessfulSignature ?? lastSignature ?? null;
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 num of this.eventListeners) {
347
- await this.solanaSwapProgram.program.removeEventListener(num);
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
- export type InitInstruction = SingleInstructionWithAccounts<SwapProgram["instructions"][2 | 3], SwapProgram>;
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
+ }