@atomiqlabs/chain-solana 13.5.13 → 13.5.14
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/LICENSE +201 -201
- package/README.md +73 -73
- package/dist/index.d.ts +81 -81
- package/dist/index.js +102 -102
- package/dist/node/index.d.ts +9 -9
- package/dist/node/index.js +13 -13
- package/dist/solana/SolanaChainType.d.ts +15 -15
- package/dist/solana/SolanaChainType.js +2 -2
- package/dist/solana/SolanaChains.d.ts +12 -12
- package/dist/solana/SolanaChains.js +45 -45
- package/dist/solana/SolanaInitializer.d.ts +94 -94
- package/dist/solana/SolanaInitializer.js +174 -174
- package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +222 -222
- package/dist/solana/btcrelay/SolanaBtcRelay.js +455 -455
- package/dist/solana/btcrelay/headers/SolanaBtcHeader.d.ts +84 -84
- package/dist/solana/btcrelay/headers/SolanaBtcHeader.js +70 -70
- package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.d.ts +92 -92
- package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.js +109 -109
- package/dist/solana/btcrelay/program/programIdl.json +671 -671
- package/dist/solana/chain/SolanaAction.d.ts +26 -26
- package/dist/solana/chain/SolanaAction.js +87 -87
- package/dist/solana/chain/SolanaChainInterface.d.ts +224 -224
- package/dist/solana/chain/SolanaChainInterface.js +275 -275
- package/dist/solana/chain/SolanaModule.d.ts +14 -14
- package/dist/solana/chain/SolanaModule.js +13 -13
- package/dist/solana/chain/modules/SolanaAddresses.d.ts +8 -8
- package/dist/solana/chain/modules/SolanaAddresses.js +22 -22
- package/dist/solana/chain/modules/SolanaBlocks.d.ts +32 -32
- package/dist/solana/chain/modules/SolanaBlocks.js +78 -78
- package/dist/solana/chain/modules/SolanaEvents.d.ts +68 -68
- package/dist/solana/chain/modules/SolanaEvents.js +238 -238
- package/dist/solana/chain/modules/SolanaFees.d.ts +189 -189
- package/dist/solana/chain/modules/SolanaFees.js +434 -434
- package/dist/solana/chain/modules/SolanaSignatures.d.ts +24 -24
- package/dist/solana/chain/modules/SolanaSignatures.js +39 -39
- package/dist/solana/chain/modules/SolanaSlots.d.ts +33 -33
- package/dist/solana/chain/modules/SolanaSlots.js +72 -72
- package/dist/solana/chain/modules/SolanaTokens.d.ts +123 -123
- package/dist/solana/chain/modules/SolanaTokens.js +242 -242
- package/dist/solana/chain/modules/SolanaTransactions.d.ts +149 -149
- package/dist/solana/chain/modules/SolanaTransactions.js +445 -445
- package/dist/solana/connection/ConnectionWithRetries.d.ts +35 -35
- package/dist/solana/connection/ConnectionWithRetries.js +86 -71
- package/dist/solana/events/SolanaChainEvents.d.ts +45 -45
- package/dist/solana/events/SolanaChainEvents.js +108 -108
- package/dist/solana/events/SolanaChainEventsBrowser.d.ts +205 -205
- package/dist/solana/events/SolanaChainEventsBrowser.js +404 -404
- package/dist/solana/program/SolanaProgramBase.d.ts +73 -73
- package/dist/solana/program/SolanaProgramBase.js +54 -54
- package/dist/solana/program/SolanaProgramModule.d.ts +8 -8
- package/dist/solana/program/SolanaProgramModule.js +11 -11
- package/dist/solana/program/modules/SolanaProgramEvents.d.ts +53 -53
- package/dist/solana/program/modules/SolanaProgramEvents.js +117 -117
- package/dist/solana/swaps/SolanaSwapData.d.ts +333 -333
- package/dist/solana/swaps/SolanaSwapData.js +535 -535
- package/dist/solana/swaps/SolanaSwapModule.d.ts +11 -11
- package/dist/solana/swaps/SolanaSwapModule.js +12 -12
- package/dist/solana/swaps/SolanaSwapProgram.d.ts +376 -376
- package/dist/solana/swaps/SolanaSwapProgram.js +769 -769
- package/dist/solana/swaps/SwapTypeEnum.d.ts +11 -11
- package/dist/solana/swaps/SwapTypeEnum.js +43 -43
- package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +95 -95
- package/dist/solana/swaps/modules/SolanaDataAccount.js +232 -232
- package/dist/solana/swaps/modules/SolanaLpVault.d.ts +69 -69
- package/dist/solana/swaps/modules/SolanaLpVault.js +171 -171
- package/dist/solana/swaps/modules/SwapClaim.d.ts +126 -126
- package/dist/solana/swaps/modules/SwapClaim.js +294 -294
- package/dist/solana/swaps/modules/SwapInit.d.ts +213 -213
- package/dist/solana/swaps/modules/SwapInit.js +658 -658
- package/dist/solana/swaps/modules/SwapRefund.d.ts +87 -87
- package/dist/solana/swaps/modules/SwapRefund.js +293 -293
- package/dist/solana/swaps/programIdl.json +945 -945
- package/dist/solana/swaps/programTypes.d.ts +943 -943
- package/dist/solana/swaps/programTypes.js +945 -945
- package/dist/solana/swaps/v1/programIdl.json +945 -945
- package/dist/solana/swaps/v1/programTypes.d.ts +943 -943
- package/dist/solana/swaps/v1/programTypes.js +945 -945
- package/dist/solana/swaps/v2/programIdl.json +952 -952
- package/dist/solana/swaps/v2/programTypes.d.ts +950 -950
- package/dist/solana/swaps/v2/programTypes.js +952 -952
- package/dist/solana/wallet/SolanaKeypairWallet.d.ts +29 -29
- package/dist/solana/wallet/SolanaKeypairWallet.js +50 -50
- package/dist/solana/wallet/SolanaSigner.d.ts +30 -30
- package/dist/solana/wallet/SolanaSigner.js +30 -30
- package/dist/utils/Utils.d.ts +58 -58
- package/dist/utils/Utils.js +170 -170
- package/node/index.d.ts +1 -1
- package/node/index.js +3 -3
- package/package.json +46 -46
- package/src/index.ts +87 -87
- package/src/node/index.ts +9 -9
- package/src/solana/SolanaChainType.ts +32 -32
- package/src/solana/SolanaChains.ts +46 -46
- package/src/solana/SolanaInitializer.ts +278 -278
- package/src/solana/btcrelay/SolanaBtcRelay.ts +615 -615
- package/src/solana/btcrelay/headers/SolanaBtcHeader.ts +116 -116
- package/src/solana/btcrelay/headers/SolanaBtcStoredHeader.ts +148 -148
- package/src/solana/btcrelay/program/programIdl.json +670 -670
- package/src/solana/chain/SolanaAction.ts +109 -109
- package/src/solana/chain/SolanaChainInterface.ts +404 -404
- package/src/solana/chain/SolanaModule.ts +20 -20
- package/src/solana/chain/modules/SolanaAddresses.ts +20 -20
- package/src/solana/chain/modules/SolanaBlocks.ts +89 -89
- package/src/solana/chain/modules/SolanaEvents.ts +271 -271
- package/src/solana/chain/modules/SolanaFees.ts +522 -522
- package/src/solana/chain/modules/SolanaSignatures.ts +39 -39
- package/src/solana/chain/modules/SolanaSlots.ts +85 -85
- package/src/solana/chain/modules/SolanaTokens.ts +300 -300
- package/src/solana/chain/modules/SolanaTransactions.ts +503 -503
- package/src/solana/connection/ConnectionWithRetries.ts +113 -96
- package/src/solana/events/SolanaChainEvents.ts +127 -127
- package/src/solana/events/SolanaChainEventsBrowser.ts +495 -495
- package/src/solana/program/SolanaProgramBase.ts +119 -119
- package/src/solana/program/SolanaProgramModule.ts +15 -15
- package/src/solana/program/modules/SolanaProgramEvents.ts +157 -157
- package/src/solana/swaps/SolanaSwapData.ts +735 -735
- package/src/solana/swaps/SolanaSwapModule.ts +19 -19
- package/src/solana/swaps/SolanaSwapProgram.ts +1074 -1074
- package/src/solana/swaps/SwapTypeEnum.ts +30 -30
- package/src/solana/swaps/modules/SolanaDataAccount.ts +302 -302
- package/src/solana/swaps/modules/SolanaLpVault.ts +208 -208
- package/src/solana/swaps/modules/SwapClaim.ts +387 -387
- package/src/solana/swaps/modules/SwapInit.ts +785 -785
- package/src/solana/swaps/modules/SwapRefund.ts +353 -353
- package/src/solana/swaps/v1/programIdl.json +944 -944
- package/src/solana/swaps/v1/programTypes.ts +1885 -1885
- package/src/solana/swaps/v2/programIdl.json +951 -951
- package/src/solana/swaps/v2/programTypes.ts +1899 -1899
- package/src/solana/wallet/SolanaKeypairWallet.ts +56 -56
- package/src/solana/wallet/SolanaSigner.ts +43 -43
- package/src/utils/Utils.ts +194 -194
|
@@ -1,769 +1,769 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SolanaSwapProgram = exports.isSwapProgramV2 = exports.isSwapProgramV1 = void 0;
|
|
4
|
-
const SolanaSwapData_1 = require("./SolanaSwapData");
|
|
5
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
-
const sha2_1 = require("@noble/hashes/sha2");
|
|
7
|
-
const programIdlV1 = require("./v1/programIdl.json");
|
|
8
|
-
const programIdlV2 = require("./v2/programIdl.json");
|
|
9
|
-
const base_1 = require("@atomiqlabs/base");
|
|
10
|
-
const spl_token_1 = require("@solana/spl-token");
|
|
11
|
-
const SolanaProgramBase_1 = require("../program/SolanaProgramBase");
|
|
12
|
-
const SwapInit_1 = require("./modules/SwapInit");
|
|
13
|
-
const SolanaDataAccount_1 = require("./modules/SolanaDataAccount");
|
|
14
|
-
const SwapRefund_1 = require("./modules/SwapRefund");
|
|
15
|
-
const SwapClaim_1 = require("./modules/SwapClaim");
|
|
16
|
-
const SolanaLpVault_1 = require("./modules/SolanaLpVault");
|
|
17
|
-
const buffer_1 = require("buffer");
|
|
18
|
-
const Utils_1 = require("../../utils/Utils");
|
|
19
|
-
const SolanaTokens_1 = require("../chain/modules/SolanaTokens");
|
|
20
|
-
const BN = require("bn.js");
|
|
21
|
-
const SolanaChains_1 = require("../SolanaChains");
|
|
22
|
-
function isSwapProgramV1(obj) {
|
|
23
|
-
return obj.idl.version === "0.1.0";
|
|
24
|
-
}
|
|
25
|
-
exports.isSwapProgramV1 = isSwapProgramV1;
|
|
26
|
-
function isSwapProgramV2(obj) {
|
|
27
|
-
return obj.idl.version === "0.2.0";
|
|
28
|
-
}
|
|
29
|
-
exports.isSwapProgramV2 = isSwapProgramV2;
|
|
30
|
-
function toPublicKeyOrNull(str) {
|
|
31
|
-
return str == null ? undefined : new web3_js_1.PublicKey(str);
|
|
32
|
-
}
|
|
33
|
-
const MAX_PARALLEL_COMMIT_STATUS_CHECKS = 5;
|
|
34
|
-
/**
|
|
35
|
-
* Solana swap (escrow manager) program representation handling PrTLC (on-chain) and HTLC (lightning) based swaps.
|
|
36
|
-
*
|
|
37
|
-
* @category Swaps
|
|
38
|
-
*/
|
|
39
|
-
class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
|
|
40
|
-
constructor(chainInterface, btcRelay, storage, programAddress, bitcoinNetwork, version) {
|
|
41
|
-
version ?? (version = "v1");
|
|
42
|
-
if (bitcoinNetwork != null && programAddress == null) {
|
|
43
|
-
programAddress = SolanaChains_1.SolanaChains[bitcoinNetwork]?.addresses[version ?? "v1"]?.swapContract;
|
|
44
|
-
}
|
|
45
|
-
super(chainInterface, version === "v1" ? programIdlV1 : programIdlV2, programAddress);
|
|
46
|
-
this._SwapVaultAuthority = SolanaSwapProgram._SwapVaultAuthority(this.program.programId); // Only necessary for V1 program
|
|
47
|
-
this._SwapVault = SolanaSwapProgram._SwapVault.bind(this, this.program.programId);
|
|
48
|
-
this._SwapUserVault = SolanaSwapProgram._SwapUserVault.bind(this, this.program.programId);
|
|
49
|
-
this._SwapEscrowState = SolanaSwapProgram._SwapEscrowState.bind(this, this.program.programId);
|
|
50
|
-
////////////////////////
|
|
51
|
-
//// Timeouts
|
|
52
|
-
/**
|
|
53
|
-
* @inheritDoc
|
|
54
|
-
*/
|
|
55
|
-
this.chainId = "SOLANA";
|
|
56
|
-
/**
|
|
57
|
-
* @inheritDoc
|
|
58
|
-
*/
|
|
59
|
-
this.claimWithSecretTimeout = 45;
|
|
60
|
-
/**
|
|
61
|
-
* @inheritDoc
|
|
62
|
-
*/
|
|
63
|
-
this.claimWithTxDataTimeout = 120;
|
|
64
|
-
/**
|
|
65
|
-
* @inheritDoc
|
|
66
|
-
*/
|
|
67
|
-
this.refundTimeout = 45;
|
|
68
|
-
/**
|
|
69
|
-
* Grace period (seconds) applied to claimer-side expiry checks.
|
|
70
|
-
*/
|
|
71
|
-
this.claimGracePeriod = 10 * 60;
|
|
72
|
-
/**
|
|
73
|
-
* Grace period (seconds) applied to offerer-side expiry checks.
|
|
74
|
-
*/
|
|
75
|
-
this.refundGracePeriod = 10 * 60;
|
|
76
|
-
/**
|
|
77
|
-
* Authorization grace period in seconds.
|
|
78
|
-
* @internal
|
|
79
|
-
*/
|
|
80
|
-
this._authGracePeriod = 30;
|
|
81
|
-
this.version = version;
|
|
82
|
-
this.ESCROW_STATE_RENT_EXEMPT = this.version === "v1" ? 2658720 : 2665680;
|
|
83
|
-
this.supportsInitWithoutClaimer = (this.version !== "v1");
|
|
84
|
-
this.Init = new SwapInit_1.SwapInit(chainInterface, this);
|
|
85
|
-
this.Refund = new SwapRefund_1.SwapRefund(chainInterface, this);
|
|
86
|
-
this.Claim = new SwapClaim_1.SwapClaim(chainInterface, this, btcRelay);
|
|
87
|
-
this._DataAccount = new SolanaDataAccount_1.SolanaDataAccount(chainInterface, this, storage);
|
|
88
|
-
this.LpVault = new SolanaLpVault_1.SolanaLpVault(chainInterface, this);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* @inheritDoc
|
|
92
|
-
*/
|
|
93
|
-
async start() {
|
|
94
|
-
await this._DataAccount.init();
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* @inheritDoc
|
|
98
|
-
*/
|
|
99
|
-
getClaimableDeposits(signer) {
|
|
100
|
-
return this._DataAccount.getDataAccountsInfo(new web3_js_1.PublicKey(signer));
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* @inheritDoc
|
|
104
|
-
*/
|
|
105
|
-
claimDeposits(signer) {
|
|
106
|
-
return this._DataAccount.sweepDataAccounts(signer);
|
|
107
|
-
}
|
|
108
|
-
////////////////////////////////////////////
|
|
109
|
-
//// Signatures
|
|
110
|
-
/**
|
|
111
|
-
* @inheritDoc
|
|
112
|
-
*/
|
|
113
|
-
preFetchForInitSignatureVerification(data) {
|
|
114
|
-
return this.Init.preFetchForInitSignatureVerification(data);
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* @inheritDoc
|
|
118
|
-
*/
|
|
119
|
-
preFetchBlockDataForSignatures() {
|
|
120
|
-
return this.Init.preFetchBlockDataForSignatures();
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* @inheritDoc
|
|
124
|
-
*/
|
|
125
|
-
getInitSignature(signer, swapData, authorizationTimeout, preFetchedBlockData, feeRate) {
|
|
126
|
-
return this.Init.signSwapInitialization(signer, swapData, authorizationTimeout, preFetchedBlockData, feeRate);
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* @inheritDoc
|
|
130
|
-
*/
|
|
131
|
-
isValidInitAuthorization(signer, swapData, sig, feeRate, preFetchedData) {
|
|
132
|
-
return this.Init.isSignatureValid(new web3_js_1.PublicKey(signer), swapData, sig.timeout, sig.prefix, sig.signature, feeRate, preFetchedData);
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* @inheritDoc
|
|
136
|
-
*/
|
|
137
|
-
getInitAuthorizationExpiry(swapData, sig, preFetchedData) {
|
|
138
|
-
return this.Init.getSignatureExpiry(sig.timeout, sig.signature, preFetchedData);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* @inheritDoc
|
|
142
|
-
*/
|
|
143
|
-
isInitAuthorizationExpired(swapData, sig) {
|
|
144
|
-
return this.Init.isSignatureExpired(sig.signature, sig.timeout);
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* @inheritDoc
|
|
148
|
-
*/
|
|
149
|
-
getRefundSignature(signer, swapData, authorizationTimeout) {
|
|
150
|
-
return this.Refund.signSwapRefund(signer, swapData, authorizationTimeout);
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* @inheritDoc
|
|
154
|
-
*/
|
|
155
|
-
isValidRefundAuthorization(swapData, sig) {
|
|
156
|
-
return this.Refund.isSignatureValid(swapData, sig.timeout, sig.prefix, sig.signature);
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* @inheritDoc
|
|
160
|
-
*/
|
|
161
|
-
getDataSignature(signer, data) {
|
|
162
|
-
return this._Chain.Signatures.getDataSignature(signer, data);
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* @inheritDoc
|
|
166
|
-
*/
|
|
167
|
-
isValidDataSignature(data, signature, publicKey) {
|
|
168
|
-
return this._Chain.Signatures.isValidDataSignature(data, signature, publicKey);
|
|
169
|
-
}
|
|
170
|
-
////////////////////////////////////////////
|
|
171
|
-
//// Swap data utils
|
|
172
|
-
/**
|
|
173
|
-
* @inheritDoc
|
|
174
|
-
*/
|
|
175
|
-
async isClaimable(signer, data) {
|
|
176
|
-
if (!data.isClaimer(signer))
|
|
177
|
-
return false;
|
|
178
|
-
if (await this.isExpired(signer, data))
|
|
179
|
-
return false;
|
|
180
|
-
return await this.isCommited(data);
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* @inheritDoc
|
|
184
|
-
*/
|
|
185
|
-
async isCommited(swapData) {
|
|
186
|
-
const paymentHash = buffer_1.Buffer.from(swapData.paymentHash, "hex");
|
|
187
|
-
const account = await this.program.account.escrowState.fetchNullable(this._SwapEscrowState(paymentHash));
|
|
188
|
-
if (account == null)
|
|
189
|
-
return false;
|
|
190
|
-
return swapData.correctPDA(account);
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* @inheritDoc
|
|
194
|
-
*/
|
|
195
|
-
isExpired(signer, data, refundSide) {
|
|
196
|
-
let currentTimestamp = new BN(Math.floor(Date.now() / 1000));
|
|
197
|
-
if (data.isClaimer(signer) && !refundSide) {
|
|
198
|
-
currentTimestamp = currentTimestamp.add(new BN(this.claimGracePeriod));
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
currentTimestamp = currentTimestamp.sub(new BN(this.refundGracePeriod));
|
|
202
|
-
}
|
|
203
|
-
return Promise.resolve(data.expiry.lt(currentTimestamp));
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* @inheritDoc
|
|
207
|
-
*/
|
|
208
|
-
async isRequestRefundable(signer, data) {
|
|
209
|
-
//V1 Swap can only be refunded by the offerer
|
|
210
|
-
if (isSwapProgramV1(this.program) && !data.isOfferer(signer))
|
|
211
|
-
return false;
|
|
212
|
-
if (!(await this.isExpired(signer, data, true)))
|
|
213
|
-
return false;
|
|
214
|
-
return await this.isCommited(data);
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* @inheritDoc
|
|
218
|
-
*/
|
|
219
|
-
getHashForOnchain(outputScript, amount, confirmations, nonce) {
|
|
220
|
-
nonce ?? (nonce = 0n);
|
|
221
|
-
const paymentHash = buffer_1.Buffer.from((0, sha2_1.sha256)(buffer_1.Buffer.concat([
|
|
222
|
-
base_1.BigIntBufferUtils.toBuffer(nonce, "le", 8),
|
|
223
|
-
base_1.BigIntBufferUtils.toBuffer(amount, "le", 8),
|
|
224
|
-
outputScript
|
|
225
|
-
]))).toString("hex");
|
|
226
|
-
return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(paymentHash, nonce, confirmations), "hex");
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* @inheritDoc
|
|
230
|
-
*/
|
|
231
|
-
getHashForHtlc(swapHash) {
|
|
232
|
-
return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(swapHash.toString("hex"), 0n, 0), "hex");
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* @inheritDoc
|
|
236
|
-
*/
|
|
237
|
-
getHashForTxId(txId, confirmations) {
|
|
238
|
-
return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(buffer_1.Buffer.from(txId, "hex").reverse().toString("hex"), 0n, confirmations), "hex");
|
|
239
|
-
}
|
|
240
|
-
////////////////////////////////////////////
|
|
241
|
-
//// Swap data getters
|
|
242
|
-
/**
|
|
243
|
-
* @inheritDoc
|
|
244
|
-
*/
|
|
245
|
-
async getCommitStatus(signer, data) {
|
|
246
|
-
const escrowStateKey = this._SwapEscrowState(buffer_1.Buffer.from(data.paymentHash, "hex"));
|
|
247
|
-
const [escrowState, isExpired] = await Promise.all([
|
|
248
|
-
this.program.account.escrowState.fetchNullable(escrowStateKey),
|
|
249
|
-
this.isExpired(signer, data)
|
|
250
|
-
]);
|
|
251
|
-
const getInitTxId = (0, Utils_1.onceAsync)(async () => {
|
|
252
|
-
const txId = await this._Events.findInEvents(escrowStateKey, async (event, tx) => {
|
|
253
|
-
if (event.name === "InitializeEvent") {
|
|
254
|
-
const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
|
|
255
|
-
if (paymentHash !== data.paymentHash)
|
|
256
|
-
return null;
|
|
257
|
-
if (!event.data.sequence.eq(data.sequence))
|
|
258
|
-
return null;
|
|
259
|
-
return tx.transaction.signatures[0];
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
if (txId == null)
|
|
263
|
-
throw new Error("Initialize event not found!");
|
|
264
|
-
return txId;
|
|
265
|
-
});
|
|
266
|
-
if (escrowState != null) {
|
|
267
|
-
if (data.correctPDA(escrowState)) {
|
|
268
|
-
if (data.isOfferer(signer) && isExpired)
|
|
269
|
-
return { type: base_1.SwapCommitStateType.REFUNDABLE, getInitTxId };
|
|
270
|
-
return { type: base_1.SwapCommitStateType.COMMITED, getInitTxId };
|
|
271
|
-
}
|
|
272
|
-
if (data.isOfferer(signer) && isExpired)
|
|
273
|
-
return { type: base_1.SwapCommitStateType.EXPIRED };
|
|
274
|
-
return { type: base_1.SwapCommitStateType.NOT_COMMITED };
|
|
275
|
-
}
|
|
276
|
-
//Check if paid or what
|
|
277
|
-
const status = await this._Events.findInEvents(escrowStateKey, async (event, tx) => {
|
|
278
|
-
if (event.name === "ClaimEvent") {
|
|
279
|
-
const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
|
|
280
|
-
if (paymentHash !== data.paymentHash)
|
|
281
|
-
return null;
|
|
282
|
-
if (!event.data.sequence.eq(data.sequence))
|
|
283
|
-
return null;
|
|
284
|
-
return {
|
|
285
|
-
type: base_1.SwapCommitStateType.PAID,
|
|
286
|
-
getInitTxId,
|
|
287
|
-
getClaimTxId: () => Promise.resolve(tx.transaction.signatures[0]),
|
|
288
|
-
getClaimResult: () => Promise.resolve(buffer_1.Buffer.from(event.data.secret).toString("hex")),
|
|
289
|
-
getTxBlock: () => Promise.resolve({
|
|
290
|
-
blockHeight: tx.slot,
|
|
291
|
-
blockTime: tx.blockTime
|
|
292
|
-
})
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
if (event.name === "RefundEvent") {
|
|
296
|
-
const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
|
|
297
|
-
if (paymentHash !== data.paymentHash)
|
|
298
|
-
return null;
|
|
299
|
-
if (!event.data.sequence.eq(data.sequence))
|
|
300
|
-
return null;
|
|
301
|
-
return {
|
|
302
|
-
type: isExpired ? base_1.SwapCommitStateType.EXPIRED : base_1.SwapCommitStateType.NOT_COMMITED,
|
|
303
|
-
getInitTxId,
|
|
304
|
-
getRefundTxId: () => Promise.resolve(tx.transaction.signatures[0]),
|
|
305
|
-
getTxBlock: () => Promise.resolve({
|
|
306
|
-
blockHeight: tx.slot,
|
|
307
|
-
blockTime: tx.blockTime
|
|
308
|
-
})
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
if (status != null)
|
|
313
|
-
return status;
|
|
314
|
-
if (isExpired)
|
|
315
|
-
return { type: base_1.SwapCommitStateType.EXPIRED };
|
|
316
|
-
return { type: base_1.SwapCommitStateType.NOT_COMMITED };
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* @inheritDoc
|
|
320
|
-
*/
|
|
321
|
-
async getCommitStatuses(request) {
|
|
322
|
-
const result = {};
|
|
323
|
-
let promises = [];
|
|
324
|
-
for (let { signer, swapData } of request) {
|
|
325
|
-
promises.push(this.getCommitStatus(signer, swapData).then(val => {
|
|
326
|
-
result[swapData.getEscrowHash()] = val;
|
|
327
|
-
}));
|
|
328
|
-
if (promises.length >= MAX_PARALLEL_COMMIT_STATUS_CHECKS) {
|
|
329
|
-
await Promise.all(promises);
|
|
330
|
-
promises = [];
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
await Promise.all(promises);
|
|
334
|
-
return result;
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* @inheritDoc
|
|
338
|
-
*/
|
|
339
|
-
async getClaimHashStatus(claimHash) {
|
|
340
|
-
const { paymentHash } = (0, Utils_1.fromClaimHash)(claimHash);
|
|
341
|
-
const escrowStateKey = this._SwapEscrowState(buffer_1.Buffer.from(paymentHash, "hex"));
|
|
342
|
-
const abortController = new AbortController();
|
|
343
|
-
//Start fetching events before checking escrow PDA, this call is used when quoting, so saving 100ms here helps a lot!
|
|
344
|
-
const eventsPromise = this._Events.findInEvents(escrowStateKey, async (event) => {
|
|
345
|
-
if (event.name === "ClaimEvent")
|
|
346
|
-
return base_1.SwapCommitStateType.PAID;
|
|
347
|
-
if (event.name === "RefundEvent")
|
|
348
|
-
return base_1.SwapCommitStateType.NOT_COMMITED;
|
|
349
|
-
}, abortController.signal).catch(e => {
|
|
350
|
-
abortController.abort(e);
|
|
351
|
-
return null;
|
|
352
|
-
});
|
|
353
|
-
const escrowState = await this.program.account.escrowState.fetchNullable(escrowStateKey);
|
|
354
|
-
abortController.signal.throwIfAborted();
|
|
355
|
-
if (escrowState != null) {
|
|
356
|
-
abortController.abort();
|
|
357
|
-
return base_1.SwapCommitStateType.COMMITED;
|
|
358
|
-
}
|
|
359
|
-
//Check if paid or what
|
|
360
|
-
const eventsStatus = await eventsPromise;
|
|
361
|
-
abortController.signal.throwIfAborted();
|
|
362
|
-
if (eventsStatus != null)
|
|
363
|
-
return eventsStatus;
|
|
364
|
-
return base_1.SwapCommitStateType.NOT_COMMITED;
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* @inheritDoc
|
|
368
|
-
*/
|
|
369
|
-
async getCommitedData(claimHashHex) {
|
|
370
|
-
const { paymentHash } = (0, Utils_1.fromClaimHash)(claimHashHex);
|
|
371
|
-
const paymentHashBuffer = buffer_1.Buffer.from(paymentHash, "hex");
|
|
372
|
-
const account = await this.program.account.escrowState.fetchNullable(this._SwapEscrowState(paymentHashBuffer));
|
|
373
|
-
if (account == null)
|
|
374
|
-
return null;
|
|
375
|
-
return SolanaSwapData_1.SolanaSwapData.fromEscrowState(this.program.programId, this.version, account);
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* @inheritDoc
|
|
379
|
-
*/
|
|
380
|
-
async getHistoricalSwaps(signer, startBlockheight) {
|
|
381
|
-
let latestBlockheight;
|
|
382
|
-
const events = [];
|
|
383
|
-
await this._Events.findInEvents(new web3_js_1.PublicKey(signer), async (event, tx) => {
|
|
384
|
-
if (latestBlockheight == null)
|
|
385
|
-
latestBlockheight = tx.slot;
|
|
386
|
-
events.push({ event, tx });
|
|
387
|
-
}, undefined, undefined, startBlockheight);
|
|
388
|
-
this.logger.debug(`getHistoricalSwaps(): Found ${events.length} atomiq related events!`);
|
|
389
|
-
const swapsOpened = {};
|
|
390
|
-
const resultingSwaps = {};
|
|
391
|
-
events.reverse();
|
|
392
|
-
for (let { event, tx } of events) {
|
|
393
|
-
const txSignature = tx.transaction.signatures[0];
|
|
394
|
-
const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
|
|
395
|
-
const escrowHash = (0, Utils_1.toEscrowHash)(paymentHash, event.data.sequence);
|
|
396
|
-
if (event.name === "InitializeEvent") {
|
|
397
|
-
//Parse swap data from initialize event
|
|
398
|
-
const txoHash = buffer_1.Buffer.from(event.data.txoHash).toString("hex");
|
|
399
|
-
const instructions = this._Events.decodeInstructions(tx.transaction.message);
|
|
400
|
-
if (instructions == null) {
|
|
401
|
-
this.logger.warn(`getHistoricalSwaps(): Skipping tx ${txSignature} because cannot parse instructions!`);
|
|
402
|
-
continue;
|
|
403
|
-
}
|
|
404
|
-
const initIx = instructions.find(ix => ix != null && (ix.name === "offererInitializePayIn" || ix.name === "offererInitialize"));
|
|
405
|
-
if (initIx == null) {
|
|
406
|
-
this.logger.warn(`getHistoricalSwaps(): Skipping tx ${txSignature} because init instruction not found!`);
|
|
407
|
-
continue;
|
|
408
|
-
}
|
|
409
|
-
swapsOpened[escrowHash] = {
|
|
410
|
-
data: SolanaSwapData_1.SolanaSwapData.fromInstruction(this.program.programId, this.version, initIx, txoHash),
|
|
411
|
-
getInitTxId: () => Promise.resolve(txSignature),
|
|
412
|
-
getTxBlock: () => Promise.resolve({
|
|
413
|
-
blockHeight: tx.slot,
|
|
414
|
-
blockTime: tx.blockTime
|
|
415
|
-
})
|
|
416
|
-
};
|
|
417
|
-
}
|
|
418
|
-
if (event.name === "ClaimEvent") {
|
|
419
|
-
const foundSwapData = swapsOpened[escrowHash];
|
|
420
|
-
delete swapsOpened[escrowHash];
|
|
421
|
-
resultingSwaps[escrowHash] = {
|
|
422
|
-
init: foundSwapData,
|
|
423
|
-
state: {
|
|
424
|
-
type: base_1.SwapCommitStateType.PAID,
|
|
425
|
-
getInitTxId: foundSwapData?.getInitTxId,
|
|
426
|
-
getClaimTxId: () => Promise.resolve(txSignature),
|
|
427
|
-
getClaimResult: () => Promise.resolve(buffer_1.Buffer.from(event.data.secret).toString("hex")),
|
|
428
|
-
getTxBlock: () => Promise.resolve({
|
|
429
|
-
blockHeight: tx.slot,
|
|
430
|
-
blockTime: tx.blockTime
|
|
431
|
-
})
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
if (event.name === "RefundEvent") {
|
|
436
|
-
const foundSwapData = swapsOpened[escrowHash];
|
|
437
|
-
delete swapsOpened[escrowHash];
|
|
438
|
-
const isExpired = foundSwapData != null && await this.isExpired(signer, foundSwapData.data);
|
|
439
|
-
resultingSwaps[escrowHash] = {
|
|
440
|
-
init: foundSwapData,
|
|
441
|
-
state: {
|
|
442
|
-
type: isExpired ? base_1.SwapCommitStateType.EXPIRED : base_1.SwapCommitStateType.NOT_COMMITED,
|
|
443
|
-
getInitTxId: foundSwapData?.getInitTxId,
|
|
444
|
-
getRefundTxId: () => Promise.resolve(txSignature),
|
|
445
|
-
getTxBlock: () => Promise.resolve({
|
|
446
|
-
blockHeight: tx.slot,
|
|
447
|
-
blockTime: tx.blockTime
|
|
448
|
-
})
|
|
449
|
-
}
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
this.logger.debug(`getHistoricalSwaps(): Found ${Object.keys(resultingSwaps).length} settled swaps!`);
|
|
454
|
-
this.logger.debug(`getHistoricalSwaps(): Found ${Object.keys(swapsOpened).length} unsettled swaps!`);
|
|
455
|
-
for (let escrowHash in swapsOpened) {
|
|
456
|
-
const foundSwapData = swapsOpened[escrowHash];
|
|
457
|
-
const isExpired = await this.isExpired(signer, foundSwapData.data);
|
|
458
|
-
resultingSwaps[escrowHash] = {
|
|
459
|
-
init: foundSwapData,
|
|
460
|
-
state: foundSwapData.data.isOfferer(signer) && isExpired
|
|
461
|
-
? { type: base_1.SwapCommitStateType.REFUNDABLE, getInitTxId: foundSwapData.getInitTxId }
|
|
462
|
-
: { type: base_1.SwapCommitStateType.COMMITED, getInitTxId: foundSwapData.getInitTxId }
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
return {
|
|
466
|
-
swaps: resultingSwaps,
|
|
467
|
-
latestBlockheight: latestBlockheight ?? startBlockheight
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
////////////////////////////////////////////
|
|
471
|
-
//// Swap data initializer
|
|
472
|
-
/**
|
|
473
|
-
* @inheritDoc
|
|
474
|
-
*/
|
|
475
|
-
createSwapData(type, offerer, claimer, token, amount, claimHash, sequence, expiry, payIn, payOut, securityDeposit, claimerBounty, depositToken) {
|
|
476
|
-
if (depositToken != null) {
|
|
477
|
-
if (!new web3_js_1.PublicKey(depositToken).equals(SolanaTokens_1.SolanaTokens.WSOL_ADDRESS))
|
|
478
|
-
throw new Error("Only SOL supported as deposit token!");
|
|
479
|
-
}
|
|
480
|
-
const tokenAddr = new web3_js_1.PublicKey(token);
|
|
481
|
-
const offererKey = new web3_js_1.PublicKey(offerer);
|
|
482
|
-
const claimerKey = new web3_js_1.PublicKey(claimer);
|
|
483
|
-
const { paymentHash, nonce, confirmations } = (0, Utils_1.fromClaimHash)(claimHash);
|
|
484
|
-
const swapData = new SolanaSwapData_1.SolanaSwapData({
|
|
485
|
-
programId: this.program.programId,
|
|
486
|
-
version: this.version,
|
|
487
|
-
offerer: offererKey,
|
|
488
|
-
claimer: claimerKey,
|
|
489
|
-
token: tokenAddr,
|
|
490
|
-
amount: (0, Utils_1.toBN)(amount),
|
|
491
|
-
paymentHash,
|
|
492
|
-
sequence: (0, Utils_1.toBN)(sequence),
|
|
493
|
-
expiry: (0, Utils_1.toBN)(expiry),
|
|
494
|
-
nonce,
|
|
495
|
-
confirmations,
|
|
496
|
-
payOut,
|
|
497
|
-
kind: SolanaSwapData_1.SolanaSwapData.typeToKind(type),
|
|
498
|
-
payIn,
|
|
499
|
-
offererAta: payIn ? (0, spl_token_1.getAssociatedTokenAddressSync)(tokenAddr, offererKey) : web3_js_1.PublicKey.default,
|
|
500
|
-
claimerAta: payOut ? (0, spl_token_1.getAssociatedTokenAddressSync)(tokenAddr, claimerKey) : web3_js_1.PublicKey.default,
|
|
501
|
-
securityDeposit: (0, Utils_1.toBN)(securityDeposit),
|
|
502
|
-
claimerBounty: (0, Utils_1.toBN)(claimerBounty)
|
|
503
|
-
});
|
|
504
|
-
return Promise.resolve(swapData);
|
|
505
|
-
}
|
|
506
|
-
////////////////////////////////////////////
|
|
507
|
-
//// Utils
|
|
508
|
-
/**
|
|
509
|
-
* @inheritDoc
|
|
510
|
-
*/
|
|
511
|
-
async getBalance(signer, tokenAddress, inContract) {
|
|
512
|
-
if (!inContract) {
|
|
513
|
-
return await this._Chain.getBalance(signer, tokenAddress);
|
|
514
|
-
}
|
|
515
|
-
const token = new web3_js_1.PublicKey(tokenAddress);
|
|
516
|
-
const publicKey = new web3_js_1.PublicKey(signer);
|
|
517
|
-
return await this.getIntermediaryBalance(publicKey, token);
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* @inheritDoc
|
|
521
|
-
*/
|
|
522
|
-
getIntermediaryData(address, token) {
|
|
523
|
-
return this.LpVault.getIntermediaryData(new web3_js_1.PublicKey(address), new web3_js_1.PublicKey(token));
|
|
524
|
-
}
|
|
525
|
-
/**
|
|
526
|
-
* @inheritDoc
|
|
527
|
-
*/
|
|
528
|
-
getIntermediaryReputation(address, token) {
|
|
529
|
-
return this.LpVault.getIntermediaryReputation(new web3_js_1.PublicKey(address), new web3_js_1.PublicKey(token));
|
|
530
|
-
}
|
|
531
|
-
/**
|
|
532
|
-
* Returns intermediary vault balance for a specific token.
|
|
533
|
-
*
|
|
534
|
-
* @param address Intermediary address
|
|
535
|
-
* @param token Token mint
|
|
536
|
-
*/
|
|
537
|
-
getIntermediaryBalance(address, token) {
|
|
538
|
-
return this.LpVault.getIntermediaryBalance(address, token);
|
|
539
|
-
}
|
|
540
|
-
////////////////////////////////////////////
|
|
541
|
-
//// Transaction initializers
|
|
542
|
-
/**
|
|
543
|
-
* @inheritDoc
|
|
544
|
-
*/
|
|
545
|
-
async txsClaimWithSecret(signer, swapData, secret, checkExpiry, initAta, feeRate, skipAtaCheck) {
|
|
546
|
-
return this.Claim.txsClaimWithSecret(typeof (signer) === "string" ? new web3_js_1.PublicKey(signer) : signer.getPublicKey(), swapData, secret, checkExpiry, initAta, feeRate, skipAtaCheck);
|
|
547
|
-
}
|
|
548
|
-
/**
|
|
549
|
-
* @inheritDoc
|
|
550
|
-
*/
|
|
551
|
-
async txsClaimWithTxData(signer, swapData, tx, requiredConfirmations, vout, commitedHeader, synchronizer, initAta, feeRate) {
|
|
552
|
-
if (swapData.confirmations !== requiredConfirmations)
|
|
553
|
-
throw new Error("Invalid requiredConfirmations provided!");
|
|
554
|
-
const { txs } = await this.Claim.txsClaimWithTxData(typeof (signer) === "string" ? new web3_js_1.PublicKey(signer) : signer, swapData, tx, vout, commitedHeader, synchronizer, initAta, feeRate);
|
|
555
|
-
return txs;
|
|
556
|
-
}
|
|
557
|
-
/**
|
|
558
|
-
* @inheritDoc
|
|
559
|
-
*/
|
|
560
|
-
txsRefund(signer, swapData, check, initAta, feeRate) {
|
|
561
|
-
return this.Refund.txsRefund(new web3_js_1.PublicKey(signer), swapData, check, initAta, feeRate);
|
|
562
|
-
}
|
|
563
|
-
/**
|
|
564
|
-
* @inheritDoc
|
|
565
|
-
*/
|
|
566
|
-
txsRefundWithAuthorization(signer, swapData, sig, check, initAta, feeRate) {
|
|
567
|
-
return this.Refund.txsRefundWithAuthorization(new web3_js_1.PublicKey(signer), swapData, sig.timeout, sig.prefix, sig.signature, check, initAta, feeRate);
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* @inheritDoc
|
|
571
|
-
*/
|
|
572
|
-
txsInit(sender, swapData, sig, skipChecks, feeRate) {
|
|
573
|
-
if (swapData.isPayIn()) {
|
|
574
|
-
return this.Init.txsInitPayIn(new web3_js_1.PublicKey(sender), swapData, sig.timeout, sig.prefix, sig.signature, skipChecks, feeRate);
|
|
575
|
-
}
|
|
576
|
-
else {
|
|
577
|
-
return this.Init.txsInit(new web3_js_1.PublicKey(sender), swapData, sig.timeout, sig.prefix, sig.signature, skipChecks, feeRate);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
/**
|
|
581
|
-
* @inheritDoc
|
|
582
|
-
*/
|
|
583
|
-
txsWithdraw(signer, token, amount, feeRate) {
|
|
584
|
-
return this.LpVault.txsWithdraw(new web3_js_1.PublicKey(signer), new web3_js_1.PublicKey(token), amount, feeRate);
|
|
585
|
-
}
|
|
586
|
-
/**
|
|
587
|
-
* @inheritDoc
|
|
588
|
-
*/
|
|
589
|
-
txsDeposit(signer, token, amount, feeRate) {
|
|
590
|
-
return this.LpVault.txsDeposit(new web3_js_1.PublicKey(signer), new web3_js_1.PublicKey(token), amount, feeRate);
|
|
591
|
-
}
|
|
592
|
-
////////////////////////////////////////////
|
|
593
|
-
//// Executors
|
|
594
|
-
/**
|
|
595
|
-
* @inheritDoc
|
|
596
|
-
*/
|
|
597
|
-
async claimWithSecret(signer, swapData, secret, checkExpiry, initAta, txOptions) {
|
|
598
|
-
const result = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, checkExpiry, initAta, txOptions?.feeRate);
|
|
599
|
-
const [signature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
600
|
-
return signature;
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* @inheritDoc
|
|
604
|
-
*/
|
|
605
|
-
async claimWithTxData(signer, swapData, tx, requiredConfirmations, vout, commitedHeader, synchronizer, initAta, txOptions) {
|
|
606
|
-
if (requiredConfirmations !== swapData.confirmations)
|
|
607
|
-
throw new Error("Invalid requiredConfirmations provided!");
|
|
608
|
-
const { txs, claimTxIndex, storageAcc } = await this.Claim.txsClaimWithTxData(signer, swapData, tx, vout, commitedHeader, synchronizer, initAta, txOptions?.feeRate);
|
|
609
|
-
const signatures = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
610
|
-
await this._DataAccount.removeDataAccount(storageAcc);
|
|
611
|
-
return signatures[claimTxIndex] ?? signatures[0];
|
|
612
|
-
}
|
|
613
|
-
/**
|
|
614
|
-
* @inheritDoc
|
|
615
|
-
*/
|
|
616
|
-
async refund(signer, swapData, check, initAta, txOptions) {
|
|
617
|
-
let result = await this.txsRefund(signer.getAddress(), swapData, check, initAta, txOptions?.feeRate);
|
|
618
|
-
const [signature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
619
|
-
return signature;
|
|
620
|
-
}
|
|
621
|
-
/**
|
|
622
|
-
* @inheritDoc
|
|
623
|
-
*/
|
|
624
|
-
async refundWithAuthorization(signer, swapData, signature, check, initAta, txOptions) {
|
|
625
|
-
let result = await this.txsRefundWithAuthorization(signer.getAddress(), swapData, signature, check, initAta, txOptions?.feeRate);
|
|
626
|
-
const [txSignature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
627
|
-
return txSignature;
|
|
628
|
-
}
|
|
629
|
-
/**
|
|
630
|
-
* @inheritDoc
|
|
631
|
-
*/
|
|
632
|
-
async init(signer, swapData, signature, skipChecks, txOptions) {
|
|
633
|
-
const result = await this.txsInit(signer.getAddress(), swapData, signature, skipChecks, txOptions?.feeRate);
|
|
634
|
-
const signatures = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
635
|
-
return signatures[signatures.length - 1];
|
|
636
|
-
}
|
|
637
|
-
/**
|
|
638
|
-
* @inheritDoc
|
|
639
|
-
*/
|
|
640
|
-
async initAndClaimWithSecret(signer, swapData, signature, secret, skipChecks, txOptions) {
|
|
641
|
-
if (!signer.getPublicKey().equals(swapData.claimer))
|
|
642
|
-
throw new Error("Invalid signer provided!");
|
|
643
|
-
const txsCommit = await this.txsInit(signer.getAddress(), swapData, signature, skipChecks, txOptions?.feeRate);
|
|
644
|
-
let txsClaim;
|
|
645
|
-
if (isSwapProgramV1(this.program)) {
|
|
646
|
-
// In V1 the initialize instruction has to contain the ATA initialization, hence we can skip checking it in claim
|
|
647
|
-
txsClaim = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, true, false, txOptions?.feeRate, true);
|
|
648
|
-
}
|
|
649
|
-
else {
|
|
650
|
-
// In V2 the initialize instruction doesn't necessarily contain the ATA initialization, hence the claim instruction needs to
|
|
651
|
-
// check and initialize the ATA if needed
|
|
652
|
-
txsClaim = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, true, true, txOptions?.feeRate, false);
|
|
653
|
-
}
|
|
654
|
-
const signatures = await this._Chain.sendAndConfirm(signer, txsCommit.concat(txsClaim), txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
655
|
-
return [signatures[txsCommit.length - 1], signatures[signatures.length - 1]];
|
|
656
|
-
}
|
|
657
|
-
/**
|
|
658
|
-
* @inheritDoc
|
|
659
|
-
*/
|
|
660
|
-
async withdraw(signer, token, amount, txOptions) {
|
|
661
|
-
const txs = await this.LpVault.txsWithdraw(signer.getPublicKey(), new web3_js_1.PublicKey(token), amount, txOptions?.feeRate);
|
|
662
|
-
const [txId] = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
|
|
663
|
-
return txId;
|
|
664
|
-
}
|
|
665
|
-
/**
|
|
666
|
-
* @inheritDoc
|
|
667
|
-
*/
|
|
668
|
-
async deposit(signer, token, amount, txOptions) {
|
|
669
|
-
const txs = await this.LpVault.txsDeposit(signer.getPublicKey(), new web3_js_1.PublicKey(token), amount, txOptions?.feeRate);
|
|
670
|
-
const [txId] = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
|
|
671
|
-
return txId;
|
|
672
|
-
}
|
|
673
|
-
////////////////////////////////////////////
|
|
674
|
-
//// Fees
|
|
675
|
-
/**
|
|
676
|
-
* @inheritDoc
|
|
677
|
-
*/
|
|
678
|
-
getInitPayInFeeRate(offerer, claimer, token, claimHash) {
|
|
679
|
-
const paymentHash = claimHash == null ? undefined : (0, Utils_1.fromClaimHash)(claimHash).paymentHash;
|
|
680
|
-
return this.Init.getInitPayInFeeRate(toPublicKeyOrNull(offerer), toPublicKeyOrNull(claimer), toPublicKeyOrNull(token), paymentHash);
|
|
681
|
-
}
|
|
682
|
-
/**
|
|
683
|
-
* @inheritDoc
|
|
684
|
-
*/
|
|
685
|
-
getInitFeeRate(offerer, claimer, token, claimHash) {
|
|
686
|
-
const paymentHash = claimHash == null ? undefined : (0, Utils_1.fromClaimHash)(claimHash).paymentHash;
|
|
687
|
-
return this.Init.getInitFeeRate(toPublicKeyOrNull(offerer), toPublicKeyOrNull(claimer), toPublicKeyOrNull(token), paymentHash);
|
|
688
|
-
}
|
|
689
|
-
/**
|
|
690
|
-
* @inheritDoc
|
|
691
|
-
*/
|
|
692
|
-
getRefundFeeRate(swapData) {
|
|
693
|
-
return this.Refund.getRefundFeeRate(swapData);
|
|
694
|
-
}
|
|
695
|
-
/**
|
|
696
|
-
* @inheritDoc
|
|
697
|
-
*/
|
|
698
|
-
getClaimFeeRate(signer, swapData) {
|
|
699
|
-
return this.Claim.getClaimFeeRate(new web3_js_1.PublicKey(signer), swapData);
|
|
700
|
-
}
|
|
701
|
-
/**
|
|
702
|
-
* @inheritDoc
|
|
703
|
-
*/
|
|
704
|
-
getClaimFee(signer, swapData, feeRate) {
|
|
705
|
-
return this.Claim.getClaimFee(new web3_js_1.PublicKey(signer), swapData, feeRate);
|
|
706
|
-
}
|
|
707
|
-
/**
|
|
708
|
-
* @inheritDoc
|
|
709
|
-
*/
|
|
710
|
-
getRawClaimFee(signer, swapData, feeRate) {
|
|
711
|
-
return this.Claim.getRawClaimFee(new web3_js_1.PublicKey(signer), swapData, feeRate);
|
|
712
|
-
}
|
|
713
|
-
/**
|
|
714
|
-
* @inheritDoc
|
|
715
|
-
*/
|
|
716
|
-
getCommitFee(signer, swapData, feeRate) {
|
|
717
|
-
return this.Init.getInitFee(swapData, feeRate);
|
|
718
|
-
}
|
|
719
|
-
/**
|
|
720
|
-
* @inheritDoc
|
|
721
|
-
*/
|
|
722
|
-
getRawCommitFee(signer, swapData, feeRate) {
|
|
723
|
-
return this.Init.getRawInitFee(swapData, feeRate);
|
|
724
|
-
}
|
|
725
|
-
/**
|
|
726
|
-
* @inheritDoc
|
|
727
|
-
*/
|
|
728
|
-
getRefundFee(signer, swapData, feeRate) {
|
|
729
|
-
return this.Refund.getRefundFee(swapData, feeRate);
|
|
730
|
-
}
|
|
731
|
-
/**
|
|
732
|
-
* @inheritDoc
|
|
733
|
-
*/
|
|
734
|
-
getRawRefundFee(signer, swapData, feeRate) {
|
|
735
|
-
return this.Refund.getRawRefundFee(swapData, feeRate);
|
|
736
|
-
}
|
|
737
|
-
/**
|
|
738
|
-
* @inheritDoc
|
|
739
|
-
*/
|
|
740
|
-
getExtraData(outputScript, amount, confirmations, nonce) {
|
|
741
|
-
return buffer_1.Buffer.from((0, sha2_1.sha256)(buffer_1.Buffer.concat([
|
|
742
|
-
base_1.BigIntBufferUtils.toBuffer(amount, "le", 8),
|
|
743
|
-
outputScript
|
|
744
|
-
])));
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
exports.SolanaSwapProgram = SolanaSwapProgram;
|
|
748
|
-
////////////////////////
|
|
749
|
-
//// PDA accessors
|
|
750
|
-
/**
|
|
751
|
-
* PDA of the swap vault authority.
|
|
752
|
-
* @internal
|
|
753
|
-
*/
|
|
754
|
-
SolanaSwapProgram._SwapVaultAuthority = SolanaProgramBase_1.SolanaProgramBase._pda("authority"); // Only necessary for V1 program
|
|
755
|
-
/**
|
|
756
|
-
* PDA helper for global token vault accounts.
|
|
757
|
-
* @internal
|
|
758
|
-
*/
|
|
759
|
-
SolanaSwapProgram._SwapVault = SolanaProgramBase_1.SolanaProgramBase._pda("vault", (tokenAddress) => [tokenAddress.toBuffer()]);
|
|
760
|
-
/**
|
|
761
|
-
* PDA helper for per-user token vault accounts.
|
|
762
|
-
* @internal
|
|
763
|
-
*/
|
|
764
|
-
SolanaSwapProgram._SwapUserVault = SolanaProgramBase_1.SolanaProgramBase._pda("uservault", (publicKey, tokenAddress) => [publicKey.toBuffer(), tokenAddress.toBuffer()]);
|
|
765
|
-
/**
|
|
766
|
-
* PDA helper for escrow state accounts.
|
|
767
|
-
* @internal
|
|
768
|
-
*/
|
|
769
|
-
SolanaSwapProgram._SwapEscrowState = SolanaProgramBase_1.SolanaProgramBase._pda("state", (hash) => [hash]);
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SolanaSwapProgram = exports.isSwapProgramV2 = exports.isSwapProgramV1 = void 0;
|
|
4
|
+
const SolanaSwapData_1 = require("./SolanaSwapData");
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
const sha2_1 = require("@noble/hashes/sha2");
|
|
7
|
+
const programIdlV1 = require("./v1/programIdl.json");
|
|
8
|
+
const programIdlV2 = require("./v2/programIdl.json");
|
|
9
|
+
const base_1 = require("@atomiqlabs/base");
|
|
10
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
11
|
+
const SolanaProgramBase_1 = require("../program/SolanaProgramBase");
|
|
12
|
+
const SwapInit_1 = require("./modules/SwapInit");
|
|
13
|
+
const SolanaDataAccount_1 = require("./modules/SolanaDataAccount");
|
|
14
|
+
const SwapRefund_1 = require("./modules/SwapRefund");
|
|
15
|
+
const SwapClaim_1 = require("./modules/SwapClaim");
|
|
16
|
+
const SolanaLpVault_1 = require("./modules/SolanaLpVault");
|
|
17
|
+
const buffer_1 = require("buffer");
|
|
18
|
+
const Utils_1 = require("../../utils/Utils");
|
|
19
|
+
const SolanaTokens_1 = require("../chain/modules/SolanaTokens");
|
|
20
|
+
const BN = require("bn.js");
|
|
21
|
+
const SolanaChains_1 = require("../SolanaChains");
|
|
22
|
+
function isSwapProgramV1(obj) {
|
|
23
|
+
return obj.idl.version === "0.1.0";
|
|
24
|
+
}
|
|
25
|
+
exports.isSwapProgramV1 = isSwapProgramV1;
|
|
26
|
+
function isSwapProgramV2(obj) {
|
|
27
|
+
return obj.idl.version === "0.2.0";
|
|
28
|
+
}
|
|
29
|
+
exports.isSwapProgramV2 = isSwapProgramV2;
|
|
30
|
+
function toPublicKeyOrNull(str) {
|
|
31
|
+
return str == null ? undefined : new web3_js_1.PublicKey(str);
|
|
32
|
+
}
|
|
33
|
+
const MAX_PARALLEL_COMMIT_STATUS_CHECKS = 5;
|
|
34
|
+
/**
|
|
35
|
+
* Solana swap (escrow manager) program representation handling PrTLC (on-chain) and HTLC (lightning) based swaps.
|
|
36
|
+
*
|
|
37
|
+
* @category Swaps
|
|
38
|
+
*/
|
|
39
|
+
class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
|
|
40
|
+
constructor(chainInterface, btcRelay, storage, programAddress, bitcoinNetwork, version) {
|
|
41
|
+
version ?? (version = "v1");
|
|
42
|
+
if (bitcoinNetwork != null && programAddress == null) {
|
|
43
|
+
programAddress = SolanaChains_1.SolanaChains[bitcoinNetwork]?.addresses[version ?? "v1"]?.swapContract;
|
|
44
|
+
}
|
|
45
|
+
super(chainInterface, version === "v1" ? programIdlV1 : programIdlV2, programAddress);
|
|
46
|
+
this._SwapVaultAuthority = SolanaSwapProgram._SwapVaultAuthority(this.program.programId); // Only necessary for V1 program
|
|
47
|
+
this._SwapVault = SolanaSwapProgram._SwapVault.bind(this, this.program.programId);
|
|
48
|
+
this._SwapUserVault = SolanaSwapProgram._SwapUserVault.bind(this, this.program.programId);
|
|
49
|
+
this._SwapEscrowState = SolanaSwapProgram._SwapEscrowState.bind(this, this.program.programId);
|
|
50
|
+
////////////////////////
|
|
51
|
+
//// Timeouts
|
|
52
|
+
/**
|
|
53
|
+
* @inheritDoc
|
|
54
|
+
*/
|
|
55
|
+
this.chainId = "SOLANA";
|
|
56
|
+
/**
|
|
57
|
+
* @inheritDoc
|
|
58
|
+
*/
|
|
59
|
+
this.claimWithSecretTimeout = 45;
|
|
60
|
+
/**
|
|
61
|
+
* @inheritDoc
|
|
62
|
+
*/
|
|
63
|
+
this.claimWithTxDataTimeout = 120;
|
|
64
|
+
/**
|
|
65
|
+
* @inheritDoc
|
|
66
|
+
*/
|
|
67
|
+
this.refundTimeout = 45;
|
|
68
|
+
/**
|
|
69
|
+
* Grace period (seconds) applied to claimer-side expiry checks.
|
|
70
|
+
*/
|
|
71
|
+
this.claimGracePeriod = 10 * 60;
|
|
72
|
+
/**
|
|
73
|
+
* Grace period (seconds) applied to offerer-side expiry checks.
|
|
74
|
+
*/
|
|
75
|
+
this.refundGracePeriod = 10 * 60;
|
|
76
|
+
/**
|
|
77
|
+
* Authorization grace period in seconds.
|
|
78
|
+
* @internal
|
|
79
|
+
*/
|
|
80
|
+
this._authGracePeriod = 30;
|
|
81
|
+
this.version = version;
|
|
82
|
+
this.ESCROW_STATE_RENT_EXEMPT = this.version === "v1" ? 2658720 : 2665680;
|
|
83
|
+
this.supportsInitWithoutClaimer = (this.version !== "v1");
|
|
84
|
+
this.Init = new SwapInit_1.SwapInit(chainInterface, this);
|
|
85
|
+
this.Refund = new SwapRefund_1.SwapRefund(chainInterface, this);
|
|
86
|
+
this.Claim = new SwapClaim_1.SwapClaim(chainInterface, this, btcRelay);
|
|
87
|
+
this._DataAccount = new SolanaDataAccount_1.SolanaDataAccount(chainInterface, this, storage);
|
|
88
|
+
this.LpVault = new SolanaLpVault_1.SolanaLpVault(chainInterface, this);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* @inheritDoc
|
|
92
|
+
*/
|
|
93
|
+
async start() {
|
|
94
|
+
await this._DataAccount.init();
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* @inheritDoc
|
|
98
|
+
*/
|
|
99
|
+
getClaimableDeposits(signer) {
|
|
100
|
+
return this._DataAccount.getDataAccountsInfo(new web3_js_1.PublicKey(signer));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* @inheritDoc
|
|
104
|
+
*/
|
|
105
|
+
claimDeposits(signer) {
|
|
106
|
+
return this._DataAccount.sweepDataAccounts(signer);
|
|
107
|
+
}
|
|
108
|
+
////////////////////////////////////////////
|
|
109
|
+
//// Signatures
|
|
110
|
+
/**
|
|
111
|
+
* @inheritDoc
|
|
112
|
+
*/
|
|
113
|
+
preFetchForInitSignatureVerification(data) {
|
|
114
|
+
return this.Init.preFetchForInitSignatureVerification(data);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* @inheritDoc
|
|
118
|
+
*/
|
|
119
|
+
preFetchBlockDataForSignatures() {
|
|
120
|
+
return this.Init.preFetchBlockDataForSignatures();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* @inheritDoc
|
|
124
|
+
*/
|
|
125
|
+
getInitSignature(signer, swapData, authorizationTimeout, preFetchedBlockData, feeRate) {
|
|
126
|
+
return this.Init.signSwapInitialization(signer, swapData, authorizationTimeout, preFetchedBlockData, feeRate);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* @inheritDoc
|
|
130
|
+
*/
|
|
131
|
+
isValidInitAuthorization(signer, swapData, sig, feeRate, preFetchedData) {
|
|
132
|
+
return this.Init.isSignatureValid(new web3_js_1.PublicKey(signer), swapData, sig.timeout, sig.prefix, sig.signature, feeRate, preFetchedData);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* @inheritDoc
|
|
136
|
+
*/
|
|
137
|
+
getInitAuthorizationExpiry(swapData, sig, preFetchedData) {
|
|
138
|
+
return this.Init.getSignatureExpiry(sig.timeout, sig.signature, preFetchedData);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* @inheritDoc
|
|
142
|
+
*/
|
|
143
|
+
isInitAuthorizationExpired(swapData, sig) {
|
|
144
|
+
return this.Init.isSignatureExpired(sig.signature, sig.timeout);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* @inheritDoc
|
|
148
|
+
*/
|
|
149
|
+
getRefundSignature(signer, swapData, authorizationTimeout) {
|
|
150
|
+
return this.Refund.signSwapRefund(signer, swapData, authorizationTimeout);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* @inheritDoc
|
|
154
|
+
*/
|
|
155
|
+
isValidRefundAuthorization(swapData, sig) {
|
|
156
|
+
return this.Refund.isSignatureValid(swapData, sig.timeout, sig.prefix, sig.signature);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* @inheritDoc
|
|
160
|
+
*/
|
|
161
|
+
getDataSignature(signer, data) {
|
|
162
|
+
return this._Chain.Signatures.getDataSignature(signer, data);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* @inheritDoc
|
|
166
|
+
*/
|
|
167
|
+
isValidDataSignature(data, signature, publicKey) {
|
|
168
|
+
return this._Chain.Signatures.isValidDataSignature(data, signature, publicKey);
|
|
169
|
+
}
|
|
170
|
+
////////////////////////////////////////////
|
|
171
|
+
//// Swap data utils
|
|
172
|
+
/**
|
|
173
|
+
* @inheritDoc
|
|
174
|
+
*/
|
|
175
|
+
async isClaimable(signer, data) {
|
|
176
|
+
if (!data.isClaimer(signer))
|
|
177
|
+
return false;
|
|
178
|
+
if (await this.isExpired(signer, data))
|
|
179
|
+
return false;
|
|
180
|
+
return await this.isCommited(data);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* @inheritDoc
|
|
184
|
+
*/
|
|
185
|
+
async isCommited(swapData) {
|
|
186
|
+
const paymentHash = buffer_1.Buffer.from(swapData.paymentHash, "hex");
|
|
187
|
+
const account = await this.program.account.escrowState.fetchNullable(this._SwapEscrowState(paymentHash));
|
|
188
|
+
if (account == null)
|
|
189
|
+
return false;
|
|
190
|
+
return swapData.correctPDA(account);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* @inheritDoc
|
|
194
|
+
*/
|
|
195
|
+
isExpired(signer, data, refundSide) {
|
|
196
|
+
let currentTimestamp = new BN(Math.floor(Date.now() / 1000));
|
|
197
|
+
if (data.isClaimer(signer) && !refundSide) {
|
|
198
|
+
currentTimestamp = currentTimestamp.add(new BN(this.claimGracePeriod));
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
currentTimestamp = currentTimestamp.sub(new BN(this.refundGracePeriod));
|
|
202
|
+
}
|
|
203
|
+
return Promise.resolve(data.expiry.lt(currentTimestamp));
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* @inheritDoc
|
|
207
|
+
*/
|
|
208
|
+
async isRequestRefundable(signer, data) {
|
|
209
|
+
//V1 Swap can only be refunded by the offerer
|
|
210
|
+
if (isSwapProgramV1(this.program) && !data.isOfferer(signer))
|
|
211
|
+
return false;
|
|
212
|
+
if (!(await this.isExpired(signer, data, true)))
|
|
213
|
+
return false;
|
|
214
|
+
return await this.isCommited(data);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* @inheritDoc
|
|
218
|
+
*/
|
|
219
|
+
getHashForOnchain(outputScript, amount, confirmations, nonce) {
|
|
220
|
+
nonce ?? (nonce = 0n);
|
|
221
|
+
const paymentHash = buffer_1.Buffer.from((0, sha2_1.sha256)(buffer_1.Buffer.concat([
|
|
222
|
+
base_1.BigIntBufferUtils.toBuffer(nonce, "le", 8),
|
|
223
|
+
base_1.BigIntBufferUtils.toBuffer(amount, "le", 8),
|
|
224
|
+
outputScript
|
|
225
|
+
]))).toString("hex");
|
|
226
|
+
return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(paymentHash, nonce, confirmations), "hex");
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* @inheritDoc
|
|
230
|
+
*/
|
|
231
|
+
getHashForHtlc(swapHash) {
|
|
232
|
+
return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(swapHash.toString("hex"), 0n, 0), "hex");
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* @inheritDoc
|
|
236
|
+
*/
|
|
237
|
+
getHashForTxId(txId, confirmations) {
|
|
238
|
+
return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(buffer_1.Buffer.from(txId, "hex").reverse().toString("hex"), 0n, confirmations), "hex");
|
|
239
|
+
}
|
|
240
|
+
////////////////////////////////////////////
|
|
241
|
+
//// Swap data getters
|
|
242
|
+
/**
|
|
243
|
+
* @inheritDoc
|
|
244
|
+
*/
|
|
245
|
+
async getCommitStatus(signer, data) {
|
|
246
|
+
const escrowStateKey = this._SwapEscrowState(buffer_1.Buffer.from(data.paymentHash, "hex"));
|
|
247
|
+
const [escrowState, isExpired] = await Promise.all([
|
|
248
|
+
this.program.account.escrowState.fetchNullable(escrowStateKey),
|
|
249
|
+
this.isExpired(signer, data)
|
|
250
|
+
]);
|
|
251
|
+
const getInitTxId = (0, Utils_1.onceAsync)(async () => {
|
|
252
|
+
const txId = await this._Events.findInEvents(escrowStateKey, async (event, tx) => {
|
|
253
|
+
if (event.name === "InitializeEvent") {
|
|
254
|
+
const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
|
|
255
|
+
if (paymentHash !== data.paymentHash)
|
|
256
|
+
return null;
|
|
257
|
+
if (!event.data.sequence.eq(data.sequence))
|
|
258
|
+
return null;
|
|
259
|
+
return tx.transaction.signatures[0];
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
if (txId == null)
|
|
263
|
+
throw new Error("Initialize event not found!");
|
|
264
|
+
return txId;
|
|
265
|
+
});
|
|
266
|
+
if (escrowState != null) {
|
|
267
|
+
if (data.correctPDA(escrowState)) {
|
|
268
|
+
if (data.isOfferer(signer) && isExpired)
|
|
269
|
+
return { type: base_1.SwapCommitStateType.REFUNDABLE, getInitTxId };
|
|
270
|
+
return { type: base_1.SwapCommitStateType.COMMITED, getInitTxId };
|
|
271
|
+
}
|
|
272
|
+
if (data.isOfferer(signer) && isExpired)
|
|
273
|
+
return { type: base_1.SwapCommitStateType.EXPIRED };
|
|
274
|
+
return { type: base_1.SwapCommitStateType.NOT_COMMITED };
|
|
275
|
+
}
|
|
276
|
+
//Check if paid or what
|
|
277
|
+
const status = await this._Events.findInEvents(escrowStateKey, async (event, tx) => {
|
|
278
|
+
if (event.name === "ClaimEvent") {
|
|
279
|
+
const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
|
|
280
|
+
if (paymentHash !== data.paymentHash)
|
|
281
|
+
return null;
|
|
282
|
+
if (!event.data.sequence.eq(data.sequence))
|
|
283
|
+
return null;
|
|
284
|
+
return {
|
|
285
|
+
type: base_1.SwapCommitStateType.PAID,
|
|
286
|
+
getInitTxId,
|
|
287
|
+
getClaimTxId: () => Promise.resolve(tx.transaction.signatures[0]),
|
|
288
|
+
getClaimResult: () => Promise.resolve(buffer_1.Buffer.from(event.data.secret).toString("hex")),
|
|
289
|
+
getTxBlock: () => Promise.resolve({
|
|
290
|
+
blockHeight: tx.slot,
|
|
291
|
+
blockTime: tx.blockTime
|
|
292
|
+
})
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
if (event.name === "RefundEvent") {
|
|
296
|
+
const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
|
|
297
|
+
if (paymentHash !== data.paymentHash)
|
|
298
|
+
return null;
|
|
299
|
+
if (!event.data.sequence.eq(data.sequence))
|
|
300
|
+
return null;
|
|
301
|
+
return {
|
|
302
|
+
type: isExpired ? base_1.SwapCommitStateType.EXPIRED : base_1.SwapCommitStateType.NOT_COMMITED,
|
|
303
|
+
getInitTxId,
|
|
304
|
+
getRefundTxId: () => Promise.resolve(tx.transaction.signatures[0]),
|
|
305
|
+
getTxBlock: () => Promise.resolve({
|
|
306
|
+
blockHeight: tx.slot,
|
|
307
|
+
blockTime: tx.blockTime
|
|
308
|
+
})
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
if (status != null)
|
|
313
|
+
return status;
|
|
314
|
+
if (isExpired)
|
|
315
|
+
return { type: base_1.SwapCommitStateType.EXPIRED };
|
|
316
|
+
return { type: base_1.SwapCommitStateType.NOT_COMMITED };
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* @inheritDoc
|
|
320
|
+
*/
|
|
321
|
+
async getCommitStatuses(request) {
|
|
322
|
+
const result = {};
|
|
323
|
+
let promises = [];
|
|
324
|
+
for (let { signer, swapData } of request) {
|
|
325
|
+
promises.push(this.getCommitStatus(signer, swapData).then(val => {
|
|
326
|
+
result[swapData.getEscrowHash()] = val;
|
|
327
|
+
}));
|
|
328
|
+
if (promises.length >= MAX_PARALLEL_COMMIT_STATUS_CHECKS) {
|
|
329
|
+
await Promise.all(promises);
|
|
330
|
+
promises = [];
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
await Promise.all(promises);
|
|
334
|
+
return result;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* @inheritDoc
|
|
338
|
+
*/
|
|
339
|
+
async getClaimHashStatus(claimHash) {
|
|
340
|
+
const { paymentHash } = (0, Utils_1.fromClaimHash)(claimHash);
|
|
341
|
+
const escrowStateKey = this._SwapEscrowState(buffer_1.Buffer.from(paymentHash, "hex"));
|
|
342
|
+
const abortController = new AbortController();
|
|
343
|
+
//Start fetching events before checking escrow PDA, this call is used when quoting, so saving 100ms here helps a lot!
|
|
344
|
+
const eventsPromise = this._Events.findInEvents(escrowStateKey, async (event) => {
|
|
345
|
+
if (event.name === "ClaimEvent")
|
|
346
|
+
return base_1.SwapCommitStateType.PAID;
|
|
347
|
+
if (event.name === "RefundEvent")
|
|
348
|
+
return base_1.SwapCommitStateType.NOT_COMMITED;
|
|
349
|
+
}, abortController.signal).catch(e => {
|
|
350
|
+
abortController.abort(e);
|
|
351
|
+
return null;
|
|
352
|
+
});
|
|
353
|
+
const escrowState = await this.program.account.escrowState.fetchNullable(escrowStateKey);
|
|
354
|
+
abortController.signal.throwIfAborted();
|
|
355
|
+
if (escrowState != null) {
|
|
356
|
+
abortController.abort();
|
|
357
|
+
return base_1.SwapCommitStateType.COMMITED;
|
|
358
|
+
}
|
|
359
|
+
//Check if paid or what
|
|
360
|
+
const eventsStatus = await eventsPromise;
|
|
361
|
+
abortController.signal.throwIfAborted();
|
|
362
|
+
if (eventsStatus != null)
|
|
363
|
+
return eventsStatus;
|
|
364
|
+
return base_1.SwapCommitStateType.NOT_COMMITED;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* @inheritDoc
|
|
368
|
+
*/
|
|
369
|
+
async getCommitedData(claimHashHex) {
|
|
370
|
+
const { paymentHash } = (0, Utils_1.fromClaimHash)(claimHashHex);
|
|
371
|
+
const paymentHashBuffer = buffer_1.Buffer.from(paymentHash, "hex");
|
|
372
|
+
const account = await this.program.account.escrowState.fetchNullable(this._SwapEscrowState(paymentHashBuffer));
|
|
373
|
+
if (account == null)
|
|
374
|
+
return null;
|
|
375
|
+
return SolanaSwapData_1.SolanaSwapData.fromEscrowState(this.program.programId, this.version, account);
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* @inheritDoc
|
|
379
|
+
*/
|
|
380
|
+
async getHistoricalSwaps(signer, startBlockheight) {
|
|
381
|
+
let latestBlockheight;
|
|
382
|
+
const events = [];
|
|
383
|
+
await this._Events.findInEvents(new web3_js_1.PublicKey(signer), async (event, tx) => {
|
|
384
|
+
if (latestBlockheight == null)
|
|
385
|
+
latestBlockheight = tx.slot;
|
|
386
|
+
events.push({ event, tx });
|
|
387
|
+
}, undefined, undefined, startBlockheight);
|
|
388
|
+
this.logger.debug(`getHistoricalSwaps(): Found ${events.length} atomiq related events!`);
|
|
389
|
+
const swapsOpened = {};
|
|
390
|
+
const resultingSwaps = {};
|
|
391
|
+
events.reverse();
|
|
392
|
+
for (let { event, tx } of events) {
|
|
393
|
+
const txSignature = tx.transaction.signatures[0];
|
|
394
|
+
const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
|
|
395
|
+
const escrowHash = (0, Utils_1.toEscrowHash)(paymentHash, event.data.sequence);
|
|
396
|
+
if (event.name === "InitializeEvent") {
|
|
397
|
+
//Parse swap data from initialize event
|
|
398
|
+
const txoHash = buffer_1.Buffer.from(event.data.txoHash).toString("hex");
|
|
399
|
+
const instructions = this._Events.decodeInstructions(tx.transaction.message);
|
|
400
|
+
if (instructions == null) {
|
|
401
|
+
this.logger.warn(`getHistoricalSwaps(): Skipping tx ${txSignature} because cannot parse instructions!`);
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
const initIx = instructions.find(ix => ix != null && (ix.name === "offererInitializePayIn" || ix.name === "offererInitialize"));
|
|
405
|
+
if (initIx == null) {
|
|
406
|
+
this.logger.warn(`getHistoricalSwaps(): Skipping tx ${txSignature} because init instruction not found!`);
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
swapsOpened[escrowHash] = {
|
|
410
|
+
data: SolanaSwapData_1.SolanaSwapData.fromInstruction(this.program.programId, this.version, initIx, txoHash),
|
|
411
|
+
getInitTxId: () => Promise.resolve(txSignature),
|
|
412
|
+
getTxBlock: () => Promise.resolve({
|
|
413
|
+
blockHeight: tx.slot,
|
|
414
|
+
blockTime: tx.blockTime
|
|
415
|
+
})
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
if (event.name === "ClaimEvent") {
|
|
419
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
420
|
+
delete swapsOpened[escrowHash];
|
|
421
|
+
resultingSwaps[escrowHash] = {
|
|
422
|
+
init: foundSwapData,
|
|
423
|
+
state: {
|
|
424
|
+
type: base_1.SwapCommitStateType.PAID,
|
|
425
|
+
getInitTxId: foundSwapData?.getInitTxId,
|
|
426
|
+
getClaimTxId: () => Promise.resolve(txSignature),
|
|
427
|
+
getClaimResult: () => Promise.resolve(buffer_1.Buffer.from(event.data.secret).toString("hex")),
|
|
428
|
+
getTxBlock: () => Promise.resolve({
|
|
429
|
+
blockHeight: tx.slot,
|
|
430
|
+
blockTime: tx.blockTime
|
|
431
|
+
})
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
if (event.name === "RefundEvent") {
|
|
436
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
437
|
+
delete swapsOpened[escrowHash];
|
|
438
|
+
const isExpired = foundSwapData != null && await this.isExpired(signer, foundSwapData.data);
|
|
439
|
+
resultingSwaps[escrowHash] = {
|
|
440
|
+
init: foundSwapData,
|
|
441
|
+
state: {
|
|
442
|
+
type: isExpired ? base_1.SwapCommitStateType.EXPIRED : base_1.SwapCommitStateType.NOT_COMMITED,
|
|
443
|
+
getInitTxId: foundSwapData?.getInitTxId,
|
|
444
|
+
getRefundTxId: () => Promise.resolve(txSignature),
|
|
445
|
+
getTxBlock: () => Promise.resolve({
|
|
446
|
+
blockHeight: tx.slot,
|
|
447
|
+
blockTime: tx.blockTime
|
|
448
|
+
})
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
this.logger.debug(`getHistoricalSwaps(): Found ${Object.keys(resultingSwaps).length} settled swaps!`);
|
|
454
|
+
this.logger.debug(`getHistoricalSwaps(): Found ${Object.keys(swapsOpened).length} unsettled swaps!`);
|
|
455
|
+
for (let escrowHash in swapsOpened) {
|
|
456
|
+
const foundSwapData = swapsOpened[escrowHash];
|
|
457
|
+
const isExpired = await this.isExpired(signer, foundSwapData.data);
|
|
458
|
+
resultingSwaps[escrowHash] = {
|
|
459
|
+
init: foundSwapData,
|
|
460
|
+
state: foundSwapData.data.isOfferer(signer) && isExpired
|
|
461
|
+
? { type: base_1.SwapCommitStateType.REFUNDABLE, getInitTxId: foundSwapData.getInitTxId }
|
|
462
|
+
: { type: base_1.SwapCommitStateType.COMMITED, getInitTxId: foundSwapData.getInitTxId }
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
return {
|
|
466
|
+
swaps: resultingSwaps,
|
|
467
|
+
latestBlockheight: latestBlockheight ?? startBlockheight
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
////////////////////////////////////////////
|
|
471
|
+
//// Swap data initializer
|
|
472
|
+
/**
|
|
473
|
+
* @inheritDoc
|
|
474
|
+
*/
|
|
475
|
+
createSwapData(type, offerer, claimer, token, amount, claimHash, sequence, expiry, payIn, payOut, securityDeposit, claimerBounty, depositToken) {
|
|
476
|
+
if (depositToken != null) {
|
|
477
|
+
if (!new web3_js_1.PublicKey(depositToken).equals(SolanaTokens_1.SolanaTokens.WSOL_ADDRESS))
|
|
478
|
+
throw new Error("Only SOL supported as deposit token!");
|
|
479
|
+
}
|
|
480
|
+
const tokenAddr = new web3_js_1.PublicKey(token);
|
|
481
|
+
const offererKey = new web3_js_1.PublicKey(offerer);
|
|
482
|
+
const claimerKey = new web3_js_1.PublicKey(claimer);
|
|
483
|
+
const { paymentHash, nonce, confirmations } = (0, Utils_1.fromClaimHash)(claimHash);
|
|
484
|
+
const swapData = new SolanaSwapData_1.SolanaSwapData({
|
|
485
|
+
programId: this.program.programId,
|
|
486
|
+
version: this.version,
|
|
487
|
+
offerer: offererKey,
|
|
488
|
+
claimer: claimerKey,
|
|
489
|
+
token: tokenAddr,
|
|
490
|
+
amount: (0, Utils_1.toBN)(amount),
|
|
491
|
+
paymentHash,
|
|
492
|
+
sequence: (0, Utils_1.toBN)(sequence),
|
|
493
|
+
expiry: (0, Utils_1.toBN)(expiry),
|
|
494
|
+
nonce,
|
|
495
|
+
confirmations,
|
|
496
|
+
payOut,
|
|
497
|
+
kind: SolanaSwapData_1.SolanaSwapData.typeToKind(type),
|
|
498
|
+
payIn,
|
|
499
|
+
offererAta: payIn ? (0, spl_token_1.getAssociatedTokenAddressSync)(tokenAddr, offererKey) : web3_js_1.PublicKey.default,
|
|
500
|
+
claimerAta: payOut ? (0, spl_token_1.getAssociatedTokenAddressSync)(tokenAddr, claimerKey) : web3_js_1.PublicKey.default,
|
|
501
|
+
securityDeposit: (0, Utils_1.toBN)(securityDeposit),
|
|
502
|
+
claimerBounty: (0, Utils_1.toBN)(claimerBounty)
|
|
503
|
+
});
|
|
504
|
+
return Promise.resolve(swapData);
|
|
505
|
+
}
|
|
506
|
+
////////////////////////////////////////////
|
|
507
|
+
//// Utils
|
|
508
|
+
/**
|
|
509
|
+
* @inheritDoc
|
|
510
|
+
*/
|
|
511
|
+
async getBalance(signer, tokenAddress, inContract) {
|
|
512
|
+
if (!inContract) {
|
|
513
|
+
return await this._Chain.getBalance(signer, tokenAddress);
|
|
514
|
+
}
|
|
515
|
+
const token = new web3_js_1.PublicKey(tokenAddress);
|
|
516
|
+
const publicKey = new web3_js_1.PublicKey(signer);
|
|
517
|
+
return await this.getIntermediaryBalance(publicKey, token);
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* @inheritDoc
|
|
521
|
+
*/
|
|
522
|
+
getIntermediaryData(address, token) {
|
|
523
|
+
return this.LpVault.getIntermediaryData(new web3_js_1.PublicKey(address), new web3_js_1.PublicKey(token));
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* @inheritDoc
|
|
527
|
+
*/
|
|
528
|
+
getIntermediaryReputation(address, token) {
|
|
529
|
+
return this.LpVault.getIntermediaryReputation(new web3_js_1.PublicKey(address), new web3_js_1.PublicKey(token));
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Returns intermediary vault balance for a specific token.
|
|
533
|
+
*
|
|
534
|
+
* @param address Intermediary address
|
|
535
|
+
* @param token Token mint
|
|
536
|
+
*/
|
|
537
|
+
getIntermediaryBalance(address, token) {
|
|
538
|
+
return this.LpVault.getIntermediaryBalance(address, token);
|
|
539
|
+
}
|
|
540
|
+
////////////////////////////////////////////
|
|
541
|
+
//// Transaction initializers
|
|
542
|
+
/**
|
|
543
|
+
* @inheritDoc
|
|
544
|
+
*/
|
|
545
|
+
async txsClaimWithSecret(signer, swapData, secret, checkExpiry, initAta, feeRate, skipAtaCheck) {
|
|
546
|
+
return this.Claim.txsClaimWithSecret(typeof (signer) === "string" ? new web3_js_1.PublicKey(signer) : signer.getPublicKey(), swapData, secret, checkExpiry, initAta, feeRate, skipAtaCheck);
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* @inheritDoc
|
|
550
|
+
*/
|
|
551
|
+
async txsClaimWithTxData(signer, swapData, tx, requiredConfirmations, vout, commitedHeader, synchronizer, initAta, feeRate) {
|
|
552
|
+
if (swapData.confirmations !== requiredConfirmations)
|
|
553
|
+
throw new Error("Invalid requiredConfirmations provided!");
|
|
554
|
+
const { txs } = await this.Claim.txsClaimWithTxData(typeof (signer) === "string" ? new web3_js_1.PublicKey(signer) : signer, swapData, tx, vout, commitedHeader, synchronizer, initAta, feeRate);
|
|
555
|
+
return txs;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* @inheritDoc
|
|
559
|
+
*/
|
|
560
|
+
txsRefund(signer, swapData, check, initAta, feeRate) {
|
|
561
|
+
return this.Refund.txsRefund(new web3_js_1.PublicKey(signer), swapData, check, initAta, feeRate);
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* @inheritDoc
|
|
565
|
+
*/
|
|
566
|
+
txsRefundWithAuthorization(signer, swapData, sig, check, initAta, feeRate) {
|
|
567
|
+
return this.Refund.txsRefundWithAuthorization(new web3_js_1.PublicKey(signer), swapData, sig.timeout, sig.prefix, sig.signature, check, initAta, feeRate);
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* @inheritDoc
|
|
571
|
+
*/
|
|
572
|
+
txsInit(sender, swapData, sig, skipChecks, feeRate) {
|
|
573
|
+
if (swapData.isPayIn()) {
|
|
574
|
+
return this.Init.txsInitPayIn(new web3_js_1.PublicKey(sender), swapData, sig.timeout, sig.prefix, sig.signature, skipChecks, feeRate);
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
return this.Init.txsInit(new web3_js_1.PublicKey(sender), swapData, sig.timeout, sig.prefix, sig.signature, skipChecks, feeRate);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* @inheritDoc
|
|
582
|
+
*/
|
|
583
|
+
txsWithdraw(signer, token, amount, feeRate) {
|
|
584
|
+
return this.LpVault.txsWithdraw(new web3_js_1.PublicKey(signer), new web3_js_1.PublicKey(token), amount, feeRate);
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* @inheritDoc
|
|
588
|
+
*/
|
|
589
|
+
txsDeposit(signer, token, amount, feeRate) {
|
|
590
|
+
return this.LpVault.txsDeposit(new web3_js_1.PublicKey(signer), new web3_js_1.PublicKey(token), amount, feeRate);
|
|
591
|
+
}
|
|
592
|
+
////////////////////////////////////////////
|
|
593
|
+
//// Executors
|
|
594
|
+
/**
|
|
595
|
+
* @inheritDoc
|
|
596
|
+
*/
|
|
597
|
+
async claimWithSecret(signer, swapData, secret, checkExpiry, initAta, txOptions) {
|
|
598
|
+
const result = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, checkExpiry, initAta, txOptions?.feeRate);
|
|
599
|
+
const [signature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
600
|
+
return signature;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* @inheritDoc
|
|
604
|
+
*/
|
|
605
|
+
async claimWithTxData(signer, swapData, tx, requiredConfirmations, vout, commitedHeader, synchronizer, initAta, txOptions) {
|
|
606
|
+
if (requiredConfirmations !== swapData.confirmations)
|
|
607
|
+
throw new Error("Invalid requiredConfirmations provided!");
|
|
608
|
+
const { txs, claimTxIndex, storageAcc } = await this.Claim.txsClaimWithTxData(signer, swapData, tx, vout, commitedHeader, synchronizer, initAta, txOptions?.feeRate);
|
|
609
|
+
const signatures = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
610
|
+
await this._DataAccount.removeDataAccount(storageAcc);
|
|
611
|
+
return signatures[claimTxIndex] ?? signatures[0];
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* @inheritDoc
|
|
615
|
+
*/
|
|
616
|
+
async refund(signer, swapData, check, initAta, txOptions) {
|
|
617
|
+
let result = await this.txsRefund(signer.getAddress(), swapData, check, initAta, txOptions?.feeRate);
|
|
618
|
+
const [signature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
619
|
+
return signature;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* @inheritDoc
|
|
623
|
+
*/
|
|
624
|
+
async refundWithAuthorization(signer, swapData, signature, check, initAta, txOptions) {
|
|
625
|
+
let result = await this.txsRefundWithAuthorization(signer.getAddress(), swapData, signature, check, initAta, txOptions?.feeRate);
|
|
626
|
+
const [txSignature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
627
|
+
return txSignature;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* @inheritDoc
|
|
631
|
+
*/
|
|
632
|
+
async init(signer, swapData, signature, skipChecks, txOptions) {
|
|
633
|
+
const result = await this.txsInit(signer.getAddress(), swapData, signature, skipChecks, txOptions?.feeRate);
|
|
634
|
+
const signatures = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
635
|
+
return signatures[signatures.length - 1];
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* @inheritDoc
|
|
639
|
+
*/
|
|
640
|
+
async initAndClaimWithSecret(signer, swapData, signature, secret, skipChecks, txOptions) {
|
|
641
|
+
if (!signer.getPublicKey().equals(swapData.claimer))
|
|
642
|
+
throw new Error("Invalid signer provided!");
|
|
643
|
+
const txsCommit = await this.txsInit(signer.getAddress(), swapData, signature, skipChecks, txOptions?.feeRate);
|
|
644
|
+
let txsClaim;
|
|
645
|
+
if (isSwapProgramV1(this.program)) {
|
|
646
|
+
// In V1 the initialize instruction has to contain the ATA initialization, hence we can skip checking it in claim
|
|
647
|
+
txsClaim = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, true, false, txOptions?.feeRate, true);
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
// In V2 the initialize instruction doesn't necessarily contain the ATA initialization, hence the claim instruction needs to
|
|
651
|
+
// check and initialize the ATA if needed
|
|
652
|
+
txsClaim = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, true, true, txOptions?.feeRate, false);
|
|
653
|
+
}
|
|
654
|
+
const signatures = await this._Chain.sendAndConfirm(signer, txsCommit.concat(txsClaim), txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
655
|
+
return [signatures[txsCommit.length - 1], signatures[signatures.length - 1]];
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* @inheritDoc
|
|
659
|
+
*/
|
|
660
|
+
async withdraw(signer, token, amount, txOptions) {
|
|
661
|
+
const txs = await this.LpVault.txsWithdraw(signer.getPublicKey(), new web3_js_1.PublicKey(token), amount, txOptions?.feeRate);
|
|
662
|
+
const [txId] = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
|
|
663
|
+
return txId;
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* @inheritDoc
|
|
667
|
+
*/
|
|
668
|
+
async deposit(signer, token, amount, txOptions) {
|
|
669
|
+
const txs = await this.LpVault.txsDeposit(signer.getPublicKey(), new web3_js_1.PublicKey(token), amount, txOptions?.feeRate);
|
|
670
|
+
const [txId] = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
|
|
671
|
+
return txId;
|
|
672
|
+
}
|
|
673
|
+
////////////////////////////////////////////
|
|
674
|
+
//// Fees
|
|
675
|
+
/**
|
|
676
|
+
* @inheritDoc
|
|
677
|
+
*/
|
|
678
|
+
getInitPayInFeeRate(offerer, claimer, token, claimHash) {
|
|
679
|
+
const paymentHash = claimHash == null ? undefined : (0, Utils_1.fromClaimHash)(claimHash).paymentHash;
|
|
680
|
+
return this.Init.getInitPayInFeeRate(toPublicKeyOrNull(offerer), toPublicKeyOrNull(claimer), toPublicKeyOrNull(token), paymentHash);
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* @inheritDoc
|
|
684
|
+
*/
|
|
685
|
+
getInitFeeRate(offerer, claimer, token, claimHash) {
|
|
686
|
+
const paymentHash = claimHash == null ? undefined : (0, Utils_1.fromClaimHash)(claimHash).paymentHash;
|
|
687
|
+
return this.Init.getInitFeeRate(toPublicKeyOrNull(offerer), toPublicKeyOrNull(claimer), toPublicKeyOrNull(token), paymentHash);
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* @inheritDoc
|
|
691
|
+
*/
|
|
692
|
+
getRefundFeeRate(swapData) {
|
|
693
|
+
return this.Refund.getRefundFeeRate(swapData);
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* @inheritDoc
|
|
697
|
+
*/
|
|
698
|
+
getClaimFeeRate(signer, swapData) {
|
|
699
|
+
return this.Claim.getClaimFeeRate(new web3_js_1.PublicKey(signer), swapData);
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* @inheritDoc
|
|
703
|
+
*/
|
|
704
|
+
getClaimFee(signer, swapData, feeRate) {
|
|
705
|
+
return this.Claim.getClaimFee(new web3_js_1.PublicKey(signer), swapData, feeRate);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* @inheritDoc
|
|
709
|
+
*/
|
|
710
|
+
getRawClaimFee(signer, swapData, feeRate) {
|
|
711
|
+
return this.Claim.getRawClaimFee(new web3_js_1.PublicKey(signer), swapData, feeRate);
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* @inheritDoc
|
|
715
|
+
*/
|
|
716
|
+
getCommitFee(signer, swapData, feeRate) {
|
|
717
|
+
return this.Init.getInitFee(swapData, feeRate);
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* @inheritDoc
|
|
721
|
+
*/
|
|
722
|
+
getRawCommitFee(signer, swapData, feeRate) {
|
|
723
|
+
return this.Init.getRawInitFee(swapData, feeRate);
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* @inheritDoc
|
|
727
|
+
*/
|
|
728
|
+
getRefundFee(signer, swapData, feeRate) {
|
|
729
|
+
return this.Refund.getRefundFee(swapData, feeRate);
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* @inheritDoc
|
|
733
|
+
*/
|
|
734
|
+
getRawRefundFee(signer, swapData, feeRate) {
|
|
735
|
+
return this.Refund.getRawRefundFee(swapData, feeRate);
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* @inheritDoc
|
|
739
|
+
*/
|
|
740
|
+
getExtraData(outputScript, amount, confirmations, nonce) {
|
|
741
|
+
return buffer_1.Buffer.from((0, sha2_1.sha256)(buffer_1.Buffer.concat([
|
|
742
|
+
base_1.BigIntBufferUtils.toBuffer(amount, "le", 8),
|
|
743
|
+
outputScript
|
|
744
|
+
])));
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
exports.SolanaSwapProgram = SolanaSwapProgram;
|
|
748
|
+
////////////////////////
|
|
749
|
+
//// PDA accessors
|
|
750
|
+
/**
|
|
751
|
+
* PDA of the swap vault authority.
|
|
752
|
+
* @internal
|
|
753
|
+
*/
|
|
754
|
+
SolanaSwapProgram._SwapVaultAuthority = SolanaProgramBase_1.SolanaProgramBase._pda("authority"); // Only necessary for V1 program
|
|
755
|
+
/**
|
|
756
|
+
* PDA helper for global token vault accounts.
|
|
757
|
+
* @internal
|
|
758
|
+
*/
|
|
759
|
+
SolanaSwapProgram._SwapVault = SolanaProgramBase_1.SolanaProgramBase._pda("vault", (tokenAddress) => [tokenAddress.toBuffer()]);
|
|
760
|
+
/**
|
|
761
|
+
* PDA helper for per-user token vault accounts.
|
|
762
|
+
* @internal
|
|
763
|
+
*/
|
|
764
|
+
SolanaSwapProgram._SwapUserVault = SolanaProgramBase_1.SolanaProgramBase._pda("uservault", (publicKey, tokenAddress) => [publicKey.toBuffer(), tokenAddress.toBuffer()]);
|
|
765
|
+
/**
|
|
766
|
+
* PDA helper for escrow state accounts.
|
|
767
|
+
* @internal
|
|
768
|
+
*/
|
|
769
|
+
SolanaSwapProgram._SwapEscrowState = SolanaProgramBase_1.SolanaProgramBase._pda("state", (hash) => [hash]);
|