Skip to content

Commit b8ad80d

Browse files
authored
Merge pull request #94 from macalinao/igm/remove-cu-thing
Change compute units to not be included by default, add simulation
2 parents 323ef6d + 4fbbb0b commit b8ad80d

File tree

8 files changed

+96
-22
lines changed

8 files changed

+96
-22
lines changed

.changeset/happy-areas-spend.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@macalinao/gill-extra": patch
3+
"@macalinao/grill": patch
4+
---
5+
6+
Add parseTransactionError, new error type

.changeset/silent-suits-return.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@macalinao/gill-extra": minor
3+
"@macalinao/grill": minor
4+
---
5+
6+
Change compute unit stuff to be not included by default

packages/gill-extra/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ export * from "./get-solscan-explorer-link.js";
1313
export * from "./ixs/index.js";
1414
export * from "./poll-confirm-transaction.js";
1515
export * from "./transaction.js";
16+
export * from "./transaction-error.js";
1617
export * from "./types.js";
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { TransactionError } from "@solana/kit";
2+
import { getSolanaErrorFromTransactionError } from "@solana/kit";
3+
4+
export const parseTransactionError = (
5+
err: TransactionError,
6+
logs: string[] | null,
7+
): string => {
8+
// First, try to extract Anchor error from logs
9+
const anchorError = [...(logs ?? [])]
10+
.reverse()
11+
.find((log) => log.includes("AnchorError"));
12+
13+
if (anchorError) {
14+
const errorMessageStart = anchorError.indexOf("Error Message: ");
15+
if (errorMessageStart !== -1) {
16+
return anchorError.slice(errorMessageStart + 15).trim();
17+
}
18+
}
19+
20+
const solanaError = getSolanaErrorFromTransactionError(err);
21+
return solanaError.message;
22+
};

packages/gill-extra/src/types.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,17 @@ import type {
44
Instruction,
55
Signature,
66
} from "@solana/kit";
7+
import type { CreateTransactionInput } from "gill";
78

8-
export interface SendTXOptions {
9-
lookupTables?: AddressesByLookupTableAddress;
10-
/**
11-
* Compute unit limit for the transaction.
12-
* Set to null to omit compute unit limit instruction.
13-
* Defaults to 1,400,000 if not specified.
14-
*/
15-
computeUnitLimit?: number | null;
9+
export interface SendTXOptions
10+
extends Pick<
11+
CreateTransactionInput<0>,
12+
"computeUnitLimit" | "computeUnitPrice"
13+
> {
1614
/**
17-
* Compute unit price for the transaction in microlamports.
18-
* Set to null to omit compute unit price instruction.
19-
* Defaults to 100,000 if not specified.
15+
* Address lookup tables (optional)
2016
*/
21-
computeUnitPrice?: bigint | null;
17+
lookupTables?: AddressesByLookupTableAddress;
2218
/**
2319
* Whether to wait for account refetch after transaction confirmation.
2420
* When true (default), the function will wait for all writable accounts
@@ -28,6 +24,10 @@ export interface SendTXOptions {
2824
* @default true
2925
*/
3026
waitForAccountRefetch?: boolean;
27+
/**
28+
* If true, skips the pre-flight simulation.
29+
*/
30+
skipPreflight?: boolean;
3131
}
3232

3333
export type SendTXFunction = (

packages/grill/src/providers/grill-provider.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,27 @@ export const GrillProvider: FC<GrillProviderProps> = ({
207207
toastIds.current.delete(txId);
208208
break;
209209
}
210+
case "error-simulation-failed": {
211+
console.error("Simulation failed", event);
212+
const description = `Simulation failed: ${event.errorMessage}`;
213+
if (existingToastId) {
214+
// Update existing toast to error
215+
toast.error(event.title, {
216+
id: existingToastId,
217+
description,
218+
duration: errorToastDuration,
219+
});
220+
} else {
221+
// Create new error toast if somehow we don't have one
222+
toast.error(event.title, {
223+
description,
224+
duration: errorToastDuration,
225+
});
226+
}
227+
// Clean up toast ID after error
228+
toastIds.current.delete(txId);
229+
break;
230+
}
210231
}
211232
},
212233
[

packages/grill/src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ export type TransactionStatusEvent = {
3535
sig: Signature;
3636
explorerLink: string;
3737
}
38+
| {
39+
type: "error-simulation-failed";
40+
errorMessage: string;
41+
}
3842
);
3943

4044
export type TransactionStatusEventCallback = (

packages/grill/src/utils/internal/create-send-tx.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ import type { SolanaClient } from "gill";
1414
import type { TransactionStatusEvent } from "../../types.js";
1515
import {
1616
getSignatureFromBytes,
17+
parseTransactionError,
1718
pollConfirmTransaction,
1819
} from "@macalinao/gill-extra";
1920
import {
2021
compressTransactionMessageUsingAddressLookupTables,
22+
getSolanaErrorFromTransactionError,
2123
signAndSendTransactionMessageWithSigners,
2224
} from "@solana/kit";
23-
import { createTransaction } from "gill";
25+
import { createTransaction, simulateTransactionFactory } from "gill";
2426

2527
export interface CreateSendTXParams {
2628
signer: TransactionSendingSigner | null;
@@ -41,6 +43,7 @@ export const createSendTX = ({
4143
onTransactionStatusEvent,
4244
getExplorerLink,
4345
}: CreateSendTXParams): SendTXFunction => {
46+
const simulateTransaction = simulateTransactionFactory({ rpc });
4447
return async (
4548
name: string,
4649
ixs: readonly Instruction[],
@@ -70,15 +73,8 @@ export const createSendTX = ({
7073
feePayer: signer,
7174
instructions: [...ixs],
7275
latestBlockhash,
73-
// the compute budget values are HIGHLY recommend to be set in order to maximize your transaction landing rate
74-
computeUnitLimit:
75-
options.computeUnitLimit === null
76-
? undefined
77-
: (options.computeUnitLimit ?? 1_400_000),
78-
computeUnitPrice:
79-
options.computeUnitPrice === null
80-
? undefined
81-
: (options.computeUnitPrice ?? 100_000n),
76+
computeUnitLimit: options.computeUnitLimit,
77+
computeUnitPrice: options.computeUnitPrice,
8278
});
8379

8480
// Apply address lookup tables if provided to compress the transaction
@@ -91,6 +87,24 @@ export const createSendTX = ({
9187
)
9288
: transactionMessage;
9389

90+
// preflight
91+
if (!options.skipPreflight) {
92+
const simulationResult = await simulateTransaction(
93+
finalTransactionMessage,
94+
);
95+
if (simulationResult.value.err) {
96+
onTransactionStatusEvent({
97+
...baseEvent,
98+
type: "error-simulation-failed",
99+
errorMessage: parseTransactionError(
100+
simulationResult.value.err,
101+
simulationResult.value.logs,
102+
),
103+
});
104+
throw getSolanaErrorFromTransactionError(simulationResult.value.err);
105+
}
106+
}
107+
94108
onTransactionStatusEvent({
95109
...baseEvent,
96110
type: "awaiting-wallet-signature",

0 commit comments

Comments
 (0)