@atomiqlabs/chain-solana 7.3.8 → 8.0.0-beta.0
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 +1 -0
- package/dist/index.js +1 -0
- package/dist/solana/SolanaChains.d.ts +14 -0
- package/dist/solana/SolanaChains.js +18 -0
- package/dist/solana/SolanaInitializer.d.ts +18 -0
- package/dist/solana/SolanaInitializer.js +59 -0
- package/dist/solana/base/SolanaAction.js +25 -38
- package/dist/solana/base/modules/SolanaBlocks.js +18 -29
- package/dist/solana/base/modules/SolanaEvents.js +15 -26
- package/dist/solana/base/modules/SolanaFees.d.ts +4 -5
- package/dist/solana/base/modules/SolanaFees.js +168 -182
- package/dist/solana/base/modules/SolanaSlots.js +16 -29
- package/dist/solana/base/modules/SolanaTokens.d.ts +6 -7
- package/dist/solana/base/modules/SolanaTokens.js +63 -84
- package/dist/solana/base/modules/SolanaTransactions.d.ts +2 -2
- package/dist/solana/base/modules/SolanaTransactions.js +143 -165
- package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +2 -3
- package/dist/solana/btcrelay/SolanaBtcRelay.js +185 -221
- package/dist/solana/events/SolanaChainEvents.js +113 -138
- package/dist/solana/events/SolanaChainEventsBrowser.js +56 -65
- package/dist/solana/program/modules/SolanaProgramEvents.js +13 -24
- package/dist/solana/swaps/SolanaSwapData.d.ts +15 -11
- package/dist/solana/swaps/SolanaSwapData.js +29 -13
- package/dist/solana/swaps/SolanaSwapProgram.d.ts +40 -41
- package/dist/solana/swaps/SolanaSwapProgram.js +212 -221
- package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +2 -3
- package/dist/solana/swaps/modules/SolanaDataAccount.js +117 -141
- package/dist/solana/swaps/modules/SolanaLpVault.d.ts +4 -5
- package/dist/solana/swaps/modules/SolanaLpVault.js +87 -110
- package/dist/solana/swaps/modules/SwapClaim.d.ts +4 -4
- package/dist/solana/swaps/modules/SwapClaim.js +122 -134
- package/dist/solana/swaps/modules/SwapInit.d.ts +2 -3
- package/dist/solana/swaps/modules/SwapInit.js +254 -285
- package/dist/solana/swaps/modules/SwapRefund.d.ts +2 -3
- package/dist/solana/swaps/modules/SwapRefund.js +103 -113
- package/dist/utils/Utils.d.ts +10 -0
- package/dist/utils/Utils.js +62 -35
- package/package.json +9 -6
- package/src/index.ts +1 -0
- package/src/solana/SolanaChains.ts +16 -0
- package/src/solana/SolanaInitializer.ts +98 -0
- package/src/solana/base/SolanaBase.ts +1 -2
- package/src/solana/base/modules/SolanaEvents.ts +0 -1
- package/src/solana/base/modules/SolanaFees.ts +35 -31
- package/src/solana/base/modules/SolanaTokens.ts +26 -27
- package/src/solana/base/modules/SolanaTransactions.ts +33 -28
- package/src/solana/btcrelay/SolanaBtcRelay.ts +6 -10
- package/src/solana/events/SolanaChainEventsBrowser.ts +14 -10
- package/src/solana/program/modules/SolanaProgramEvents.ts +1 -1
- package/src/solana/swaps/SolanaSwapData.ts +38 -19
- package/src/solana/swaps/SolanaSwapProgram.ts +133 -105
- package/src/solana/swaps/modules/SolanaDataAccount.ts +4 -6
- package/src/solana/swaps/modules/SolanaLpVault.ts +18 -18
- package/src/solana/swaps/modules/SwapClaim.ts +14 -17
- package/src/solana/swaps/modules/SwapInit.ts +35 -38
- package/src/solana/swaps/modules/SwapRefund.ts +20 -23
- package/src/utils/Utils.ts +35 -0
|
@@ -6,6 +6,8 @@ import {IdlAccounts, IdlTypes} from "@coral-xyz/anchor";
|
|
|
6
6
|
import {SwapTypeEnum} from "./SwapTypeEnum";
|
|
7
7
|
import {Buffer} from "buffer";
|
|
8
8
|
import {getAssociatedTokenAddressSync} from "@solana/spl-token";
|
|
9
|
+
import {toBigInt, toClaimHash, toEscrowHash} from "../../utils/Utils";
|
|
10
|
+
import {SolanaTokens} from "../base/modules/SolanaTokens";
|
|
9
11
|
|
|
10
12
|
const EXPIRY_BLOCKHEIGHT_THRESHOLD = new BN("1000000000");
|
|
11
13
|
|
|
@@ -161,8 +163,8 @@ export class SolanaSwapData extends SwapData {
|
|
|
161
163
|
}
|
|
162
164
|
}
|
|
163
165
|
|
|
164
|
-
getAmount():
|
|
165
|
-
return this.amount;
|
|
166
|
+
getAmount(): bigint {
|
|
167
|
+
return toBigInt(this.amount);
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
getToken(): string {
|
|
@@ -177,17 +179,17 @@ export class SolanaSwapData extends SwapData {
|
|
|
177
179
|
return SolanaSwapData.kindToType(this.kind);
|
|
178
180
|
}
|
|
179
181
|
|
|
180
|
-
getExpiry():
|
|
182
|
+
getExpiry(): bigint {
|
|
181
183
|
if(this.expiry.lt(EXPIRY_BLOCKHEIGHT_THRESHOLD)) return null;
|
|
182
|
-
return this.expiry;
|
|
184
|
+
return toBigInt(this.expiry);
|
|
183
185
|
}
|
|
184
186
|
|
|
185
|
-
|
|
187
|
+
getConfirmationsHint(): number {
|
|
186
188
|
return this.confirmations;
|
|
187
189
|
}
|
|
188
190
|
|
|
189
|
-
|
|
190
|
-
return this.nonce;
|
|
191
|
+
getNonceHint(): bigint {
|
|
192
|
+
return toBigInt(this.nonce);
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
isPayIn(): boolean {
|
|
@@ -198,32 +200,41 @@ export class SolanaSwapData extends SwapData {
|
|
|
198
200
|
return this.payOut;
|
|
199
201
|
}
|
|
200
202
|
|
|
201
|
-
|
|
202
|
-
return this.paymentHash;
|
|
203
|
+
getClaimHash(): string {
|
|
204
|
+
return toClaimHash(this.paymentHash, toBigInt(this.nonce), this.confirmations);
|
|
203
205
|
}
|
|
204
206
|
|
|
205
|
-
|
|
206
|
-
return this.sequence;
|
|
207
|
+
getEscrowHash(): string {
|
|
208
|
+
return toEscrowHash(this.paymentHash, this.sequence);
|
|
207
209
|
}
|
|
208
210
|
|
|
209
|
-
|
|
211
|
+
getSequence(): bigint {
|
|
212
|
+
return toBigInt(this.sequence);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
getTxoHashHint(): string {
|
|
216
|
+
if(this.txoHash==="0000000000000000000000000000000000000000000000000000000000000000") return null; //Txo hash opt-out flag
|
|
217
|
+
return this.txoHash;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
getExtraData(): string {
|
|
210
221
|
return this.txoHash;
|
|
211
222
|
}
|
|
212
223
|
|
|
213
|
-
|
|
224
|
+
setExtraData(txoHash: string): void {
|
|
214
225
|
this.txoHash = txoHash;
|
|
215
226
|
}
|
|
216
227
|
|
|
217
|
-
getSecurityDeposit() {
|
|
218
|
-
return this.securityDeposit;
|
|
228
|
+
getSecurityDeposit(): bigint {
|
|
229
|
+
return toBigInt(this.securityDeposit);
|
|
219
230
|
}
|
|
220
231
|
|
|
221
|
-
getClaimerBounty() {
|
|
222
|
-
return this.claimerBounty;
|
|
232
|
+
getClaimerBounty(): bigint {
|
|
233
|
+
return toBigInt(this.claimerBounty);
|
|
223
234
|
}
|
|
224
235
|
|
|
225
|
-
getTotalDeposit() {
|
|
226
|
-
return this.claimerBounty.lt(this.securityDeposit) ? this.securityDeposit : this.claimerBounty;
|
|
236
|
+
getTotalDeposit(): bigint {
|
|
237
|
+
return toBigInt(this.claimerBounty.lt(this.securityDeposit) ? this.securityDeposit : this.claimerBounty);
|
|
227
238
|
}
|
|
228
239
|
|
|
229
240
|
toSwapDataStruct(): IdlTypes<SwapProgram>["SwapData"] {
|
|
@@ -355,6 +366,14 @@ export class SolanaSwapData extends SwapData {
|
|
|
355
366
|
return this.offerer.equals(new PublicKey(address));
|
|
356
367
|
}
|
|
357
368
|
|
|
369
|
+
getDepositToken(): string {
|
|
370
|
+
return SolanaTokens.WSOL_ADDRESS.toString();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
isDepositToken(token: string): boolean {
|
|
374
|
+
return SolanaTokens.WSOL_ADDRESS.equals(new PublicKey(token));
|
|
375
|
+
}
|
|
376
|
+
|
|
358
377
|
}
|
|
359
378
|
|
|
360
379
|
SwapData.deserializers["sol"] = SolanaSwapData;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {SolanaSwapData} from "./SolanaSwapData";
|
|
2
2
|
import {IdlAccounts} from "@coral-xyz/anchor";
|
|
3
|
-
import * as BN from "bn.js";
|
|
4
3
|
import {
|
|
5
4
|
Connection, Keypair,
|
|
6
5
|
PublicKey,
|
|
@@ -11,7 +10,7 @@ import {SolanaBtcRelay} from "../btcrelay/SolanaBtcRelay";
|
|
|
11
10
|
import * as programIdl from "./programIdl.json";
|
|
12
11
|
import {
|
|
13
12
|
IStorageManager, SwapContract, ChainSwapType, IntermediaryReputationType,
|
|
14
|
-
SwapCommitStatus, TransactionConfirmationOptions, SignatureData, RelaySynchronizer
|
|
13
|
+
SwapCommitStatus, TransactionConfirmationOptions, SignatureData, RelaySynchronizer, BigIntBufferUtils
|
|
15
14
|
} from "@atomiqlabs/base";
|
|
16
15
|
import {SolanaBtcStoredHeader} from "../btcrelay/headers/SolanaBtcStoredHeader";
|
|
17
16
|
import {
|
|
@@ -30,6 +29,9 @@ import {SolanaLpVault} from "./modules/SolanaLpVault";
|
|
|
30
29
|
import {Buffer} from "buffer";
|
|
31
30
|
import {SolanaSigner} from "../wallet/SolanaSigner";
|
|
32
31
|
import {SolanaKeypairWallet} from "../wallet/SolanaKeypairWallet";
|
|
32
|
+
import {fromClaimHash, toBN, toClaimHash} from "../../utils/Utils";
|
|
33
|
+
import {SolanaTokens} from "../base/modules/SolanaTokens";
|
|
34
|
+
import * as BN from "bn.js";
|
|
33
35
|
|
|
34
36
|
function toPublicKeyOrNull(str: string | null): PublicKey | null {
|
|
35
37
|
return str==null ? null : new PublicKey(str);
|
|
@@ -98,11 +100,11 @@ export class SolanaSwapProgram
|
|
|
98
100
|
await this.DataAccount.init();
|
|
99
101
|
}
|
|
100
102
|
|
|
101
|
-
getClaimableDeposits(signer: string): Promise<{count: number, totalValue:
|
|
103
|
+
getClaimableDeposits(signer: string): Promise<{count: number, totalValue: bigint}> {
|
|
102
104
|
return this.DataAccount.getDataAccountsInfo(new PublicKey(signer));
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
claimDeposits(signer: SolanaSigner): Promise<{txIds: string[], count: number, totalValue:
|
|
107
|
+
claimDeposits(signer: SolanaSigner): Promise<{txIds: string[], count: number, totalValue: bigint}> {
|
|
106
108
|
return this.DataAccount.sweepDataAccounts(signer);
|
|
107
109
|
}
|
|
108
110
|
|
|
@@ -156,10 +158,10 @@ export class SolanaSwapProgram
|
|
|
156
158
|
* @param signer
|
|
157
159
|
* @param data
|
|
158
160
|
*/
|
|
159
|
-
isClaimable(signer: string, data: SolanaSwapData): Promise<boolean> {
|
|
160
|
-
if(!data.isClaimer(signer)) return
|
|
161
|
-
if(this.isExpired(signer, data)) return
|
|
162
|
-
return this.isCommited(data);
|
|
161
|
+
async isClaimable(signer: string, data: SolanaSwapData): Promise<boolean> {
|
|
162
|
+
if(!data.isClaimer(signer)) return false;
|
|
163
|
+
if(await this.isExpired(signer, data)) return false;
|
|
164
|
+
return await this.isCommited(data);
|
|
163
165
|
}
|
|
164
166
|
|
|
165
167
|
/**
|
|
@@ -183,11 +185,11 @@ export class SolanaSwapProgram
|
|
|
183
185
|
* @param signer
|
|
184
186
|
* @param data
|
|
185
187
|
*/
|
|
186
|
-
isExpired(signer: string, data: SolanaSwapData): boolean {
|
|
188
|
+
isExpired(signer: string, data: SolanaSwapData): Promise<boolean> {
|
|
187
189
|
let currentTimestamp: BN = new BN(Math.floor(Date.now()/1000));
|
|
188
190
|
if(data.isClaimer(signer)) currentTimestamp = currentTimestamp.sub(new BN(this.refundGracePeriod));
|
|
189
191
|
if(data.isOfferer(signer)) currentTimestamp = currentTimestamp.add(new BN(this.claimGracePeriod));
|
|
190
|
-
return data.expiry.lt(currentTimestamp);
|
|
192
|
+
return Promise.resolve(data.expiry.lt(currentTimestamp));
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
/**
|
|
@@ -197,11 +199,11 @@ export class SolanaSwapProgram
|
|
|
197
199
|
* @param signer
|
|
198
200
|
* @param data
|
|
199
201
|
*/
|
|
200
|
-
isRequestRefundable(signer: string, data: SolanaSwapData): Promise<boolean> {
|
|
202
|
+
async isRequestRefundable(signer: string, data: SolanaSwapData): Promise<boolean> {
|
|
201
203
|
//Swap can only be refunded by the offerer
|
|
202
|
-
if(!data.isOfferer(signer)) return
|
|
203
|
-
if(!this.isExpired(signer, data)) return
|
|
204
|
-
return this.isCommited(data);
|
|
204
|
+
if(!data.isOfferer(signer)) return false;
|
|
205
|
+
if(!(await this.isExpired(signer, data))) return false;
|
|
206
|
+
return await this.isCommited(data);
|
|
205
207
|
}
|
|
206
208
|
|
|
207
209
|
/**
|
|
@@ -209,14 +211,33 @@ export class SolanaSwapProgram
|
|
|
209
211
|
*
|
|
210
212
|
* @param outputScript output script required to claim the swap
|
|
211
213
|
* @param amount sats sent required to claim the swap
|
|
214
|
+
* @param confirmations
|
|
212
215
|
* @param nonce swap nonce uniquely identifying the transaction to prevent replay attacks
|
|
213
216
|
*/
|
|
214
|
-
getHashForOnchain(outputScript: Buffer, amount:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
217
|
+
getHashForOnchain(outputScript: Buffer, amount: bigint, confirmations: number, nonce?: bigint): Buffer {
|
|
218
|
+
nonce ??= 0n;
|
|
219
|
+
const paymentHash = createHash("sha256").update(Buffer.concat([
|
|
220
|
+
BigIntBufferUtils.toBuffer(nonce, "le", 8),
|
|
221
|
+
BigIntBufferUtils.toBuffer(amount, "le", 8),
|
|
218
222
|
outputScript
|
|
219
|
-
])).digest();
|
|
223
|
+
])).digest().toString("hex");
|
|
224
|
+
return Buffer.from(toClaimHash(paymentHash, nonce, confirmations), "hex");
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
getHashForHtlc(swapHash: Buffer): Buffer {
|
|
228
|
+
return Buffer.from(toClaimHash(
|
|
229
|
+
swapHash.toString("hex"),
|
|
230
|
+
0n,
|
|
231
|
+
0
|
|
232
|
+
), "hex");
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
getHashForTxId(txId: string, confirmations: number): Buffer {
|
|
236
|
+
return Buffer.from(toClaimHash(
|
|
237
|
+
Buffer.from(txId, "hex").reverse().toString("hex"),
|
|
238
|
+
0n,
|
|
239
|
+
confirmations
|
|
240
|
+
), "hex");
|
|
220
241
|
}
|
|
221
242
|
|
|
222
243
|
////////////////////////////////////////////
|
|
@@ -230,14 +251,18 @@ export class SolanaSwapProgram
|
|
|
230
251
|
*/
|
|
231
252
|
async getCommitStatus(signer: string, data: SolanaSwapData): Promise<SwapCommitStatus> {
|
|
232
253
|
const escrowStateKey = this.SwapEscrowState(Buffer.from(data.paymentHash, "hex"));
|
|
233
|
-
const escrowState
|
|
254
|
+
const [escrowState, isExpired] = await Promise.all([
|
|
255
|
+
this.program.account.escrowState.fetchNullable(escrowStateKey) as Promise<IdlAccounts<SwapProgram>["escrowState"]>,
|
|
256
|
+
this.isExpired(signer,data)
|
|
257
|
+
]);
|
|
258
|
+
|
|
234
259
|
if(escrowState!=null) {
|
|
235
260
|
if(data.correctPDA(escrowState)) {
|
|
236
|
-
if(data.isOfferer(signer) &&
|
|
261
|
+
if(data.isOfferer(signer) && isExpired) return SwapCommitStatus.REFUNDABLE;
|
|
237
262
|
return SwapCommitStatus.COMMITED;
|
|
238
263
|
}
|
|
239
264
|
|
|
240
|
-
if(data.isOfferer(signer) &&
|
|
265
|
+
if(data.isOfferer(signer) && isExpired) return SwapCommitStatus.EXPIRED;
|
|
241
266
|
return SwapCommitStatus.NOT_COMMITED;
|
|
242
267
|
}
|
|
243
268
|
|
|
@@ -249,13 +274,13 @@ export class SolanaSwapProgram
|
|
|
249
274
|
}
|
|
250
275
|
if(event.name==="RefundEvent") {
|
|
251
276
|
if(!event.data.sequence.eq(data.sequence)) return null;
|
|
252
|
-
if(
|
|
277
|
+
if(isExpired) return SwapCommitStatus.EXPIRED;
|
|
253
278
|
return SwapCommitStatus.NOT_COMMITED;
|
|
254
279
|
}
|
|
255
280
|
});
|
|
256
281
|
if(status!=null) return status;
|
|
257
282
|
|
|
258
|
-
if(
|
|
283
|
+
if(isExpired) {
|
|
259
284
|
return SwapCommitStatus.EXPIRED;
|
|
260
285
|
}
|
|
261
286
|
return SwapCommitStatus.NOT_COMMITED;
|
|
@@ -264,9 +289,10 @@ export class SolanaSwapProgram
|
|
|
264
289
|
/**
|
|
265
290
|
* Checks the status of the specific payment hash
|
|
266
291
|
*
|
|
267
|
-
* @param
|
|
292
|
+
* @param claimHash
|
|
268
293
|
*/
|
|
269
|
-
async
|
|
294
|
+
async getClaimHashStatus(claimHash: string): Promise<SwapCommitStatus> {
|
|
295
|
+
const {paymentHash} = fromClaimHash(claimHash);
|
|
270
296
|
const escrowStateKey = this.SwapEscrowState(Buffer.from(paymentHash, "hex"));
|
|
271
297
|
const abortController = new AbortController();
|
|
272
298
|
|
|
@@ -298,12 +324,13 @@ export class SolanaSwapProgram
|
|
|
298
324
|
* Returns the data committed for a specific payment hash, or null if no data is currently commited for
|
|
299
325
|
* the specific swap
|
|
300
326
|
*
|
|
301
|
-
* @param
|
|
327
|
+
* @param claimHashHex
|
|
302
328
|
*/
|
|
303
|
-
async getCommitedData(
|
|
304
|
-
const paymentHash =
|
|
329
|
+
async getCommitedData(claimHashHex: string): Promise<SolanaSwapData> {
|
|
330
|
+
const {paymentHash} = fromClaimHash(claimHashHex);
|
|
331
|
+
const paymentHashBuffer = Buffer.from(paymentHash, "hex");
|
|
305
332
|
|
|
306
|
-
const account: IdlAccounts<SwapProgram>["escrowState"] = await this.program.account.escrowState.fetchNullable(this.SwapEscrowState(
|
|
333
|
+
const account: IdlAccounts<SwapProgram>["escrowState"] = await this.program.account.escrowState.fetchNullable(this.SwapEscrowState(paymentHashBuffer));
|
|
307
334
|
if(account==null) return null;
|
|
308
335
|
|
|
309
336
|
return SolanaSwapData.fromEscrowState(account);
|
|
@@ -316,60 +343,64 @@ export class SolanaSwapProgram
|
|
|
316
343
|
offerer: string,
|
|
317
344
|
claimer: string,
|
|
318
345
|
token: string,
|
|
319
|
-
amount:
|
|
320
|
-
|
|
321
|
-
sequence:
|
|
322
|
-
expiry:
|
|
323
|
-
escrowNonce: BN,
|
|
324
|
-
confirmations: number,
|
|
346
|
+
amount: bigint,
|
|
347
|
+
claimHash: string,
|
|
348
|
+
sequence: bigint,
|
|
349
|
+
expiry: bigint,
|
|
325
350
|
payIn: boolean,
|
|
326
351
|
payOut: boolean,
|
|
327
|
-
securityDeposit:
|
|
328
|
-
claimerBounty:
|
|
352
|
+
securityDeposit: bigint,
|
|
353
|
+
claimerBounty: bigint,
|
|
354
|
+
depositToken?: string
|
|
329
355
|
): Promise<SolanaSwapData> {
|
|
356
|
+
if(depositToken!=null) {
|
|
357
|
+
if(!new PublicKey(depositToken).equals(SolanaTokens.WSOL_ADDRESS)) throw new Error("Only SOL supported as deposit token!");
|
|
358
|
+
}
|
|
330
359
|
const tokenAddr: PublicKey = new PublicKey(token);
|
|
331
360
|
const offererKey = offerer==null ? null : new PublicKey(offerer);
|
|
332
361
|
const claimerKey = claimer==null ? null : new PublicKey(claimer);
|
|
362
|
+
const {paymentHash, nonce, confirmations} = fromClaimHash(claimHash);
|
|
333
363
|
return Promise.resolve(new SolanaSwapData(
|
|
334
364
|
offererKey,
|
|
335
365
|
claimerKey,
|
|
336
366
|
tokenAddr,
|
|
337
|
-
amount,
|
|
367
|
+
toBN(amount),
|
|
338
368
|
paymentHash,
|
|
339
|
-
sequence,
|
|
340
|
-
expiry,
|
|
341
|
-
|
|
369
|
+
toBN(sequence),
|
|
370
|
+
toBN(expiry),
|
|
371
|
+
nonce,
|
|
342
372
|
confirmations,
|
|
343
373
|
payOut,
|
|
344
374
|
type==null ? null : SolanaSwapData.typeToKind(type),
|
|
345
375
|
payIn,
|
|
346
376
|
offererKey==null ? null : payIn ? getAssociatedTokenAddressSync(tokenAddr, offererKey) : PublicKey.default,
|
|
347
377
|
claimerKey==null ? null : payOut ? getAssociatedTokenAddressSync(tokenAddr, claimerKey) : PublicKey.default,
|
|
348
|
-
securityDeposit,
|
|
349
|
-
claimerBounty,
|
|
378
|
+
toBN(securityDeposit),
|
|
379
|
+
toBN(claimerBounty),
|
|
350
380
|
null
|
|
351
381
|
));
|
|
352
382
|
}
|
|
353
383
|
|
|
354
384
|
////////////////////////////////////////////
|
|
355
385
|
//// Utils
|
|
356
|
-
async getBalance(signer: string, tokenAddress: string, inContract: boolean): Promise<
|
|
386
|
+
async getBalance(signer: string, tokenAddress: string, inContract: boolean): Promise<bigint> {
|
|
357
387
|
const token = new PublicKey(tokenAddress);
|
|
358
388
|
const publicKey = new PublicKey(signer);
|
|
359
389
|
|
|
360
390
|
if(inContract) return await this.getIntermediaryBalance(publicKey, token);
|
|
361
391
|
|
|
362
|
-
let { balance
|
|
363
|
-
if(token.equals(
|
|
364
|
-
const accountRentExemptCost =
|
|
365
|
-
balance =
|
|
392
|
+
let { balance } = await this.Tokens.getTokenBalance(publicKey, token);
|
|
393
|
+
if(token.equals(SolanaTokens.WSOL_ADDRESS)) {
|
|
394
|
+
const accountRentExemptCost = 1000000n;
|
|
395
|
+
balance = balance - accountRentExemptCost;
|
|
396
|
+
if(balance < 0n) balance = 0n;
|
|
366
397
|
}
|
|
367
398
|
this.logger.debug("getBalance(): token balance, token: "+token.toBase58()+" balance: "+balance.toString(10));
|
|
368
399
|
return balance;
|
|
369
400
|
}
|
|
370
401
|
|
|
371
402
|
getIntermediaryData(address: string, token: string): Promise<{
|
|
372
|
-
balance:
|
|
403
|
+
balance: bigint,
|
|
373
404
|
reputation: IntermediaryReputationType
|
|
374
405
|
}> {
|
|
375
406
|
return this.LpVault.getIntermediaryData(new PublicKey(address), new PublicKey(token));
|
|
@@ -379,7 +410,7 @@ export class SolanaSwapProgram
|
|
|
379
410
|
return this.LpVault.getIntermediaryReputation(new PublicKey(address), new PublicKey(token));
|
|
380
411
|
}
|
|
381
412
|
|
|
382
|
-
getIntermediaryBalance(address: PublicKey, token: PublicKey): Promise<
|
|
413
|
+
getIntermediaryBalance(address: PublicKey, token: PublicKey): Promise<bigint> {
|
|
383
414
|
return this.LpVault.getIntermediaryBalance(address, token);
|
|
384
415
|
}
|
|
385
416
|
|
|
@@ -408,8 +439,8 @@ export class SolanaSwapProgram
|
|
|
408
439
|
async txsClaimWithTxData(
|
|
409
440
|
signer: string | SolanaSigner,
|
|
410
441
|
swapData: SolanaSwapData,
|
|
411
|
-
|
|
412
|
-
|
|
442
|
+
tx: { blockhash: string, confirmations: number, txid: string, hex: string, height: number },
|
|
443
|
+
requiredConfirmations: number,
|
|
413
444
|
vout: number,
|
|
414
445
|
commitedHeader?: SolanaBtcStoredHeader,
|
|
415
446
|
synchronizer?: RelaySynchronizer<any, SolanaTx, any>,
|
|
@@ -417,34 +448,37 @@ export class SolanaSwapProgram
|
|
|
417
448
|
feeRate?: string,
|
|
418
449
|
storageAccHolder?: {storageAcc: PublicKey}
|
|
419
450
|
): Promise<SolanaTx[] | null> {
|
|
420
|
-
|
|
451
|
+
if(swapData.confirmations!==requiredConfirmations) throw new Error("Invalid requiredConfirmations provided!");
|
|
452
|
+
return this.Claim.txsClaimWithTxData(typeof(signer)==="string" ? new PublicKey(signer) : signer, swapData, tx, vout, commitedHeader, synchronizer, initAta, storageAccHolder, feeRate);
|
|
421
453
|
}
|
|
422
454
|
|
|
423
|
-
txsRefund(swapData: SolanaSwapData, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]> {
|
|
455
|
+
txsRefund(signer: string, swapData: SolanaSwapData, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]> {
|
|
456
|
+
if(!swapData.isOfferer(signer)) throw new Error("Only offerer can refund on Solana");
|
|
424
457
|
return this.Refund.txsRefund(swapData, check, initAta, feeRate);
|
|
425
458
|
}
|
|
426
459
|
|
|
427
|
-
txsRefundWithAuthorization(swapData: SolanaSwapData, {timeout, prefix, signature}, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]> {
|
|
460
|
+
txsRefundWithAuthorization(signer: string, swapData: SolanaSwapData, {timeout, prefix, signature}, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]> {
|
|
461
|
+
if(!swapData.isOfferer(signer)) throw new Error("Only offerer can refund on Solana");
|
|
428
462
|
return this.Refund.txsRefundWithAuthorization(swapData,timeout,prefix,signature,check,initAta,feeRate);
|
|
429
463
|
}
|
|
430
464
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
465
|
+
txsInit(swapData: SolanaSwapData, {timeout, prefix, signature}, skipChecks?: boolean, feeRate?: string): Promise<SolanaTx[]> {
|
|
466
|
+
if(swapData.isPayIn()) {
|
|
467
|
+
return this.Init.txsInitPayIn(swapData, timeout, prefix, signature, skipChecks, feeRate);
|
|
468
|
+
} else {
|
|
469
|
+
return this.Init.txsInit(swapData, timeout, prefix, signature, skipChecks, feeRate);
|
|
470
|
+
}
|
|
437
471
|
}
|
|
438
472
|
|
|
439
|
-
txsWithdraw(signer: string, token: string, amount:
|
|
473
|
+
txsWithdraw(signer: string, token: string, amount: bigint, feeRate?: string): Promise<SolanaTx[]> {
|
|
440
474
|
return this.LpVault.txsWithdraw(new PublicKey(signer), new PublicKey(token), amount, feeRate);
|
|
441
475
|
}
|
|
442
476
|
|
|
443
|
-
txsDeposit(signer: string, token: string, amount:
|
|
477
|
+
txsDeposit(signer: string, token: string, amount: bigint, feeRate?: string): Promise<SolanaTx[]> {
|
|
444
478
|
return this.LpVault.txsDeposit(new PublicKey(signer), new PublicKey(token), amount, feeRate);
|
|
445
479
|
}
|
|
446
480
|
|
|
447
|
-
txsTransfer(signer: string, token: string, amount:
|
|
481
|
+
txsTransfer(signer: string, token: string, amount: bigint, dstAddress: string, feeRate?: string): Promise<SolanaTx[]> {
|
|
448
482
|
return this.Tokens.txsTransfer(new PublicKey(signer), new PublicKey(token), amount, new PublicKey(dstAddress), feeRate);
|
|
449
483
|
}
|
|
450
484
|
|
|
@@ -466,20 +500,22 @@ export class SolanaSwapProgram
|
|
|
466
500
|
async claimWithTxData(
|
|
467
501
|
signer: SolanaSigner,
|
|
468
502
|
swapData: SolanaSwapData,
|
|
469
|
-
|
|
470
|
-
|
|
503
|
+
tx: { blockhash: string, confirmations: number, txid: string, hex: string, height: number },
|
|
504
|
+
requiredConfirmations: number,
|
|
471
505
|
vout: number,
|
|
472
506
|
commitedHeader?: SolanaBtcStoredHeader,
|
|
473
507
|
synchronizer?: RelaySynchronizer<any, SolanaTx, any>,
|
|
474
508
|
initAta?: boolean,
|
|
475
509
|
txOptions?: TransactionConfirmationOptions
|
|
476
510
|
): Promise<string> {
|
|
511
|
+
if(requiredConfirmations!==swapData.confirmations) throw new Error("Invalid requiredConfirmations provided!");
|
|
512
|
+
|
|
477
513
|
const data: {storageAcc: PublicKey} = {
|
|
478
514
|
storageAcc: null
|
|
479
515
|
};
|
|
480
516
|
|
|
481
517
|
const txs = await this.Claim.txsClaimWithTxData(
|
|
482
|
-
signer, swapData,
|
|
518
|
+
signer, swapData, tx, vout,
|
|
483
519
|
commitedHeader, synchronizer, initAta, data, txOptions?.feeRate
|
|
484
520
|
);
|
|
485
521
|
if(txs===null) throw new Error("Btc relay not synchronized to required blockheight!");
|
|
@@ -498,9 +534,7 @@ export class SolanaSwapProgram
|
|
|
498
534
|
initAta?: boolean,
|
|
499
535
|
txOptions?: TransactionConfirmationOptions
|
|
500
536
|
): Promise<string> {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
let result = await this.txsRefund(swapData, check, initAta, txOptions?.feeRate);
|
|
537
|
+
let result = await this.txsRefund(signer.getAddress(), swapData, check, initAta, txOptions?.feeRate);
|
|
504
538
|
|
|
505
539
|
const [signature] = await this.Transactions.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
506
540
|
|
|
@@ -515,42 +549,27 @@ export class SolanaSwapProgram
|
|
|
515
549
|
initAta?: boolean,
|
|
516
550
|
txOptions?: TransactionConfirmationOptions
|
|
517
551
|
): Promise<string> {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
let result = await this.txsRefundWithAuthorization(swapData, signature, check, initAta, txOptions?.feeRate);
|
|
552
|
+
let result = await this.txsRefundWithAuthorization(signer.getAddress(), swapData, signature, check, initAta, txOptions?.feeRate);
|
|
521
553
|
|
|
522
554
|
const [txSignature] = await this.Transactions.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
523
555
|
|
|
524
556
|
return txSignature;
|
|
525
557
|
}
|
|
526
558
|
|
|
527
|
-
async initPayIn(
|
|
528
|
-
signer: SolanaSigner,
|
|
529
|
-
swapData: SolanaSwapData,
|
|
530
|
-
signature: SignatureData,
|
|
531
|
-
skipChecks?: boolean,
|
|
532
|
-
txOptions?: TransactionConfirmationOptions
|
|
533
|
-
): Promise<string> {
|
|
534
|
-
if(!signer.getPublicKey().equals(swapData.offerer)) throw new Error("Invalid signer provided!");
|
|
535
|
-
|
|
536
|
-
let result = await this.txsInitPayIn(swapData, signature, skipChecks, txOptions?.feeRate);
|
|
537
|
-
|
|
538
|
-
const signatures = await this.Transactions.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
539
|
-
|
|
540
|
-
return signatures[signatures.length-1];
|
|
541
|
-
}
|
|
542
|
-
|
|
543
559
|
async init(
|
|
544
560
|
signer: SolanaSigner,
|
|
545
561
|
swapData: SolanaSwapData,
|
|
546
562
|
signature: SignatureData,
|
|
547
|
-
txoHash?: Buffer,
|
|
548
563
|
skipChecks?: boolean,
|
|
549
564
|
txOptions?: TransactionConfirmationOptions
|
|
550
565
|
): Promise<string> {
|
|
551
|
-
if(
|
|
566
|
+
if(swapData.isPayIn()) {
|
|
567
|
+
if(!signer.getPublicKey().equals(swapData.offerer)) throw new Error("Invalid signer provided!");
|
|
568
|
+
} else {
|
|
569
|
+
if(!signer.getPublicKey().equals(swapData.claimer)) throw new Error("Invalid signer provided!");
|
|
570
|
+
}
|
|
552
571
|
|
|
553
|
-
|
|
572
|
+
const result = await this.txsInit(swapData, signature, skipChecks, txOptions?.feeRate);
|
|
554
573
|
|
|
555
574
|
const [txSignature] = await this.Transactions.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
556
575
|
|
|
@@ -567,7 +586,7 @@ export class SolanaSwapProgram
|
|
|
567
586
|
): Promise<string[]> {
|
|
568
587
|
if(!signer.getPublicKey().equals(swapData.claimer)) throw new Error("Invalid signer provided!");
|
|
569
588
|
|
|
570
|
-
const txsCommit = await this.txsInit(swapData, signature,
|
|
589
|
+
const txsCommit = await this.txsInit(swapData, signature, skipChecks, txOptions?.feeRate);
|
|
571
590
|
const txsClaim = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, true, false, txOptions?.feeRate, true);
|
|
572
591
|
|
|
573
592
|
return await this.Transactions.sendAndConfirm(signer, txsCommit.concat(txsClaim), txOptions?.waitForConfirmation, txOptions?.abortSignal);
|
|
@@ -576,7 +595,7 @@ export class SolanaSwapProgram
|
|
|
576
595
|
async withdraw(
|
|
577
596
|
signer: SolanaSigner,
|
|
578
597
|
token: string,
|
|
579
|
-
amount:
|
|
598
|
+
amount: bigint,
|
|
580
599
|
txOptions?: TransactionConfirmationOptions
|
|
581
600
|
): Promise<string> {
|
|
582
601
|
const txs = await this.LpVault.txsWithdraw(signer.getPublicKey(), new PublicKey(token), amount, txOptions?.feeRate);
|
|
@@ -587,7 +606,7 @@ export class SolanaSwapProgram
|
|
|
587
606
|
async deposit(
|
|
588
607
|
signer: SolanaSigner,
|
|
589
608
|
token: string,
|
|
590
|
-
amount:
|
|
609
|
+
amount: bigint,
|
|
591
610
|
txOptions?: TransactionConfirmationOptions
|
|
592
611
|
): Promise<string> {
|
|
593
612
|
const txs = await this.LpVault.txsDeposit(signer.getPublicKey(), new PublicKey(token), amount, txOptions?.feeRate);
|
|
@@ -598,7 +617,7 @@ export class SolanaSwapProgram
|
|
|
598
617
|
async transfer(
|
|
599
618
|
signer: SolanaSigner,
|
|
600
619
|
token: string,
|
|
601
|
-
amount:
|
|
620
|
+
amount: bigint,
|
|
602
621
|
dstAddress: string,
|
|
603
622
|
txOptions?: TransactionConfirmationOptions
|
|
604
623
|
): Promise<string> {
|
|
@@ -638,7 +657,8 @@ export class SolanaSwapProgram
|
|
|
638
657
|
|
|
639
658
|
////////////////////////////////////////////
|
|
640
659
|
//// Fees
|
|
641
|
-
getInitPayInFeeRate(offerer?: string, claimer?: string, token?: string,
|
|
660
|
+
getInitPayInFeeRate(offerer?: string, claimer?: string, token?: string, claimHash?: string): Promise<string> {
|
|
661
|
+
const paymentHash = claimHash==null ? null : fromClaimHash(claimHash).paymentHash;
|
|
642
662
|
return this.Init.getInitPayInFeeRate(
|
|
643
663
|
toPublicKeyOrNull(offerer),
|
|
644
664
|
toPublicKeyOrNull(claimer),
|
|
@@ -647,7 +667,8 @@ export class SolanaSwapProgram
|
|
|
647
667
|
);
|
|
648
668
|
}
|
|
649
669
|
|
|
650
|
-
getInitFeeRate(offerer?: string, claimer?: string, token?: string,
|
|
670
|
+
getInitFeeRate(offerer?: string, claimer?: string, token?: string, claimHash?: string): Promise<string> {
|
|
671
|
+
const paymentHash = claimHash==null ? null : fromClaimHash(claimHash).paymentHash;
|
|
651
672
|
return this.Init.getInitFeeRate(
|
|
652
673
|
toPublicKeyOrNull(offerer),
|
|
653
674
|
toPublicKeyOrNull(claimer),
|
|
@@ -664,39 +685,39 @@ export class SolanaSwapProgram
|
|
|
664
685
|
return this.Claim.getClaimFeeRate(new PublicKey(signer), swapData);
|
|
665
686
|
}
|
|
666
687
|
|
|
667
|
-
getClaimFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<
|
|
688
|
+
getClaimFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
668
689
|
return this.Claim.getClaimFee(new PublicKey(signer), swapData, feeRate);
|
|
669
690
|
}
|
|
670
691
|
|
|
671
|
-
getRawClaimFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<
|
|
692
|
+
getRawClaimFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
672
693
|
return this.Claim.getRawClaimFee(new PublicKey(signer), swapData, feeRate);
|
|
673
694
|
}
|
|
674
695
|
|
|
675
696
|
/**
|
|
676
697
|
* Get the estimated solana fee of the commit transaction
|
|
677
698
|
*/
|
|
678
|
-
getCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<
|
|
699
|
+
getCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
679
700
|
return this.Init.getInitFee(swapData, feeRate);
|
|
680
701
|
}
|
|
681
702
|
|
|
682
703
|
/**
|
|
683
704
|
* Get the estimated solana fee of the commit transaction, without any deposits
|
|
684
705
|
*/
|
|
685
|
-
getRawCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<
|
|
706
|
+
getRawCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
686
707
|
return this.Init.getRawInitFee(swapData, feeRate);
|
|
687
708
|
}
|
|
688
709
|
|
|
689
710
|
/**
|
|
690
711
|
* Get the estimated solana transaction fee of the refund transaction
|
|
691
712
|
*/
|
|
692
|
-
getRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<
|
|
713
|
+
getRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
693
714
|
return this.Refund.getRefundFee(swapData, feeRate);
|
|
694
715
|
}
|
|
695
716
|
|
|
696
717
|
/**
|
|
697
718
|
* Get the estimated solana transaction fee of the refund transaction
|
|
698
719
|
*/
|
|
699
|
-
getRawRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<
|
|
720
|
+
getRawRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
|
|
700
721
|
return this.Refund.getRawRefundFee(swapData, feeRate);
|
|
701
722
|
}
|
|
702
723
|
|
|
@@ -743,4 +764,11 @@ export class SolanaSwapProgram
|
|
|
743
764
|
return new SolanaSigner(wallet, keypair);
|
|
744
765
|
}
|
|
745
766
|
|
|
767
|
+
getExtraData(outputScript: Buffer, amount: bigint, confirmations: number, nonce?: bigint): Buffer {
|
|
768
|
+
return createHash("sha256").update(Buffer.concat([
|
|
769
|
+
BigIntBufferUtils.toBuffer(amount, "le", 8),
|
|
770
|
+
outputScript
|
|
771
|
+
])).digest();
|
|
772
|
+
}
|
|
773
|
+
|
|
746
774
|
}
|