@stabbleorg/anchor-contrib
Advanced tools
Comparing version 0.9.1 to 1.0.0
@@ -0,29 +1,25 @@ | ||
export declare const SMART_TX_TIMEOUT = 60000; | ||
export declare const MINIMUM_PRIORITY_FEE = 10000000000; | ||
export declare namespace DAS { | ||
type TokenBalance = { | ||
id: string; | ||
token_info: { | ||
balance: number; | ||
decimals: number; | ||
}; | ||
}; | ||
type NativeBalance = { | ||
lamports: number; | ||
}; | ||
type SearchAssetsResponse = { | ||
items: TokenBalance[]; | ||
nativeBalance: NativeBalance; | ||
}; | ||
} | ||
export type PriorityLevel = "Default" | "Min" | "Low" | "Medium" | "High" | "VeryHigh" | "UnsafeMax"; | ||
export type HeliusResponse<T> = { | ||
result: T; | ||
}; | ||
export type GetPriorityFeeEstimateResponse = { | ||
priorityFeeEstimate?: number; | ||
}; | ||
export type SlotPriorityFee = { | ||
slot: number; | ||
prioritizationFee: number; | ||
export type RpcResponse<T> = { | ||
result: T; | ||
}; | ||
export type TokenAsset = { | ||
id: string; | ||
token_info: { | ||
balance: number; | ||
decimals: number; | ||
}; | ||
}; | ||
export type NativeAsset = { | ||
lamports: number; | ||
}; | ||
export type SearchAssetsResponse = { | ||
items: TokenAsset[]; | ||
nativeBalance: NativeAsset; | ||
}; | ||
/** | ||
* 0xMert suggests to set at least 10,001 lamports as priority fees when sending transactions via Helius | ||
*/ | ||
export declare const MIN_PRIORITY_FEE_RECOMMENDED: number; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.MIN_PRIORITY_FEE_RECOMMENDED = void 0; | ||
/** | ||
* 0xMert suggests to set at least 10,001 lamports as priority fees when sending transactions via Helius | ||
*/ | ||
exports.MIN_PRIORITY_FEE_RECOMMENDED = 10001000000; | ||
exports.MINIMUM_PRIORITY_FEE = exports.SMART_TX_TIMEOUT = void 0; | ||
// The transaction will be routed through Helius's staked | ||
// connections and should be confirmed in 60 seconds | ||
exports.SMART_TX_TIMEOUT = 60000; | ||
exports.MINIMUM_PRIORITY_FEE = 10000000000; | ||
//# sourceMappingURL=helius.js.map |
export * from "./wallet"; | ||
export * from "./helius"; | ||
export * from "./listener"; | ||
export * from "./parser"; | ||
export * from "./safeAmount"; | ||
export * from "./constants"; | ||
export * from "./types"; | ||
export * from "./utils"; |
@@ -19,5 +19,5 @@ "use strict"; | ||
__exportStar(require("./helius"), exports); | ||
__exportStar(require("./listener"), exports); | ||
__exportStar(require("./parser"), exports); | ||
__exportStar(require("./safeAmount"), exports); | ||
__exportStar(require("./constants"), exports); | ||
__exportStar(require("./types"), exports); | ||
__exportStar(require("./utils"), exports); | ||
//# sourceMappingURL=index.js.map |
import { Provider } from "@coral-xyz/anchor"; | ||
import { AddressLookupTableAccount, BlockhashWithExpiryBlockHeight, ConfirmOptions, PublicKey, Signer, TokenAccountBalancePair, Transaction, TransactionInstruction, TransactionSignature, VersionedTransaction } from "@solana/web3.js"; | ||
import { AddressLookupTableAccount, BlockhashWithExpiryBlockHeight, ConfirmOptions, PublicKey, Signer, TokenAccountBalancePair, TransactionInstruction, TransactionSignature, VersionedTransaction } from "@solana/web3.js"; | ||
import { PriorityLevel } from "./helius"; | ||
import { FloatLike } from "./safeAmount"; | ||
export type TransactionArgs<T> = { | ||
altAccounts?: AddressLookupTableAccount[]; | ||
priorityLevel?: PriorityLevel; | ||
} & T; | ||
export type TransactionWithRecentBlockAndSlot = { | ||
transaction: VersionedTransaction; | ||
recentBlock: BlockhashWithExpiryBlockHeight; | ||
slot: number; | ||
}; | ||
export type AddressWithOptionalInstruction = { | ||
address: PublicKey; | ||
instruction?: TransactionInstruction; | ||
}; | ||
import { AddressWithTransactionInstruction, FloatLike, TransactionWithBlockhash } from "./types"; | ||
export interface SignerProvider extends Provider { | ||
sendAndConfirmWithBlockhash(tx: Transaction | VersionedTransaction, signers?: Signer[], opts?: ConfirmOptions, blockhash?: BlockhashWithExpiryBlockHeight): Promise<TransactionSignature>; | ||
sendAndConfirmWithBlockhash(transaction: VersionedTransaction, signers?: Signer[], options?: ConfirmOptions, blockhash?: BlockhashWithExpiryBlockHeight): Promise<TransactionSignature>; | ||
} | ||
@@ -26,10 +13,10 @@ export declare class WalletContext<T extends Provider = Provider> { | ||
getAssociatedTokenAddress(mintAddress: PublicKey): PublicKey; | ||
getOrCreateAssociatedTokenAddressInstruction(mintAddress: PublicKey, ownerAddress?: PublicKey, allowOwnerOffcurve?: boolean): Promise<AddressWithOptionalInstruction>; | ||
createIntermediateTokenAccountInstructions(accountAddress: PublicKey, mintAddress: PublicKey): Promise<TransactionInstruction[]>; | ||
closeIntermediateTokenAccountInstruction(accountAddress: PublicKey): TransactionInstruction; | ||
getOrCreateAssociatedTokenAddressInstruction(mintAddress: PublicKey, ownerAddress?: PublicKey, allowOwnerOffcurve?: boolean): Promise<AddressWithTransactionInstruction>; | ||
createTokenAccountInstructions(accountAddress: PublicKey, mintAddress?: PublicKey): Promise<TransactionInstruction[]>; | ||
closeTokenAccountInstruction(accountAddress: PublicKey): TransactionInstruction; | ||
transferWSOLInstructions(accountAddress: PublicKey, amount: FloatLike): Promise<TransactionInstruction[]>; | ||
getTokenBalances(): Promise<TokenAccountBalancePair[]>; | ||
getPriorityFeeEstimate(transaction: VersionedTransaction, priorityLevel?: PriorityLevel): Promise<number>; | ||
createTransaction(instructions: TransactionInstruction[], altAccounts?: AddressLookupTableAccount[], priorityLevel?: PriorityLevel): Promise<TransactionWithRecentBlockAndSlot>; | ||
sendAndConfirmTransaction(transaction: Transaction | VersionedTransaction, recentBlock: BlockhashWithExpiryBlockHeight, minContextSlot: number, signers?: Signer[]): Promise<TransactionSignature>; | ||
getPriorityFeeEstimate(transaction: VersionedTransaction, priorityLevel: PriorityLevel): Promise<number>; | ||
createSmartTransaction(instructions: TransactionInstruction[], altAccounts?: AddressLookupTableAccount[], priorityLevel?: PriorityLevel): Promise<TransactionWithBlockhash>; | ||
sendSmartTransaction(transaction: VersionedTransaction, signers?: Signer[], options?: ConfirmOptions, blockhash?: BlockhashWithExpiryBlockHeight): Promise<TransactionSignature>; | ||
} |
@@ -21,3 +21,4 @@ "use strict"; | ||
const helius_1 = require("./helius"); | ||
const safeAmount_1 = require("./safeAmount"); | ||
const constants_1 = require("./constants"); | ||
const utils_1 = require("./utils"); | ||
class WalletContext { | ||
@@ -53,4 +54,4 @@ constructor(provider) { | ||
} | ||
createIntermediateTokenAccountInstructions(accountAddress, mintAddress) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
createTokenAccountInstructions(accountAddress_1) { | ||
return __awaiter(this, arguments, void 0, function* (accountAddress, mintAddress = spl_token_1.NATIVE_MINT) { | ||
return [ | ||
@@ -61,3 +62,3 @@ web3_js_1.SystemProgram.createAccount({ | ||
space: spl_token_1.AccountLayout.span, | ||
lamports: yield this.provider.connection.getMinimumBalanceForRentExemption(spl_token_1.AccountLayout.span), | ||
lamports: constants_1.TOKEN_ACCOUNT_RENT_FEE_LAMPORTS, | ||
programId: spl_token_1.TOKEN_PROGRAM_ID, | ||
@@ -69,3 +70,3 @@ }), | ||
} | ||
closeIntermediateTokenAccountInstruction(accountAddress) { | ||
closeTokenAccountInstruction(accountAddress) { | ||
return (0, spl_token_1.createCloseAccountInstruction)(accountAddress, this.walletAddress, this.walletAddress); | ||
@@ -75,9 +76,10 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const instructions = yield this.createIntermediateTokenAccountInstructions(accountAddress, spl_token_1.NATIVE_MINT); | ||
instructions.push(web3_js_1.SystemProgram.transfer({ | ||
fromPubkey: this.walletAddress, | ||
toPubkey: accountAddress, | ||
lamports: BigInt(safeAmount_1.SafeAmount.toGiga(amount).toString()), | ||
}), (0, spl_token_1.createSyncNativeInstruction)(accountAddress)); | ||
return instructions; | ||
return [ | ||
web3_js_1.SystemProgram.transfer({ | ||
fromPubkey: this.walletAddress, | ||
toPubkey: accountAddress, | ||
lamports: BigInt(utils_1.SafeAmount.toGiga(amount).toString()), | ||
}), | ||
(0, spl_token_1.createSyncNativeInstruction)(accountAddress), | ||
]; | ||
}); | ||
@@ -89,5 +91,3 @@ } | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
headers: { "Content-Type": "application/json" }, | ||
body: JSON.stringify({ | ||
@@ -98,3 +98,3 @@ jsonrpc: "2.0", | ||
params: { | ||
ownerAddress: this.walletAddress, | ||
ownerAddress: this.walletAddress.toBase58(), | ||
tokenType: "fungible", | ||
@@ -113,3 +113,3 @@ displayOptions: { | ||
const balances = result.items.map((item) => { | ||
const uiAmountString = safeAmount_1.SafeAmount.toUiAmountString(item.token_info.balance, item.token_info.decimals); | ||
const uiAmountString = utils_1.SafeAmount.toUiAmountString(item.token_info.balance, item.token_info.decimals); | ||
return { | ||
@@ -125,3 +125,3 @@ address: new web3_js_1.PublicKey(item.id), | ||
const wrappedSOL = balances.find((balance) => balance.address.equals(spl_token_1.NATIVE_MINT)); | ||
const uiAmountString = safeAmount_1.SafeAmount.toNanoString(result.nativeBalance.lamports); | ||
const uiAmountString = utils_1.SafeAmount.toNanoString(result.nativeBalance.lamports); | ||
if (wrappedSOL) { | ||
@@ -146,4 +146,4 @@ const newUiAmount = new decimal_js_1.default(wrappedSOL.uiAmountString).add(new decimal_js_1.default(uiAmountString)).toDP(9); | ||
} | ||
getPriorityFeeEstimate(transaction_1) { | ||
return __awaiter(this, arguments, void 0, function* (transaction, priorityLevel = "Medium") { | ||
getPriorityFeeEstimate(transaction, priorityLevel) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
@@ -166,79 +166,78 @@ const response = yield fetch(this.provider.connection.rpcEndpoint, { | ||
const { result } = (yield response.json()); | ||
return Math.trunc(result.priorityFeeEstimate || 0); | ||
return result.priorityFeeEstimate ? Math.ceil(result.priorityFeeEstimate) : 0; | ||
} | ||
catch (err) { | ||
const response = yield fetch(this.provider.connection.rpcEndpoint, { | ||
method: "POST", | ||
headers: { "Content-Type": "application/json" }, | ||
body: JSON.stringify({ | ||
jsonrpc: "2.0", | ||
id: this.walletAddress.toBase58(), | ||
method: "getRecentPrioritizationFees", | ||
params: [ | ||
transaction.message.staticAccountKeys | ||
.filter((_, index) => transaction.message.isAccountSigner(index)) | ||
.map((key) => key.toBase58()), | ||
], | ||
}), | ||
}); | ||
const { result } = (yield response.json()); | ||
const priorityFeeEstimate = result.reduce((sum, item) => sum + item.prioritizationFee, 0) / result.length; | ||
return priorityFeeEstimate; | ||
return 0; | ||
} | ||
}); | ||
} | ||
createTransaction(instructions_1) { | ||
createSmartTransaction(instructions_1) { | ||
return __awaiter(this, arguments, void 0, function* (instructions, altAccounts = [], priorityLevel = "High") { | ||
const { value: recentBlock, context: { slot }, } = yield this.provider.connection.getLatestBlockhashAndContext(); | ||
try { | ||
// transaction to simulate | ||
const transaction = new web3_js_1.VersionedTransaction(new web3_js_1.TransactionMessage({ | ||
payerKey: this.walletAddress, | ||
recentBlockhash: recentBlock.blockhash, | ||
instructions: [ | ||
web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ | ||
microLamports: 0, | ||
}), | ||
web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ | ||
units: 140000000, | ||
}), | ||
...instructions, | ||
], | ||
}).compileToV0Message(altAccounts)); | ||
// calculate priority fee | ||
let priorityFee = yield this.getPriorityFeeEstimate(transaction, priorityLevel); | ||
// calculate exact compute units needed | ||
const { value: sim } = yield this.provider.connection.simulateTransaction(transaction); | ||
if (sim.unitsConsumed) { | ||
instructions.unshift(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ | ||
units: sim.unitsConsumed, | ||
})); | ||
const minPriorityFee = Math.ceil(helius_1.MIN_PRIORITY_FEE_RECOMMENDED / sim.unitsConsumed); | ||
if (minPriorityFee > priorityFee) | ||
priorityFee = minPriorityFee; | ||
const { value: blockhash, context: { slot: minContextSlot }, } = yield this.provider.connection.getLatestBlockhashAndContext(); | ||
const hasCBInstructions = instructions.some((instruction) => instruction.programId.equals(web3_js_1.ComputeBudgetProgram.programId)); | ||
if (!hasCBInstructions) { | ||
try { | ||
// transaction to simulate | ||
const transaction = new web3_js_1.VersionedTransaction(new web3_js_1.TransactionMessage({ | ||
payerKey: this.walletAddress, | ||
recentBlockhash: blockhash.blockhash, | ||
instructions: [ | ||
web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ | ||
microLamports: 1, | ||
}), | ||
web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ | ||
units: 140000000, | ||
}), | ||
...instructions, | ||
], | ||
}).compileToV0Message(altAccounts)); | ||
// calculate exact compute units needed | ||
const { value: sim } = yield this.provider.connection.simulateTransaction(transaction); | ||
if (sim.unitsConsumed) { | ||
instructions.unshift(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ | ||
units: sim.unitsConsumed, | ||
})); | ||
const priorityFee = yield this.getPriorityFeeEstimate(transaction, priorityLevel); | ||
const minPriorityFee = Math.ceil(helius_1.MINIMUM_PRIORITY_FEE / sim.unitsConsumed); | ||
instructions.unshift(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ | ||
microLamports: Math.max(priorityFee, minPriorityFee), | ||
})); | ||
} | ||
} | ||
if (priorityFee) { | ||
instructions.unshift(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ | ||
microLamports: priorityFee, | ||
})); | ||
} | ||
catch (err) { } | ||
} | ||
catch (err) { } | ||
// transaction to send | ||
const transaction = new web3_js_1.VersionedTransaction(new web3_js_1.TransactionMessage({ | ||
payerKey: this.walletAddress, | ||
recentBlockhash: recentBlock.blockhash, | ||
recentBlockhash: blockhash.blockhash, | ||
instructions, | ||
}).compileToV0Message(altAccounts)); | ||
return { transaction, recentBlock, slot }; | ||
return { transaction, blockhash, minContextSlot }; | ||
}); | ||
} | ||
sendAndConfirmTransaction(transaction_1, recentBlock_1, minContextSlot_1) { | ||
return __awaiter(this, arguments, void 0, function* (transaction, recentBlock, minContextSlot, signers = []) { | ||
sendSmartTransaction(transaction_1) { | ||
return __awaiter(this, arguments, void 0, function* (transaction, signers = [], options, blockhash) { | ||
const confirmOptions = Object.assign({ maxRetries: 0, commitment: "confirmed", preflightCommitment: "confirmed", skipPreflight: true }, options); | ||
if ("sendAndConfirmWithBlockhash" in this.provider) { | ||
return this.provider.sendAndConfirmWithBlockhash(transaction, signers, { minContextSlot }, recentBlock); | ||
return this.provider.sendAndConfirmWithBlockhash(transaction, signers, confirmOptions, blockhash); | ||
} | ||
if (!this.provider.sendAndConfirm) | ||
throw Error("'sendAndConfirm' is not implemented in this Provider"); | ||
return this.provider.sendAndConfirm(transaction, signers, { minContextSlot }); | ||
if (!this.provider.sendAndConfirm) { | ||
throw Error("The 'sendAndConfirm' is not implemented in this Provider"); | ||
} | ||
const startTime = Date.now(); | ||
while (Date.now() - startTime < helius_1.SMART_TX_TIMEOUT) { | ||
try { | ||
const signature = yield this.provider.sendAndConfirm(transaction, signers, confirmOptions); | ||
return signature; | ||
} | ||
catch (err) { | ||
if (err instanceof web3_js_1.TransactionExpiredTimeoutError) { | ||
continue; | ||
} | ||
else { | ||
throw err; | ||
} | ||
} | ||
} | ||
throw Error("Transaction failed to confirm in 60s"); | ||
}); | ||
@@ -245,0 +244,0 @@ } |
{ | ||
"name": "@stabbleorg/anchor-contrib", | ||
"version": "0.9.1", | ||
"version": "1.0.0", | ||
"main": "dist/index.js", | ||
@@ -19,3 +19,3 @@ "types": "dist/index.d.ts", | ||
"@solana/spl-token": "^0.4.0", | ||
"@solana/web3.js": "^1.91.0", | ||
"@solana/web3.js": "^1.92.0", | ||
"bn.js": "^5.2.1", | ||
@@ -27,5 +27,5 @@ "bs58": "^5.0.0", | ||
"@types/bn.js": "^5.1.5", | ||
"prettier": "^3.2.5", | ||
"prettier": "^3.3.0", | ||
"typescript": "^5.4.5" | ||
} | ||
} |
@@ -1,36 +0,34 @@ | ||
export type PriorityLevel = "Default" | "Min" | "Low" | "Medium" | "High" | "VeryHigh" | "UnsafeMax"; | ||
// The transaction will be routed through Helius's staked | ||
// connections and should be confirmed in 60 seconds | ||
export const SMART_TX_TIMEOUT = 60000; | ||
export type HeliusResponse<T> = { | ||
result: T; | ||
}; | ||
export const MINIMUM_PRIORITY_FEE = 10_000_000_000; | ||
export type GetPriorityFeeEstimateResponse = { | ||
priorityFeeEstimate?: number; | ||
}; | ||
export namespace DAS { | ||
export type TokenBalance = { | ||
id: string; | ||
token_info: { | ||
balance: number; | ||
decimals: number; | ||
}; | ||
}; | ||
export type SlotPriorityFee = { | ||
slot: number; | ||
prioritizationFee: number; | ||
}; | ||
export type NativeBalance = { | ||
lamports: number; | ||
}; | ||
export type TokenAsset = { | ||
id: string; | ||
token_info: { | ||
balance: number; | ||
decimals: number; | ||
export type SearchAssetsResponse = { | ||
items: TokenBalance[]; | ||
nativeBalance: NativeBalance; | ||
}; | ||
}; | ||
} | ||
export type NativeAsset = { | ||
lamports: number; | ||
export type PriorityLevel = "Default" | "Min" | "Low" | "Medium" | "High" | "VeryHigh" | "UnsafeMax"; | ||
export type GetPriorityFeeEstimateResponse = { | ||
priorityFeeEstimate?: number; | ||
}; | ||
export type SearchAssetsResponse = { | ||
items: TokenAsset[]; | ||
nativeBalance: NativeAsset; | ||
export type RpcResponse<T> = { | ||
result: T; | ||
}; | ||
/** | ||
* 0xMert suggests to set at least 10,001 lamports as priority fees when sending transactions via Helius | ||
*/ | ||
export const MIN_PRIORITY_FEE_RECOMMENDED: number = 10001000000; |
export * from "./wallet"; | ||
export * from "./helius"; | ||
export * from "./listener"; | ||
export * from "./parser"; | ||
export * from "./safeAmount"; | ||
export * from "./constants"; | ||
export * from "./types"; | ||
export * from "./utils"; |
@@ -25,3 +25,3 @@ import bs58 from "bs58"; | ||
TokenAccountBalancePair, | ||
Transaction, | ||
TransactionExpiredTimeoutError, | ||
TransactionInstruction, | ||
@@ -33,32 +33,18 @@ TransactionMessage, | ||
import { | ||
HeliusResponse, | ||
PriorityLevel, | ||
RpcResponse, | ||
GetPriorityFeeEstimateResponse, | ||
PriorityLevel, | ||
SearchAssetsResponse, | ||
SlotPriorityFee, | ||
MIN_PRIORITY_FEE_RECOMMENDED, | ||
DAS, | ||
SMART_TX_TIMEOUT, | ||
MINIMUM_PRIORITY_FEE, | ||
} from "./helius"; | ||
import { FloatLike, SafeAmount } from "./safeAmount"; | ||
import { AddressWithTransactionInstruction, FloatLike, TransactionWithBlockhash } from "./types"; | ||
import { TOKEN_ACCOUNT_RENT_FEE_LAMPORTS } from "./constants"; | ||
import { SafeAmount } from "./utils"; | ||
export type TransactionArgs<T> = { | ||
altAccounts?: AddressLookupTableAccount[]; | ||
priorityLevel?: PriorityLevel; | ||
} & T; | ||
export type TransactionWithRecentBlockAndSlot = { | ||
transaction: VersionedTransaction; | ||
recentBlock: BlockhashWithExpiryBlockHeight; | ||
slot: number; | ||
}; | ||
export type AddressWithOptionalInstruction = { | ||
address: PublicKey; | ||
instruction?: TransactionInstruction; | ||
}; | ||
export interface SignerProvider extends Provider { | ||
sendAndConfirmWithBlockhash( | ||
tx: Transaction | VersionedTransaction, | ||
transaction: VersionedTransaction, | ||
signers?: Signer[], | ||
opts?: ConfirmOptions, | ||
options?: ConfirmOptions, | ||
blockhash?: BlockhashWithExpiryBlockHeight, | ||
@@ -84,3 +70,3 @@ ): Promise<TransactionSignature>; | ||
allowOwnerOffcurve: boolean = false, | ||
): Promise<AddressWithOptionalInstruction> { | ||
): Promise<AddressWithTransactionInstruction> { | ||
const address = getAssociatedTokenAddressSync(mintAddress, ownerAddress, allowOwnerOffcurve); | ||
@@ -102,5 +88,5 @@ | ||
async createIntermediateTokenAccountInstructions( | ||
async createTokenAccountInstructions( | ||
accountAddress: PublicKey, | ||
mintAddress: PublicKey, | ||
mintAddress: PublicKey = NATIVE_MINT, | ||
): Promise<TransactionInstruction[]> { | ||
@@ -112,3 +98,3 @@ return [ | ||
space: AccountLayout.span, | ||
lamports: await this.provider.connection.getMinimumBalanceForRentExemption(AccountLayout.span), | ||
lamports: TOKEN_ACCOUNT_RENT_FEE_LAMPORTS, | ||
programId: TOKEN_PROGRAM_ID, | ||
@@ -120,3 +106,3 @@ }), | ||
closeIntermediateTokenAccountInstruction(accountAddress: PublicKey): TransactionInstruction { | ||
closeTokenAccountInstruction(accountAddress: PublicKey): TransactionInstruction { | ||
return createCloseAccountInstruction(accountAddress, this.walletAddress, this.walletAddress); | ||
@@ -126,4 +112,3 @@ } | ||
async transferWSOLInstructions(accountAddress: PublicKey, amount: FloatLike): Promise<TransactionInstruction[]> { | ||
const instructions = await this.createIntermediateTokenAccountInstructions(accountAddress, NATIVE_MINT); | ||
instructions.push( | ||
return [ | ||
SystemProgram.transfer({ | ||
@@ -135,4 +120,3 @@ fromPubkey: this.walletAddress, | ||
createSyncNativeInstruction(accountAddress), | ||
); | ||
return instructions; | ||
]; | ||
} | ||
@@ -143,5 +127,3 @@ | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
headers: { "Content-Type": "application/json" }, | ||
body: JSON.stringify({ | ||
@@ -152,3 +134,3 @@ jsonrpc: "2.0", | ||
params: { | ||
ownerAddress: this.walletAddress, | ||
ownerAddress: this.walletAddress.toBase58(), | ||
tokenType: "fungible", | ||
@@ -166,3 +148,4 @@ displayOptions: { | ||
const { result } = (await response.json()) as HeliusResponse<SearchAssetsResponse>; | ||
const { result } = (await response.json()) as RpcResponse<DAS.SearchAssetsResponse>; | ||
const balances = result.items.map<TokenAccountBalancePair>((item) => { | ||
@@ -202,6 +185,3 @@ const uiAmountString = SafeAmount.toUiAmountString(item.token_info.balance, item.token_info.decimals); | ||
async getPriorityFeeEstimate( | ||
transaction: VersionedTransaction, | ||
priorityLevel: PriorityLevel = "Medium", | ||
): Promise<number> { | ||
async getPriorityFeeEstimate(transaction: VersionedTransaction, priorityLevel: PriorityLevel): Promise<number> { | ||
try { | ||
@@ -224,83 +204,65 @@ const response = await fetch(this.provider.connection.rpcEndpoint, { | ||
const { result } = (await response.json()) as HeliusResponse<GetPriorityFeeEstimateResponse>; | ||
const { result } = (await response.json()) as RpcResponse<GetPriorityFeeEstimateResponse>; | ||
return Math.trunc(result.priorityFeeEstimate || 0); | ||
return result.priorityFeeEstimate ? Math.ceil(result.priorityFeeEstimate) : 0; | ||
} catch (err) { | ||
const response = await fetch(this.provider.connection.rpcEndpoint, { | ||
method: "POST", | ||
headers: { "Content-Type": "application/json" }, | ||
body: JSON.stringify({ | ||
jsonrpc: "2.0", | ||
id: this.walletAddress.toBase58(), | ||
method: "getRecentPrioritizationFees", | ||
params: [ | ||
transaction.message.staticAccountKeys | ||
.filter((_, index) => transaction.message.isAccountSigner(index)) | ||
.map((key) => key.toBase58()), | ||
], | ||
}), | ||
}); | ||
const { result } = (await response.json()) as HeliusResponse<SlotPriorityFee[]>; | ||
const priorityFeeEstimate = result.reduce((sum, item) => sum + item.prioritizationFee, 0) / result.length; | ||
return priorityFeeEstimate; | ||
return 0; | ||
} | ||
} | ||
async createTransaction( | ||
async createSmartTransaction( | ||
instructions: TransactionInstruction[], | ||
altAccounts: AddressLookupTableAccount[] = [], | ||
priorityLevel: PriorityLevel = "High", | ||
): Promise<TransactionWithRecentBlockAndSlot> { | ||
): Promise<TransactionWithBlockhash> { | ||
const { | ||
value: recentBlock, | ||
context: { slot }, | ||
value: blockhash, | ||
context: { slot: minContextSlot }, | ||
} = await this.provider.connection.getLatestBlockhashAndContext(); | ||
try { | ||
// transaction to simulate | ||
const transaction = new VersionedTransaction( | ||
new TransactionMessage({ | ||
payerKey: this.walletAddress, | ||
recentBlockhash: recentBlock.blockhash, | ||
instructions: [ | ||
ComputeBudgetProgram.setComputeUnitPrice({ | ||
microLamports: 0, | ||
}), | ||
ComputeBudgetProgram.setComputeUnitLimit({ | ||
units: 140000000, | ||
}), | ||
...instructions, | ||
], | ||
}).compileToV0Message(altAccounts), | ||
); | ||
const hasCBInstructions = instructions.some((instruction) => | ||
instruction.programId.equals(ComputeBudgetProgram.programId), | ||
); | ||
// calculate priority fee | ||
let priorityFee = await this.getPriorityFeeEstimate(transaction, priorityLevel); | ||
// calculate exact compute units needed | ||
const { value: sim } = await this.provider.connection.simulateTransaction(transaction); | ||
if (sim.unitsConsumed) { | ||
instructions.unshift( | ||
ComputeBudgetProgram.setComputeUnitLimit({ | ||
units: sim.unitsConsumed, | ||
}), | ||
if (!hasCBInstructions) { | ||
try { | ||
// transaction to simulate | ||
const transaction = new VersionedTransaction( | ||
new TransactionMessage({ | ||
payerKey: this.walletAddress, | ||
recentBlockhash: blockhash.blockhash, | ||
instructions: [ | ||
ComputeBudgetProgram.setComputeUnitPrice({ | ||
microLamports: 1, | ||
}), | ||
ComputeBudgetProgram.setComputeUnitLimit({ | ||
units: 140_000_000, | ||
}), | ||
...instructions, | ||
], | ||
}).compileToV0Message(altAccounts), | ||
); | ||
const minPriorityFee = Math.ceil(MIN_PRIORITY_FEE_RECOMMENDED / sim.unitsConsumed); | ||
// calculate exact compute units needed | ||
const { value: sim } = await this.provider.connection.simulateTransaction(transaction); | ||
if (minPriorityFee > priorityFee) priorityFee = minPriorityFee; | ||
} | ||
if (sim.unitsConsumed) { | ||
instructions.unshift( | ||
ComputeBudgetProgram.setComputeUnitLimit({ | ||
units: sim.unitsConsumed, | ||
}), | ||
); | ||
if (priorityFee) { | ||
instructions.unshift( | ||
ComputeBudgetProgram.setComputeUnitPrice({ | ||
microLamports: priorityFee, | ||
}), | ||
); | ||
} | ||
} catch (err) {} | ||
const priorityFee = await this.getPriorityFeeEstimate(transaction, priorityLevel); | ||
const minPriorityFee = Math.ceil(MINIMUM_PRIORITY_FEE / sim.unitsConsumed); | ||
instructions.unshift( | ||
ComputeBudgetProgram.setComputeUnitPrice({ | ||
microLamports: Math.max(priorityFee, minPriorityFee), | ||
}), | ||
); | ||
} | ||
} catch (err) {} | ||
} | ||
// transaction to send | ||
@@ -310,3 +272,3 @@ const transaction = new VersionedTransaction( | ||
payerKey: this.walletAddress, | ||
recentBlockhash: recentBlock.blockhash, | ||
recentBlockhash: blockhash.blockhash, | ||
instructions, | ||
@@ -316,11 +278,19 @@ }).compileToV0Message(altAccounts), | ||
return { transaction, recentBlock, slot }; | ||
return { transaction, blockhash, minContextSlot }; | ||
} | ||
async sendAndConfirmTransaction( | ||
transaction: Transaction | VersionedTransaction, | ||
recentBlock: BlockhashWithExpiryBlockHeight, | ||
minContextSlot: number, | ||
async sendSmartTransaction( | ||
transaction: VersionedTransaction, | ||
signers: Signer[] = [], | ||
options?: ConfirmOptions, | ||
blockhash?: BlockhashWithExpiryBlockHeight, | ||
): Promise<TransactionSignature> { | ||
const confirmOptions: ConfirmOptions = { | ||
maxRetries: 0, | ||
commitment: "confirmed", | ||
preflightCommitment: "confirmed", | ||
skipPreflight: true, | ||
...options, | ||
}; | ||
if ("sendAndConfirmWithBlockhash" in this.provider) { | ||
@@ -330,11 +300,29 @@ return (this.provider as SignerProvider).sendAndConfirmWithBlockhash( | ||
signers, | ||
{ minContextSlot }, | ||
recentBlock, | ||
confirmOptions, | ||
blockhash, | ||
); | ||
} | ||
if (!this.provider.sendAndConfirm) throw Error("'sendAndConfirm' is not implemented in this Provider"); | ||
if (!this.provider.sendAndConfirm) { | ||
throw Error("The 'sendAndConfirm' is not implemented in this Provider"); | ||
} | ||
return this.provider.sendAndConfirm(transaction, signers, { minContextSlot }); | ||
const startTime = Date.now(); | ||
while (Date.now() - startTime < SMART_TX_TIMEOUT) { | ||
try { | ||
const signature = await this.provider.sendAndConfirm(transaction, signers, confirmOptions); | ||
return signature; | ||
} catch (err) { | ||
if (err instanceof TransactionExpiredTimeoutError) { | ||
continue; | ||
} else { | ||
throw err; | ||
} | ||
} | ||
} | ||
throw Error("Transaction failed to confirm in 60s"); | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
45503
845
1
2
Updated@solana/web3.js@^1.92.0