@atomiqlabs/chain-solana 7.2.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/LICENSE +201 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +44 -0
- package/dist/solana/SolanaChainType.d.ts +9 -0
- package/dist/solana/SolanaChainType.js +2 -0
- package/dist/solana/base/SolanaAction.d.ts +26 -0
- package/dist/solana/base/SolanaAction.js +99 -0
- package/dist/solana/base/SolanaBase.d.ts +36 -0
- package/dist/solana/base/SolanaBase.js +30 -0
- package/dist/solana/base/SolanaModule.d.ts +14 -0
- package/dist/solana/base/SolanaModule.js +13 -0
- package/dist/solana/base/modules/SolanaAddresses.d.ts +9 -0
- package/dist/solana/base/modules/SolanaAddresses.js +23 -0
- package/dist/solana/base/modules/SolanaBlocks.d.ts +28 -0
- package/dist/solana/base/modules/SolanaBlocks.js +83 -0
- package/dist/solana/base/modules/SolanaEvents.d.ts +25 -0
- package/dist/solana/base/modules/SolanaEvents.js +69 -0
- package/dist/solana/base/modules/SolanaFees.d.ts +121 -0
- package/dist/solana/base/modules/SolanaFees.js +393 -0
- package/dist/solana/base/modules/SolanaSignatures.d.ts +23 -0
- package/dist/solana/base/modules/SolanaSignatures.js +39 -0
- package/dist/solana/base/modules/SolanaSlots.d.ts +31 -0
- package/dist/solana/base/modules/SolanaSlots.js +81 -0
- package/dist/solana/base/modules/SolanaTokens.d.ts +134 -0
- package/dist/solana/base/modules/SolanaTokens.js +269 -0
- package/dist/solana/base/modules/SolanaTransactions.d.ts +124 -0
- package/dist/solana/base/modules/SolanaTransactions.js +354 -0
- package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +229 -0
- package/dist/solana/btcrelay/SolanaBtcRelay.js +477 -0
- package/dist/solana/btcrelay/headers/SolanaBtcHeader.d.ts +29 -0
- package/dist/solana/btcrelay/headers/SolanaBtcHeader.js +34 -0
- package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.d.ts +46 -0
- package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.js +78 -0
- package/dist/solana/btcrelay/program/programIdl.json +671 -0
- package/dist/solana/events/SolanaChainEvents.d.ts +84 -0
- package/dist/solana/events/SolanaChainEvents.js +268 -0
- package/dist/solana/events/SolanaChainEventsBrowser.d.ts +85 -0
- package/dist/solana/events/SolanaChainEventsBrowser.js +202 -0
- package/dist/solana/program/SolanaProgramBase.d.ts +34 -0
- package/dist/solana/program/SolanaProgramBase.js +43 -0
- package/dist/solana/program/modules/SolanaProgramEvents.d.ts +58 -0
- package/dist/solana/program/modules/SolanaProgramEvents.js +114 -0
- package/dist/solana/swaps/SolanaSwapData.d.ts +55 -0
- package/dist/solana/swaps/SolanaSwapData.js +251 -0
- package/dist/solana/swaps/SolanaSwapModule.d.ts +9 -0
- package/dist/solana/swaps/SolanaSwapModule.js +12 -0
- package/dist/solana/swaps/SolanaSwapProgram.d.ts +218 -0
- package/dist/solana/swaps/SolanaSwapProgram.js +523 -0
- package/dist/solana/swaps/SwapTypeEnum.d.ts +11 -0
- package/dist/solana/swaps/SwapTypeEnum.js +42 -0
- package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +94 -0
- package/dist/solana/swaps/modules/SolanaDataAccount.js +255 -0
- package/dist/solana/swaps/modules/SolanaLpVault.d.ts +72 -0
- package/dist/solana/swaps/modules/SolanaLpVault.js +196 -0
- package/dist/solana/swaps/modules/SwapClaim.d.ts +129 -0
- package/dist/solana/swaps/modules/SwapClaim.js +307 -0
- package/dist/solana/swaps/modules/SwapInit.d.ts +212 -0
- package/dist/solana/swaps/modules/SwapInit.js +508 -0
- package/dist/solana/swaps/modules/SwapRefund.d.ts +83 -0
- package/dist/solana/swaps/modules/SwapRefund.js +264 -0
- package/dist/solana/swaps/programIdl.json +945 -0
- package/dist/solana/swaps/programTypes.d.ts +943 -0
- package/dist/solana/swaps/programTypes.js +945 -0
- package/dist/solana/wallet/SolanaKeypairWallet.d.ts +9 -0
- package/dist/solana/wallet/SolanaKeypairWallet.js +33 -0
- package/dist/solana/wallet/SolanaSigner.d.ts +10 -0
- package/dist/solana/wallet/SolanaSigner.js +16 -0
- package/dist/utils/Utils.d.ts +43 -0
- package/dist/utils/Utils.js +143 -0
- package/package.json +40 -0
- package/src/index.ts +35 -0
- package/src/solana/SolanaChainType.ts +20 -0
- package/src/solana/base/SolanaAction.ts +109 -0
- package/src/solana/base/SolanaBase.ts +57 -0
- package/src/solana/base/SolanaModule.ts +21 -0
- package/src/solana/base/modules/SolanaAddresses.ts +22 -0
- package/src/solana/base/modules/SolanaBlocks.ts +79 -0
- package/src/solana/base/modules/SolanaEvents.ts +58 -0
- package/src/solana/base/modules/SolanaFees.ts +445 -0
- package/src/solana/base/modules/SolanaSignatures.ts +40 -0
- package/src/solana/base/modules/SolanaSlots.ts +83 -0
- package/src/solana/base/modules/SolanaTokens.ts +310 -0
- package/src/solana/base/modules/SolanaTransactions.ts +366 -0
- package/src/solana/btcrelay/SolanaBtcRelay.ts +591 -0
- package/src/solana/btcrelay/headers/SolanaBtcHeader.ts +58 -0
- package/src/solana/btcrelay/headers/SolanaBtcStoredHeader.ts +103 -0
- package/src/solana/btcrelay/program/programIdl.json +671 -0
- package/src/solana/events/SolanaChainEvents.ts +286 -0
- package/src/solana/events/SolanaChainEventsBrowser.ts +251 -0
- package/src/solana/program/SolanaProgramBase.ts +77 -0
- package/src/solana/program/modules/SolanaProgramEvents.ts +140 -0
- package/src/solana/swaps/SolanaSwapData.ts +360 -0
- package/src/solana/swaps/SolanaSwapModule.ts +17 -0
- package/src/solana/swaps/SolanaSwapProgram.ts +739 -0
- package/src/solana/swaps/SwapTypeEnum.ts +30 -0
- package/src/solana/swaps/modules/SolanaDataAccount.ts +309 -0
- package/src/solana/swaps/modules/SolanaLpVault.ts +216 -0
- package/src/solana/swaps/modules/SwapClaim.ts +397 -0
- package/src/solana/swaps/modules/SwapInit.ts +621 -0
- package/src/solana/swaps/modules/SwapRefund.ts +316 -0
- package/src/solana/swaps/programIdl.json +945 -0
- package/src/solana/swaps/programTypes.ts +1885 -0
- package/src/solana/wallet/SolanaKeypairWallet.ts +36 -0
- package/src/solana/wallet/SolanaSigner.ts +23 -0
- package/src/utils/Utils.ts +145 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SolanaDataAccount = exports.StoredDataAccount = void 0;
|
|
13
|
+
const SolanaSwapModule_1 = require("../SolanaSwapModule");
|
|
14
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
15
|
+
const SolanaAction_1 = require("../../base/SolanaAction");
|
|
16
|
+
const Utils_1 = require("../../../utils/Utils");
|
|
17
|
+
const randomBytes = require("randombytes");
|
|
18
|
+
const SolanaSigner_1 = require("../../wallet/SolanaSigner");
|
|
19
|
+
const BN = require("bn.js");
|
|
20
|
+
class StoredDataAccount {
|
|
21
|
+
constructor(accountKeyOrData, owner) {
|
|
22
|
+
if (accountKeyOrData instanceof web3_js_1.PublicKey) {
|
|
23
|
+
this.accountKey = accountKeyOrData;
|
|
24
|
+
this.owner = owner;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
this.accountKey = new web3_js_1.PublicKey(accountKeyOrData.accountKey);
|
|
28
|
+
this.owner = new web3_js_1.PublicKey(accountKeyOrData.owner);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
serialize() {
|
|
32
|
+
return {
|
|
33
|
+
accountKey: this.accountKey.toBase58(),
|
|
34
|
+
owner: this.owner.toBase58()
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.StoredDataAccount = StoredDataAccount;
|
|
39
|
+
class SolanaDataAccount extends SolanaSwapModule_1.SolanaSwapModule {
|
|
40
|
+
/**
|
|
41
|
+
* Action for initialization of the data account
|
|
42
|
+
*
|
|
43
|
+
* @param signer
|
|
44
|
+
* @param accountKey
|
|
45
|
+
* @param dataLength
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
48
|
+
InitDataAccount(signer, accountKey, dataLength) {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
const accountSize = 32 + dataLength;
|
|
51
|
+
const lamportsDeposit = yield (0, Utils_1.tryWithRetries)(() => this.connection.getMinimumBalanceForRentExemption(accountSize), this.retryPolicy);
|
|
52
|
+
return new SolanaAction_1.SolanaAction(signer, this.root, [
|
|
53
|
+
web3_js_1.SystemProgram.createAccount({
|
|
54
|
+
fromPubkey: signer,
|
|
55
|
+
newAccountPubkey: accountKey.publicKey,
|
|
56
|
+
lamports: lamportsDeposit,
|
|
57
|
+
space: accountSize,
|
|
58
|
+
programId: this.program.programId
|
|
59
|
+
}),
|
|
60
|
+
yield this.program.methods
|
|
61
|
+
.initData()
|
|
62
|
+
.accounts({
|
|
63
|
+
signer,
|
|
64
|
+
data: accountKey.publicKey
|
|
65
|
+
})
|
|
66
|
+
.instruction(),
|
|
67
|
+
], SolanaDataAccount.CUCosts.DATA_CREATE, null, [accountKey]);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Action for closing the specific data account
|
|
72
|
+
*
|
|
73
|
+
* @param signer
|
|
74
|
+
* @param publicKey
|
|
75
|
+
*/
|
|
76
|
+
CloseDataAccount(signer, publicKey) {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
return new SolanaAction_1.SolanaAction(signer, this.root, yield this.program.methods
|
|
79
|
+
.closeData()
|
|
80
|
+
.accounts({
|
|
81
|
+
signer,
|
|
82
|
+
data: publicKey
|
|
83
|
+
})
|
|
84
|
+
.instruction(), SolanaDataAccount.CUCosts.DATA_REMOVE, yield this.root.Fees.getFeeRate([signer, publicKey]));
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Action for writing data to a data account, writes up to sizeLimit starting from the offset position of the
|
|
89
|
+
* provided writeData buffer
|
|
90
|
+
*
|
|
91
|
+
* @param signer
|
|
92
|
+
* @param accountKey account public key to write to
|
|
93
|
+
* @param writeData buffer holding the write data
|
|
94
|
+
* @param offset data from buffer starting at offset are written
|
|
95
|
+
* @param sizeLimit maximum amount of data to be written to the data account in this action
|
|
96
|
+
* @private
|
|
97
|
+
* @returns {Promise<{bytesWritten: number, action: SolanaAction}>} bytes written to the data account & action
|
|
98
|
+
*/
|
|
99
|
+
WriteData(signer, accountKey, writeData, offset, sizeLimit) {
|
|
100
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
const writeLen = Math.min(writeData.length - offset, sizeLimit);
|
|
102
|
+
return {
|
|
103
|
+
bytesWritten: writeLen,
|
|
104
|
+
action: new SolanaAction_1.SolanaAction(signer, this.root, yield this.program.methods
|
|
105
|
+
.writeData(offset, writeData.slice(offset, offset + writeLen))
|
|
106
|
+
.accounts({
|
|
107
|
+
signer,
|
|
108
|
+
data: accountKey.publicKey
|
|
109
|
+
})
|
|
110
|
+
.instruction(), SolanaDataAccount.CUCosts.DATA_WRITE)
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
constructor(root, storage) {
|
|
115
|
+
super(root);
|
|
116
|
+
this.SwapTxDataAlt = this.root.keypair((reversedTxId, signer) => [Buffer.from(signer.secretKey), reversedTxId]);
|
|
117
|
+
this.SwapTxDataAltBuffer = this.root.keypair((reversedTxId, secret) => [secret, reversedTxId]);
|
|
118
|
+
this.storage = storage;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Saves data account to the storage, the storage is required such that we are able to close the accounts later
|
|
122
|
+
* manually in case the claim doesn't happen (expires due to fees, etc.)
|
|
123
|
+
*
|
|
124
|
+
* @param signer
|
|
125
|
+
* @param publicKey
|
|
126
|
+
* @private
|
|
127
|
+
*/
|
|
128
|
+
saveDataAccount(signer, publicKey) {
|
|
129
|
+
return this.storage.saveData(publicKey.toBase58(), new StoredDataAccount(publicKey, signer));
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Initializes the data account handler, loads the existing data accounts which should be checked and closed
|
|
133
|
+
*/
|
|
134
|
+
init() {
|
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
yield this.storage.init();
|
|
137
|
+
const loadedData = yield this.storage.loadData(StoredDataAccount);
|
|
138
|
+
this.logger.info("init(): initialized & loaded stored data accounts, count: " + loadedData.length);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Removes data account from the list of accounts that should be checked for reclaiming the locked SOL, this should
|
|
143
|
+
* be called after a batch of transactions claiming the swap was confirmed
|
|
144
|
+
*
|
|
145
|
+
* @param publicKey
|
|
146
|
+
*/
|
|
147
|
+
removeDataAccount(publicKey) {
|
|
148
|
+
return this.storage.removeData(publicKey.toBase58());
|
|
149
|
+
}
|
|
150
|
+
getDataAccountsInfo(signer) {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
const closePublicKeys = [];
|
|
153
|
+
let totalLocked = new BN(0);
|
|
154
|
+
for (let key in this.storage.data) {
|
|
155
|
+
const { accountKey, owner } = this.storage.data[key];
|
|
156
|
+
if (!owner.equals(signer))
|
|
157
|
+
continue;
|
|
158
|
+
try {
|
|
159
|
+
const fetchedDataAccount = yield this.connection.getAccountInfo(accountKey);
|
|
160
|
+
if (fetchedDataAccount == null) {
|
|
161
|
+
yield this.removeDataAccount(accountKey);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
closePublicKeys.push(accountKey);
|
|
165
|
+
totalLocked = totalLocked.add(new BN(fetchedDataAccount.lamports));
|
|
166
|
+
}
|
|
167
|
+
catch (e) { }
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
closePublicKeys,
|
|
171
|
+
count: closePublicKeys.length,
|
|
172
|
+
totalValue: totalLocked
|
|
173
|
+
};
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Sweeps all old data accounts, reclaiming the SOL locked in the PDAs
|
|
178
|
+
*/
|
|
179
|
+
sweepDataAccounts(signer) {
|
|
180
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
181
|
+
const { closePublicKeys, totalValue } = yield this.getDataAccountsInfo(signer.getPublicKey());
|
|
182
|
+
if (closePublicKeys.length === 0) {
|
|
183
|
+
this.logger.debug("sweepDataAccounts(): no old data accounts found, no need to close any!");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
this.logger.debug("sweepDataAccounts(): closing old data accounts: ", closePublicKeys);
|
|
187
|
+
let txns = [];
|
|
188
|
+
for (let publicKey of closePublicKeys) {
|
|
189
|
+
yield (yield this.CloseDataAccount(signer.getPublicKey(), publicKey)).addToTxs(txns);
|
|
190
|
+
}
|
|
191
|
+
const result = yield this.root.Transactions.sendAndConfirm(signer, txns, true, null, true);
|
|
192
|
+
this.logger.info("sweepDataAccounts(): old data accounts closed: " +
|
|
193
|
+
closePublicKeys.map(pk => pk.toBase58()).join());
|
|
194
|
+
for (let publicKey of closePublicKeys) {
|
|
195
|
+
yield this.removeDataAccount(publicKey);
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
txIds: result,
|
|
199
|
+
count: closePublicKeys.length,
|
|
200
|
+
totalValue: totalValue
|
|
201
|
+
};
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Adds the transactions writing (and also initializing if it doesn't exist) data to the data account
|
|
206
|
+
*
|
|
207
|
+
* @param signer
|
|
208
|
+
* @param reversedTxId reversed btc tx id is used to derive the data account address
|
|
209
|
+
* @param writeData full data to be written to the data account
|
|
210
|
+
* @param txs solana transactions array, where txns for writing & initializing will be added
|
|
211
|
+
* @param feeRate fee rate to use for the transactions
|
|
212
|
+
*/
|
|
213
|
+
addTxsWriteData(signer, reversedTxId, writeData, txs, feeRate) {
|
|
214
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
215
|
+
let txDataKey;
|
|
216
|
+
let fetchedDataAccount = null;
|
|
217
|
+
if (signer instanceof SolanaSigner_1.SolanaSigner && signer.keypair != null) {
|
|
218
|
+
txDataKey = this.SwapTxDataAlt(reversedTxId, signer.keypair);
|
|
219
|
+
fetchedDataAccount = yield (0, Utils_1.tryWithRetries)(() => this.connection.getAccountInfo(txDataKey.publicKey), this.retryPolicy);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
const secret = randomBytes(32);
|
|
223
|
+
txDataKey = this.SwapTxDataAltBuffer(reversedTxId, secret);
|
|
224
|
+
}
|
|
225
|
+
const signerKey = signer instanceof SolanaSigner_1.SolanaSigner ? signer.getPublicKey() : signer;
|
|
226
|
+
let pointer = 0;
|
|
227
|
+
if (fetchedDataAccount == null) {
|
|
228
|
+
const action = new SolanaAction_1.SolanaAction(signerKey, this.root);
|
|
229
|
+
action.add(yield this.InitDataAccount(signerKey, txDataKey, writeData.length));
|
|
230
|
+
const { bytesWritten, action: writeAction } = yield this.WriteData(signerKey, txDataKey, writeData, pointer, 420);
|
|
231
|
+
this.logger.debug("addTxsWriteData(): Write partial data (" + pointer + " .. " + (pointer + bytesWritten) + ")/" + writeData.length +
|
|
232
|
+
" key: " + txDataKey.publicKey.toBase58());
|
|
233
|
+
pointer += bytesWritten;
|
|
234
|
+
action.add(writeAction);
|
|
235
|
+
yield action.addToTxs(txs, feeRate);
|
|
236
|
+
yield this.saveDataAccount(signerKey, txDataKey.publicKey);
|
|
237
|
+
}
|
|
238
|
+
while (pointer < writeData.length) {
|
|
239
|
+
const { bytesWritten, action } = yield this.WriteData(signerKey, txDataKey, writeData, pointer, 950);
|
|
240
|
+
this.logger.debug("addTxsWriteData(): Write partial data (" + pointer + " .. " + (pointer + bytesWritten) + ")/" + writeData.length +
|
|
241
|
+
" key: " + txDataKey.publicKey.toBase58());
|
|
242
|
+
pointer += bytesWritten;
|
|
243
|
+
yield action.addToTxs(txs, feeRate);
|
|
244
|
+
}
|
|
245
|
+
return txDataKey.publicKey;
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
exports.SolanaDataAccount = SolanaDataAccount;
|
|
250
|
+
SolanaDataAccount.CUCosts = {
|
|
251
|
+
DATA_REMOVE: 50000,
|
|
252
|
+
DATA_CREATE_AND_WRITE: 15000,
|
|
253
|
+
DATA_CREATE: 5000,
|
|
254
|
+
DATA_WRITE: 15000
|
|
255
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { SolanaSwapModule } from "../SolanaSwapModule";
|
|
2
|
+
import * as BN from "bn.js";
|
|
3
|
+
import { PublicKey } from "@solana/web3.js";
|
|
4
|
+
import { SolanaTx } from "../../base/modules/SolanaTransactions";
|
|
5
|
+
import { IntermediaryReputationType } from "@atomiqlabs/base";
|
|
6
|
+
export declare class SolanaLpVault extends SolanaSwapModule {
|
|
7
|
+
private static readonly CUCosts;
|
|
8
|
+
/**
|
|
9
|
+
* Action for withdrawing funds from the LP vault
|
|
10
|
+
*
|
|
11
|
+
* @param signer
|
|
12
|
+
* @param token
|
|
13
|
+
* @param amount
|
|
14
|
+
* @constructor
|
|
15
|
+
* @private
|
|
16
|
+
*/
|
|
17
|
+
private Withdraw;
|
|
18
|
+
/**
|
|
19
|
+
* Action for depositing funds to the LP vault
|
|
20
|
+
*
|
|
21
|
+
* @param signer
|
|
22
|
+
* @param token
|
|
23
|
+
* @param amount
|
|
24
|
+
* @constructor
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
private Deposit;
|
|
28
|
+
/**
|
|
29
|
+
* Returns intermediary's reputation & vault balance for a specific token
|
|
30
|
+
*
|
|
31
|
+
* @param address
|
|
32
|
+
* @param token
|
|
33
|
+
*/
|
|
34
|
+
getIntermediaryData(address: PublicKey, token: PublicKey): Promise<{
|
|
35
|
+
balance: BN;
|
|
36
|
+
reputation: IntermediaryReputationType;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Returns intermediary's reputation for a specific token
|
|
40
|
+
*
|
|
41
|
+
* @param address
|
|
42
|
+
* @param token
|
|
43
|
+
*/
|
|
44
|
+
getIntermediaryReputation(address: PublicKey, token: PublicKey): Promise<IntermediaryReputationType>;
|
|
45
|
+
/**
|
|
46
|
+
* Returns the balance of the token an intermediary has in his LP vault
|
|
47
|
+
*
|
|
48
|
+
* @param address
|
|
49
|
+
* @param token
|
|
50
|
+
*/
|
|
51
|
+
getIntermediaryBalance(address: PublicKey, token: PublicKey): Promise<BN>;
|
|
52
|
+
/**
|
|
53
|
+
* Creates transactions for withdrawing funds from the LP vault, creates ATA if it doesn't exist and unwraps
|
|
54
|
+
* WSOL to SOL if required
|
|
55
|
+
*
|
|
56
|
+
* @param signer
|
|
57
|
+
* @param token
|
|
58
|
+
* @param amount
|
|
59
|
+
* @param feeRate
|
|
60
|
+
*/
|
|
61
|
+
txsWithdraw(signer: PublicKey, token: PublicKey, amount: BN, feeRate?: string): Promise<SolanaTx[]>;
|
|
62
|
+
/**
|
|
63
|
+
* Creates transaction for depositing funds into the LP vault, wraps SOL to WSOL if required
|
|
64
|
+
*
|
|
65
|
+
* @param signer
|
|
66
|
+
* @param token
|
|
67
|
+
* @param amount
|
|
68
|
+
* @param feeRate
|
|
69
|
+
*/
|
|
70
|
+
txsDeposit(signer: PublicKey, token: PublicKey, amount: BN, feeRate?: string): Promise<SolanaTx[]>;
|
|
71
|
+
getFeeRate(signer: PublicKey, token: PublicKey): Promise<string>;
|
|
72
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SolanaLpVault = void 0;
|
|
13
|
+
const SolanaSwapModule_1 = require("../SolanaSwapModule");
|
|
14
|
+
const SolanaAction_1 = require("../../base/SolanaAction");
|
|
15
|
+
const BN = require("bn.js");
|
|
16
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
17
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
18
|
+
const Utils_1 = require("../../../utils/Utils");
|
|
19
|
+
class SolanaLpVault extends SolanaSwapModule_1.SolanaSwapModule {
|
|
20
|
+
/**
|
|
21
|
+
* Action for withdrawing funds from the LP vault
|
|
22
|
+
*
|
|
23
|
+
* @param signer
|
|
24
|
+
* @param token
|
|
25
|
+
* @param amount
|
|
26
|
+
* @constructor
|
|
27
|
+
* @private
|
|
28
|
+
*/
|
|
29
|
+
Withdraw(signer, token, amount) {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(token, signer);
|
|
32
|
+
return new SolanaAction_1.SolanaAction(signer, this.root, yield this.program.methods
|
|
33
|
+
.withdraw(new BN(amount))
|
|
34
|
+
.accounts({
|
|
35
|
+
signer,
|
|
36
|
+
signerAta: ata,
|
|
37
|
+
userData: this.root.SwapUserVault(signer, token),
|
|
38
|
+
vault: this.root.SwapVault(token),
|
|
39
|
+
vaultAuthority: this.root.SwapVaultAuthority,
|
|
40
|
+
mint: token,
|
|
41
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID
|
|
42
|
+
})
|
|
43
|
+
.instruction(), SolanaLpVault.CUCosts.WITHDRAW);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Action for depositing funds to the LP vault
|
|
48
|
+
*
|
|
49
|
+
* @param signer
|
|
50
|
+
* @param token
|
|
51
|
+
* @param amount
|
|
52
|
+
* @constructor
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
55
|
+
Deposit(signer, token, amount) {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(token, signer);
|
|
58
|
+
return new SolanaAction_1.SolanaAction(signer, this.root, yield this.program.methods
|
|
59
|
+
.deposit(new BN(amount))
|
|
60
|
+
.accounts({
|
|
61
|
+
signer,
|
|
62
|
+
signerAta: ata,
|
|
63
|
+
userData: this.root.SwapUserVault(signer, token),
|
|
64
|
+
vault: this.root.SwapVault(token),
|
|
65
|
+
vaultAuthority: this.root.SwapVaultAuthority,
|
|
66
|
+
mint: token,
|
|
67
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
68
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID
|
|
69
|
+
})
|
|
70
|
+
.instruction(), SolanaLpVault.CUCosts.DEPOSIT);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Returns intermediary's reputation & vault balance for a specific token
|
|
75
|
+
*
|
|
76
|
+
* @param address
|
|
77
|
+
* @param token
|
|
78
|
+
*/
|
|
79
|
+
getIntermediaryData(address, token) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
const data = yield this.program.account.userAccount.fetchNullable(this.root.SwapUserVault(address, token));
|
|
82
|
+
if (data == null)
|
|
83
|
+
return null;
|
|
84
|
+
const response = [];
|
|
85
|
+
for (let i = 0; i < data.successVolume.length; i++) {
|
|
86
|
+
response[i] = {
|
|
87
|
+
successVolume: data.successVolume[i],
|
|
88
|
+
successCount: data.successCount[i],
|
|
89
|
+
failVolume: data.failVolume[i],
|
|
90
|
+
failCount: data.failCount[i],
|
|
91
|
+
coopCloseVolume: data.coopCloseVolume[i],
|
|
92
|
+
coopCloseCount: data.coopCloseCount[i]
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
balance: data.amount,
|
|
97
|
+
reputation: response
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Returns intermediary's reputation for a specific token
|
|
103
|
+
*
|
|
104
|
+
* @param address
|
|
105
|
+
* @param token
|
|
106
|
+
*/
|
|
107
|
+
getIntermediaryReputation(address, token) {
|
|
108
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
109
|
+
const intermediaryData = yield this.getIntermediaryData(address, token);
|
|
110
|
+
return intermediaryData === null || intermediaryData === void 0 ? void 0 : intermediaryData.reputation;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Returns the balance of the token an intermediary has in his LP vault
|
|
115
|
+
*
|
|
116
|
+
* @param address
|
|
117
|
+
* @param token
|
|
118
|
+
*/
|
|
119
|
+
getIntermediaryBalance(address, token) {
|
|
120
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
121
|
+
const intermediaryData = yield this.getIntermediaryData(address, token);
|
|
122
|
+
const balance = intermediaryData === null || intermediaryData === void 0 ? void 0 : intermediaryData.balance;
|
|
123
|
+
this.logger.debug("getIntermediaryBalance(): token LP balance fetched, token: " + token.toString() +
|
|
124
|
+
" address: " + address + " amount: " + (balance == null ? "null" : balance.toString()));
|
|
125
|
+
return intermediaryData === null || intermediaryData === void 0 ? void 0 : intermediaryData.balance;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Creates transactions for withdrawing funds from the LP vault, creates ATA if it doesn't exist and unwraps
|
|
130
|
+
* WSOL to SOL if required
|
|
131
|
+
*
|
|
132
|
+
* @param signer
|
|
133
|
+
* @param token
|
|
134
|
+
* @param amount
|
|
135
|
+
* @param feeRate
|
|
136
|
+
*/
|
|
137
|
+
txsWithdraw(signer, token, amount, feeRate) {
|
|
138
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
139
|
+
const ata = yield (0, spl_token_1.getAssociatedTokenAddress)(token, signer);
|
|
140
|
+
feeRate = feeRate || (yield this.getFeeRate(signer, token));
|
|
141
|
+
const action = new SolanaAction_1.SolanaAction(signer, this.root);
|
|
142
|
+
if (!(yield this.root.Tokens.ataExists(ata))) {
|
|
143
|
+
action.add(this.root.Tokens.InitAta(signer, signer, token));
|
|
144
|
+
}
|
|
145
|
+
action.add(yield this.Withdraw(signer, token, amount));
|
|
146
|
+
const shouldUnwrap = token.equals(this.root.Tokens.WSOL_ADDRESS);
|
|
147
|
+
if (shouldUnwrap)
|
|
148
|
+
action.add(this.root.Tokens.Unwrap(signer));
|
|
149
|
+
this.logger.debug("txsWithdraw(): withdraw TX created, token: " + token.toString() +
|
|
150
|
+
" amount: " + amount.toString(10) + " unwrapping: " + shouldUnwrap);
|
|
151
|
+
return [yield action.tx(feeRate)];
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Creates transaction for depositing funds into the LP vault, wraps SOL to WSOL if required
|
|
156
|
+
*
|
|
157
|
+
* @param signer
|
|
158
|
+
* @param token
|
|
159
|
+
* @param amount
|
|
160
|
+
* @param feeRate
|
|
161
|
+
*/
|
|
162
|
+
txsDeposit(signer, token, amount, feeRate) {
|
|
163
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
164
|
+
const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(token, signer);
|
|
165
|
+
feeRate = feeRate || (yield this.getFeeRate(signer, token));
|
|
166
|
+
const action = new SolanaAction_1.SolanaAction(signer, this.root);
|
|
167
|
+
let wrapping = false;
|
|
168
|
+
if (token.equals(this.root.Tokens.WSOL_ADDRESS)) {
|
|
169
|
+
const account = yield (0, Utils_1.tryWithRetries)(() => this.root.Tokens.getATAOrNull(ata), this.retryPolicy);
|
|
170
|
+
let balance = account == null ? new BN(0) : new BN(account.amount.toString());
|
|
171
|
+
if (balance.lt(amount)) {
|
|
172
|
+
action.add(this.root.Tokens.Wrap(signer, amount.sub(balance), account == null));
|
|
173
|
+
wrapping = true;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
action.addAction(yield this.Deposit(signer, token, amount));
|
|
177
|
+
this.logger.debug("txsDeposit(): deposit TX created, token: " + token.toString() +
|
|
178
|
+
" amount: " + amount.toString(10) + " wrapping: " + wrapping);
|
|
179
|
+
return [yield action.tx(feeRate)];
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
getFeeRate(signer, token) {
|
|
183
|
+
const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(token, signer);
|
|
184
|
+
return this.root.Fees.getFeeRate([
|
|
185
|
+
signer,
|
|
186
|
+
ata,
|
|
187
|
+
this.root.SwapUserVault(signer, token),
|
|
188
|
+
this.root.SwapVault(token)
|
|
189
|
+
]);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
exports.SolanaLpVault = SolanaLpVault;
|
|
193
|
+
SolanaLpVault.CUCosts = {
|
|
194
|
+
WITHDRAW: 50000,
|
|
195
|
+
DEPOSIT: 50000
|
|
196
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { SolanaSwapModule } from "../SolanaSwapModule";
|
|
2
|
+
import { SolanaSwapData } from "../SolanaSwapData";
|
|
3
|
+
import { RelaySynchronizer } from "@atomiqlabs/base";
|
|
4
|
+
import { PublicKey } from "@solana/web3.js";
|
|
5
|
+
import { SolanaTx } from "../../base/modules/SolanaTransactions";
|
|
6
|
+
import { SolanaBtcStoredHeader } from "../../btcrelay/headers/SolanaBtcStoredHeader";
|
|
7
|
+
import { SolanaBtcRelay } from "../../btcrelay/SolanaBtcRelay";
|
|
8
|
+
import { SolanaSwapProgram } from "../SolanaSwapProgram";
|
|
9
|
+
import * as BN from "bn.js";
|
|
10
|
+
import { SolanaSigner } from "../../wallet/SolanaSigner";
|
|
11
|
+
export declare class SwapClaim extends SolanaSwapModule {
|
|
12
|
+
private static readonly CUCosts;
|
|
13
|
+
readonly btcRelay: SolanaBtcRelay<any>;
|
|
14
|
+
/**
|
|
15
|
+
* Claim action which uses the provided hex encoded secret for claiming the swap
|
|
16
|
+
*
|
|
17
|
+
* @param signer
|
|
18
|
+
* @param swapData
|
|
19
|
+
* @param secret
|
|
20
|
+
* @constructor
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
private Claim;
|
|
24
|
+
/**
|
|
25
|
+
* Verify and claim action required for BTC on-chain swaps verified through btc relay, adds the btc relay verify
|
|
26
|
+
* instruction to the 0th index in the transaction, also intentionally sets compute budget to null such that no
|
|
27
|
+
* compute budget instruction is added, since that takes up too much space and txs are limited to 1232 bytes
|
|
28
|
+
*
|
|
29
|
+
* @param signer
|
|
30
|
+
* @param swapData
|
|
31
|
+
* @param storeDataKey
|
|
32
|
+
* @param merkleProof
|
|
33
|
+
* @param commitedHeader
|
|
34
|
+
* @constructor
|
|
35
|
+
* @private
|
|
36
|
+
*/
|
|
37
|
+
private VerifyAndClaim;
|
|
38
|
+
constructor(root: SolanaSwapProgram, btcRelay: SolanaBtcRelay<any>);
|
|
39
|
+
/**
|
|
40
|
+
* Gets the compute budget required for claiming the swap
|
|
41
|
+
*
|
|
42
|
+
* @param swapData
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
private getComputeBudget;
|
|
46
|
+
/**
|
|
47
|
+
* Gets committed header, identified by blockhash & blockheight, determines required BTC relay blockheight based on
|
|
48
|
+
* requiredConfirmations
|
|
49
|
+
* If synchronizer is passed & blockhash is not found, it produces transactions to sync up the btc relay to the
|
|
50
|
+
* current chain tip & adds them to the txs array
|
|
51
|
+
*
|
|
52
|
+
* @param signer
|
|
53
|
+
* @param txBlockheight transaction blockheight
|
|
54
|
+
* @param requiredConfirmations required confirmation for the swap to be claimable with that TX
|
|
55
|
+
* @param blockhash blockhash of the block which includes the transaction
|
|
56
|
+
* @param txs solana transaction array, in case we need to synchronize the btc relay ourselves the synchronization
|
|
57
|
+
* txns are added here
|
|
58
|
+
* @param synchronizer optional synchronizer to use to synchronize the btc relay in case it is not yet synchronized
|
|
59
|
+
* to the required blockheight
|
|
60
|
+
* @private
|
|
61
|
+
*/
|
|
62
|
+
private getCommitedHeaderAndSynchronize;
|
|
63
|
+
/**
|
|
64
|
+
* Adds the transactions required for initialization and writing of transaction data to the data account
|
|
65
|
+
*
|
|
66
|
+
* @param signer
|
|
67
|
+
* @param tx transaction to be written
|
|
68
|
+
* @param vout vout of the transaction to use to satisfy swap conditions
|
|
69
|
+
* @param feeRate fee rate for the transactions
|
|
70
|
+
* @param txs solana transaction array, init & write transactions are added here
|
|
71
|
+
* @private
|
|
72
|
+
* @returns {Promise<PublicKey>} publicKey/address of the data account
|
|
73
|
+
*/
|
|
74
|
+
private addTxsWriteTransactionData;
|
|
75
|
+
/**
|
|
76
|
+
* Checks whether we should unwrap the WSOL to SOL when claiming the swap
|
|
77
|
+
*
|
|
78
|
+
* @param signer
|
|
79
|
+
* @param swapData
|
|
80
|
+
* @private
|
|
81
|
+
*/
|
|
82
|
+
private shouldUnwrap;
|
|
83
|
+
/**
|
|
84
|
+
* Creates transactions claiming the swap using a secret (for HTLC swaps)
|
|
85
|
+
*
|
|
86
|
+
* @param signer
|
|
87
|
+
* @param swapData swap to claim
|
|
88
|
+
* @param secret hex encoded secret pre-image to the HTLC hash
|
|
89
|
+
* @param checkExpiry whether to check if the swap is already expired (trying to claim an expired swap with a secret
|
|
90
|
+
* is dangerous because we might end up revealing the secret to the counterparty without being able to claim the swap)
|
|
91
|
+
* @param initAta whether to init the claimer's ATA if it doesn't exist
|
|
92
|
+
* @param feeRate fee rate to use for the transaction
|
|
93
|
+
* @param skipAtaCheck whether to check if ATA exists
|
|
94
|
+
*/
|
|
95
|
+
txsClaimWithSecret(signer: PublicKey, swapData: SolanaSwapData, secret: string, checkExpiry?: boolean, initAta?: boolean, feeRate?: string, skipAtaCheck?: boolean): Promise<SolanaTx[]>;
|
|
96
|
+
/**
|
|
97
|
+
* Creates transaction claiming the swap using a confirmed transaction data (for BTC on-chain swaps)
|
|
98
|
+
*
|
|
99
|
+
* @param signer
|
|
100
|
+
* @param swapData swap to claim
|
|
101
|
+
* @param blockheight blockheight of the bitcoin transaction
|
|
102
|
+
* @param tx bitcoin transaction that satisfies the swap condition
|
|
103
|
+
* @param vout vout of the bitcoin transaction that satisfies the swap condition
|
|
104
|
+
* @param commitedHeader commited header data from btc relay (fetched internally if null)
|
|
105
|
+
* @param synchronizer optional synchronizer to use in case we need to sync up the btc relay ourselves
|
|
106
|
+
* @param initAta whether to initialize claimer's ATA
|
|
107
|
+
* @param storageAccHolder an object holder filled in with the created data account where tx data is written
|
|
108
|
+
* @param feeRate fee rate to be used for the transactions
|
|
109
|
+
*/
|
|
110
|
+
txsClaimWithTxData(signer: PublicKey | SolanaSigner, swapData: SolanaSwapData, blockheight: number, tx: {
|
|
111
|
+
blockhash: string;
|
|
112
|
+
confirmations: number;
|
|
113
|
+
txid: string;
|
|
114
|
+
hex: string;
|
|
115
|
+
}, vout: number, commitedHeader?: SolanaBtcStoredHeader, synchronizer?: RelaySynchronizer<any, SolanaTx, any>, initAta?: boolean, storageAccHolder?: {
|
|
116
|
+
storageAcc: PublicKey;
|
|
117
|
+
}, feeRate?: string): Promise<SolanaTx[] | null>;
|
|
118
|
+
getClaimFeeRate(signer: PublicKey, swapData: SolanaSwapData): Promise<string>;
|
|
119
|
+
/**
|
|
120
|
+
* Get the estimated solana transaction fee of the claim transaction, this fee might be negative since it
|
|
121
|
+
* includes the rebate for closing the swap PDA
|
|
122
|
+
*/
|
|
123
|
+
getClaimFee(signer: PublicKey, swapData: SolanaSwapData, feeRate?: string): Promise<BN>;
|
|
124
|
+
/**
|
|
125
|
+
* Get the estimated solana transaction fee of the claim transaction in the worst case scenario in case where the
|
|
126
|
+
* ATA needs to be initialized again (i.e. adding the ATA rent exempt lamports to the fee)
|
|
127
|
+
*/
|
|
128
|
+
getRawClaimFee(signer: PublicKey, swapData: SolanaSwapData, feeRate?: string): Promise<BN>;
|
|
129
|
+
}
|