@atomiqlabs/chain-solana 13.1.0 → 13.2.1
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/solana/chain/SolanaChainInterface.d.ts +4 -0
- package/dist/solana/chain/SolanaChainInterface.js +7 -0
- package/dist/solana/chain/modules/SolanaTransactions.d.ts +2 -3
- package/dist/solana/chain/modules/SolanaTransactions.js +13 -9
- package/package.json +3 -2
- package/src/solana/chain/SolanaChainInterface.ts +8 -0
- package/src/solana/chain/modules/SolanaTransactions.ts +12 -9
|
@@ -133,6 +133,10 @@ export declare class SolanaChainInterface implements ChainInterface<SolanaTx, Si
|
|
|
133
133
|
* @inheritDoc
|
|
134
134
|
*/
|
|
135
135
|
sendSignedAndConfirm(txs: SignedSolanaTx[], waitForConfirmation?: boolean, abortSignal?: AbortSignal, parallel?: boolean, onBeforePublish?: (txId: string, rawTx: string) => Promise<void>): Promise<string[]>;
|
|
136
|
+
/**
|
|
137
|
+
* @inheritDoc
|
|
138
|
+
*/
|
|
139
|
+
prepareTxs(txs: SolanaTx[]): Promise<SolanaTx[]>;
|
|
136
140
|
/**
|
|
137
141
|
* @inheritDoc
|
|
138
142
|
*/
|
|
@@ -109,6 +109,13 @@ class SolanaChainInterface {
|
|
|
109
109
|
sendSignedAndConfirm(txs, waitForConfirmation, abortSignal, parallel, onBeforePublish) {
|
|
110
110
|
return this.Transactions.sendSignedAndConfirm(txs, waitForConfirmation, abortSignal, parallel, onBeforePublish);
|
|
111
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* @inheritDoc
|
|
114
|
+
*/
|
|
115
|
+
async prepareTxs(txs) {
|
|
116
|
+
await this.Transactions.prepareTransactions(txs);
|
|
117
|
+
return txs;
|
|
118
|
+
}
|
|
112
119
|
/**
|
|
113
120
|
* @inheritDoc
|
|
114
121
|
*/
|
|
@@ -73,11 +73,10 @@ export declare class SolanaTransactions extends SolanaModule {
|
|
|
73
73
|
* Prepares solana transactions, assigns recentBlockhash if needed, applies Phantom hotfix,
|
|
74
74
|
* sets feePayer to ourselves, calls beforeTxSigned callback & signs transaction with provided signers array
|
|
75
75
|
*
|
|
76
|
-
* @param signer
|
|
77
76
|
* @param txs
|
|
78
|
-
* @
|
|
77
|
+
* @param signer
|
|
79
78
|
*/
|
|
80
|
-
|
|
79
|
+
prepareTransactions(txs: SolanaTx[], signer?: SolanaSigner): Promise<void>;
|
|
81
80
|
/**
|
|
82
81
|
* Sends out a signed transaction to the RPC
|
|
83
82
|
*
|
|
@@ -159,11 +159,15 @@ class SolanaTransactions extends SolanaModule_1.SolanaModule {
|
|
|
159
159
|
* Prepares solana transactions, assigns recentBlockhash if needed, applies Phantom hotfix,
|
|
160
160
|
* sets feePayer to ourselves, calls beforeTxSigned callback & signs transaction with provided signers array
|
|
161
161
|
*
|
|
162
|
-
* @param signer
|
|
163
162
|
* @param txs
|
|
164
|
-
* @
|
|
163
|
+
* @param signer
|
|
165
164
|
*/
|
|
166
|
-
async prepareTransactions(
|
|
165
|
+
async prepareTransactions(txs, signer) {
|
|
166
|
+
if (txs.length === 0)
|
|
167
|
+
return;
|
|
168
|
+
const signerAddress = signer?.getPublicKey() ?? txs[0].tx.feePayer;
|
|
169
|
+
if (signerAddress == null)
|
|
170
|
+
throw new Error("Cannot get tx sender address!");
|
|
167
171
|
let latestBlockData = null;
|
|
168
172
|
for (let tx of txs) {
|
|
169
173
|
if (tx.tx.recentBlockhash == null) {
|
|
@@ -177,13 +181,13 @@ class SolanaTransactions extends SolanaModule_1.SolanaModule {
|
|
|
177
181
|
}
|
|
178
182
|
//This is a hotfix for Phantom adding compute unit price instruction on the first position & breaking
|
|
179
183
|
// required instructions order (e.g. btc relay verify needs to be 0th instruction in a tx)
|
|
180
|
-
if (signer.keypair == null && tx.tx.signatures.length === 0) {
|
|
184
|
+
if ((signer == null || signer.keypair == null) && tx.tx.signatures.length === 0) {
|
|
181
185
|
const foundIx = tx.tx.instructions.find(ix => ix.programId.equals(web3_js_1.ComputeBudgetProgram.programId) && web3_js_1.ComputeBudgetInstruction.decodeInstructionType(ix) === "SetComputeUnitPrice");
|
|
182
186
|
if (foundIx == null)
|
|
183
187
|
tx.tx.instructions.splice(tx.tx.instructions.length - 1, 0, web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 }));
|
|
184
188
|
}
|
|
185
|
-
tx.tx.feePayer =
|
|
186
|
-
if (this.cbkBeforeTxSigned != null)
|
|
189
|
+
tx.tx.feePayer = signerAddress;
|
|
190
|
+
if (signer != null && this.cbkBeforeTxSigned != null)
|
|
187
191
|
await this.cbkBeforeTxSigned(tx);
|
|
188
192
|
if (tx.signers != null && tx.signers.length > 0)
|
|
189
193
|
for (let signer of tx.signers)
|
|
@@ -235,7 +239,7 @@ class SolanaTransactions extends SolanaModule_1.SolanaModule {
|
|
|
235
239
|
const signatures = [];
|
|
236
240
|
for (let e = 0; e < _txs.length; e += BATCH_SIZE) {
|
|
237
241
|
const txs = _txs.slice(e, e + BATCH_SIZE);
|
|
238
|
-
await this.prepareTransactions(
|
|
242
|
+
await this.prepareTransactions(txs, signer);
|
|
239
243
|
const signedTxs = await signer.wallet.signAllTransactions(txs.map(e => e.tx));
|
|
240
244
|
signedTxs.forEach((tx, index) => {
|
|
241
245
|
const solTx = txs[index];
|
|
@@ -305,7 +309,7 @@ class SolanaTransactions extends SolanaModule_1.SolanaModule {
|
|
|
305
309
|
*/
|
|
306
310
|
serializeUnsignedTx(tx) {
|
|
307
311
|
return JSON.stringify({
|
|
308
|
-
tx: tx.tx.serialize().toString("hex"),
|
|
312
|
+
tx: tx.tx.serialize({ requireAllSignatures: false, verifySignatures: false }).toString("hex"),
|
|
309
313
|
signers: tx.signers.map(e => buffer_1.Buffer.from(e.secretKey).toString("hex")),
|
|
310
314
|
lastValidBlockheight: tx.tx.lastValidBlockHeight
|
|
311
315
|
});
|
|
@@ -316,7 +320,7 @@ class SolanaTransactions extends SolanaModule_1.SolanaModule {
|
|
|
316
320
|
* @param signedTx
|
|
317
321
|
*/
|
|
318
322
|
serializeSignedTx(signedTx) {
|
|
319
|
-
return signedTx.serialize().toString("hex");
|
|
323
|
+
return signedTx.serialize({ requireAllSignatures: false, verifySignatures: false }).toString("hex");
|
|
320
324
|
}
|
|
321
325
|
/**
|
|
322
326
|
* Deserializes saved solana transaction, extracting the transaction, signers & last valid blockheight
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atomiqlabs/chain-solana",
|
|
3
|
-
"version": "13.1
|
|
3
|
+
"version": "13.2.1",
|
|
4
4
|
"description": "Solana specific base implementation",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types:": "./dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
+
"build": "npx -y -p typescript@4.9 tsc",
|
|
8
9
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
10
|
"build:ts4": "npx -p typescript@4.9 tsc --noEmit",
|
|
10
11
|
"build:ts5": "npx -p typescript@5 tsc --noEmit"
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
"author": "adambor",
|
|
26
27
|
"license": "ISC",
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"@atomiqlabs/base": "^13.0
|
|
29
|
+
"@atomiqlabs/base": "^13.2.0",
|
|
29
30
|
"@coral-xyz/anchor": "0.29.0",
|
|
30
31
|
"@noble/hashes": "^1.7.1",
|
|
31
32
|
"@solana/spl-token": "0.4.14",
|
|
@@ -216,6 +216,14 @@ export class SolanaChainInterface implements ChainInterface<
|
|
|
216
216
|
return this.Transactions.sendSignedAndConfirm(txs, waitForConfirmation, abortSignal, parallel, onBeforePublish);
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
/**
|
|
220
|
+
* @inheritDoc
|
|
221
|
+
*/
|
|
222
|
+
async prepareTxs(txs: SolanaTx[]): Promise<SolanaTx[]> {
|
|
223
|
+
await this.Transactions.prepareTransactions(txs);
|
|
224
|
+
return txs;
|
|
225
|
+
}
|
|
226
|
+
|
|
219
227
|
/**
|
|
220
228
|
* @inheritDoc
|
|
221
229
|
*/
|
|
@@ -195,11 +195,14 @@ export class SolanaTransactions extends SolanaModule {
|
|
|
195
195
|
* Prepares solana transactions, assigns recentBlockhash if needed, applies Phantom hotfix,
|
|
196
196
|
* sets feePayer to ourselves, calls beforeTxSigned callback & signs transaction with provided signers array
|
|
197
197
|
*
|
|
198
|
-
* @param signer
|
|
199
198
|
* @param txs
|
|
200
|
-
* @
|
|
199
|
+
* @param signer
|
|
201
200
|
*/
|
|
202
|
-
|
|
201
|
+
public async prepareTransactions(txs: SolanaTx[], signer?: SolanaSigner): Promise<void> {
|
|
202
|
+
if(txs.length===0) return;
|
|
203
|
+
const signerAddress = signer?.getPublicKey() ?? txs[0].tx.feePayer;
|
|
204
|
+
if(signerAddress==null) throw new Error("Cannot get tx sender address!");
|
|
205
|
+
|
|
203
206
|
let latestBlockData: {blockhash: string, lastValidBlockHeight: number} | null = null;
|
|
204
207
|
|
|
205
208
|
for(let tx of txs) {
|
|
@@ -215,13 +218,13 @@ export class SolanaTransactions extends SolanaModule {
|
|
|
215
218
|
|
|
216
219
|
//This is a hotfix for Phantom adding compute unit price instruction on the first position & breaking
|
|
217
220
|
// required instructions order (e.g. btc relay verify needs to be 0th instruction in a tx)
|
|
218
|
-
if(signer.keypair==null && tx.tx.signatures.length===0) {
|
|
221
|
+
if((signer==null || signer.keypair==null) && tx.tx.signatures.length===0) {
|
|
219
222
|
const foundIx = tx.tx.instructions.find(ix => ix.programId.equals(ComputeBudgetProgram.programId) && ComputeBudgetInstruction.decodeInstructionType(ix)==="SetComputeUnitPrice")
|
|
220
223
|
if(foundIx==null) tx.tx.instructions.splice(tx.tx.instructions.length-1, 0, ComputeBudgetProgram.setComputeUnitPrice({microLamports: 1}));
|
|
221
224
|
}
|
|
222
225
|
|
|
223
|
-
tx.tx.feePayer =
|
|
224
|
-
if(this.cbkBeforeTxSigned!=null) await this.cbkBeforeTxSigned(tx);
|
|
226
|
+
tx.tx.feePayer = signerAddress;
|
|
227
|
+
if(signer!=null && this.cbkBeforeTxSigned!=null) await this.cbkBeforeTxSigned(tx);
|
|
225
228
|
if(tx.signers!=null && tx.signers.length>0) for(let signer of tx.signers) tx.tx.sign(signer);
|
|
226
229
|
}
|
|
227
230
|
}
|
|
@@ -275,7 +278,7 @@ export class SolanaTransactions extends SolanaModule {
|
|
|
275
278
|
for(let e=0;e<_txs.length;e+=BATCH_SIZE) {
|
|
276
279
|
const txs = _txs.slice(e, e+BATCH_SIZE);
|
|
277
280
|
|
|
278
|
-
await this.prepareTransactions(
|
|
281
|
+
await this.prepareTransactions(txs, signer)
|
|
279
282
|
const signedTxs = await signer.wallet.signAllTransactions(txs.map(e => e.tx));
|
|
280
283
|
signedTxs.forEach((tx, index) => {
|
|
281
284
|
const solTx = txs[index];
|
|
@@ -357,7 +360,7 @@ export class SolanaTransactions extends SolanaModule {
|
|
|
357
360
|
*/
|
|
358
361
|
public serializeUnsignedTx(tx: SolanaTx): string {
|
|
359
362
|
return JSON.stringify({
|
|
360
|
-
tx: tx.tx.serialize().toString("hex"),
|
|
363
|
+
tx: tx.tx.serialize({requireAllSignatures: false, verifySignatures: false}).toString("hex"),
|
|
361
364
|
signers: tx.signers.map(e => Buffer.from(e.secretKey).toString("hex")),
|
|
362
365
|
lastValidBlockheight: tx.tx.lastValidBlockHeight
|
|
363
366
|
});
|
|
@@ -369,7 +372,7 @@ export class SolanaTransactions extends SolanaModule {
|
|
|
369
372
|
* @param signedTx
|
|
370
373
|
*/
|
|
371
374
|
public serializeSignedTx(signedTx: Transaction): string {
|
|
372
|
-
return signedTx.serialize().toString("hex");
|
|
375
|
+
return signedTx.serialize({requireAllSignatures: false, verifySignatures: false}).toString("hex");
|
|
373
376
|
}
|
|
374
377
|
|
|
375
378
|
/**
|