@atomiqlabs/chain-solana 12.0.11 → 12.0.13
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/dist/index.d.ts +29 -29
- package/dist/index.js +45 -45
- package/dist/solana/SolanaChainType.d.ts +11 -11
- package/dist/solana/SolanaChainType.js +2 -2
- package/dist/solana/SolanaChains.d.ts +20 -20
- package/dist/solana/SolanaChains.js +25 -25
- package/dist/solana/SolanaInitializer.d.ts +18 -18
- package/dist/solana/SolanaInitializer.js +63 -63
- package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +228 -228
- package/dist/solana/btcrelay/SolanaBtcRelay.js +441 -441
- package/dist/solana/btcrelay/headers/SolanaBtcHeader.d.ts +29 -29
- package/dist/solana/btcrelay/headers/SolanaBtcHeader.js +34 -34
- package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.d.ts +46 -46
- package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.js +78 -78
- package/dist/solana/btcrelay/program/programIdl.json +671 -671
- package/dist/solana/chain/SolanaAction.d.ts +26 -26
- package/dist/solana/chain/SolanaAction.js +86 -86
- package/dist/solana/chain/SolanaChainInterface.d.ts +65 -65
- package/dist/solana/chain/SolanaChainInterface.js +125 -125
- 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 +28 -28
- package/dist/solana/chain/modules/SolanaBlocks.js +72 -72
- package/dist/solana/chain/modules/SolanaEvents.d.ts +68 -68
- package/dist/solana/chain/modules/SolanaEvents.js +225 -225
- package/dist/solana/chain/modules/SolanaFees.d.ts +121 -121
- package/dist/solana/chain/modules/SolanaFees.js +379 -379
- package/dist/solana/chain/modules/SolanaSignatures.d.ts +23 -23
- package/dist/solana/chain/modules/SolanaSignatures.js +39 -39
- package/dist/solana/chain/modules/SolanaSlots.d.ts +31 -31
- package/dist/solana/chain/modules/SolanaSlots.js +68 -68
- package/dist/solana/chain/modules/SolanaTokens.d.ts +136 -136
- package/dist/solana/chain/modules/SolanaTokens.js +248 -248
- package/dist/solana/chain/modules/SolanaTransactions.d.ts +124 -124
- package/dist/solana/chain/modules/SolanaTransactions.js +323 -323
- package/dist/solana/events/SolanaChainEvents.d.ts +88 -88
- package/dist/solana/events/SolanaChainEvents.js +256 -256
- package/dist/solana/events/SolanaChainEventsBrowser.d.ts +75 -75
- package/dist/solana/events/SolanaChainEventsBrowser.js +172 -172
- package/dist/solana/program/SolanaProgramBase.d.ts +40 -40
- package/dist/solana/program/SolanaProgramBase.js +43 -43
- 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 +114 -114
- package/dist/solana/swaps/SolanaSwapData.d.ts +71 -71
- package/dist/solana/swaps/SolanaSwapData.js +292 -292
- package/dist/solana/swaps/SolanaSwapModule.d.ts +10 -10
- package/dist/solana/swaps/SolanaSwapModule.js +11 -11
- package/dist/solana/swaps/SolanaSwapProgram.d.ts +224 -224
- package/dist/solana/swaps/SolanaSwapProgram.js +570 -567
- package/dist/solana/swaps/SwapTypeEnum.d.ts +11 -11
- package/dist/solana/swaps/SwapTypeEnum.js +42 -42
- package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +94 -94
- package/dist/solana/swaps/modules/SolanaDataAccount.js +231 -231
- package/dist/solana/swaps/modules/SolanaLpVault.d.ts +71 -71
- package/dist/solana/swaps/modules/SolanaLpVault.js +173 -173
- package/dist/solana/swaps/modules/SwapClaim.d.ts +129 -129
- package/dist/solana/swaps/modules/SwapClaim.js +291 -291
- package/dist/solana/swaps/modules/SwapInit.d.ts +217 -217
- package/dist/solana/swaps/modules/SwapInit.js +519 -519
- package/dist/solana/swaps/modules/SwapRefund.d.ts +82 -82
- package/dist/solana/swaps/modules/SwapRefund.js +262 -262
- 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/wallet/SolanaKeypairWallet.d.ts +9 -9
- package/dist/solana/wallet/SolanaKeypairWallet.js +33 -33
- package/dist/solana/wallet/SolanaSigner.d.ts +11 -11
- package/dist/solana/wallet/SolanaSigner.js +17 -17
- package/dist/utils/Utils.d.ts +53 -53
- package/dist/utils/Utils.js +170 -170
- package/package.json +41 -41
- package/src/index.ts +36 -36
- package/src/solana/SolanaChainType.ts +27 -27
- package/src/solana/SolanaChains.ts +23 -23
- package/src/solana/SolanaInitializer.ts +102 -102
- package/src/solana/btcrelay/SolanaBtcRelay.ts +589 -589
- package/src/solana/btcrelay/headers/SolanaBtcHeader.ts +57 -57
- package/src/solana/btcrelay/headers/SolanaBtcStoredHeader.ts +102 -102
- package/src/solana/btcrelay/program/programIdl.json +670 -670
- package/src/solana/chain/SolanaAction.ts +108 -108
- package/src/solana/chain/SolanaChainInterface.ts +192 -192
- package/src/solana/chain/SolanaModule.ts +20 -20
- package/src/solana/chain/modules/SolanaAddresses.ts +20 -20
- package/src/solana/chain/modules/SolanaBlocks.ts +78 -78
- package/src/solana/chain/modules/SolanaEvents.ts +256 -256
- package/src/solana/chain/modules/SolanaFees.ts +450 -450
- package/src/solana/chain/modules/SolanaSignatures.ts +39 -39
- package/src/solana/chain/modules/SolanaSlots.ts +82 -82
- package/src/solana/chain/modules/SolanaTokens.ts +307 -307
- package/src/solana/chain/modules/SolanaTransactions.ts +365 -365
- package/src/solana/events/SolanaChainEvents.ts +299 -299
- package/src/solana/events/SolanaChainEventsBrowser.ts +209 -209
- package/src/solana/program/SolanaProgramBase.ts +79 -79
- package/src/solana/program/SolanaProgramModule.ts +15 -15
- package/src/solana/program/modules/SolanaProgramEvents.ts +155 -155
- package/src/solana/swaps/SolanaSwapData.ts +430 -430
- package/src/solana/swaps/SolanaSwapModule.ts +16 -16
- package/src/solana/swaps/SolanaSwapProgram.ts +854 -849
- package/src/solana/swaps/SwapTypeEnum.ts +29 -29
- package/src/solana/swaps/modules/SolanaDataAccount.ts +307 -307
- package/src/solana/swaps/modules/SolanaLpVault.ts +215 -215
- package/src/solana/swaps/modules/SwapClaim.ts +389 -389
- package/src/solana/swaps/modules/SwapInit.ts +663 -663
- package/src/solana/swaps/modules/SwapRefund.ts +323 -323
- package/src/solana/swaps/programIdl.json +944 -944
- package/src/solana/swaps/programTypes.ts +1885 -1885
- package/src/solana/wallet/SolanaKeypairWallet.ts +36 -36
- package/src/solana/wallet/SolanaSigner.ts +24 -24
- package/src/utils/Utils.ts +180 -180
|
@@ -1,231 +1,231 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SolanaDataAccount = exports.StoredDataAccount = void 0;
|
|
4
|
-
const SolanaSwapModule_1 = require("../SolanaSwapModule");
|
|
5
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
-
const SolanaAction_1 = require("../../chain/SolanaAction");
|
|
7
|
-
const Utils_1 = require("../../../utils/Utils");
|
|
8
|
-
const SolanaSigner_1 = require("../../wallet/SolanaSigner");
|
|
9
|
-
const utils_1 = require("@noble/hashes/utils");
|
|
10
|
-
class StoredDataAccount {
|
|
11
|
-
constructor(accountKeyOrData, owner) {
|
|
12
|
-
if (accountKeyOrData instanceof web3_js_1.PublicKey) {
|
|
13
|
-
this.accountKey = accountKeyOrData;
|
|
14
|
-
this.owner = owner;
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
this.accountKey = new web3_js_1.PublicKey(accountKeyOrData.accountKey);
|
|
18
|
-
this.owner = new web3_js_1.PublicKey(accountKeyOrData.owner);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
serialize() {
|
|
22
|
-
return {
|
|
23
|
-
accountKey: this.accountKey.toBase58(),
|
|
24
|
-
owner: this.owner.toBase58()
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
exports.StoredDataAccount = StoredDataAccount;
|
|
29
|
-
class SolanaDataAccount extends SolanaSwapModule_1.SolanaSwapModule {
|
|
30
|
-
/**
|
|
31
|
-
* Action for initialization of the data account
|
|
32
|
-
*
|
|
33
|
-
* @param signer
|
|
34
|
-
* @param accountKey
|
|
35
|
-
* @param dataLength
|
|
36
|
-
* @private
|
|
37
|
-
*/
|
|
38
|
-
async InitDataAccount(signer, accountKey, dataLength) {
|
|
39
|
-
const accountSize = 32 + dataLength;
|
|
40
|
-
const lamportsDeposit = await (0, Utils_1.tryWithRetries)(() => this.connection.getMinimumBalanceForRentExemption(accountSize), this.retryPolicy);
|
|
41
|
-
return new SolanaAction_1.SolanaAction(signer, this.root, [
|
|
42
|
-
web3_js_1.SystemProgram.createAccount({
|
|
43
|
-
fromPubkey: signer,
|
|
44
|
-
newAccountPubkey: accountKey.publicKey,
|
|
45
|
-
lamports: lamportsDeposit,
|
|
46
|
-
space: accountSize,
|
|
47
|
-
programId: this.swapProgram.programId
|
|
48
|
-
}),
|
|
49
|
-
await this.swapProgram.methods
|
|
50
|
-
.initData()
|
|
51
|
-
.accounts({
|
|
52
|
-
signer,
|
|
53
|
-
data: accountKey.publicKey
|
|
54
|
-
})
|
|
55
|
-
.instruction(),
|
|
56
|
-
], SolanaDataAccount.CUCosts.DATA_CREATE, null, [accountKey]);
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Action for closing the specific data account
|
|
60
|
-
*
|
|
61
|
-
* @param signer
|
|
62
|
-
* @param publicKey
|
|
63
|
-
*/
|
|
64
|
-
async CloseDataAccount(signer, publicKey) {
|
|
65
|
-
return new SolanaAction_1.SolanaAction(signer, this.root, await this.swapProgram.methods
|
|
66
|
-
.closeData()
|
|
67
|
-
.accounts({
|
|
68
|
-
signer,
|
|
69
|
-
data: publicKey
|
|
70
|
-
})
|
|
71
|
-
.instruction(), SolanaDataAccount.CUCosts.DATA_REMOVE, await this.root.Fees.getFeeRate([signer, publicKey]));
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Action for writing data to a data account, writes up to sizeLimit starting from the offset position of the
|
|
75
|
-
* provided writeData buffer
|
|
76
|
-
*
|
|
77
|
-
* @param signer
|
|
78
|
-
* @param accountKey account public key to write to
|
|
79
|
-
* @param writeData buffer holding the write data
|
|
80
|
-
* @param offset data from buffer starting at offset are written
|
|
81
|
-
* @param sizeLimit maximum amount of data to be written to the data account in this action
|
|
82
|
-
* @private
|
|
83
|
-
* @returns {Promise<{bytesWritten: number, action: SolanaAction}>} bytes written to the data account & action
|
|
84
|
-
*/
|
|
85
|
-
async WriteData(signer, accountKey, writeData, offset, sizeLimit) {
|
|
86
|
-
const writeLen = Math.min(writeData.length - offset, sizeLimit);
|
|
87
|
-
return {
|
|
88
|
-
bytesWritten: writeLen,
|
|
89
|
-
action: new SolanaAction_1.SolanaAction(signer, this.root, await this.swapProgram.methods
|
|
90
|
-
.writeData(offset, writeData.slice(offset, offset + writeLen))
|
|
91
|
-
.accounts({
|
|
92
|
-
signer,
|
|
93
|
-
data: accountKey.publicKey
|
|
94
|
-
})
|
|
95
|
-
.instruction(), SolanaDataAccount.CUCosts.DATA_WRITE)
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
constructor(chainInterface, program, storage) {
|
|
99
|
-
super(chainInterface, program);
|
|
100
|
-
this.SwapTxDataAlt = this.program.keypair((reversedTxId, signer) => [Buffer.from(signer.secretKey), reversedTxId]);
|
|
101
|
-
this.SwapTxDataAltBuffer = this.program.keypair((reversedTxId, secret) => [secret, reversedTxId]);
|
|
102
|
-
this.storage = storage;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Saves data account to the storage, the storage is required such that we are able to close the accounts later
|
|
106
|
-
* manually in case the claim doesn't happen (expires due to fees, etc.)
|
|
107
|
-
*
|
|
108
|
-
* @param signer
|
|
109
|
-
* @param publicKey
|
|
110
|
-
* @private
|
|
111
|
-
*/
|
|
112
|
-
saveDataAccount(signer, publicKey) {
|
|
113
|
-
return this.storage.saveData(publicKey.toBase58(), new StoredDataAccount(publicKey, signer));
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Initializes the data account handler, loads the existing data accounts which should be checked and closed
|
|
117
|
-
*/
|
|
118
|
-
async init() {
|
|
119
|
-
await this.storage.init();
|
|
120
|
-
const loadedData = await this.storage.loadData(StoredDataAccount);
|
|
121
|
-
this.logger.info("init(): initialized & loaded stored data accounts, count: " + loadedData.length);
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Removes data account from the list of accounts that should be checked for reclaiming the locked SOL, this should
|
|
125
|
-
* be called after a batch of transactions claiming the swap was confirmed
|
|
126
|
-
*
|
|
127
|
-
* @param publicKey
|
|
128
|
-
*/
|
|
129
|
-
removeDataAccount(publicKey) {
|
|
130
|
-
return this.storage.removeData(publicKey.toBase58());
|
|
131
|
-
}
|
|
132
|
-
async getDataAccountsInfo(signer) {
|
|
133
|
-
const closePublicKeys = [];
|
|
134
|
-
let totalLocked = 0n;
|
|
135
|
-
for (let key in this.storage.data) {
|
|
136
|
-
const { accountKey, owner } = this.storage.data[key];
|
|
137
|
-
if (!owner.equals(signer))
|
|
138
|
-
continue;
|
|
139
|
-
try {
|
|
140
|
-
const fetchedDataAccount = await this.connection.getAccountInfo(accountKey);
|
|
141
|
-
if (fetchedDataAccount == null) {
|
|
142
|
-
await this.removeDataAccount(accountKey);
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
closePublicKeys.push(accountKey);
|
|
146
|
-
totalLocked += BigInt(fetchedDataAccount.lamports);
|
|
147
|
-
}
|
|
148
|
-
catch (e) { }
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
closePublicKeys,
|
|
152
|
-
count: closePublicKeys.length,
|
|
153
|
-
totalValue: totalLocked
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Sweeps all old data accounts, reclaiming the SOL locked in the PDAs
|
|
158
|
-
*/
|
|
159
|
-
async sweepDataAccounts(signer) {
|
|
160
|
-
const { closePublicKeys, totalValue } = await this.getDataAccountsInfo(signer.getPublicKey());
|
|
161
|
-
if (closePublicKeys.length === 0) {
|
|
162
|
-
this.logger.debug("sweepDataAccounts(): no old data accounts found, no need to close any!");
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
this.logger.debug("sweepDataAccounts(): closing old data accounts: ", closePublicKeys);
|
|
166
|
-
let txns = [];
|
|
167
|
-
for (let publicKey of closePublicKeys) {
|
|
168
|
-
await (await this.CloseDataAccount(signer.getPublicKey(), publicKey)).addToTxs(txns);
|
|
169
|
-
}
|
|
170
|
-
const result = await this.root.Transactions.sendAndConfirm(signer, txns, true, null, true);
|
|
171
|
-
this.logger.info("sweepDataAccounts(): old data accounts closed: " +
|
|
172
|
-
closePublicKeys.map(pk => pk.toBase58()).join());
|
|
173
|
-
for (let publicKey of closePublicKeys) {
|
|
174
|
-
await this.removeDataAccount(publicKey);
|
|
175
|
-
}
|
|
176
|
-
return {
|
|
177
|
-
txIds: result,
|
|
178
|
-
count: closePublicKeys.length,
|
|
179
|
-
totalValue: totalValue
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Adds the transactions writing (and also initializing if it doesn't exist) data to the data account
|
|
184
|
-
*
|
|
185
|
-
* @param signer
|
|
186
|
-
* @param reversedTxId reversed btc tx id is used to derive the data account address
|
|
187
|
-
* @param writeData full data to be written to the data account
|
|
188
|
-
* @param txs solana transactions array, where txns for writing & initializing will be added
|
|
189
|
-
* @param feeRate fee rate to use for the transactions
|
|
190
|
-
*/
|
|
191
|
-
async addTxsWriteData(signer, reversedTxId, writeData, txs, feeRate) {
|
|
192
|
-
let txDataKey;
|
|
193
|
-
let fetchedDataAccount = null;
|
|
194
|
-
if (signer instanceof SolanaSigner_1.SolanaSigner && signer.keypair != null) {
|
|
195
|
-
txDataKey = this.SwapTxDataAlt(reversedTxId, signer.keypair);
|
|
196
|
-
fetchedDataAccount = await (0, Utils_1.tryWithRetries)(() => this.connection.getAccountInfo(txDataKey.publicKey), this.retryPolicy);
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
const secret = Buffer.from((0, utils_1.randomBytes)(32));
|
|
200
|
-
txDataKey = this.SwapTxDataAltBuffer(reversedTxId, secret);
|
|
201
|
-
}
|
|
202
|
-
const signerKey = signer instanceof SolanaSigner_1.SolanaSigner ? signer.getPublicKey() : signer;
|
|
203
|
-
let pointer = 0;
|
|
204
|
-
if (fetchedDataAccount == null) {
|
|
205
|
-
const action = new SolanaAction_1.SolanaAction(signerKey, this.root);
|
|
206
|
-
action.add(await this.InitDataAccount(signerKey, txDataKey, writeData.length));
|
|
207
|
-
const { bytesWritten, action: writeAction } = await this.WriteData(signerKey, txDataKey, writeData, pointer, 420);
|
|
208
|
-
this.logger.debug("addTxsWriteData(): Write partial data (" + pointer + " .. " + (pointer + bytesWritten) + ")/" + writeData.length +
|
|
209
|
-
" key: " + txDataKey.publicKey.toBase58());
|
|
210
|
-
pointer += bytesWritten;
|
|
211
|
-
action.add(writeAction);
|
|
212
|
-
await action.addToTxs(txs, feeRate);
|
|
213
|
-
await this.saveDataAccount(signerKey, txDataKey.publicKey);
|
|
214
|
-
}
|
|
215
|
-
while (pointer < writeData.length) {
|
|
216
|
-
const { bytesWritten, action } = await this.WriteData(signerKey, txDataKey, writeData, pointer, 950);
|
|
217
|
-
this.logger.debug("addTxsWriteData(): Write partial data (" + pointer + " .. " + (pointer + bytesWritten) + ")/" + writeData.length +
|
|
218
|
-
" key: " + txDataKey.publicKey.toBase58());
|
|
219
|
-
pointer += bytesWritten;
|
|
220
|
-
await action.addToTxs(txs, feeRate);
|
|
221
|
-
}
|
|
222
|
-
return txDataKey.publicKey;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
exports.SolanaDataAccount = SolanaDataAccount;
|
|
226
|
-
SolanaDataAccount.CUCosts = {
|
|
227
|
-
DATA_REMOVE: 50000,
|
|
228
|
-
DATA_CREATE_AND_WRITE: 15000,
|
|
229
|
-
DATA_CREATE: 5000,
|
|
230
|
-
DATA_WRITE: 15000
|
|
231
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SolanaDataAccount = exports.StoredDataAccount = void 0;
|
|
4
|
+
const SolanaSwapModule_1 = require("../SolanaSwapModule");
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
const SolanaAction_1 = require("../../chain/SolanaAction");
|
|
7
|
+
const Utils_1 = require("../../../utils/Utils");
|
|
8
|
+
const SolanaSigner_1 = require("../../wallet/SolanaSigner");
|
|
9
|
+
const utils_1 = require("@noble/hashes/utils");
|
|
10
|
+
class StoredDataAccount {
|
|
11
|
+
constructor(accountKeyOrData, owner) {
|
|
12
|
+
if (accountKeyOrData instanceof web3_js_1.PublicKey) {
|
|
13
|
+
this.accountKey = accountKeyOrData;
|
|
14
|
+
this.owner = owner;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
this.accountKey = new web3_js_1.PublicKey(accountKeyOrData.accountKey);
|
|
18
|
+
this.owner = new web3_js_1.PublicKey(accountKeyOrData.owner);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
serialize() {
|
|
22
|
+
return {
|
|
23
|
+
accountKey: this.accountKey.toBase58(),
|
|
24
|
+
owner: this.owner.toBase58()
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.StoredDataAccount = StoredDataAccount;
|
|
29
|
+
class SolanaDataAccount extends SolanaSwapModule_1.SolanaSwapModule {
|
|
30
|
+
/**
|
|
31
|
+
* Action for initialization of the data account
|
|
32
|
+
*
|
|
33
|
+
* @param signer
|
|
34
|
+
* @param accountKey
|
|
35
|
+
* @param dataLength
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
async InitDataAccount(signer, accountKey, dataLength) {
|
|
39
|
+
const accountSize = 32 + dataLength;
|
|
40
|
+
const lamportsDeposit = await (0, Utils_1.tryWithRetries)(() => this.connection.getMinimumBalanceForRentExemption(accountSize), this.retryPolicy);
|
|
41
|
+
return new SolanaAction_1.SolanaAction(signer, this.root, [
|
|
42
|
+
web3_js_1.SystemProgram.createAccount({
|
|
43
|
+
fromPubkey: signer,
|
|
44
|
+
newAccountPubkey: accountKey.publicKey,
|
|
45
|
+
lamports: lamportsDeposit,
|
|
46
|
+
space: accountSize,
|
|
47
|
+
programId: this.swapProgram.programId
|
|
48
|
+
}),
|
|
49
|
+
await this.swapProgram.methods
|
|
50
|
+
.initData()
|
|
51
|
+
.accounts({
|
|
52
|
+
signer,
|
|
53
|
+
data: accountKey.publicKey
|
|
54
|
+
})
|
|
55
|
+
.instruction(),
|
|
56
|
+
], SolanaDataAccount.CUCosts.DATA_CREATE, null, [accountKey]);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Action for closing the specific data account
|
|
60
|
+
*
|
|
61
|
+
* @param signer
|
|
62
|
+
* @param publicKey
|
|
63
|
+
*/
|
|
64
|
+
async CloseDataAccount(signer, publicKey) {
|
|
65
|
+
return new SolanaAction_1.SolanaAction(signer, this.root, await this.swapProgram.methods
|
|
66
|
+
.closeData()
|
|
67
|
+
.accounts({
|
|
68
|
+
signer,
|
|
69
|
+
data: publicKey
|
|
70
|
+
})
|
|
71
|
+
.instruction(), SolanaDataAccount.CUCosts.DATA_REMOVE, await this.root.Fees.getFeeRate([signer, publicKey]));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Action for writing data to a data account, writes up to sizeLimit starting from the offset position of the
|
|
75
|
+
* provided writeData buffer
|
|
76
|
+
*
|
|
77
|
+
* @param signer
|
|
78
|
+
* @param accountKey account public key to write to
|
|
79
|
+
* @param writeData buffer holding the write data
|
|
80
|
+
* @param offset data from buffer starting at offset are written
|
|
81
|
+
* @param sizeLimit maximum amount of data to be written to the data account in this action
|
|
82
|
+
* @private
|
|
83
|
+
* @returns {Promise<{bytesWritten: number, action: SolanaAction}>} bytes written to the data account & action
|
|
84
|
+
*/
|
|
85
|
+
async WriteData(signer, accountKey, writeData, offset, sizeLimit) {
|
|
86
|
+
const writeLen = Math.min(writeData.length - offset, sizeLimit);
|
|
87
|
+
return {
|
|
88
|
+
bytesWritten: writeLen,
|
|
89
|
+
action: new SolanaAction_1.SolanaAction(signer, this.root, await this.swapProgram.methods
|
|
90
|
+
.writeData(offset, writeData.slice(offset, offset + writeLen))
|
|
91
|
+
.accounts({
|
|
92
|
+
signer,
|
|
93
|
+
data: accountKey.publicKey
|
|
94
|
+
})
|
|
95
|
+
.instruction(), SolanaDataAccount.CUCosts.DATA_WRITE)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
constructor(chainInterface, program, storage) {
|
|
99
|
+
super(chainInterface, program);
|
|
100
|
+
this.SwapTxDataAlt = this.program.keypair((reversedTxId, signer) => [Buffer.from(signer.secretKey), reversedTxId]);
|
|
101
|
+
this.SwapTxDataAltBuffer = this.program.keypair((reversedTxId, secret) => [secret, reversedTxId]);
|
|
102
|
+
this.storage = storage;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Saves data account to the storage, the storage is required such that we are able to close the accounts later
|
|
106
|
+
* manually in case the claim doesn't happen (expires due to fees, etc.)
|
|
107
|
+
*
|
|
108
|
+
* @param signer
|
|
109
|
+
* @param publicKey
|
|
110
|
+
* @private
|
|
111
|
+
*/
|
|
112
|
+
saveDataAccount(signer, publicKey) {
|
|
113
|
+
return this.storage.saveData(publicKey.toBase58(), new StoredDataAccount(publicKey, signer));
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Initializes the data account handler, loads the existing data accounts which should be checked and closed
|
|
117
|
+
*/
|
|
118
|
+
async init() {
|
|
119
|
+
await this.storage.init();
|
|
120
|
+
const loadedData = await this.storage.loadData(StoredDataAccount);
|
|
121
|
+
this.logger.info("init(): initialized & loaded stored data accounts, count: " + loadedData.length);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Removes data account from the list of accounts that should be checked for reclaiming the locked SOL, this should
|
|
125
|
+
* be called after a batch of transactions claiming the swap was confirmed
|
|
126
|
+
*
|
|
127
|
+
* @param publicKey
|
|
128
|
+
*/
|
|
129
|
+
removeDataAccount(publicKey) {
|
|
130
|
+
return this.storage.removeData(publicKey.toBase58());
|
|
131
|
+
}
|
|
132
|
+
async getDataAccountsInfo(signer) {
|
|
133
|
+
const closePublicKeys = [];
|
|
134
|
+
let totalLocked = 0n;
|
|
135
|
+
for (let key in this.storage.data) {
|
|
136
|
+
const { accountKey, owner } = this.storage.data[key];
|
|
137
|
+
if (!owner.equals(signer))
|
|
138
|
+
continue;
|
|
139
|
+
try {
|
|
140
|
+
const fetchedDataAccount = await this.connection.getAccountInfo(accountKey);
|
|
141
|
+
if (fetchedDataAccount == null) {
|
|
142
|
+
await this.removeDataAccount(accountKey);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
closePublicKeys.push(accountKey);
|
|
146
|
+
totalLocked += BigInt(fetchedDataAccount.lamports);
|
|
147
|
+
}
|
|
148
|
+
catch (e) { }
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
closePublicKeys,
|
|
152
|
+
count: closePublicKeys.length,
|
|
153
|
+
totalValue: totalLocked
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Sweeps all old data accounts, reclaiming the SOL locked in the PDAs
|
|
158
|
+
*/
|
|
159
|
+
async sweepDataAccounts(signer) {
|
|
160
|
+
const { closePublicKeys, totalValue } = await this.getDataAccountsInfo(signer.getPublicKey());
|
|
161
|
+
if (closePublicKeys.length === 0) {
|
|
162
|
+
this.logger.debug("sweepDataAccounts(): no old data accounts found, no need to close any!");
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
this.logger.debug("sweepDataAccounts(): closing old data accounts: ", closePublicKeys);
|
|
166
|
+
let txns = [];
|
|
167
|
+
for (let publicKey of closePublicKeys) {
|
|
168
|
+
await (await this.CloseDataAccount(signer.getPublicKey(), publicKey)).addToTxs(txns);
|
|
169
|
+
}
|
|
170
|
+
const result = await this.root.Transactions.sendAndConfirm(signer, txns, true, null, true);
|
|
171
|
+
this.logger.info("sweepDataAccounts(): old data accounts closed: " +
|
|
172
|
+
closePublicKeys.map(pk => pk.toBase58()).join());
|
|
173
|
+
for (let publicKey of closePublicKeys) {
|
|
174
|
+
await this.removeDataAccount(publicKey);
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
txIds: result,
|
|
178
|
+
count: closePublicKeys.length,
|
|
179
|
+
totalValue: totalValue
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Adds the transactions writing (and also initializing if it doesn't exist) data to the data account
|
|
184
|
+
*
|
|
185
|
+
* @param signer
|
|
186
|
+
* @param reversedTxId reversed btc tx id is used to derive the data account address
|
|
187
|
+
* @param writeData full data to be written to the data account
|
|
188
|
+
* @param txs solana transactions array, where txns for writing & initializing will be added
|
|
189
|
+
* @param feeRate fee rate to use for the transactions
|
|
190
|
+
*/
|
|
191
|
+
async addTxsWriteData(signer, reversedTxId, writeData, txs, feeRate) {
|
|
192
|
+
let txDataKey;
|
|
193
|
+
let fetchedDataAccount = null;
|
|
194
|
+
if (signer instanceof SolanaSigner_1.SolanaSigner && signer.keypair != null) {
|
|
195
|
+
txDataKey = this.SwapTxDataAlt(reversedTxId, signer.keypair);
|
|
196
|
+
fetchedDataAccount = await (0, Utils_1.tryWithRetries)(() => this.connection.getAccountInfo(txDataKey.publicKey), this.retryPolicy);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const secret = Buffer.from((0, utils_1.randomBytes)(32));
|
|
200
|
+
txDataKey = this.SwapTxDataAltBuffer(reversedTxId, secret);
|
|
201
|
+
}
|
|
202
|
+
const signerKey = signer instanceof SolanaSigner_1.SolanaSigner ? signer.getPublicKey() : signer;
|
|
203
|
+
let pointer = 0;
|
|
204
|
+
if (fetchedDataAccount == null) {
|
|
205
|
+
const action = new SolanaAction_1.SolanaAction(signerKey, this.root);
|
|
206
|
+
action.add(await this.InitDataAccount(signerKey, txDataKey, writeData.length));
|
|
207
|
+
const { bytesWritten, action: writeAction } = await this.WriteData(signerKey, txDataKey, writeData, pointer, 420);
|
|
208
|
+
this.logger.debug("addTxsWriteData(): Write partial data (" + pointer + " .. " + (pointer + bytesWritten) + ")/" + writeData.length +
|
|
209
|
+
" key: " + txDataKey.publicKey.toBase58());
|
|
210
|
+
pointer += bytesWritten;
|
|
211
|
+
action.add(writeAction);
|
|
212
|
+
await action.addToTxs(txs, feeRate);
|
|
213
|
+
await this.saveDataAccount(signerKey, txDataKey.publicKey);
|
|
214
|
+
}
|
|
215
|
+
while (pointer < writeData.length) {
|
|
216
|
+
const { bytesWritten, action } = await this.WriteData(signerKey, txDataKey, writeData, pointer, 950);
|
|
217
|
+
this.logger.debug("addTxsWriteData(): Write partial data (" + pointer + " .. " + (pointer + bytesWritten) + ")/" + writeData.length +
|
|
218
|
+
" key: " + txDataKey.publicKey.toBase58());
|
|
219
|
+
pointer += bytesWritten;
|
|
220
|
+
await action.addToTxs(txs, feeRate);
|
|
221
|
+
}
|
|
222
|
+
return txDataKey.publicKey;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
exports.SolanaDataAccount = SolanaDataAccount;
|
|
226
|
+
SolanaDataAccount.CUCosts = {
|
|
227
|
+
DATA_REMOVE: 50000,
|
|
228
|
+
DATA_CREATE_AND_WRITE: 15000,
|
|
229
|
+
DATA_CREATE: 5000,
|
|
230
|
+
DATA_WRITE: 15000
|
|
231
|
+
};
|
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
import { SolanaSwapModule } from "../SolanaSwapModule";
|
|
2
|
-
import { PublicKey } from "@solana/web3.js";
|
|
3
|
-
import { SolanaTx } from "../../chain/modules/SolanaTransactions";
|
|
4
|
-
import { IntermediaryReputationType } from "@atomiqlabs/base";
|
|
5
|
-
export declare class SolanaLpVault extends SolanaSwapModule {
|
|
6
|
-
private static readonly CUCosts;
|
|
7
|
-
/**
|
|
8
|
-
* Action for withdrawing funds from the LP vault
|
|
9
|
-
*
|
|
10
|
-
* @param signer
|
|
11
|
-
* @param token
|
|
12
|
-
* @param amount
|
|
13
|
-
* @constructor
|
|
14
|
-
* @private
|
|
15
|
-
*/
|
|
16
|
-
private Withdraw;
|
|
17
|
-
/**
|
|
18
|
-
* Action for depositing funds to the LP vault
|
|
19
|
-
*
|
|
20
|
-
* @param signer
|
|
21
|
-
* @param token
|
|
22
|
-
* @param amount
|
|
23
|
-
* @constructor
|
|
24
|
-
* @private
|
|
25
|
-
*/
|
|
26
|
-
private Deposit;
|
|
27
|
-
/**
|
|
28
|
-
* Returns intermediary's reputation & vault balance for a specific token
|
|
29
|
-
*
|
|
30
|
-
* @param address
|
|
31
|
-
* @param token
|
|
32
|
-
*/
|
|
33
|
-
getIntermediaryData(address: PublicKey, token: PublicKey): Promise<{
|
|
34
|
-
balance: bigint;
|
|
35
|
-
reputation: IntermediaryReputationType;
|
|
36
|
-
}>;
|
|
37
|
-
/**
|
|
38
|
-
* Returns intermediary's reputation for a specific token
|
|
39
|
-
*
|
|
40
|
-
* @param address
|
|
41
|
-
* @param token
|
|
42
|
-
*/
|
|
43
|
-
getIntermediaryReputation(address: PublicKey, token: PublicKey): Promise<IntermediaryReputationType>;
|
|
44
|
-
/**
|
|
45
|
-
* Returns the balance of the token an intermediary has in his LP vault
|
|
46
|
-
*
|
|
47
|
-
* @param address
|
|
48
|
-
* @param token
|
|
49
|
-
*/
|
|
50
|
-
getIntermediaryBalance(address: PublicKey, token: PublicKey): Promise<bigint>;
|
|
51
|
-
/**
|
|
52
|
-
* Creates transactions for withdrawing funds from the LP vault, creates ATA if it doesn't exist and unwraps
|
|
53
|
-
* WSOL to SOL if required
|
|
54
|
-
*
|
|
55
|
-
* @param signer
|
|
56
|
-
* @param token
|
|
57
|
-
* @param amount
|
|
58
|
-
* @param feeRate
|
|
59
|
-
*/
|
|
60
|
-
txsWithdraw(signer: PublicKey, token: PublicKey, amount: bigint, feeRate?: string): Promise<SolanaTx[]>;
|
|
61
|
-
/**
|
|
62
|
-
* Creates transaction for depositing funds into the LP vault, wraps SOL to WSOL if required
|
|
63
|
-
*
|
|
64
|
-
* @param signer
|
|
65
|
-
* @param token
|
|
66
|
-
* @param amount
|
|
67
|
-
* @param feeRate
|
|
68
|
-
*/
|
|
69
|
-
txsDeposit(signer: PublicKey, token: PublicKey, amount: bigint, feeRate?: string): Promise<SolanaTx[]>;
|
|
70
|
-
getFeeRate(signer: PublicKey, token: PublicKey): Promise<string>;
|
|
71
|
-
}
|
|
1
|
+
import { SolanaSwapModule } from "../SolanaSwapModule";
|
|
2
|
+
import { PublicKey } from "@solana/web3.js";
|
|
3
|
+
import { SolanaTx } from "../../chain/modules/SolanaTransactions";
|
|
4
|
+
import { IntermediaryReputationType } from "@atomiqlabs/base";
|
|
5
|
+
export declare class SolanaLpVault extends SolanaSwapModule {
|
|
6
|
+
private static readonly CUCosts;
|
|
7
|
+
/**
|
|
8
|
+
* Action for withdrawing funds from the LP vault
|
|
9
|
+
*
|
|
10
|
+
* @param signer
|
|
11
|
+
* @param token
|
|
12
|
+
* @param amount
|
|
13
|
+
* @constructor
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
private Withdraw;
|
|
17
|
+
/**
|
|
18
|
+
* Action for depositing funds to the LP vault
|
|
19
|
+
*
|
|
20
|
+
* @param signer
|
|
21
|
+
* @param token
|
|
22
|
+
* @param amount
|
|
23
|
+
* @constructor
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
private Deposit;
|
|
27
|
+
/**
|
|
28
|
+
* Returns intermediary's reputation & vault balance for a specific token
|
|
29
|
+
*
|
|
30
|
+
* @param address
|
|
31
|
+
* @param token
|
|
32
|
+
*/
|
|
33
|
+
getIntermediaryData(address: PublicKey, token: PublicKey): Promise<{
|
|
34
|
+
balance: bigint;
|
|
35
|
+
reputation: IntermediaryReputationType;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Returns intermediary's reputation for a specific token
|
|
39
|
+
*
|
|
40
|
+
* @param address
|
|
41
|
+
* @param token
|
|
42
|
+
*/
|
|
43
|
+
getIntermediaryReputation(address: PublicKey, token: PublicKey): Promise<IntermediaryReputationType>;
|
|
44
|
+
/**
|
|
45
|
+
* Returns the balance of the token an intermediary has in his LP vault
|
|
46
|
+
*
|
|
47
|
+
* @param address
|
|
48
|
+
* @param token
|
|
49
|
+
*/
|
|
50
|
+
getIntermediaryBalance(address: PublicKey, token: PublicKey): Promise<bigint>;
|
|
51
|
+
/**
|
|
52
|
+
* Creates transactions for withdrawing funds from the LP vault, creates ATA if it doesn't exist and unwraps
|
|
53
|
+
* WSOL to SOL if required
|
|
54
|
+
*
|
|
55
|
+
* @param signer
|
|
56
|
+
* @param token
|
|
57
|
+
* @param amount
|
|
58
|
+
* @param feeRate
|
|
59
|
+
*/
|
|
60
|
+
txsWithdraw(signer: PublicKey, token: PublicKey, amount: bigint, feeRate?: string): Promise<SolanaTx[]>;
|
|
61
|
+
/**
|
|
62
|
+
* Creates transaction for depositing funds into the LP vault, wraps SOL to WSOL if required
|
|
63
|
+
*
|
|
64
|
+
* @param signer
|
|
65
|
+
* @param token
|
|
66
|
+
* @param amount
|
|
67
|
+
* @param feeRate
|
|
68
|
+
*/
|
|
69
|
+
txsDeposit(signer: PublicKey, token: PublicKey, amount: bigint, feeRate?: string): Promise<SolanaTx[]>;
|
|
70
|
+
getFeeRate(signer: PublicKey, token: PublicKey): Promise<string>;
|
|
71
|
+
}
|