@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
|
@@ -9,6 +9,8 @@ const SolanaSwapModule_1 = require("../SolanaSwapModule");
|
|
|
9
9
|
const Utils_1 = require("../../../utils/Utils");
|
|
10
10
|
const buffer_1 = require("buffer");
|
|
11
11
|
const SolanaTokens_1 = require("../../chain/modules/SolanaTokens");
|
|
12
|
+
const SolanaSwapProgram_1 = require("../SolanaSwapProgram");
|
|
13
|
+
const BN = require("bn.js");
|
|
12
14
|
class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
13
15
|
constructor() {
|
|
14
16
|
super(...arguments);
|
|
@@ -18,14 +20,16 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
18
20
|
/**
|
|
19
21
|
* bare Init action based on the data passed in swapData
|
|
20
22
|
*
|
|
23
|
+
* @param sender
|
|
21
24
|
* @param swapData
|
|
22
25
|
* @param timeout
|
|
23
26
|
* @private
|
|
24
27
|
*/
|
|
25
|
-
async Init(swapData, timeout) {
|
|
28
|
+
async Init(sender, swapData, timeout) {
|
|
26
29
|
const claimerAta = (0, spl_token_1.getAssociatedTokenAddressSync)(swapData.token, swapData.claimer);
|
|
27
30
|
const paymentHash = buffer_1.Buffer.from(swapData.paymentHash, "hex");
|
|
28
31
|
const accounts = {
|
|
32
|
+
initializer: sender,
|
|
29
33
|
claimer: swapData.claimer,
|
|
30
34
|
offerer: swapData.offerer,
|
|
31
35
|
escrowState: this.program._SwapEscrowState(paymentHash),
|
|
@@ -36,58 +40,116 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
36
40
|
};
|
|
37
41
|
if (swapData.payIn) {
|
|
38
42
|
const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(swapData.token, swapData.offerer);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
let instruction;
|
|
44
|
+
const program = this.swapProgram;
|
|
45
|
+
if ((0, SolanaSwapProgram_1.isSwapProgramV1)(program)) {
|
|
46
|
+
if (!swapData.securityDeposit.eq(new BN(0)))
|
|
47
|
+
throw new Error("Swap data for V1 payIn=true swaps cannot have any security deposit!");
|
|
48
|
+
if (!swapData.claimerBounty.eq(new BN(0)))
|
|
49
|
+
throw new Error("Swap data for V1 payIn=true swaps cannot have any claimer bounty!");
|
|
50
|
+
instruction = await program.methods
|
|
51
|
+
.offererInitializePayIn(swapData.toSwapDataStruct(), [...buffer_1.Buffer.alloc(32, 0)], (0, Utils_1.toBN)(timeout))
|
|
52
|
+
.accounts({
|
|
53
|
+
...accounts,
|
|
54
|
+
offererAta: ata,
|
|
55
|
+
vault: this.program._SwapVault(swapData.token),
|
|
56
|
+
vaultAuthority: this.program._SwapVaultAuthority,
|
|
57
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
58
|
+
})
|
|
59
|
+
.instruction();
|
|
60
|
+
}
|
|
61
|
+
else if ((0, SolanaSwapProgram_1.isSwapProgramV2)(program)) {
|
|
62
|
+
instruction = await program.methods
|
|
63
|
+
.offererInitializePayIn(swapData.toSwapDataStruct(), swapData.securityDeposit, swapData.claimerBounty, [...(swapData.txoHash != null ? buffer_1.Buffer.from(swapData.txoHash, "hex") : buffer_1.Buffer.alloc(32, 0))], (0, Utils_1.toBN)(timeout))
|
|
64
|
+
.accounts({
|
|
65
|
+
...accounts,
|
|
66
|
+
offererAta: ata,
|
|
67
|
+
vault: this.program._SwapVault(swapData.token),
|
|
68
|
+
vaultAuthority: this.program._SwapVaultAuthority,
|
|
69
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
70
|
+
})
|
|
71
|
+
.instruction();
|
|
72
|
+
// Mark the claimer as signer for non payOut swaps
|
|
73
|
+
if (!swapData.isPayOut()) {
|
|
74
|
+
instruction.keys.forEach(key => {
|
|
75
|
+
if (key.pubkey.equals(swapData.claimer))
|
|
76
|
+
key.isSigner = true;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else
|
|
81
|
+
throw new Error("Invalid swap program version!");
|
|
82
|
+
return new SolanaAction_1.SolanaAction(sender, this.root, instruction, SwapInit.CUCosts.INIT_PAY_IN);
|
|
49
83
|
}
|
|
50
84
|
else {
|
|
51
|
-
|
|
85
|
+
const instruction = await this.swapProgram.methods
|
|
52
86
|
.offererInitialize(swapData.toSwapDataStruct(), swapData.securityDeposit, swapData.claimerBounty, [...(swapData.txoHash != null ? buffer_1.Buffer.from(swapData.txoHash, "hex") : buffer_1.Buffer.alloc(32, 0))], (0, Utils_1.toBN)(timeout))
|
|
53
87
|
.accounts({
|
|
54
88
|
...accounts,
|
|
55
89
|
offererUserData: this.program._SwapUserVault(swapData.offerer, swapData.token),
|
|
56
90
|
})
|
|
57
|
-
.instruction()
|
|
91
|
+
.instruction();
|
|
92
|
+
// Mark the claimer as signer for non payOut swaps
|
|
93
|
+
if ((0, SolanaSwapProgram_1.isSwapProgramV2)(this.swapProgram) && !swapData.isPayOut()) {
|
|
94
|
+
instruction.keys.forEach(key => {
|
|
95
|
+
if (key.pubkey.equals(swapData.claimer))
|
|
96
|
+
key.isSigner = true;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return new SolanaAction_1.SolanaAction(sender, this.root, instruction, SwapInit.CUCosts.INIT);
|
|
58
100
|
}
|
|
59
101
|
}
|
|
60
102
|
/**
|
|
61
103
|
* InitPayIn action which includes SOL to WSOL wrapping if indicated by the fee rate
|
|
62
104
|
*
|
|
105
|
+
* @param signer
|
|
63
106
|
* @param swapData
|
|
64
107
|
* @param timeout
|
|
65
108
|
* @param feeRate
|
|
66
109
|
* @private
|
|
67
110
|
*/
|
|
68
|
-
async InitPayIn(swapData, timeout, feeRate) {
|
|
111
|
+
async InitPayIn(sender, swapData, timeout, feeRate) {
|
|
69
112
|
if (!swapData.isPayIn())
|
|
70
113
|
throw new Error("Must be payIn==true");
|
|
71
|
-
|
|
114
|
+
if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
|
|
115
|
+
if (!sender.equals(swapData.offerer))
|
|
116
|
+
throw new Error("Transaction signer must be offerer for payIn=true escrows!");
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
if (!sender.equals(swapData.offerer) && !sender.equals(swapData.claimer))
|
|
120
|
+
throw new Error("Transaction signer must be either offerer or claimer claimer!");
|
|
121
|
+
}
|
|
122
|
+
const action = new SolanaAction_1.SolanaAction(sender, this.root);
|
|
72
123
|
if (this.shouldWrapOnInit(swapData, feeRate))
|
|
73
|
-
action.addAction(this.Wrap(swapData, feeRate));
|
|
74
|
-
action.addAction(await this.Init(swapData, timeout));
|
|
124
|
+
action.addAction(this.Wrap(swapData, feeRate), undefined, true);
|
|
125
|
+
action.addAction(await this.Init(sender, swapData, timeout));
|
|
75
126
|
return action;
|
|
76
127
|
}
|
|
77
128
|
/**
|
|
78
129
|
* InitNotPayIn action with additional createAssociatedTokenAccountIdempotentInstruction instruction, such that
|
|
79
130
|
* a recipient ATA is created if it doesn't exist
|
|
80
131
|
*
|
|
132
|
+
* @param sender
|
|
81
133
|
* @param swapData
|
|
82
134
|
* @param timeout
|
|
83
135
|
* @private
|
|
84
136
|
*/
|
|
85
|
-
async InitNotPayIn(swapData, timeout) {
|
|
137
|
+
async InitNotPayIn(sender, swapData, timeout) {
|
|
86
138
|
if (swapData.isPayIn())
|
|
87
139
|
throw new Error("Must be payIn==false");
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
140
|
+
if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
|
|
141
|
+
if (!sender.equals(swapData.claimer))
|
|
142
|
+
throw new Error("Transaction signer must be claimer for payIn=false escrows!");
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
if (!sender.equals(swapData.offerer) && !sender.equals(swapData.claimer))
|
|
146
|
+
throw new Error("Transaction signer must be either offerer or claimer claimer!");
|
|
147
|
+
}
|
|
148
|
+
const action = new SolanaAction_1.SolanaAction(sender, this.root);
|
|
149
|
+
if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
|
|
150
|
+
action.addIx((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(sender, swapData.claimerAta ?? await (0, spl_token_1.getAssociatedTokenAddress)(swapData.token, swapData.claimer), swapData.claimer, swapData.token));
|
|
151
|
+
} // V2 doesn't explicitly check the token account on initialization, no need to open it
|
|
152
|
+
action.addAction(await this.Init(sender, swapData, timeout));
|
|
91
153
|
return action;
|
|
92
154
|
}
|
|
93
155
|
Wrap(swapData, feeRate) {
|
|
@@ -139,10 +201,19 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
139
201
|
* @param feeRate
|
|
140
202
|
* @private
|
|
141
203
|
*/
|
|
142
|
-
async getTxToSign(swapData, timeout, feeRate) {
|
|
204
|
+
async getTxToSign(signer, swapData, timeout, feeRate) {
|
|
205
|
+
let txSender;
|
|
206
|
+
if (signer.equals(swapData.offerer)) {
|
|
207
|
+
txSender = swapData.claimer;
|
|
208
|
+
}
|
|
209
|
+
else if (signer.equals(swapData.claimer)) {
|
|
210
|
+
txSender = swapData.offerer;
|
|
211
|
+
}
|
|
212
|
+
else
|
|
213
|
+
throw new Error("Signer needs to be either claimer or offerer of the swap!");
|
|
143
214
|
const action = swapData.isPayIn() ?
|
|
144
|
-
await this.InitPayIn(swapData, BigInt(timeout), feeRate) :
|
|
145
|
-
await this.InitNotPayIn(swapData, BigInt(timeout));
|
|
215
|
+
await this.InitPayIn(txSender, swapData, BigInt(timeout), feeRate) :
|
|
216
|
+
await this.InitNotPayIn(txSender, swapData, BigInt(timeout));
|
|
146
217
|
const tx = (await action.tx(feeRate)).tx;
|
|
147
218
|
return tx;
|
|
148
219
|
}
|
|
@@ -234,14 +305,20 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
234
305
|
async signSwapInitialization(signer, swapData, authorizationTimeout, preFetchedBlockData, feeRate) {
|
|
235
306
|
if (signer.keypair == null)
|
|
236
307
|
throw new Error("Unsupported");
|
|
237
|
-
if (
|
|
238
|
-
|
|
308
|
+
if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
|
|
309
|
+
if (!signer.getPublicKey().equals(swapData.isPayIn() ? swapData.claimer : swapData.offerer))
|
|
310
|
+
throw new Error("Invalid signer, wrong public key!");
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
if (!signer.getPublicKey().equals(swapData.offerer) && !signer.getPublicKey().equals(swapData.claimer))
|
|
314
|
+
throw new Error("Invalid signer, must be either offerer or claimer claimer!");
|
|
315
|
+
}
|
|
239
316
|
if (preFetchedBlockData != null && Date.now() - preFetchedBlockData.timestamp > this.SIGNATURE_PREFETCH_DATA_VALIDITY)
|
|
240
317
|
preFetchedBlockData = undefined;
|
|
241
318
|
const { block: latestBlock, slot: latestSlot } = preFetchedBlockData || await this.root.Blocks.findLatestParsedBlock("finalized");
|
|
242
319
|
const authTimeout = Math.floor(Date.now() / 1000) + authorizationTimeout;
|
|
243
|
-
const txToSign = await this.getTxToSign(swapData, authTimeout.toString(10), feeRate);
|
|
244
|
-
txToSign.feePayer =
|
|
320
|
+
const txToSign = await this.getTxToSign(signer.getPublicKey(), swapData, authTimeout.toString(10), feeRate);
|
|
321
|
+
txToSign.feePayer = signer.getPublicKey().equals(swapData.offerer) ? swapData.claimer : swapData.offerer;
|
|
245
322
|
txToSign.recentBlockhash = latestBlock.blockhash;
|
|
246
323
|
txToSign.sign(signer.keypair);
|
|
247
324
|
// this.logger.debug("signSwapInitialization(): Signed tx: ",txToSign);
|
|
@@ -267,15 +344,25 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
267
344
|
* @public
|
|
268
345
|
*/
|
|
269
346
|
async isSignatureValid(sender, swapData, timeout, prefix, signature, feeRate, preFetchedData) {
|
|
270
|
-
if (
|
|
271
|
-
if (
|
|
272
|
-
|
|
347
|
+
if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
|
|
348
|
+
if (swapData.isPayIn()) {
|
|
349
|
+
if (!swapData.offerer.equals(sender))
|
|
350
|
+
throw new base_1.SignatureVerificationError("Sender needs to be offerer in payIn=true swaps");
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
if (!swapData.claimer.equals(sender))
|
|
354
|
+
throw new base_1.SignatureVerificationError("Sender needs to be claimer in payIn=false swaps");
|
|
355
|
+
}
|
|
273
356
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
357
|
+
let signer;
|
|
358
|
+
if (sender.equals(swapData.offerer)) {
|
|
359
|
+
signer = swapData.claimer;
|
|
360
|
+
}
|
|
361
|
+
else if (sender.equals(swapData.claimer)) {
|
|
362
|
+
signer = swapData.offerer;
|
|
277
363
|
}
|
|
278
|
-
|
|
364
|
+
else
|
|
365
|
+
throw new Error("Signer needs to be either claimer or offerer of the swap!");
|
|
279
366
|
if (!swapData.isPayIn() && await this.program.isExpired(sender.toString(), swapData)) {
|
|
280
367
|
throw new base_1.SignatureVerificationError("Swap will expire too soon!");
|
|
281
368
|
}
|
|
@@ -285,25 +372,31 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
285
372
|
const isExpired = (BigInt(timeout) - currentTimestamp) < BigInt(this.program._authGracePeriod);
|
|
286
373
|
if (isExpired)
|
|
287
374
|
throw new base_1.SignatureVerificationError("Authorization expired!");
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
375
|
+
const requiresCounterpartySignature = (0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram) || !swapData.isPayOut() || sender.equals(swapData.claimer);
|
|
376
|
+
if (requiresCounterpartySignature) {
|
|
377
|
+
if (signature == null)
|
|
378
|
+
throw new base_1.SignatureVerificationError("Counterparty signature is required to initiate the swap!");
|
|
379
|
+
const [transactionSlot, signatureString] = signature.split(";");
|
|
380
|
+
const txSlot = parseInt(transactionSlot);
|
|
381
|
+
const [latestSlot, blockhash] = await Promise.all([
|
|
382
|
+
this.getSlotForSignature(preFetchedData),
|
|
383
|
+
this.getBlockhashForSignature(txSlot, preFetchedData)
|
|
384
|
+
]);
|
|
385
|
+
const lastValidTransactionSlot = txSlot + this.root._TX_SLOT_VALIDITY;
|
|
386
|
+
const slotsLeft = lastValidTransactionSlot - latestSlot - this.SIGNATURE_SLOT_BUFFER;
|
|
387
|
+
if (slotsLeft < 0)
|
|
388
|
+
throw new base_1.SignatureVerificationError("Authorization expired!");
|
|
389
|
+
const txToSign = await this.getTxToSign(signer, swapData, timeout, feeRate);
|
|
390
|
+
txToSign.feePayer = sender;
|
|
391
|
+
txToSign.recentBlockhash = blockhash;
|
|
392
|
+
txToSign.addSignature(signer, buffer_1.Buffer.from(signatureString, "hex"));
|
|
393
|
+
// this.logger.debug("isSignatureValid(): Signed tx: ",txToSign);
|
|
394
|
+
const valid = txToSign.verifySignatures(false);
|
|
395
|
+
if (!valid)
|
|
396
|
+
throw new base_1.SignatureVerificationError("Invalid signature!");
|
|
397
|
+
return buffer_1.Buffer.from(blockhash);
|
|
398
|
+
}
|
|
399
|
+
return buffer_1.Buffer.alloc(32, 0);
|
|
307
400
|
}
|
|
308
401
|
/**
|
|
309
402
|
* Gets expiry of the provided signature data, this is a minimum of slot expiry & swap signature expiry
|
|
@@ -314,16 +407,18 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
314
407
|
* @public
|
|
315
408
|
*/
|
|
316
409
|
async getSignatureExpiry(timeout, signature, preFetchedData) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
410
|
+
let expiry = (parseInt(timeout) - this.program._authGracePeriod) * 1000;
|
|
411
|
+
if (signature != null) {
|
|
412
|
+
const [transactionSlotStr, signatureString] = signature.split(";");
|
|
413
|
+
const txSlot = parseInt(transactionSlotStr);
|
|
414
|
+
const latestSlot = await this.getSlotForSignature(preFetchedData);
|
|
415
|
+
const lastValidTransactionSlot = txSlot + this.root._TX_SLOT_VALIDITY;
|
|
416
|
+
const slotsLeft = lastValidTransactionSlot - latestSlot - this.SIGNATURE_SLOT_BUFFER;
|
|
417
|
+
const slotExpiryTime = Date.now() + (slotsLeft * this.root._SLOT_TIME);
|
|
418
|
+
if (slotExpiryTime < expiry)
|
|
419
|
+
expiry = slotExpiryTime;
|
|
420
|
+
}
|
|
421
|
+
if (expiry < Date.now())
|
|
327
422
|
return 0;
|
|
328
423
|
return expiry;
|
|
329
424
|
}
|
|
@@ -335,13 +430,15 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
335
430
|
* @public
|
|
336
431
|
*/
|
|
337
432
|
async isSignatureExpired(signature, timeout) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
433
|
+
if (signature != null) {
|
|
434
|
+
const [transactionSlotStr, signatureString] = signature.split(";");
|
|
435
|
+
const txSlot = parseInt(transactionSlotStr);
|
|
436
|
+
const lastValidTransactionSlot = txSlot + this.root._TX_SLOT_VALIDITY;
|
|
437
|
+
const latestSlot = await this.root.Slots.getSlot("finalized");
|
|
438
|
+
const slotsLeft = lastValidTransactionSlot - latestSlot + this.SIGNATURE_SLOT_BUFFER;
|
|
439
|
+
if (slotsLeft < 0)
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
345
442
|
if ((parseInt(timeout) + this.program._authGracePeriod) * 1000 < Date.now())
|
|
346
443
|
return true;
|
|
347
444
|
return false;
|
|
@@ -351,6 +448,7 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
351
448
|
* the init transaction (if indicated by the fee rate) or adds the wrapping in a separate transaction (if no
|
|
352
449
|
* indication in the fee rate)
|
|
353
450
|
*
|
|
451
|
+
* @param sender
|
|
354
452
|
* @param swapData swap to initialize
|
|
355
453
|
* @param timeout init signature timeout
|
|
356
454
|
* @param prefix init signature prefix
|
|
@@ -358,20 +456,37 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
358
456
|
* @param skipChecks whether to skip signature validity checks
|
|
359
457
|
* @param feeRate fee rate to use for the transaction
|
|
360
458
|
*/
|
|
361
|
-
async txsInitPayIn(swapData, timeout, prefix, signature, skipChecks, feeRate) {
|
|
459
|
+
async txsInitPayIn(sender, swapData, timeout, prefix, signature, skipChecks, feeRate) {
|
|
460
|
+
if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
|
|
461
|
+
if (!sender.equals(swapData.offerer))
|
|
462
|
+
throw new Error("Transaction sender has to be the offerer!");
|
|
463
|
+
}
|
|
464
|
+
let signer;
|
|
465
|
+
if (sender.equals(swapData.offerer)) {
|
|
466
|
+
signer = swapData.claimer;
|
|
467
|
+
}
|
|
468
|
+
else if (sender.equals(swapData.claimer)) {
|
|
469
|
+
signer = swapData.offerer;
|
|
470
|
+
}
|
|
471
|
+
else
|
|
472
|
+
throw new Error("Signer needs to be either claimer or offerer of the swap!");
|
|
362
473
|
if (swapData.offererAta == undefined)
|
|
363
474
|
throw new base_1.SwapDataVerificationError("No offererAta specified for payIn swap!");
|
|
364
475
|
const offererAta = swapData.offererAta;
|
|
476
|
+
const requiresCounterpartySignature = (0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram) || !swapData.isPayOut() || sender.equals(swapData.claimer);
|
|
365
477
|
if (!skipChecks) {
|
|
366
478
|
const [_, payStatus] = await Promise.all([
|
|
367
|
-
this.isSignatureValid(
|
|
479
|
+
requiresCounterpartySignature ? this.isSignatureValid(sender, swapData, timeout, prefix, signature, feeRate) : Promise.resolve(),
|
|
368
480
|
this.program.getClaimHashStatus(swapData.getClaimHash())
|
|
369
481
|
]);
|
|
370
482
|
if (payStatus !== base_1.SwapCommitStateType.NOT_COMMITED)
|
|
371
483
|
throw new base_1.SwapDataVerificationError("Invoice already being paid for or paid");
|
|
372
484
|
}
|
|
373
|
-
|
|
374
|
-
|
|
485
|
+
let block;
|
|
486
|
+
if (requiresCounterpartySignature) {
|
|
487
|
+
const slotNumber = signature.split(";")[0];
|
|
488
|
+
block = await (0, Utils_1.tryWithRetries)(() => this.root.Blocks.getParsedBlock(parseInt(slotNumber)), { maxRetries: 3, delay: 100, exponential: true });
|
|
489
|
+
}
|
|
375
490
|
const txs = [];
|
|
376
491
|
let isWrapping = false;
|
|
377
492
|
const isWrappedInSignedTx = feeRate != null && feeRate.split("#").length > 1;
|
|
@@ -379,14 +494,17 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
379
494
|
const ataAcc = await this.root.Tokens.getATAOrNull(offererAta);
|
|
380
495
|
const balance = ataAcc?.amount ?? 0n;
|
|
381
496
|
if (balance < swapData.getAmount()) {
|
|
497
|
+
if (!swapData.offerer.equals(sender))
|
|
498
|
+
throw new Error("Additional SOL needs to be wrapped but the sender is not offerer!");
|
|
382
499
|
//Need to wrap more SOL to WSOL
|
|
383
500
|
await this.root.Tokens.Wrap(swapData.offerer, swapData.getAmount() - balance, ataAcc == null)
|
|
384
501
|
.addToTxs(txs, feeRate, block);
|
|
385
502
|
isWrapping = true;
|
|
386
503
|
}
|
|
387
504
|
}
|
|
388
|
-
const initTx = await (await this.InitPayIn(swapData, BigInt(timeout), feeRate)).tx(feeRate, block);
|
|
389
|
-
|
|
505
|
+
const initTx = await (await this.InitPayIn(sender, swapData, BigInt(timeout), feeRate)).tx(feeRate, block);
|
|
506
|
+
if (requiresCounterpartySignature)
|
|
507
|
+
initTx.tx.addSignature(signer, buffer_1.Buffer.from(signature.split(";")[1], "hex"));
|
|
390
508
|
txs.push(initTx);
|
|
391
509
|
this.logger.debug("txsInitPayIn(): create swap init TX, swap: " + swapData.getClaimHash() +
|
|
392
510
|
" wrapping client-side: " + isWrapping + " feerate: " + feeRate);
|
|
@@ -395,6 +513,7 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
395
513
|
/**
|
|
396
514
|
* Creates init transactions (InitNotPayIn) with a valid signature from an intermediary
|
|
397
515
|
*
|
|
516
|
+
* @param sender
|
|
398
517
|
* @param swapData swap to initialize
|
|
399
518
|
* @param timeout init signature timeout
|
|
400
519
|
* @param prefix init signature prefix
|
|
@@ -402,14 +521,32 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
402
521
|
* @param skipChecks whether to skip signature validity checks
|
|
403
522
|
* @param feeRate fee rate to use for the transaction
|
|
404
523
|
*/
|
|
405
|
-
async txsInit(swapData, timeout, prefix, signature, skipChecks, feeRate) {
|
|
406
|
-
if (
|
|
407
|
-
|
|
524
|
+
async txsInit(sender, swapData, timeout, prefix, signature, skipChecks, feeRate) {
|
|
525
|
+
if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
|
|
526
|
+
if (!sender.equals(swapData.claimer))
|
|
527
|
+
throw new Error("Transaction sender has to be the claimer!");
|
|
528
|
+
}
|
|
529
|
+
let signer;
|
|
530
|
+
if (sender.equals(swapData.offerer)) {
|
|
531
|
+
signer = swapData.claimer;
|
|
532
|
+
}
|
|
533
|
+
else if (sender.equals(swapData.claimer)) {
|
|
534
|
+
signer = swapData.offerer;
|
|
535
|
+
}
|
|
536
|
+
else
|
|
537
|
+
throw new Error("Signer needs to be either claimer or offerer of the swap!");
|
|
538
|
+
const requiresCounterpartySignature = (0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram) || !swapData.isPayOut() || sender.equals(swapData.claimer);
|
|
539
|
+
let block;
|
|
540
|
+
if (requiresCounterpartySignature) {
|
|
541
|
+
if (!skipChecks) {
|
|
542
|
+
await this.isSignatureValid(sender, swapData, timeout, prefix, signature, feeRate);
|
|
543
|
+
}
|
|
544
|
+
const slotNumber = signature.split(";")[0];
|
|
545
|
+
block = await (0, Utils_1.tryWithRetries)(() => this.root.Blocks.getParsedBlock(parseInt(slotNumber)), { maxRetries: 3, delay: 100, exponential: true });
|
|
408
546
|
}
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
initTx.tx.addSignature(swapData.offerer, buffer_1.Buffer.from(signatureStr, "hex"));
|
|
547
|
+
const initTx = await (await this.InitNotPayIn(sender, swapData, BigInt(timeout))).tx(feeRate, block);
|
|
548
|
+
if (requiresCounterpartySignature)
|
|
549
|
+
initTx.tx.addSignature(signer, buffer_1.Buffer.from(signature.split(";")[1], "hex"));
|
|
413
550
|
this.logger.debug("txsInit(): create swap init TX, swap: " + swapData.getClaimHash() + " feerate: " + feeRate);
|
|
414
551
|
return [initTx];
|
|
415
552
|
}
|
|
@@ -481,7 +618,7 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
|
|
|
481
618
|
: await this.getInitFeeRate(swapData.offerer, swapData.claimer, swapData.token, swapData.paymentHash));
|
|
482
619
|
const [rawFee, initAta] = await Promise.all([
|
|
483
620
|
this.getRawInitFee(swapData, feeRate),
|
|
484
|
-
swapData != null && swapData.payOut ?
|
|
621
|
+
(0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram) && swapData != null && swapData.payOut ?
|
|
485
622
|
this.root.Tokens.getATAOrNull((0, spl_token_1.getAssociatedTokenAddressSync)(swapData.token, swapData.claimer)).then(acc => acc == null) :
|
|
486
623
|
Promise.resolve(null)
|
|
487
624
|
]);
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { SolanaSwapModule } from "../SolanaSwapModule";
|
|
4
4
|
import { SolanaSwapData } from "../SolanaSwapData";
|
|
5
5
|
import { SolanaTx } from "../../chain/modules/SolanaTransactions";
|
|
6
|
+
import { PublicKey } from "@solana/web3.js";
|
|
6
7
|
import { Buffer } from "buffer";
|
|
7
8
|
import { SolanaSigner } from "../../wallet/SolanaSigner";
|
|
8
9
|
export declare class SwapRefund extends SolanaSwapModule {
|
|
@@ -10,6 +11,7 @@ export declare class SwapRefund extends SolanaSwapModule {
|
|
|
10
11
|
/**
|
|
11
12
|
* Action for generic Refund instruction
|
|
12
13
|
*
|
|
14
|
+
* @param signer
|
|
13
15
|
* @param swapData
|
|
14
16
|
* @param refundAuthTimeout optional refund authorization timeout (should be 0 for refunding expired swaps)
|
|
15
17
|
* @private
|
|
@@ -18,6 +20,7 @@ export declare class SwapRefund extends SolanaSwapModule {
|
|
|
18
20
|
/**
|
|
19
21
|
* Action for refunding with signature, adds the Ed25519 verify instruction
|
|
20
22
|
*
|
|
23
|
+
* @param signer
|
|
21
24
|
* @param swapData
|
|
22
25
|
* @param timeout
|
|
23
26
|
* @param prefix
|
|
@@ -37,6 +40,7 @@ export declare class SwapRefund extends SolanaSwapModule {
|
|
|
37
40
|
/**
|
|
38
41
|
* Checks whether we should unwrap the WSOL to SOL when refunding the swap
|
|
39
42
|
*
|
|
43
|
+
* @param signer
|
|
40
44
|
* @param swapData
|
|
41
45
|
* @private
|
|
42
46
|
*/
|
|
@@ -50,15 +54,17 @@ export declare class SwapRefund extends SolanaSwapModule {
|
|
|
50
54
|
/**
|
|
51
55
|
* Creates transactions required for refunding timed out swap, also unwraps WSOL to SOL
|
|
52
56
|
*
|
|
57
|
+
* @param signer
|
|
53
58
|
* @param swapData swap data to refund
|
|
54
59
|
* @param check whether to check if swap is already expired and refundable
|
|
55
60
|
* @param initAta should initialize ATA if it doesn't exist
|
|
56
61
|
* @param feeRate fee rate to be used for the transactions
|
|
57
62
|
*/
|
|
58
|
-
txsRefund(swapData: SolanaSwapData, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]>;
|
|
63
|
+
txsRefund(signer: PublicKey, swapData: SolanaSwapData, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]>;
|
|
59
64
|
/**
|
|
60
65
|
* Creates transactions required for refunding the swap with authorization signature, also unwraps WSOL to SOL
|
|
61
66
|
*
|
|
67
|
+
* @param signer
|
|
62
68
|
* @param swapData swap data to refund
|
|
63
69
|
* @param timeout signature timeout
|
|
64
70
|
* @param prefix signature prefix of the counterparty
|
|
@@ -67,7 +73,7 @@ export declare class SwapRefund extends SolanaSwapModule {
|
|
|
67
73
|
* @param initAta should initialize ATA if it doesn't exist
|
|
68
74
|
* @param feeRate fee rate to be used for the transactions
|
|
69
75
|
*/
|
|
70
|
-
txsRefundWithAuthorization(swapData: SolanaSwapData, timeout: string, prefix: string, signature: string, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]>;
|
|
76
|
+
txsRefundWithAuthorization(signer: PublicKey, swapData: SolanaSwapData, timeout: string, prefix: string, signature: string, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]>;
|
|
71
77
|
getRefundFeeRate(swapData: SolanaSwapData): Promise<string>;
|
|
72
78
|
/**
|
|
73
79
|
* Get the estimated solana transaction fee of the refund transaction, in the worst case scenario in case where the
|