@hawksightco/hawk-sdk 0.0.18 → 0.0.19
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.
|
@@ -47,6 +47,14 @@ export declare class Transaction {
|
|
|
47
47
|
* @throws Error if a signer is not required or has already signed the transaction when not idempotent.
|
|
48
48
|
*/
|
|
49
49
|
sign(signers: web3.Signer[], idempotent?: boolean): void;
|
|
50
|
+
/**
|
|
51
|
+
* Add a signature on the transaction with provided signature.
|
|
52
|
+
*
|
|
53
|
+
* @param publicKey The public key of the signer
|
|
54
|
+
* @param signature A signature of the signed transaction
|
|
55
|
+
* @throws Error if a signer is not required or has already signed the transaction.
|
|
56
|
+
*/
|
|
57
|
+
addSignature(publicKey: web3.PublicKey, signature: Uint8Array): void;
|
|
50
58
|
/**
|
|
51
59
|
* Checks if all required signers have signed the transaction.
|
|
52
60
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Transaction.d.ts","sourceRoot":"","sources":["../../../src/classes/Transaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"Transaction.d.ts","sourceRoot":"","sources":["../../../src/classes/Transaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AAGxC,OAAO,EACL,4BAA4B,EAC5B,2BAA2B,EAC5B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;GAGG;AACH,qBAAa,WAAW;IA+CpB,QAAQ,CAAC,kBAAkB,EAAE,2BAA2B;IACxD,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS;IACjC,OAAO,CAAC,eAAe;IACvB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,yBAAyB,EAAE;IAC/C,OAAO,CAAC,cAAc;IAlDxB,2FAA2F;IAC3F,OAAO,CAAC,UAAU,CAA0B;IAC5C,IAAI,SAAS,IAAI,IAAI,CAAC,kBAAkB,CAEvC;IAED,+DAA+D;IAC/D,OAAO,CAAC,qBAAqB,CAA4B;IACzD,IAAI,oBAAoB,IAAI,IAAI,CAAC,oBAAoB,CAEpD;IAED,+EAA+E;IAC/E,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAElD,oFAAoF;IACpF,OAAO,CAAC,oBAAoB,CAAc;IAC1C,IAAI,mBAAmB,IAAI,MAAM,CAEhC;IAED,6CAA6C;IAC7C,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED,yEAAyE;IACzE,OAAO,CAAC,aAAa,CAAgC;IACrD,IAAI,YAAY,IAAI,IAAI,CAAC,sBAAsB,EAAE,CAEhD;IAED,8BAA8B;IAC9B,IAAI,oBAAoB,IAAI,MAAM,CAEjC;IAED;;;;;;;OAOG;gBAEQ,kBAAkB,EAAE,2BAA2B,EAC/C,QAAQ,EAAE,IAAI,CAAC,SAAS,EACzB,eAAe,EAAE,IAAI,CAAC,8BAA8B,EACnD,IAAI,EAAE,IAAI,CAAC,yBAAyB,EAAE,EACvC,cAAc,EAAE,cAAc;IAyCxC;;;;;;OAMG;IACH,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,UAAU,GAAE,OAAe,GAAG,IAAI;IAuB/D;;;;;;OAMG;IACH,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,UAAU,GAAG,IAAI;IAcpE;;;;OAIG;IACH,yBAAyB,IAAI,OAAO;IAIpC;;OAEG;IACG,gBAAgB,CACpB,UAAU,EAAE,IAAI,CAAC,UAAU,EAC3B,aAAa,EAAE,MAAM,CAAC,0CAA0C,EAChE,gBAAgB,EAAE,MAAM,EACxB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC;IA6CzC;;;;;OAKG;IACG,mBAAmB,CACvB,UAAU,EAAE,IAAI,CAAC,UAAU,GAC1B,OAAO,CAAC,4BAA4B,CAAC;IA4BxC;;OAEG;IACH,gBAAgB,CACd,eAAe,EAAE,IAAI,CAAC,8BAA8B,GACnD,CAAC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,oBAAoB,CAAC;IAcvD;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAUpC;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAUpC;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAW7B"}
|
|
@@ -34,21 +34,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
35
|
exports.Transaction = void 0;
|
|
36
36
|
const web3 = __importStar(require("@solana/web3.js"));
|
|
37
|
-
const functions_1 = require("../functions");
|
|
38
37
|
const bn_js_1 = require("bn.js");
|
|
38
|
+
const functions_1 = require("../functions");
|
|
39
39
|
/**
|
|
40
40
|
* Represents a transaction object in Solana using the web3.js library.
|
|
41
41
|
* This class encapsulates the logic for creating, signing, and verifying signatures of transactions.
|
|
42
42
|
*/
|
|
43
43
|
class Transaction {
|
|
44
|
-
get txMessage() {
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
get txMessage() {
|
|
45
|
+
return this._txMessage;
|
|
46
|
+
}
|
|
47
|
+
get versionedTransaction() {
|
|
48
|
+
return this._versionedTransaction;
|
|
49
|
+
}
|
|
50
|
+
get priorityFeeEstimate() {
|
|
51
|
+
return this._priorityFeeEstimate;
|
|
52
|
+
}
|
|
47
53
|
/** The blockhash of a recent ledger entry */
|
|
48
|
-
get recentBlockhash() {
|
|
49
|
-
|
|
54
|
+
get recentBlockhash() {
|
|
55
|
+
return this.latestBlockhash.blockhash;
|
|
56
|
+
}
|
|
57
|
+
get instructions() {
|
|
58
|
+
return this._instructions;
|
|
59
|
+
}
|
|
50
60
|
/** last valid block height */
|
|
51
|
-
get lastValidBlockHeight() {
|
|
61
|
+
get lastValidBlockHeight() {
|
|
62
|
+
return this.latestBlockhash.lastValidBlockHeight;
|
|
63
|
+
}
|
|
52
64
|
/**
|
|
53
65
|
* Constructs a new Transaction object.
|
|
54
66
|
*
|
|
@@ -76,13 +88,17 @@ class Transaction {
|
|
|
76
88
|
/** Estimated fee in SOL for priority fee when addPriorityFee() method is called. */
|
|
77
89
|
this._priorityFeeEstimate = "";
|
|
78
90
|
// Construct main instructions
|
|
79
|
-
const mainIxs = txMetadataResponse.mainInstructions.map(ix => {
|
|
91
|
+
const mainIxs = txMetadataResponse.mainInstructions.map((ix) => {
|
|
80
92
|
return new web3.TransactionInstruction({
|
|
81
|
-
keys: ix.accounts.map(meta => {
|
|
82
|
-
return {
|
|
93
|
+
keys: ix.accounts.map((meta) => {
|
|
94
|
+
return {
|
|
95
|
+
pubkey: new web3.PublicKey(meta.pubkey),
|
|
96
|
+
isSigner: meta.isSigner,
|
|
97
|
+
isWritable: meta.isWritable,
|
|
98
|
+
};
|
|
83
99
|
}),
|
|
84
100
|
programId: new web3.PublicKey(ix.programId),
|
|
85
|
-
data: Buffer.from(ix.data,
|
|
101
|
+
data: Buffer.from(ix.data, "base64"),
|
|
86
102
|
});
|
|
87
103
|
});
|
|
88
104
|
this._instructions = [...mainIxs];
|
|
@@ -90,11 +106,10 @@ class Transaction {
|
|
|
90
106
|
this._txMessage = txMessage;
|
|
91
107
|
this._versionedTransaction = versionedTransaction;
|
|
92
108
|
this.requiredSigners = this.getRequiredSigners();
|
|
93
|
-
if (typeof this.requiredSigners[payerKey.toString()] !==
|
|
109
|
+
if (typeof this.requiredSigners[payerKey.toString()] !== "boolean") {
|
|
94
110
|
throw new Error(`Warning: The payer ${payerKey} is not one of the required signers of this transaction.`);
|
|
95
111
|
}
|
|
96
112
|
}
|
|
97
|
-
;
|
|
98
113
|
/**
|
|
99
114
|
* Signs the transaction with provided signers.
|
|
100
115
|
*
|
|
@@ -104,9 +119,9 @@ class Transaction {
|
|
|
104
119
|
*/
|
|
105
120
|
sign(signers, idempotent = false) {
|
|
106
121
|
// First validate all signers
|
|
107
|
-
signers.forEach(signer => {
|
|
122
|
+
signers.forEach((signer) => {
|
|
108
123
|
const key = signer.publicKey.toString();
|
|
109
|
-
if (typeof this.requiredSigners[key] !==
|
|
124
|
+
if (typeof this.requiredSigners[key] !== "boolean") {
|
|
110
125
|
throw new Error(`Key ${key} is not a required signer!`);
|
|
111
126
|
}
|
|
112
127
|
if (!idempotent && this.requiredSigners[key]) {
|
|
@@ -114,19 +129,37 @@ class Transaction {
|
|
|
114
129
|
}
|
|
115
130
|
});
|
|
116
131
|
// If all signers are valid and the process is idempotent or they haven't signed yet, update and sign
|
|
117
|
-
signers.forEach(signer => {
|
|
132
|
+
signers.forEach((signer) => {
|
|
118
133
|
const key = signer.publicKey.toString();
|
|
119
134
|
this.requiredSigners[key] = true;
|
|
120
135
|
});
|
|
121
136
|
this.versionedTransaction.sign(signers);
|
|
122
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Add a signature on the transaction with provided signature.
|
|
140
|
+
*
|
|
141
|
+
* @param publicKey The public key of the signer
|
|
142
|
+
* @param signature A signature of the signed transaction
|
|
143
|
+
* @throws Error if a signer is not required or has already signed the transaction.
|
|
144
|
+
*/
|
|
145
|
+
addSignature(publicKey, signature) {
|
|
146
|
+
const key = publicKey.toBase58();
|
|
147
|
+
if (typeof this.requiredSigners[key] !== "boolean") {
|
|
148
|
+
throw new Error(`Key ${key} is not a required signer!`);
|
|
149
|
+
}
|
|
150
|
+
if (this.requiredSigners[key]) {
|
|
151
|
+
throw new Error(`Key ${key} has already been signed by required signer!`);
|
|
152
|
+
}
|
|
153
|
+
this.requiredSigners[key] = true;
|
|
154
|
+
this.versionedTransaction.addSignature(publicKey, signature);
|
|
155
|
+
}
|
|
123
156
|
/**
|
|
124
157
|
* Checks if all required signers have signed the transaction.
|
|
125
158
|
*
|
|
126
159
|
* @returns Boolean indicating whether all required signers have signed.
|
|
127
160
|
*/
|
|
128
161
|
isSignedByRequiredSigners() {
|
|
129
|
-
return Object.values(this.requiredSigners).every(isSigned => isSigned);
|
|
162
|
+
return Object.values(this.requiredSigners).every((isSigned) => isSigned);
|
|
130
163
|
}
|
|
131
164
|
/**
|
|
132
165
|
* Add priority fee instructions (compute budget)
|
|
@@ -137,10 +170,14 @@ class Transaction {
|
|
|
137
170
|
this.removePriorityFeeIxs();
|
|
138
171
|
// Then get fee estimate by simulating the transaction
|
|
139
172
|
const estimate = yield (0, functions_1.getFeeEstimate)(this.generalUtility, priorityLevel, this.txMetadataResponse);
|
|
140
|
-
const priorityFeeEstimate = maxPriorityFee !== undefined && maxPriorityFee > 0
|
|
173
|
+
const priorityFeeEstimate = maxPriorityFee !== undefined && maxPriorityFee > 0
|
|
174
|
+
? Math.round(Math.min(estimate, maxPriorityFee))
|
|
175
|
+
: Math.round(estimate);
|
|
141
176
|
// Create priority fee ixs for transaction
|
|
142
177
|
const priorityFeeIxs = [
|
|
143
|
-
web3.ComputeBudgetProgram.setComputeUnitLimit({
|
|
178
|
+
web3.ComputeBudgetProgram.setComputeUnitLimit({
|
|
179
|
+
units: computeUnitLimit,
|
|
180
|
+
}),
|
|
144
181
|
web3.ComputeBudgetProgram.setComputeUnitPrice({
|
|
145
182
|
// CU * CU PRICE -> 1400000 * feeEstimate.priorityFeeEstimate
|
|
146
183
|
microLamports: priorityFeeEstimate,
|
|
@@ -149,9 +186,11 @@ class Transaction {
|
|
|
149
186
|
this._priorityFeeEstimate = (new bn_js_1.BN(priorityFeeEstimate)
|
|
150
187
|
.mul(new bn_js_1.BN(computeUnitLimit))
|
|
151
188
|
.div(new bn_js_1.BN(1000000))
|
|
152
|
-
.add(new bn_js_1.BN(5000))
|
|
189
|
+
.add(new bn_js_1.BN(5000))
|
|
190
|
+
.toNumber() / 1000000000).toString();
|
|
153
191
|
// Append priority fee instruction at the beginning
|
|
154
192
|
this._instructions.unshift(...priorityFeeIxs);
|
|
193
|
+
console.log(this._instructions);
|
|
155
194
|
// Rebuild versioned transaction
|
|
156
195
|
const blockhash = yield connection.getLatestBlockhash();
|
|
157
196
|
this.buildTransaction(blockhash);
|
|
@@ -180,7 +219,7 @@ class Transaction {
|
|
|
180
219
|
sigVerify: false,
|
|
181
220
|
});
|
|
182
221
|
if (simulation.value.unitsConsumed === undefined) {
|
|
183
|
-
throw new Error(
|
|
222
|
+
throw new Error("Unable to calculate compute budget.");
|
|
184
223
|
}
|
|
185
224
|
return {
|
|
186
225
|
err: simulation.value.err,
|
|
@@ -210,17 +249,20 @@ class Transaction {
|
|
|
210
249
|
* @returns A record of signer public keys mapped to a boolean indicating whether they have signed.
|
|
211
250
|
*/
|
|
212
251
|
getRequiredSigners() {
|
|
213
|
-
const signerKeys = this.instructions.flatMap(ix => ix.keys
|
|
252
|
+
const signerKeys = this.instructions.flatMap((ix) => ix.keys
|
|
253
|
+
.filter((meta) => meta.isSigner)
|
|
254
|
+
.map((meta) => meta.pubkey.toString()));
|
|
214
255
|
const result = {};
|
|
215
|
-
signerKeys.forEach(key => result[key] = false);
|
|
256
|
+
signerKeys.forEach((key) => (result[key] = false));
|
|
216
257
|
return result;
|
|
217
258
|
}
|
|
218
259
|
/**
|
|
219
260
|
* Find setComputeUnitLimit index within the instructions
|
|
220
261
|
*/
|
|
221
262
|
findSetComputeUnitLimitIndex() {
|
|
222
|
-
return this.instructions.findIndex(ix => {
|
|
223
|
-
const isComputeBudgetProgram = ix.programId.toString() ===
|
|
263
|
+
return this.instructions.findIndex((ix) => {
|
|
264
|
+
const isComputeBudgetProgram = ix.programId.toString() ===
|
|
265
|
+
"ComputeBudget111111111111111111111111111111";
|
|
224
266
|
const isSetComputeLimitIx = ix.data[0] === 2;
|
|
225
267
|
return isComputeBudgetProgram && isSetComputeLimitIx;
|
|
226
268
|
});
|
|
@@ -229,8 +271,9 @@ class Transaction {
|
|
|
229
271
|
* Find setComputeUnitPrice index within the instructions
|
|
230
272
|
*/
|
|
231
273
|
findSetComputeUnitPriceIndex() {
|
|
232
|
-
return this.instructions.findIndex(ix => {
|
|
233
|
-
const isComputeBudgetProgram = ix.programId.toString() ===
|
|
274
|
+
return this.instructions.findIndex((ix) => {
|
|
275
|
+
const isComputeBudgetProgram = ix.programId.toString() ===
|
|
276
|
+
"ComputeBudget111111111111111111111111111111";
|
|
234
277
|
const isSetComputeUnitPriceIx = ix.data[0] === 3;
|
|
235
278
|
return isComputeBudgetProgram && isSetComputeUnitPriceIx;
|
|
236
279
|
});
|