Bläddra i källkod

use kit under the hood (#68)

* feat: add kit as dep

* feat: add send and confirm with signers factory

* refactor: reexport kit

* refactor: removed kit

* chore: changeset

* refactor: revert to same debug
Nick Frostbutter 8 månader sedan
förälder
incheckning
a320da828d
30 ändrade filer med 266 tillägg och 2240 borttagningar
  1. 5 0
      .changeset/slimy-moons-sing.md
  2. 1 1
      .prettierrc
  3. 0 26
      package.json
  4. 2 24
      packages/gill/package.json
  5. 0 114
      packages/gill/src/__tests__/kit/airdrop-internal-test.ts
  6. 0 279
      packages/gill/src/__tests__/kit/compute-limit-internal-test.ts
  7. 0 362
      packages/gill/src/__tests__/kit/decompile-transaction-message-fetching-lookup-tables-test.ts
  8. 0 330
      packages/gill/src/__tests__/kit/send-transaction-internal-test.ts
  9. 6 9
      packages/gill/src/__typetests__/create-solana-client.ts
  10. 0 62
      packages/gill/src/__typetests__/kit/airdrop-typetests.ts
  11. 0 69
      packages/gill/src/__typetests__/kit/send-and-confirm-durable-nonce-transaction-typetests.ts
  12. 0 69
      packages/gill/src/__typetests__/kit/send-and-confirm-transaction-typetests.ts
  13. 68 0
      packages/gill/src/__typetests__/send-and-confirm-transaction-with-signers-typetests.ts
  14. 8 9
      packages/gill/src/core/create-solana-client.ts
  15. 1 0
      packages/gill/src/core/index.ts
  16. 16 23
      packages/gill/src/core/prepare-transaction.ts
  17. 101 0
      packages/gill/src/core/send-and-confirm-transaction-with-signers.ts
  18. 1 25
      packages/gill/src/index.ts
  19. 0 38
      packages/gill/src/kit/airdrop-internal.ts
  20. 0 54
      packages/gill/src/kit/airdrop.ts
  21. 0 200
      packages/gill/src/kit/compute-limit-internal.ts
  22. 0 31
      packages/gill/src/kit/compute-limit.ts
  23. 0 66
      packages/gill/src/kit/decompile-transaction-message-fetching-lookup-tables.ts
  24. 0 11
      packages/gill/src/kit/index.ts
  25. 0 75
      packages/gill/src/kit/send-and-confirm-durable-nonce-transaction.ts
  26. 0 80
      packages/gill/src/kit/send-and-confirm-transaction.ts
  27. 0 139
      packages/gill/src/kit/send-transaction-internal.ts
  28. 0 25
      packages/gill/src/kit/send-transaction-without-confirming.ts
  29. 3 3
      packages/gill/src/types/rpc.ts
  30. 54 116
      pnpm-lock.yaml

+ 5 - 0
.changeset/slimy-moons-sing.md

@@ -0,0 +1,5 @@
+---
+"gill": minor
+---
+
+consume kit instead of manually reexporting

+ 1 - 1
.prettierrc

@@ -7,5 +7,5 @@
   "trailingComma": "all",
   "proseWrap": "always",
   "arrowParens": "always",
-  "printWidth": 100
+  "printWidth": 120
 }

+ 0 - 26
package.json

@@ -29,32 +29,6 @@
     "pnpm": "^9",
     "yarn": "please-use-pnpm"
   },
-  "peerDependencies": {
-    "@solana/web3.js": ">=2.0.0",
-    "@solana/kit": "*"
-  },
-  "peerDependenciesMeta": {
-    "@solana/web3.js@^2.0.0": {
-      "optional": true
-    },
-    "@solana/kit": {
-      "optional": true
-    }
-  },
-  "overrides": {
-    "@solana/web3.js@^2.0.0": "npm:gill",
-    "@solana/kit": "npm:gill"
-  },
-  "resolutions": {
-    "@solana/web3.js@^2.0.0": "npm:gill",
-    "@solana/kit": "npm:gill"
-  },
-  "pnpm": {
-    "overrides": {
-      "@solana/web3.js@^2.0.0": "npm:gill",
-      "@solana/kit": "npm:gill"
-    }
-  },
   "devDependencies": {
     "@changesets/changelog-github": "^0.5.0",
     "@changesets/cli": "^2.27.10",

+ 2 - 24
packages/gill/package.json

@@ -106,6 +106,7 @@
     "@solana/functional": "^2.1.0",
     "@solana/instructions": "^2.1.0",
     "@solana/keys": "^2.1.0",
+    "@solana/kit": "^2.1.0",
     "@solana/programs": "^2.1.0",
     "@solana/rpc": "^2.1.0",
     "@solana/rpc-parsed-types": "^2.1.0",
@@ -118,29 +119,6 @@
     "@solana/transactions": "^2.1.0"
   },
   "peerDependencies": {
-    "typescript": ">=5",
-    "@solana/kit": "*"
-  },
-  "peerDependenciesMeta": {
-    "@solana/web3.js@^2.0.0": {
-      "optional": true
-    },
-    "@solana/kit": {
-      "optional": true
-    }
-  },
-  "overrides": {
-    "@solana/web3.js@^2.0.0": "npm:gill",
-    "@solana/kit": "npm:gill"
-  },
-  "resolutions": {
-    "@solana/web3.js@^2.0.0": "npm:gill",
-    "@solana/kit": "npm:gill"
-  },
-  "pnpm": {
-    "overrides": {
-      "@solana/web3.js@^2.0.0": "npm:gill",
-      "@solana/kit": "npm:gill"
-    }
+    "typescript": ">=5"
   }
 }

+ 0 - 114
packages/gill/src/__tests__/kit/airdrop-internal-test.ts

@@ -1,114 +0,0 @@
-import type { Address } from '@solana/addresses';
-import type { Signature } from '@solana/keys';
-import type { GetSignatureStatusesApi, RequestAirdropApi, Rpc } from '@solana/rpc';
-import { lamports } from '@solana/rpc-types';
-
-import { requestAndConfirmAirdrop_INTERNAL_ONLY_DO_NOT_EXPORT } from '../../kit/airdrop-internal';
-
-const FOREVER_PROMISE = new Promise(() => {
-    /* never resolve */
-});
-
-describe('requestAndConfirmAirdrop', () => {
-    let confirmSignatureOnlyTransaction: jest.Mock;
-    let rpc: Rpc<GetSignatureStatusesApi & RequestAirdropApi>;
-    let requestAirdrop: jest.Mock;
-    let sendAirdropRequest: jest.Mock;
-    beforeEach(() => {
-        jest.useFakeTimers();
-        confirmSignatureOnlyTransaction = jest.fn().mockReturnValue(FOREVER_PROMISE);
-        sendAirdropRequest = jest.fn().mockReturnValue(FOREVER_PROMISE);
-        requestAirdrop = jest.fn().mockReturnValue({ send: sendAirdropRequest });
-        rpc = {
-            getSignatureStatuses: jest.fn().mockReturnValue({ send: jest.fn() }),
-            requestAirdrop,
-        };
-    });
-    it('aborts the `requestAirdrop` request when aborted', () => {
-        const abortController = new AbortController();
-        requestAndConfirmAirdrop_INTERNAL_ONLY_DO_NOT_EXPORT({
-            abortSignal: abortController.signal,
-            commitment: 'finalized',
-            confirmSignatureOnlyTransaction,
-            lamports: lamports(1n),
-            recipientAddress: '123' as Address,
-            rpc,
-        }).catch(() => {});
-        expect(sendAirdropRequest).toHaveBeenCalledWith({
-            abortSignal: expect.objectContaining({ aborted: false }),
-        });
-        abortController.abort();
-        expect(sendAirdropRequest).toHaveBeenCalledWith({
-            abortSignal: expect.objectContaining({ aborted: true }),
-        });
-    });
-    it('aborts the `confirmSignatureOnlyTransaction` call when aborted', async () => {
-        expect.assertions(2);
-        const abortController = new AbortController();
-        sendAirdropRequest.mockResolvedValue('abc' as Signature);
-        requestAndConfirmAirdrop_INTERNAL_ONLY_DO_NOT_EXPORT({
-            abortSignal: abortController.signal,
-            commitment: 'finalized',
-            confirmSignatureOnlyTransaction,
-            lamports: lamports(1n),
-            recipientAddress: '123' as Address,
-            rpc,
-        }).catch(() => {});
-        await jest.runAllTimersAsync();
-        expect(confirmSignatureOnlyTransaction).toHaveBeenCalledWith(
-            expect.objectContaining({
-                abortSignal: expect.objectContaining({ aborted: false }),
-            }),
-        );
-        abortController.abort();
-        expect(confirmSignatureOnlyTransaction).toHaveBeenCalledWith(
-            expect.objectContaining({
-                abortSignal: expect.objectContaining({ aborted: true }),
-            }),
-        );
-    });
-    it('passes the expected input to the airdrop request', () => {
-        sendAirdropRequest.mockResolvedValue('abc' as Signature);
-        requestAndConfirmAirdrop_INTERNAL_ONLY_DO_NOT_EXPORT({
-            abortSignal: new AbortController().signal,
-            commitment: 'finalized',
-            confirmSignatureOnlyTransaction,
-            lamports: lamports(1n),
-            recipientAddress: '123' as Address,
-            rpc,
-        }).catch(() => {});
-        expect(requestAirdrop).toHaveBeenCalledWith('123', 1n, { commitment: 'finalized' });
-    });
-    it('passes the expected input to the transaction confirmer', async () => {
-        expect.assertions(1);
-        sendAirdropRequest.mockResolvedValue('abc' as Signature);
-        requestAndConfirmAirdrop_INTERNAL_ONLY_DO_NOT_EXPORT({
-            abortSignal: new AbortController().signal,
-            commitment: 'finalized',
-            confirmSignatureOnlyTransaction,
-            lamports: lamports(1n),
-            recipientAddress: '123' as Address,
-            rpc,
-        }).catch(() => {});
-        await jest.runAllTimersAsync();
-        expect(confirmSignatureOnlyTransaction).toHaveBeenCalledWith({
-            abortSignal: expect.any(AbortSignal),
-            commitment: 'finalized',
-            signature: 'abc' as Signature,
-        });
-    });
-    it('returns the airdrop transaction signature on success', async () => {
-        expect.assertions(1);
-        sendAirdropRequest.mockResolvedValue('abc' as Signature);
-        confirmSignatureOnlyTransaction.mockResolvedValue(undefined);
-        const airdropPromise = requestAndConfirmAirdrop_INTERNAL_ONLY_DO_NOT_EXPORT({
-            abortSignal: new AbortController().signal,
-            commitment: 'finalized',
-            confirmSignatureOnlyTransaction,
-            lamports: lamports(1n),
-            recipientAddress: '123' as Address,
-            rpc,
-        });
-        await expect(airdropPromise).resolves.toBe('abc');
-    });
-});

+ 0 - 279
packages/gill/src/__tests__/kit/compute-limit-internal-test.ts

@@ -1,279 +0,0 @@
-import { Address } from '@solana/addresses';
-import {
-    SOLANA_ERROR__INSTRUCTION_ERROR__INSUFFICIENT_FUNDS,
-    SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT,
-    SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT,
-    SolanaError,
-} from '@solana/errors';
-import { AccountRole } from '@solana/instructions';
-import { Rpc, SimulateTransactionApi } from '@solana/rpc';
-import { Blockhash, TransactionError } from '@solana/rpc-types';
-import { ITransactionMessageWithFeePayer, Nonce, TransactionMessage } from '@solana/transaction-messages';
-
-import { getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT } from '../../kit/compute-limit-internal';
-
-const FOREVER_PROMISE = new Promise(() => {
-    /* never resolve */
-});
-
-const MOCK_BLOCKHASH_LIFETIME_CONSTRAINT = {
-    blockhash: 'GNtuHnNyW68wviopST3ki37Afv7LPphxfSwiHAkX5Q9H' as Blockhash,
-    lastValidBlockHeight: 0n,
-} as const;
-
-describe('getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT', () => {
-    let sendSimulateTransactionRequest: jest.Mock;
-    let mockTransactionMessage: ITransactionMessageWithFeePayer & TransactionMessage;
-    let rpc: Rpc<SimulateTransactionApi>;
-    let simulateTransaction: jest.Mock;
-    beforeEach(() => {
-        mockTransactionMessage = {
-            feePayer: { address: '7U8VWgTUucttJPt5Bbkt48WknWqRGBfstBt8qqLHnfPT' as Address },
-            instructions: [],
-            version: 0,
-        };
-        sendSimulateTransactionRequest = jest.fn().mockReturnValue(FOREVER_PROMISE);
-        simulateTransaction = jest.fn().mockReturnValue({ send: sendSimulateTransactionRequest });
-        rpc = {
-            simulateTransaction,
-        };
-    });
-    it('aborts the `simulateTransaction` request when aborted', () => {
-        const abortController = new AbortController();
-        getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-            abortSignal: abortController.signal,
-            rpc,
-            transactionMessage: {
-                ...mockTransactionMessage,
-                lifetimeConstraint: MOCK_BLOCKHASH_LIFETIME_CONSTRAINT,
-            },
-        }).catch(() => {});
-        expect(sendSimulateTransactionRequest).toHaveBeenCalledWith({
-            abortSignal: expect.objectContaining({ aborted: false }),
-        });
-        abortController.abort();
-        expect(sendSimulateTransactionRequest).toHaveBeenCalledWith({
-            abortSignal: expect.objectContaining({ aborted: true }),
-        });
-    });
-    it('passes the expected basic input to the simulation request', () => {
-        const transactionMessage = {
-            ...mockTransactionMessage,
-            lifetimeConstraint: MOCK_BLOCKHASH_LIFETIME_CONSTRAINT,
-        };
-        getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-            commitment: 'finalized',
-            minContextSlot: 42n,
-            rpc,
-            transactionMessage,
-        }).catch(() => {});
-        expect(simulateTransaction).toHaveBeenCalledWith(
-            expect.any(String),
-            expect.objectContaining({
-                commitment: 'finalized',
-                encoding: 'base64',
-                minContextSlot: 42n,
-                sigVerify: false,
-            }),
-        );
-    });
-    it('appends a set compute unit limit instruction when one does not exist', async () => {
-        expect.assertions(1);
-        await jest.isolateModulesAsync(async () => {
-            jest.mock('@solana/transactions');
-            const [
-                { compileTransaction },
-                { getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT },
-            ] = await Promise.all([
-                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-                // @ts-ignore
-                import('@solana/transactions'),
-                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-                // @ts-ignore
-                import('../../kit/compute-limit-internal'),
-            ]);
-            const transactionMessage = {
-                ...mockTransactionMessage, // No `SetComputeUnitLimit` instruction
-                lifetimeConstraint: MOCK_BLOCKHASH_LIFETIME_CONSTRAINT,
-            };
-            getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-                rpc,
-                transactionMessage,
-            }).catch(() => {});
-            expect(compileTransaction).toHaveBeenCalledWith({
-                ...transactionMessage,
-                instructions: [
-                    ...transactionMessage.instructions,
-                    {
-                        data:
-                            // prettier-ignore
-                            new Uint8Array([
-                                0x02, // SetComputeUnitLimit instruction inde
-                                0xc0, 0x5c, 0x15, 0x00, // 1,400,000, MAX_COMPUTE_UNITS
-                            ]),
-                        programAddress: 'ComputeBudget111111111111111111111111111111',
-                    },
-                ],
-            });
-        });
-    });
-    it('replaces the existing set compute unit limit instruction when one exists', async () => {
-        expect.assertions(1);
-        await jest.isolateModulesAsync(async () => {
-            jest.mock('@solana/transactions');
-            const [
-                { compileTransaction },
-                { getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT },
-            ] = await Promise.all([
-                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-                // @ts-ignore
-                import('@solana/transactions'),
-                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-                // @ts-ignore
-                import('../../kit/compute-limit-internal'),
-            ]);
-            const transactionMessage = {
-                ...mockTransactionMessage,
-                instructions: [
-                    { programAddress: '4Kk4nA3F2nWHCcuyT8nR6oF7HQUQHmmzAVD5k8FQPKB2' as Address },
-                    {
-                        data:
-                            // prettier-ignore
-                            new Uint8Array([
-                            0x02, // SetComputeUnitLimit instruction inde
-                            0x01, 0x02, 0x03, 0x04, // ComputeUnits(u32)
-                        ]),
-                        programAddress: 'ComputeBudget111111111111111111111111111111' as Address,
-                    },
-                    { programAddress: '4Kk4nA3F2nWHCcuyT8nR6oF7HQUQHmmzAVD5k8FQPKB2' as Address },
-                ],
-                lifetimeConstraint: MOCK_BLOCKHASH_LIFETIME_CONSTRAINT,
-            };
-            getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-                rpc,
-                transactionMessage,
-            }).catch(() => {});
-            expect(compileTransaction).toHaveBeenCalledWith(
-                expect.objectContaining({
-                    instructions: [
-                        transactionMessage.instructions[0],
-                        {
-                            ...transactionMessage.instructions[1],
-                            data: new Uint8Array([0x02, 0xc0, 0x5c, 0x15, 0x00]), // Replaced with MAX_COMPUTE_UNITS
-                        },
-                        transactionMessage.instructions[2],
-                    ],
-                }),
-            );
-        });
-    });
-    it('does not ask for a replacement blockhash when the transaction message is a durable nonce transaction', () => {
-        getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-            rpc,
-            transactionMessage: {
-                ...mockTransactionMessage,
-                instructions: [
-                    {
-                        accounts: [
-                            {
-                                address: '7wJFRFuAE9x5Ptnz2VoBWsfecTCfuuM2sQCpECGypnTU' as Address,
-                                role: AccountRole.WRITABLE,
-                            },
-                            {
-                                address: 'SysvarRecentB1ockHashes11111111111111111111' as Address,
-                                role: AccountRole.READONLY,
-                            },
-                            {
-                                address: 'HzMoc78z1VNNf9nwD4Czt6CDYEb9LVD8KsVGP46FEmyJ' as Address,
-                                role: AccountRole.READONLY_SIGNER,
-                            },
-                        ],
-                        data: new Uint8Array([4, 0, 0, 0]),
-                        programAddress: '11111111111111111111111111111111' as Address,
-                    },
-                ],
-                lifetimeConstraint: {
-                    nonce: 'BzAqD6382v5r1pcELoi8HWrBDV4dSL9NGemMn2JYAhxc' as Nonce,
-                },
-            },
-        }).catch(() => {});
-        expect(simulateTransaction).toHaveBeenCalledWith(
-            expect.anything(),
-            expect.objectContaining({ replaceRecentBlockhash: false }),
-        );
-    });
-    it('asks for a replacement blockhash even when the transaction message has a blockhash lifetime', () => {
-        getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-            rpc,
-            transactionMessage: {
-                ...mockTransactionMessage,
-                lifetimeConstraint: MOCK_BLOCKHASH_LIFETIME_CONSTRAINT,
-            },
-        }).catch(() => {});
-        expect(simulateTransaction).toHaveBeenCalledWith(
-            expect.anything(),
-            expect.objectContaining({ replaceRecentBlockhash: true }),
-        );
-    });
-    it('asks for a replacement blockhash when the transaction message has no lifetime', () => {
-        getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-            rpc,
-            transactionMessage: mockTransactionMessage,
-        }).catch(() => {});
-        expect(simulateTransaction).toHaveBeenCalledWith(
-            expect.anything(),
-            expect.objectContaining({ replaceRecentBlockhash: true }),
-        );
-    });
-    it('returns the estimated compute units on success', async () => {
-        expect.assertions(1);
-        sendSimulateTransactionRequest.mockResolvedValue({ value: { unitsConsumed: 42n } });
-        const estimatePromise = getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-            rpc,
-            transactionMessage: mockTransactionMessage,
-        });
-        await expect(estimatePromise).resolves.toBe(42);
-    });
-    it('caps the estimated compute units to MAX_COMPUTE_UNITS of 1.4M', async () => {
-        expect.assertions(1);
-        sendSimulateTransactionRequest.mockResolvedValue({
-            value: { unitsConsumed: 1400000n /* MAX_COMPUTE_UNITS */ },
-        });
-        const estimatePromise = getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-            rpc,
-            transactionMessage: mockTransactionMessage,
-        });
-        await expect(estimatePromise).resolves.toBe(1400000);
-    });
-    it('throws with the transaction error as cause when the transaction fails in simulation', async () => {
-        expect.assertions(1);
-        const transactionError: TransactionError = 'AccountNotFound';
-        sendSimulateTransactionRequest.mockResolvedValue({ value: { err: transactionError, unitsConsumed: 42n } });
-        const estimatePromise = getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-            rpc,
-            transactionMessage: mockTransactionMessage,
-        });
-        await expect(estimatePromise).rejects.toThrow(
-            new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT, {
-                cause: transactionError,
-                unitsConsumed: 42,
-            }),
-        );
-    });
-    it('throws with the cause when simulation fails', async () => {
-        expect.assertions(1);
-        const simulationError = new SolanaError(SOLANA_ERROR__INSTRUCTION_ERROR__INSUFFICIENT_FUNDS, {
-            index: 42,
-        });
-        sendSimulateTransactionRequest.mockRejectedValue(simulationError);
-        const estimatePromise = getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-            rpc,
-            transactionMessage: mockTransactionMessage,
-        });
-        await expect(estimatePromise).rejects.toThrow(
-            new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT, {
-                cause: simulationError,
-            }),
-        );
-    });
-});

+ 0 - 362
packages/gill/src/__tests__/kit/decompile-transaction-message-fetching-lookup-tables-test.ts

@@ -1,362 +0,0 @@
-import { FetchAccountsConfig, fetchJsonParsedAccounts } from '@solana/accounts';
-import type { Address } from '@solana/addresses';
-import type { GetMultipleAccountsApi, Rpc } from '@solana/rpc';
-import type { Blockhash, Lamports } from '@solana/rpc-types';
-import {
-    CompiledTransactionMessage,
-    decompileTransactionMessage,
-    TransactionMessage,
-} from '@solana/transaction-messages';
-
-import { decompileTransactionMessageFetchingLookupTables } from '../../kit/decompile-transaction-message-fetching-lookup-tables';
-
-jest.mock('@solana/accounts');
-jest.mock('@solana/transaction-messages');
-
-describe('decompileTransactionMessageFetchingLookupTables', () => {
-    const blockhash = 'abc' as Blockhash;
-    const rpc: Rpc<GetMultipleAccountsApi> = {
-        getMultipleAccounts: jest.fn(),
-    };
-
-    describe('for a legacy transaction', () => {
-        const compiledTransactionMessage: CompiledTransactionMessage = {
-            // no `addressTableLookups` field
-            header: {
-                numReadonlyNonSignerAccounts: 0,
-                numReadonlySignerAccounts: 0,
-                numSignerAccounts: 0,
-            },
-            instructions: [],
-            lifetimeToken: blockhash,
-            staticAccounts: [],
-            version: 'legacy',
-        };
-
-        const transactionMessage = { version: 'legacy' } as unknown as TransactionMessage;
-
-        beforeEach(() => {
-            (decompileTransactionMessage as jest.Mock).mockReturnValue(transactionMessage);
-            // reset mock calls
-            jest.clearAllMocks();
-        });
-
-        it('should return the result of `decompileTransactionMessage`', async () => {
-            expect.assertions(1);
-            await expect(
-                decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc),
-            ).resolves.toStrictEqual(transactionMessage);
-        });
-
-        it('should not call the `fetchJsonParsedAccounts` function', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(fetchJsonParsedAccounts).not.toHaveBeenCalled();
-        });
-
-        it('should call `decompileTransactionMessage` with the input transaction', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                compiledTransactionMessage,
-                expect.any(Object), // config
-            );
-        });
-
-        it('should call the `decompileTransactionMessage` with no lookup tables', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                expect.any(Object), // transaction
-                expect.objectContaining({
-                    addressesByLookupTableAddress: {},
-                }),
-            );
-        });
-
-        it('should pass `lastValidBlockHeight` to `decompileTransactionMessage`', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc, {
-                lastValidBlockHeight: 100n,
-            });
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                expect.any(Object), // transaction
-                expect.objectContaining({
-                    lastValidBlockHeight: 100n,
-                }),
-            );
-        });
-    });
-
-    describe('for a versioned transaction with no `addressTableLookups` field', () => {
-        const compiledTransactionMessage: CompiledTransactionMessage = {
-            // no `addressTableLookups` field
-            header: {
-                numReadonlyNonSignerAccounts: 0,
-                numReadonlySignerAccounts: 0,
-                numSignerAccounts: 0,
-            },
-            instructions: [],
-            lifetimeToken: blockhash,
-            staticAccounts: [],
-            version: 0,
-        };
-
-        const transactionMessage = { version: 0 } as unknown as TransactionMessage;
-
-        beforeEach(() => {
-            (decompileTransactionMessage as jest.Mock).mockReturnValue(transactionMessage);
-            // reset mock calls
-            jest.clearAllMocks();
-        });
-
-        it('should return the result of `decompileTransactionMessage`', async () => {
-            expect.assertions(1);
-            await expect(
-                decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc),
-            ).resolves.toStrictEqual(transactionMessage);
-        });
-
-        it('should not call the `fetchJsonParsedAccounts` function', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(fetchJsonParsedAccounts).not.toHaveBeenCalled();
-        });
-
-        it('should call `decompileTransactionMessage` with the input transaction', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                compiledTransactionMessage,
-                expect.any(Object), // config
-            );
-        });
-
-        it('should call `decompileTransactionMessage` with no lookup tables', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                expect.any(Object), // transaction
-                expect.objectContaining({
-                    addressesByLookupTableAddress: {},
-                }),
-            );
-        });
-
-        it('should pass `lastValidBlockHeight` to `decompileTransactionMessage`', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc, {
-                lastValidBlockHeight: 100n,
-            });
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                expect.any(Object), // transaction
-                expect.objectContaining({
-                    lastValidBlockHeight: 100n,
-                }),
-            );
-        });
-    });
-
-    describe('for a versioned transaction with empty `addressTableLookups`', () => {
-        const compiledTransactionMessage: CompiledTransactionMessage = {
-            addressTableLookups: [],
-            header: {
-                numReadonlyNonSignerAccounts: 0,
-                numReadonlySignerAccounts: 0,
-                numSignerAccounts: 0,
-            },
-            instructions: [],
-            lifetimeToken: blockhash,
-            staticAccounts: [],
-            version: 0,
-        };
-
-        const transactionMessage = { version: 0 } as unknown as TransactionMessage;
-
-        beforeEach(() => {
-            (decompileTransactionMessage as jest.Mock).mockReturnValue(transactionMessage);
-            // reset mock calls
-            jest.clearAllMocks();
-        });
-
-        it('should return the result of `decompileTransactionMessage`', async () => {
-            expect.assertions(1);
-            await expect(
-                decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc),
-            ).resolves.toStrictEqual(transactionMessage);
-        });
-
-        it('should not call the `fetchJsonParsedAccounts` function', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(fetchJsonParsedAccounts).not.toHaveBeenCalled();
-        });
-
-        it('should call `decompileTransactionMessage` with the input transaction', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                compiledTransactionMessage,
-                expect.any(Object), // config
-            );
-        });
-
-        it('should call `decompileTransactionMessage` with no lookup tables', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                expect.any(Object), // transaction
-                expect.objectContaining({
-                    addressesByLookupTableAddress: {},
-                }),
-            );
-        });
-
-        it('should pass `lastValidBlockHeight` to `decompileTransactionMessage`', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc, {
-                lastValidBlockHeight: 100n,
-            });
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                expect.any(Object), // transaction
-                expect.objectContaining({
-                    lastValidBlockHeight: 100n,
-                }),
-            );
-        });
-    });
-
-    describe('for a versioned transaction with non-empty `addressTableLookups`', () => {
-        const lookupTableAddress1 = '1111' as Address;
-        const lookupTableAddress2 = '2222' as Address;
-
-        const compiledTransactionMessage: CompiledTransactionMessage = {
-            addressTableLookups: [
-                {
-                    lookupTableAddress: lookupTableAddress1,
-                    readableIndices: [0],
-                    writableIndices: [],
-                },
-                {
-                    lookupTableAddress: lookupTableAddress2,
-                    readableIndices: [0],
-                    writableIndices: [],
-                },
-            ],
-            header: {
-                numReadonlyNonSignerAccounts: 0,
-                numReadonlySignerAccounts: 0,
-                numSignerAccounts: 0,
-            },
-            instructions: [],
-            lifetimeToken: blockhash,
-            staticAccounts: [],
-            version: 0,
-        };
-
-        const transactionMessage = { version: 0 } as unknown as TransactionMessage;
-
-        const addressInLookup1 = '3333' as Address;
-        const addressInLookup2 = '4444' as Address;
-
-        const fetchedLookupTables: Awaited<ReturnType<typeof fetchJsonParsedAccounts>> = [
-            {
-                address: lookupTableAddress1,
-                data: {
-                    addresses: [addressInLookup1],
-                },
-                executable: false,
-                exists: true,
-                lamports: 0n as Lamports,
-                programAddress: 'program' as Address,
-                space: 0n,
-            },
-            {
-                address: lookupTableAddress2,
-                data: {
-                    addresses: [addressInLookup2],
-                },
-                executable: false,
-                exists: true,
-                lamports: 0n as Lamports,
-                programAddress: 'program' as Address,
-                space: 0n,
-            },
-        ];
-
-        beforeEach(() => {
-            (decompileTransactionMessage as jest.Mock).mockReturnValue(transactionMessage);
-            (fetchJsonParsedAccounts as jest.Mock).mockResolvedValue(fetchedLookupTables);
-
-            // reset mock calls
-            jest.clearAllMocks();
-        });
-
-        it('should return the result of `decompileTransactionMessage`', async () => {
-            expect.assertions(1);
-            await expect(
-                decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc),
-            ).resolves.toStrictEqual(transactionMessage);
-        });
-
-        it('should call `fetchJsonParsedAccounts` with the lookup table addresses', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(fetchJsonParsedAccounts).toHaveBeenCalledWith(rpc, [lookupTableAddress1, lookupTableAddress2], {});
-        });
-
-        it('should pass config to `fetchJsonParsedAccounts`', async () => {
-            expect.assertions(1);
-            const fetchAccountsConfig: FetchAccountsConfig = {
-                abortSignal: new AbortController().signal,
-                commitment: 'confirmed',
-                minContextSlot: 100n,
-            };
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc, {
-                ...fetchAccountsConfig,
-                lastValidBlockHeight: 100n,
-            });
-            expect(fetchJsonParsedAccounts).toHaveBeenCalledWith(
-                rpc,
-                [lookupTableAddress1, lookupTableAddress2],
-                fetchAccountsConfig,
-            );
-        });
-
-        it('should call `decompileTransactionMessage` with the input transaction', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                compiledTransactionMessage,
-                expect.any(Object), // config
-            );
-        });
-
-        it('should call `decompileTransactionMessage` with the addresses from the lookup tables', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc);
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                expect.any(Object), // transaction
-                expect.objectContaining({
-                    addressesByLookupTableAddress: {
-                        [lookupTableAddress1]: [addressInLookup1],
-                        [lookupTableAddress2]: [addressInLookup2],
-                    },
-                }),
-            );
-        });
-
-        it('should pass `lastValidBlockHeight` to `decompileTransactionMessage`', async () => {
-            expect.assertions(1);
-            await decompileTransactionMessageFetchingLookupTables(compiledTransactionMessage, rpc, {
-                lastValidBlockHeight: 100n,
-            });
-            expect(decompileTransactionMessage).toHaveBeenCalledWith(
-                expect.any(Object), // transaction
-                expect.objectContaining({
-                    lastValidBlockHeight: 100n,
-                }),
-            );
-        });
-    });
-});

+ 0 - 330
packages/gill/src/__tests__/kit/send-transaction-internal-test.ts

@@ -1,330 +0,0 @@
-import { Signature } from '@solana/keys';
-import type { Rpc, SendTransactionApi } from '@solana/rpc';
-import type { Commitment } from '@solana/rpc-types';
-import {
-    Base64EncodedWireTransaction,
-    FullySignedTransaction,
-    getBase64EncodedWireTransaction,
-    TransactionWithBlockhashLifetime,
-    TransactionWithDurableNonceLifetime,
-} from '@solana/transactions';
-
-import {
-    sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT,
-    sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT,
-} from '../../kit/send-transaction-internal';
-
-jest.mock('@solana/transactions');
-
-const FOREVER_PROMISE = new Promise(() => {
-    /* never resolve */
-});
-
-describe('sendAndConfirmTransaction', () => {
-    const MOCK_TRANSACTION = {} as FullySignedTransaction & TransactionWithBlockhashLifetime;
-    let confirmRecentTransaction: jest.Mock;
-    let createPendingRequest: jest.Mock;
-    let rpc: Rpc<SendTransactionApi>;
-    let sendTransaction: jest.Mock;
-    beforeEach(() => {
-        jest.useFakeTimers();
-        confirmRecentTransaction = jest.fn().mockReturnValue(FOREVER_PROMISE);
-        sendTransaction = jest.fn().mockReturnValue(FOREVER_PROMISE);
-        createPendingRequest = jest.fn().mockReturnValue({ send: sendTransaction });
-        rpc = {
-            sendTransaction: createPendingRequest,
-        };
-        jest.mocked(getBase64EncodedWireTransaction).mockReturnValue(
-            'MOCK_WIRE_TRANSACTION' as Base64EncodedWireTransaction,
-        );
-    });
-    it('encodes the transaction into wire format before sending', () => {
-        sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT({
-            abortSignal: new AbortController().signal,
-            commitment: 'finalized',
-            confirmRecentTransaction,
-            rpc,
-            transaction: MOCK_TRANSACTION,
-        }).catch(() => {});
-        expect(getBase64EncodedWireTransaction).toHaveBeenCalledWith(MOCK_TRANSACTION);
-        expect(createPendingRequest).toHaveBeenCalledWith('MOCK_WIRE_TRANSACTION', expect.anything());
-    });
-    it('calls `sendTransaction` with the expected inputs', () => {
-        const sendTransactionConfig = {
-            maxRetries: 42n,
-            minContextSlot: 123n,
-            preflightCommitment: 'confirmed' as Commitment,
-            skipPreflight: false,
-        } as Parameters<SendTransactionApi['sendTransaction']>[1];
-        sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT({
-            ...sendTransactionConfig,
-            abortSignal: new AbortController().signal,
-            commitment: 'finalized' as Commitment,
-            confirmRecentTransaction,
-            rpc,
-            transaction: MOCK_TRANSACTION,
-        }).catch(() => {});
-        expect(getBase64EncodedWireTransaction).toHaveBeenCalledWith(MOCK_TRANSACTION);
-        expect(createPendingRequest).toHaveBeenCalledWith('MOCK_WIRE_TRANSACTION', {
-            ...sendTransactionConfig,
-            encoding: 'base64',
-        });
-    });
-    it('calls `confirmRecentTransaction` with the expected inputs', async () => {
-        expect.assertions(1);
-        const sendTransactionConfig = {
-            maxRetries: 42n,
-            minContextSlot: 123n,
-            preflightCommitment: 'confirmed' as Commitment,
-            skipPreflight: false,
-        } as Parameters<SendTransactionApi['sendTransaction']>[1];
-        sendTransaction.mockResolvedValue('abc' as Signature);
-        const abortSignal = new AbortController().signal;
-        sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT({
-            ...sendTransactionConfig,
-            abortSignal,
-            commitment: 'finalized' as Commitment,
-            confirmRecentTransaction,
-            rpc,
-            transaction: MOCK_TRANSACTION,
-        }).catch(() => {});
-        await jest.runAllTimersAsync();
-        expect(confirmRecentTransaction).toHaveBeenCalledWith({
-            abortSignal,
-            commitment: 'finalized',
-            transaction: MOCK_TRANSACTION,
-        });
-    });
-    it.each`
-        commitment     | expectedPreflightCommitment
-        ${'processed'} | ${'processed'}
-        ${'confirmed'} | ${'confirmed'}
-    `(
-        'when missing a `preflightCommitment` and the commitment is $commitment, applies a downgraded `preflightCommitment`',
-        ({ commitment, expectedPreflightCommitment }) => {
-            sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT({
-                abortSignal: new AbortController().signal,
-                commitment,
-                confirmRecentTransaction,
-                rpc,
-                transaction: MOCK_TRANSACTION,
-            }).catch(() => {});
-            expect(createPendingRequest).toHaveBeenCalledWith(
-                expect.anything(),
-                expect.objectContaining({
-                    preflightCommitment: expectedPreflightCommitment,
-                }),
-            );
-        },
-    );
-    it.each`
-        commitment     | preflightCommitment | expectedPreflightCommitment
-        ${'processed'} | ${'processed'}      | ${'processed'}
-        ${'processed'} | ${'confirmed'}      | ${'confirmed'}
-        ${'processed'} | ${'finalized'}      | ${'finalized'}
-        ${'confirmed'} | ${'processed'}      | ${'processed'}
-        ${'confirmed'} | ${'confirmed'}      | ${'confirmed'}
-        ${'confirmed'} | ${'finalized'}      | ${'finalized'}
-        ${'finalized'} | ${'processed'}      | ${'processed'}
-        ${'finalized'} | ${'confirmed'}      | ${'confirmed'}
-        ${'finalized'} | ${'finalized'}      | ${'finalized'}
-    `(
-        'honours the explicit `preflightCommitment` no matter that the commitment is $commitment',
-        ({ commitment, preflightCommitment, expectedPreflightCommitment }) => {
-            sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT({
-                abortSignal: new AbortController().signal,
-                commitment,
-                confirmRecentTransaction,
-                preflightCommitment,
-                rpc,
-                transaction: MOCK_TRANSACTION,
-            }).catch(() => {});
-            expect(createPendingRequest).toHaveBeenCalledWith(
-                expect.anything(),
-                expect.objectContaining({
-                    preflightCommitment: expectedPreflightCommitment,
-                }),
-            );
-        },
-    );
-    it('when missing a `preflightCommitment` and the commitment is the same as the server default for `preflightCommitment`, does not apply a `preflightCommitment`', () => {
-        expect.assertions(1);
-        sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT({
-            abortSignal: new AbortController().signal,
-            commitment: 'finalized',
-            confirmRecentTransaction,
-            rpc,
-            transaction: MOCK_TRANSACTION,
-        }).catch(() => {});
-        expect(createPendingRequest.mock.lastCall![1]).not.toHaveProperty('preflightCommitment');
-    });
-    it('returns the signature of the transaction', async () => {
-        expect.assertions(1);
-        sendTransaction.mockResolvedValue('abc');
-        confirmRecentTransaction.mockResolvedValue(undefined);
-        await expect(
-            sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT({
-                abortSignal: new AbortController().signal,
-                commitment: 'finalized',
-                confirmRecentTransaction,
-                rpc,
-                transaction: MOCK_TRANSACTION,
-            }),
-        ).resolves.toBe('abc');
-    });
-});
-
-describe('sendAndConfirmDurableNonceTransaction', () => {
-    const MOCK_DURABLE_NONCE_TRANSACTION = {} as unknown as FullySignedTransaction &
-        TransactionWithDurableNonceLifetime;
-    let confirmDurableNonceTransaction: jest.Mock;
-    let createPendingRequest: jest.Mock;
-    let rpc: Rpc<SendTransactionApi>;
-    let sendTransaction: jest.Mock;
-    beforeEach(() => {
-        jest.useFakeTimers();
-        confirmDurableNonceTransaction = jest.fn().mockReturnValue(FOREVER_PROMISE);
-        sendTransaction = jest.fn().mockReturnValue(FOREVER_PROMISE);
-        createPendingRequest = jest.fn().mockReturnValue({ send: sendTransaction });
-        rpc = {
-            sendTransaction: createPendingRequest,
-        };
-        jest.mocked(getBase64EncodedWireTransaction).mockReturnValue(
-            'MOCK_WIRE_TRANSACTION' as Base64EncodedWireTransaction,
-        );
-    });
-    it('encodes the transaction into wire format before sending', () => {
-        sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-            abortSignal: new AbortController().signal,
-            commitment: 'finalized',
-            confirmDurableNonceTransaction,
-            rpc,
-            transaction: MOCK_DURABLE_NONCE_TRANSACTION,
-        }).catch(() => {});
-        expect(getBase64EncodedWireTransaction).toHaveBeenCalledWith(MOCK_DURABLE_NONCE_TRANSACTION);
-        expect(createPendingRequest).toHaveBeenCalledWith('MOCK_WIRE_TRANSACTION', expect.anything());
-    });
-    it('calls `sendTransaction` with the expected inputs', () => {
-        const sendTransactionConfig = {
-            maxRetries: 42n,
-            minContextSlot: 123n,
-            preflightCommitment: 'confirmed' as Commitment,
-            skipPreflight: false,
-        } as Parameters<SendTransactionApi['sendTransaction']>[1];
-        sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-            ...sendTransactionConfig,
-            abortSignal: new AbortController().signal,
-            commitment: 'finalized' as Commitment,
-            confirmDurableNonceTransaction,
-            rpc,
-            transaction: MOCK_DURABLE_NONCE_TRANSACTION,
-        }).catch(() => {});
-        expect(getBase64EncodedWireTransaction).toHaveBeenCalledWith(MOCK_DURABLE_NONCE_TRANSACTION);
-        expect(createPendingRequest).toHaveBeenCalledWith('MOCK_WIRE_TRANSACTION', {
-            ...sendTransactionConfig,
-            encoding: 'base64',
-        });
-    });
-    it('calls `confirmDurableNonceTransaction` with the expected inputs', async () => {
-        expect.assertions(1);
-        const sendTransactionConfig = {
-            maxRetries: 42n,
-            minContextSlot: 123n,
-            preflightCommitment: 'confirmed' as Commitment,
-            skipPreflight: false,
-        } as Parameters<SendTransactionApi['sendTransaction']>[1];
-        sendTransaction.mockResolvedValue('abc' as Signature);
-        const abortSignal = new AbortController().signal;
-        sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-            ...sendTransactionConfig,
-            abortSignal,
-            commitment: 'finalized' as Commitment,
-            confirmDurableNonceTransaction,
-            rpc,
-            transaction: MOCK_DURABLE_NONCE_TRANSACTION,
-        }).catch(() => {});
-        await jest.runAllTimersAsync();
-        expect(confirmDurableNonceTransaction).toHaveBeenCalledWith({
-            abortSignal,
-            commitment: 'finalized',
-            transaction: MOCK_DURABLE_NONCE_TRANSACTION,
-        });
-    });
-    it.each`
-        commitment     | expectedPreflightCommitment
-        ${'processed'} | ${'processed'}
-        ${'confirmed'} | ${'confirmed'}
-    `(
-        'when missing a `preflightCommitment` and the commitment is $commitment, applies a downgraded `preflightCommitment`',
-        ({ commitment, expectedPreflightCommitment }) => {
-            sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-                abortSignal: new AbortController().signal,
-                commitment,
-                confirmDurableNonceTransaction,
-                rpc,
-                transaction: MOCK_DURABLE_NONCE_TRANSACTION,
-            }).catch(() => {});
-            expect(createPendingRequest).toHaveBeenCalledWith(
-                expect.anything(),
-                expect.objectContaining({
-                    preflightCommitment: expectedPreflightCommitment,
-                }),
-            );
-        },
-    );
-    it.each`
-        commitment     | preflightCommitment | expectedPreflightCommitment
-        ${'processed'} | ${'processed'}      | ${'processed'}
-        ${'processed'} | ${'confirmed'}      | ${'confirmed'}
-        ${'processed'} | ${'finalized'}      | ${'finalized'}
-        ${'confirmed'} | ${'processed'}      | ${'processed'}
-        ${'confirmed'} | ${'confirmed'}      | ${'confirmed'}
-        ${'confirmed'} | ${'finalized'}      | ${'finalized'}
-        ${'finalized'} | ${'processed'}      | ${'processed'}
-        ${'finalized'} | ${'confirmed'}      | ${'confirmed'}
-        ${'finalized'} | ${'finalized'}      | ${'finalized'}
-    `(
-        'honours the explicit `preflightCommitment` no matter that the commitment is $commitment',
-        ({ commitment, preflightCommitment, expectedPreflightCommitment }) => {
-            sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-                abortSignal: new AbortController().signal,
-                commitment,
-                confirmDurableNonceTransaction,
-                preflightCommitment,
-                rpc,
-                transaction: MOCK_DURABLE_NONCE_TRANSACTION,
-            }).catch(() => {});
-            expect(createPendingRequest).toHaveBeenCalledWith(
-                expect.anything(),
-                expect.objectContaining({
-                    preflightCommitment: expectedPreflightCommitment,
-                }),
-            );
-        },
-    );
-    it('when missing a `preflightCommitment` and the commitment is the same as the server default for `preflightCommitment`, does not apply a `preflightCommitment`', () => {
-        expect.assertions(1);
-        sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-            abortSignal: new AbortController().signal,
-            commitment: 'finalized',
-            confirmDurableNonceTransaction,
-            rpc,
-            transaction: MOCK_DURABLE_NONCE_TRANSACTION,
-        }).catch(() => {});
-        expect(createPendingRequest.mock.lastCall![1]).not.toHaveProperty('preflightCommitment');
-    });
-    it('returns the signature of the transaction', async () => {
-        expect.assertions(1);
-        sendTransaction.mockResolvedValue('abc');
-        confirmDurableNonceTransaction.mockResolvedValue(undefined);
-        await expect(
-            sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-                abortSignal: new AbortController().signal,
-                commitment: 'finalized',
-                confirmDurableNonceTransaction,
-                rpc,
-                transaction: MOCK_DURABLE_NONCE_TRANSACTION,
-            }),
-        ).resolves.toBe('abc');
-    });
-});

+ 6 - 9
packages/gill/src/__typetests__/create-solana-client.ts

@@ -1,19 +1,14 @@
-/* eslint-disable @typescript-eslint/ban-ts-comment */
-
-import {
+import { sendAndConfirmDurableNonceTransactionFactory, sendAndConfirmTransactionFactory } from "@solana/kit";
+import type {
+  RequestAirdropApi,
   Rpc,
   RpcDevnet,
-  RpcTestnet,
   RpcMainnet,
+  RpcTestnet,
   SolanaRpcApi,
-  RequestAirdropApi,
   SolanaRpcApiMainnet,
 } from "@solana/rpc";
 import { createSolanaClient } from "../core";
-import {
-  sendAndConfirmDurableNonceTransactionFactory,
-  sendAndConfirmTransactionFactory,
-} from "../kit";
 
 // [DESCRIBE] createSolanaClient
 {
@@ -131,10 +126,12 @@ import {
 
     sendAndConfirmTransactionFactory({
       rpc: localnetRpc,
+      // @ts-ignore - kit does not yet support `localnet` as a cluster
       rpcSubscriptions: localnetRpcSubscriptions,
     });
     sendAndConfirmDurableNonceTransactionFactory({
       rpc: localnetRpc,
+      // @ts-ignore - kit does not yet support `localnet` as a cluster
       rpcSubscriptions: localnetRpcSubscriptions,
     });
   }

+ 0 - 62
packages/gill/src/__typetests__/kit/airdrop-typetests.ts

@@ -1,62 +0,0 @@
-/* eslint-disable @typescript-eslint/ban-ts-comment */
-import { GetSignatureStatusesApi, RequestAirdropApi, Rpc, RpcDevnet, RpcMainnet, RpcTestnet } from '@solana/rpc';
-import {
-    RpcSubscriptions,
-    RpcSubscriptionsDevnet,
-    RpcSubscriptionsMainnet,
-    RpcSubscriptionsTestnet,
-    SignatureNotificationsApi,
-} from '@solana/rpc-subscriptions';
-
-import { airdropFactory } from "../../kit/airdrop";
-
-const rpc = null as unknown as Rpc<GetSignatureStatusesApi & RequestAirdropApi>;
-const rpcDevnet = null as unknown as RpcDevnet<GetSignatureStatusesApi & RequestAirdropApi>;
-const rpcTestnet = null as unknown as RpcTestnet<GetSignatureStatusesApi & RequestAirdropApi>;
-const rpcMainnet = null as unknown as RpcMainnet<GetSignatureStatusesApi /* note lack of `RequestAirdropApi` here */>;
-// No sense discriminating against RPCs who decide to offer mainnet airdrops!
-const rpcMainnetWithAirdrop = null as unknown as RpcMainnet<GetSignatureStatusesApi & RequestAirdropApi>;
-
-const rpcSubscriptions = null as unknown as RpcSubscriptions<SignatureNotificationsApi>;
-const rpcSubscriptionsDevnet = null as unknown as RpcSubscriptionsDevnet<SignatureNotificationsApi>;
-const rpcSubscriptionsMainnet = null as unknown as RpcSubscriptionsMainnet<SignatureNotificationsApi>;
-const rpcSubscriptionsTestnet = null as unknown as RpcSubscriptionsTestnet<SignatureNotificationsApi>;
-
-// [DESCRIBE] airdropFactory
-{
-    {
-        // It typechecks when the RPC clusters match and have the `RequestAirdropApi`
-        airdropFactory({ rpc, rpcSubscriptions });
-        airdropFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsDevnet });
-        airdropFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsTestnet });
-        airdropFactory({ rpc: rpcMainnetWithAirdrop, rpcSubscriptions: rpcSubscriptionsMainnet });
-    }
-    {
-        // It typechecks when either RPC is generic
-        airdropFactory({ rpc, rpcSubscriptions });
-        airdropFactory({ rpc: rpcDevnet, rpcSubscriptions });
-        airdropFactory({ rpc: rpcTestnet, rpcSubscriptions });
-        airdropFactory({ rpc, rpcSubscriptions: rpcSubscriptionsDevnet });
-        airdropFactory({ rpc, rpcSubscriptions: rpcSubscriptionsTestnet });
-    }
-    {
-        // It fails to typecheck when used with an RPC that doesn't have `RequestAirdropApi`
-        // @ts-expect-error
-        airdropFactory({ rpc: rpcMainnet, rpcSubscriptions: rpcSubscriptionsMainnet });
-    }
-    {
-        // It fails to typecheck when explicit RPC clusters mismatch
-        // @ts-expect-error
-        airdropFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsTestnet });
-        // @ts-expect-error
-        airdropFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsMainnet });
-        // @ts-expect-error
-        airdropFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsMainnet });
-        // @ts-expect-error
-        airdropFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsDevnet });
-        // @ts-expect-error
-        airdropFactory({ rpc: rpcMainnetWithAirdrop, rpcSubscriptions: rpcSubscriptionsDevnet });
-        // @ts-expect-error
-        airdropFactory({ rpc: rpcMainnetWithAirdrop, rpcSubscriptions: rpcSubscriptionsTestnet });
-    }
-}

+ 0 - 69
packages/gill/src/__typetests__/kit/send-and-confirm-durable-nonce-transaction-typetests.ts

@@ -1,69 +0,0 @@
-/* eslint-disable @typescript-eslint/ban-ts-comment */
-import {
-  GetAccountInfoApi,
-  GetSignatureStatusesApi,
-  Rpc,
-  RpcDevnet,
-  RpcMainnet,
-  RpcTestnet,
-  SendTransactionApi,
-} from '@solana/rpc';
-import {
-  AccountNotificationsApi,
-  RpcSubscriptions,
-  RpcSubscriptionsDevnet,
-  RpcSubscriptionsMainnet,
-  RpcSubscriptionsTestnet,
-  SignatureNotificationsApi,
-} from '@solana/rpc-subscriptions';
-
-import { sendAndConfirmDurableNonceTransactionFactory } from '../../kit/send-and-confirm-durable-nonce-transaction';
-
-const rpc = null as unknown as Rpc<GetAccountInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
-const rpcDevnet = null as unknown as RpcDevnet<GetAccountInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
-const rpcTestnet = null as unknown as RpcTestnet<GetAccountInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
-const rpcMainnet = null as unknown as RpcMainnet<GetAccountInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
-
-const rpcSubscriptions = null as unknown as RpcSubscriptions<AccountNotificationsApi & SignatureNotificationsApi>;
-const rpcSubscriptionsDevnet = null as unknown as RpcSubscriptionsDevnet<
-  AccountNotificationsApi & SignatureNotificationsApi
->;
-const rpcSubscriptionsMainnet = null as unknown as RpcSubscriptionsMainnet<
-  AccountNotificationsApi & SignatureNotificationsApi
->;
-const rpcSubscriptionsTestnet = null as unknown as RpcSubscriptionsTestnet<
-  AccountNotificationsApi & SignatureNotificationsApi
->;
-
-// [DESCRIBE] sendAndConfirmDurableNonceTransactionFactory
-{
-  {
-      // It typechecks when the RPC clusters match.
-      sendAndConfirmDurableNonceTransactionFactory({ rpc, rpcSubscriptions });
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsDevnet });
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsTestnet });
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcMainnet, rpcSubscriptions: rpcSubscriptionsMainnet });
-  }
-  {
-      // It typechecks when either RPC is generic.
-      sendAndConfirmDurableNonceTransactionFactory({ rpc, rpcSubscriptions });
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcDevnet, rpcSubscriptions });
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcTestnet, rpcSubscriptions });
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcMainnet, rpcSubscriptions });
-  }
-  {
-      // It fails to typecheck when explicit RPC clusters mismatch.
-      // @ts-expect-error
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsTestnet });
-      // @ts-expect-error
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsMainnet });
-      // @ts-expect-error
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsMainnet });
-      // @ts-expect-error
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsDevnet });
-      // @ts-expect-error
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcMainnet, rpcSubscriptions: rpcSubscriptionsDevnet });
-      // @ts-expect-error
-      sendAndConfirmDurableNonceTransactionFactory({ rpc: rpcMainnet, rpcSubscriptions: rpcSubscriptionsTestnet });
-  }
-}

+ 0 - 69
packages/gill/src/__typetests__/kit/send-and-confirm-transaction-typetests.ts

@@ -1,69 +0,0 @@
-/* eslint-disable @typescript-eslint/ban-ts-comment */
-import {
-  GetEpochInfoApi,
-  GetSignatureStatusesApi,
-  Rpc,
-  RpcDevnet,
-  RpcMainnet,
-  RpcTestnet,
-  SendTransactionApi,
-} from '@solana/rpc';
-import {
-  RpcSubscriptions,
-  RpcSubscriptionsDevnet,
-  RpcSubscriptionsMainnet,
-  RpcSubscriptionsTestnet,
-  SignatureNotificationsApi,
-  SlotNotificationsApi,
-} from '@solana/rpc-subscriptions';
-
-import { sendAndConfirmTransactionFactory } from '../../kit/send-and-confirm-transaction';
-
-const rpc = null as unknown as Rpc<GetEpochInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
-const rpcDevnet = null as unknown as RpcDevnet<GetEpochInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
-const rpcTestnet = null as unknown as RpcTestnet<GetEpochInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
-const rpcMainnet = null as unknown as RpcMainnet<GetEpochInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
-
-const rpcSubscriptions = null as unknown as RpcSubscriptions<SignatureNotificationsApi & SlotNotificationsApi>;
-const rpcSubscriptionsDevnet = null as unknown as RpcSubscriptionsDevnet<
-  SignatureNotificationsApi & SlotNotificationsApi
->;
-const rpcSubscriptionsMainnet = null as unknown as RpcSubscriptionsMainnet<
-  SignatureNotificationsApi & SlotNotificationsApi
->;
-const rpcSubscriptionsTestnet = null as unknown as RpcSubscriptionsTestnet<
-  SignatureNotificationsApi & SlotNotificationsApi
->;
-
-// [DESCRIBE] sendAndConfirmTransactionFactory
-{
-  {
-      // It typechecks when the RPC clusters match.
-      sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
-      sendAndConfirmTransactionFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsDevnet });
-      sendAndConfirmTransactionFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsTestnet });
-      sendAndConfirmTransactionFactory({ rpc: rpcMainnet, rpcSubscriptions: rpcSubscriptionsMainnet });
-  }
-  {
-      // It typechecks when either RPC is generic.
-      sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
-      sendAndConfirmTransactionFactory({ rpc: rpcDevnet, rpcSubscriptions });
-      sendAndConfirmTransactionFactory({ rpc: rpcTestnet, rpcSubscriptions });
-      sendAndConfirmTransactionFactory({ rpc: rpcMainnet, rpcSubscriptions });
-  }
-  {
-      // It fails to typecheck when explicit RPC clusters mismatch.
-      // @ts-expect-error
-      sendAndConfirmTransactionFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsTestnet });
-      // @ts-expect-error
-      sendAndConfirmTransactionFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsMainnet });
-      // @ts-expect-error
-      sendAndConfirmTransactionFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsMainnet });
-      // @ts-expect-error
-      sendAndConfirmTransactionFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsDevnet });
-      // @ts-expect-error
-      sendAndConfirmTransactionFactory({ rpc: rpcMainnet, rpcSubscriptions: rpcSubscriptionsDevnet });
-      // @ts-expect-error
-      sendAndConfirmTransactionFactory({ rpc: rpcMainnet, rpcSubscriptions: rpcSubscriptionsTestnet });
-  }
-}

+ 68 - 0
packages/gill/src/__typetests__/send-and-confirm-transaction-with-signers-typetests.ts

@@ -0,0 +1,68 @@
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+import {
+  GetEpochInfoApi,
+  GetSignatureStatusesApi,
+  Rpc,
+  RpcDevnet,
+  RpcMainnet,
+  RpcTestnet,
+  SendTransactionApi,
+} from "@solana/rpc";
+import {
+  RpcSubscriptions,
+  RpcSubscriptionsDevnet,
+  RpcSubscriptionsMainnet,
+  RpcSubscriptionsTestnet,
+  SignatureNotificationsApi,
+  SlotNotificationsApi,
+} from "@solana/rpc-subscriptions";
+import { sendAndConfirmTransactionWithSignersFactory } from "../core/send-and-confirm-transaction-with-signers";
+
+const rpc = null as unknown as Rpc<GetEpochInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
+const rpcDevnet = null as unknown as RpcDevnet<GetEpochInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
+const rpcTestnet = null as unknown as RpcTestnet<GetEpochInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
+const rpcMainnet = null as unknown as RpcMainnet<GetEpochInfoApi & GetSignatureStatusesApi & SendTransactionApi>;
+
+const rpcSubscriptions = null as unknown as RpcSubscriptions<SignatureNotificationsApi & SlotNotificationsApi>;
+const rpcSubscriptionsDevnet = null as unknown as RpcSubscriptionsDevnet<
+  SignatureNotificationsApi & SlotNotificationsApi
+>;
+const rpcSubscriptionsMainnet = null as unknown as RpcSubscriptionsMainnet<
+  SignatureNotificationsApi & SlotNotificationsApi
+>;
+const rpcSubscriptionsTestnet = null as unknown as RpcSubscriptionsTestnet<
+  SignatureNotificationsApi & SlotNotificationsApi
+>;
+
+// [DESCRIBE] sendAndConfirmTransactionWithSignersFactory
+{
+  {
+    // It typechecks when the RPC clusters match.
+    sendAndConfirmTransactionWithSignersFactory({ rpc, rpcSubscriptions });
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsDevnet });
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsTestnet });
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcMainnet, rpcSubscriptions: rpcSubscriptionsMainnet });
+  }
+  {
+    // It typechecks when either RPC is generic.
+    sendAndConfirmTransactionWithSignersFactory({ rpc, rpcSubscriptions });
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcDevnet, rpcSubscriptions });
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcTestnet, rpcSubscriptions });
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcMainnet, rpcSubscriptions });
+  }
+  {
+    // It fails to typecheck when explicit RPC clusters mismatch.
+    // @ts-expect-error
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsTestnet });
+    // @ts-expect-error
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcDevnet, rpcSubscriptions: rpcSubscriptionsMainnet });
+    // @ts-expect-error
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsMainnet });
+    // @ts-expect-error
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcTestnet, rpcSubscriptions: rpcSubscriptionsDevnet });
+    // @ts-expect-error
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcMainnet, rpcSubscriptions: rpcSubscriptionsDevnet });
+    // @ts-expect-error
+    sendAndConfirmTransactionWithSignersFactory({ rpc: rpcMainnet, rpcSubscriptions: rpcSubscriptionsTestnet });
+  }
+}

+ 8 - 9
packages/gill/src/core/create-solana-client.ts

@@ -2,15 +2,10 @@ import { createSolanaRpc } from "@solana/rpc";
 import { createSolanaRpcSubscriptions } from "@solana/rpc-subscriptions";
 import type { DevnetUrl, MainnetUrl, TestnetUrl } from "@solana/rpc-types";
 
-import type {
-  LocalnetUrl,
-  SolanaClient,
-  ModifiedClusterUrl,
-  CreateSolanaClientArgs,
-} from "../types/rpc";
-import { sendAndConfirmTransactionFactory } from "../kit";
+import type { LocalnetUrl, SolanaClient, ModifiedClusterUrl, CreateSolanaClientArgs } from "../types/rpc";
 import { getPublicSolanaRpcUrl } from "./rpc";
 import { simulateTransactionFactory } from "./simulate-transaction";
+import { sendAndConfirmTransactionWithSignersFactory } from "./send-and-confirm-transaction-with-signers";
 
 /**
  * Create a Solana `rpc` and `rpcSubscriptions` client
@@ -83,8 +78,12 @@ export function createSolanaClient<TCluster extends ModifiedClusterUrl>({
   return {
     rpc,
     rpcSubscriptions,
-    // @ts-ignore
-    sendAndConfirmTransaction: sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions }),
+    sendAndConfirmTransaction: sendAndConfirmTransactionWithSignersFactory({
+      // @ts-ignore - TODO(FIXME:nick)
+      rpc,
+      // @ts-ignore - TODO(FIXME:nick)
+      rpcSubscriptions,
+    }),
     // @ts-ignore
     simulateTransaction: simulateTransactionFactory({ rpc }),
   };

+ 1 - 0
packages/gill/src/core/index.ts

@@ -4,6 +4,7 @@ export * from "./utils";
 export * from "./rpc";
 export * from "./explorer";
 export * from "./create-transaction";
+export * from "./send-and-confirm-transaction-with-signers";
 export * from "./prepare-transaction";
 export * from "./create-solana-client";
 export * from "./accounts";

+ 16 - 23
packages/gill/src/core/prepare-transaction.ts

@@ -1,21 +1,22 @@
+import { COMPUTE_BUDGET_PROGRAM_ADDRESS, getSetComputeUnitLimitInstruction } from "@solana-program/compute-budget";
+import type {
+  CompilableTransactionMessage,
+  GetLatestBlockhashApi,
+  ITransactionMessageWithFeePayer,
+  Rpc,
+  SimulateTransactionApi,
+  TransactionMessage,
+  TransactionMessageWithBlockhashLifetime,
+} from "@solana/kit";
 import {
-  COMPUTE_BUDGET_PROGRAM_ADDRESS,
-  getSetComputeUnitLimitInstruction,
-} from "@solana-program/compute-budget";
-import {
-  type CompilableTransactionMessage,
-  type ITransactionMessageWithFeePayer,
-  type TransactionMessage,
-  type TransactionMessageWithBlockhashLifetime,
   appendTransactionMessageInstruction,
   assertIsTransactionMessageWithBlockhashLifetime,
+  getComputeUnitEstimateForTransactionMessageFactory,
   setTransactionMessageLifetimeUsingBlockhash,
-} from "@solana/transaction-messages";
-import type { GetLatestBlockhashApi, Rpc, SimulateTransactionApi } from "@solana/rpc";
+} from "@solana/kit";
 import { isSetComputeLimitInstruction } from "../programs/compute-budget";
-import { getComputeUnitEstimateForTransactionMessageFactory } from "../kit";
-import { debug, isDebugEnabled } from "./debug";
 import { transactionToBase64WithSigners } from "./base64-to-transaction";
+import { debug, isDebugEnabled } from "./debug";
 
 type PrepareCompilableTransactionMessage =
   | CompilableTransactionMessage
@@ -81,9 +82,7 @@ export async function prepareTransaction<TMessage extends PrepareCompilableTrans
 
   // set a compute unit limit instruction
   if (computeBudgetIndex.limit < 0 || config.computeUnitLimitReset) {
-    const units = await getComputeUnitEstimateForTransactionMessageFactory({ rpc: config.rpc })(
-      config.transaction,
-    );
+    const units = await getComputeUnitEstimateForTransactionMessageFactory({ rpc: config.rpc })(config.transaction);
     debug(`Obtained compute units from simulation: ${units}`, "debug");
     const ix = getSetComputeUnitLimitInstruction({
       units: units * config.computeUnitLimitMultiplier,
@@ -106,10 +105,7 @@ export async function prepareTransaction<TMessage extends PrepareCompilableTrans
     const { value: latestBlockhash } = await config.rpc.getLatestBlockhash().send();
     if ("lifetimeConstraint" in config.transaction == false) {
       debug("Transaction missing latest blockhash, fetching one.", "debug");
-      config.transaction = setTransactionMessageLifetimeUsingBlockhash(
-        latestBlockhash,
-        config.transaction,
-      );
+      config.transaction = setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, config.transaction);
     } else if (config.blockhashReset) {
       debug("Auto resetting the latest blockhash.", "debug");
       config.transaction = Object.freeze({
@@ -123,10 +119,7 @@ export async function prepareTransaction<TMessage extends PrepareCompilableTrans
 
   // skip the async call if debugging is off
   if (isDebugEnabled()) {
-    debug(
-      `Transaction as base64: ${await transactionToBase64WithSigners(config.transaction)}`,
-      "debug",
-    );
+    debug(`Transaction as base64: ${await transactionToBase64WithSigners(config.transaction)}`, "debug");
   }
 
   return config.transaction;

+ 101 - 0
packages/gill/src/core/send-and-confirm-transaction-with-signers.ts

@@ -0,0 +1,101 @@
+import type {
+  CompilableTransactionMessage,
+  FullySignedTransaction,
+  GetEpochInfoApi,
+  GetSignatureStatusesApi,
+  Rpc,
+  RpcSubscriptions,
+  SendTransactionApi,
+  Signature,
+  SignatureNotificationsApi,
+  SlotNotificationsApi,
+  TransactionWithBlockhashLifetime,
+} from "@solana/kit";
+import {
+  Commitment,
+  getBase64EncodedWireTransaction,
+  getSignatureFromTransaction,
+  sendAndConfirmTransactionFactory,
+  signTransactionMessageWithSigners,
+} from "@solana/kit";
+import { type waitForRecentTransactionConfirmation } from "@solana/transaction-confirmation";
+import { debug } from "./debug";
+import { getExplorerLink } from "./explorer";
+
+interface SendAndConfirmTransactionWithBlockhashLifetimeConfig
+  extends SendTransactionBaseConfig,
+    SendTransactionConfigWithoutEncoding {
+  confirmRecentTransaction: (
+    config: Omit<
+      Parameters<typeof waitForRecentTransactionConfirmation>[0],
+      "getBlockHeightExceedencePromise" | "getRecentSignatureConfirmationPromise"
+    >,
+  ) => Promise<void>;
+  transaction: FullySignedTransaction & TransactionWithBlockhashLifetime;
+}
+
+interface SendTransactionBaseConfig extends SendTransactionConfigWithoutEncoding {
+  abortSignal?: AbortSignal;
+  commitment: Commitment;
+  rpc: Rpc<SendTransactionApi>;
+  transaction: FullySignedTransaction;
+}
+
+type SendTransactionConfigWithoutEncoding = Omit<
+  NonNullable<Parameters<SendTransactionApi["sendTransaction"]>[1]>,
+  "encoding"
+>;
+
+export type SendAndConfirmTransactionWithSignersFunction = (
+  transaction: (FullySignedTransaction & TransactionWithBlockhashLifetime) | CompilableTransactionMessage,
+  config?: Omit<
+    SendAndConfirmTransactionWithBlockhashLifetimeConfig,
+    "confirmRecentTransaction" | "rpc" | "transaction"
+  >,
+) => Promise<Signature>;
+
+type SendAndConfirmTransactionWithSignersFactoryConfig<TCluster> = {
+  rpc: Rpc<GetEpochInfoApi & GetSignatureStatusesApi & SendTransactionApi> & {
+    "~cluster"?: TCluster;
+  };
+  rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi & SlotNotificationsApi> & {
+    "~cluster"?: TCluster;
+  };
+};
+
+export function sendAndConfirmTransactionWithSignersFactory({
+  rpc,
+  rpcSubscriptions,
+}: SendAndConfirmTransactionWithSignersFactoryConfig<"devnet">): SendAndConfirmTransactionWithSignersFunction;
+export function sendAndConfirmTransactionWithSignersFactory({
+  rpc,
+  rpcSubscriptions,
+}: SendAndConfirmTransactionWithSignersFactoryConfig<"testnet">): SendAndConfirmTransactionWithSignersFunction;
+export function sendAndConfirmTransactionWithSignersFactory({
+  rpc,
+  rpcSubscriptions,
+}: SendAndConfirmTransactionWithSignersFactoryConfig<"mainnet">): SendAndConfirmTransactionWithSignersFunction;
+export function sendAndConfirmTransactionWithSignersFactory({
+  rpc,
+  rpcSubscriptions,
+}: SendAndConfirmTransactionWithSignersFactoryConfig<"localnet">): SendAndConfirmTransactionWithSignersFunction;
+export function sendAndConfirmTransactionWithSignersFactory<
+  TCluster extends "devnet" | "mainnet" | "testnet" | "localnet" | undefined = undefined,
+>({
+  rpc,
+  rpcSubscriptions,
+}: SendAndConfirmTransactionWithSignersFactoryConfig<TCluster>): SendAndConfirmTransactionWithSignersFunction {
+  // @ts-ignore - TODO(FIXME)
+  const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
+  return async function sendAndConfirmTransactionWithSigners(transaction, config = { commitment: "confirmed" }) {
+    if ("messageBytes" in transaction == false) {
+      transaction = (await signTransactionMessageWithSigners(transaction)) as Readonly<
+        FullySignedTransaction & TransactionWithBlockhashLifetime
+      >;
+    }
+    debug(`Sending transaction: ${getExplorerLink({ transaction: getSignatureFromTransaction(transaction) })}`);
+    debug(`Transaction as base64: ${getBase64EncodedWireTransaction(transaction)}`, "debug");
+    await sendAndConfirmTransaction(transaction, config);
+    return getSignatureFromTransaction(transaction);
+  };
+}

+ 1 - 25
packages/gill/src/index.ts

@@ -1,29 +1,5 @@
-export * from "@solana/accounts";
-export * from "@solana/addresses";
-export * from "@solana/codecs";
-export * from "@solana/errors";
-export * from "@solana/functional";
-export * from "@solana/instructions";
-export * from "@solana/keys";
-export * from "@solana/programs";
-export * from "@solana/rpc";
-export * from "@solana/rpc-parsed-types";
-export * from "@solana/rpc-subscriptions";
-export * from "@solana/rpc-types";
-export * from "@solana/signers";
-export * from "@solana/transaction-messages";
-export * from "@solana/transactions";
+export * from "@solana/kit";
 
-export type {
-  RpcRequest,
-  RpcRequestTransformer,
-  RpcResponse,
-  RpcResponseData,
-  RpcResponseTransformer,
-} from "@solana/rpc-spec-types";
-export { createRpcMessage } from "@solana/rpc-spec-types";
-
-export * from "./kit";
 export * from "./types";
 export * from "./core";
 

+ 0 - 38
packages/gill/src/kit/airdrop-internal.ts

@@ -1,38 +0,0 @@
-import type { Address } from '@solana/addresses';
-import type { Signature } from '@solana/keys';
-import type { RequestAirdropApi, Rpc } from '@solana/rpc';
-import type { Commitment, Lamports } from '@solana/rpc-types';
-import { waitForRecentTransactionConfirmationUntilTimeout } from '@solana/transaction-confirmation';
-
-type RequestAndConfirmAirdropConfig = Readonly<{
-    abortSignal?: AbortSignal;
-    commitment: Commitment;
-    confirmSignatureOnlyTransaction: (
-        config: Omit<
-            Parameters<typeof waitForRecentTransactionConfirmationUntilTimeout>[0],
-            'getRecentSignatureConfirmationPromise' | 'getTimeoutPromise'
-        >,
-    ) => Promise<void>;
-    lamports: Lamports;
-    recipientAddress: Address;
-    rpc: Rpc<RequestAirdropApi>;
-}>;
-
-export async function requestAndConfirmAirdrop_INTERNAL_ONLY_DO_NOT_EXPORT({
-    abortSignal,
-    commitment,
-    confirmSignatureOnlyTransaction,
-    lamports,
-    recipientAddress,
-    rpc,
-}: RequestAndConfirmAirdropConfig): Promise<Signature> {
-    const airdropTransactionSignature = await rpc
-        .requestAirdrop(recipientAddress, lamports, { commitment })
-        .send({ abortSignal });
-    await confirmSignatureOnlyTransaction({
-        abortSignal,
-        commitment,
-        signature: airdropTransactionSignature,
-    });
-    return airdropTransactionSignature;
-}

+ 0 - 54
packages/gill/src/kit/airdrop.ts

@@ -1,54 +0,0 @@
-import type { Signature } from '@solana/keys';
-import type { GetSignatureStatusesApi, RequestAirdropApi, Rpc } from '@solana/rpc';
-import type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';
-import {
-    createRecentSignatureConfirmationPromiseFactory,
-    getTimeoutPromise,
-    waitForRecentTransactionConfirmationUntilTimeout,
-} from '@solana/transaction-confirmation';
-
-import { requestAndConfirmAirdrop_INTERNAL_ONLY_DO_NOT_EXPORT } from './airdrop-internal';
-
-type AirdropFunction = (
-    config: Omit<
-        Parameters<typeof requestAndConfirmAirdrop_INTERNAL_ONLY_DO_NOT_EXPORT>[0],
-        'confirmSignatureOnlyTransaction' | 'rpc'
-    >,
-) => Promise<Signature>;
-
-type AirdropFactoryConfig<TCluster> = {
-    rpc: Rpc<GetSignatureStatusesApi & RequestAirdropApi> & { '~cluster'?: TCluster };
-    rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };
-};
-
-export function airdropFactory({ rpc, rpcSubscriptions }: AirdropFactoryConfig<'devnet'>): AirdropFunction;
-export function airdropFactory({ rpc, rpcSubscriptions }: AirdropFactoryConfig<'mainnet'>): AirdropFunction;
-export function airdropFactory({ rpc, rpcSubscriptions }: AirdropFactoryConfig<'testnet'>): AirdropFunction;
-export function airdropFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({
-    rpc,
-    rpcSubscriptions,
-}: AirdropFactoryConfig<TCluster>): AirdropFunction {
-    const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({
-        rpc,
-        rpcSubscriptions,
-    } as Parameters<typeof createRecentSignatureConfirmationPromiseFactory>[0]);
-    async function confirmSignatureOnlyTransaction(
-        config: Omit<
-            Parameters<typeof waitForRecentTransactionConfirmationUntilTimeout>[0],
-            'getRecentSignatureConfirmationPromise' | 'getTimeoutPromise'
-        >,
-    ) {
-        await waitForRecentTransactionConfirmationUntilTimeout({
-            ...config,
-            getRecentSignatureConfirmationPromise,
-            getTimeoutPromise,
-        });
-    }
-    return async function airdrop(config) {
-        return await requestAndConfirmAirdrop_INTERNAL_ONLY_DO_NOT_EXPORT({
-            ...config,
-            confirmSignatureOnlyTransaction,
-            rpc,
-        });
-    };
-}

+ 0 - 200
packages/gill/src/kit/compute-limit-internal.ts

@@ -1,200 +0,0 @@
-import type { Address } from '@solana/addresses';
-import { getU32Encoder } from '@solana/codecs';
-import {
-    isSolanaError,
-    SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT,
-    SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT,
-    SolanaError,
-} from '@solana/errors';
-import {
-    type IInstruction,
-    type IInstructionWithData,
-    isInstructionForProgram,
-    isInstructionWithData,
-} from '@solana/instructions';
-import type { Rpc, SimulateTransactionApi } from '@solana/rpc';
-import type { Blockhash, Commitment, Slot } from '@solana/rpc-types';
-import {
-    appendTransactionMessageInstruction,
-    type CompilableTransactionMessage,
-    isDurableNonceTransaction,
-    isTransactionMessageWithBlockhashLifetime,
-    type ITransactionMessageWithFeePayer,
-    setTransactionMessageLifetimeUsingBlockhash,
-    type TransactionMessage,
-} from '@solana/transaction-messages';
-import { compileTransaction, getBase64EncodedWireTransaction } from '@solana/transactions';
-
-type ComputeUnitEstimateForTransactionMessageConfig = Readonly<{
-    abortSignal?: AbortSignal;
-    commitment?: Commitment;
-    minContextSlot?: Slot;
-    rpc: Rpc<SimulateTransactionApi>;
-    transactionMessage: CompilableTransactionMessage | (ITransactionMessageWithFeePayer & TransactionMessage);
-}>;
-
-const COMPUTE_BUDGET_PROGRAM_ADDRESS =
-    'ComputeBudget111111111111111111111111111111' as Address<'ComputeBudget111111111111111111111111111111'>;
-// HACK: Since the `compileTransaction()` method will not compile a transaction with no lifetime we
-// supply a dummy lifetime.
-const INVALID_BUT_SUFFICIENT_FOR_COMPILATION_BLOCKHASH = {
-    blockhash: '11111111111111111111111111111111' as Blockhash,
-    lastValidBlockHeight: 0n, // This is not included in compiled transactions; it can be anything.
-} as const;
-const SET_COMPUTE_UNIT_LIMIT_INSTRUCTION_INDEX = 0x02;
-
-function createComputeUnitLimitInstruction(units: number): IInstruction<typeof COMPUTE_BUDGET_PROGRAM_ADDRESS> {
-    const data = new Uint8Array(5);
-    data[0] = SET_COMPUTE_UNIT_LIMIT_INSTRUCTION_INDEX;
-    getU32Encoder().write(units, data, 1 /* offset */);
-    return Object.freeze({
-        data,
-        programAddress: COMPUTE_BUDGET_PROGRAM_ADDRESS,
-    });
-}
-
-function isSetComputeLimitInstruction(
-    instruction: IInstruction,
-): instruction is IInstruction<typeof COMPUTE_BUDGET_PROGRAM_ADDRESS> & IInstructionWithData<Uint8Array> {
-    return (
-        isInstructionForProgram(instruction, COMPUTE_BUDGET_PROGRAM_ADDRESS) &&
-        isInstructionWithData(instruction) &&
-        instruction.data[0] === SET_COMPUTE_UNIT_LIMIT_INSTRUCTION_INDEX
-    );
-}
-
-/**
- * Simulates a transaction message on the network and returns the number of compute units it
- * consumed during simulation.
- *
- * The estimate this function returns can be used to set a compute unit limit on the transaction.
- * Correctly budgeting a compute unit limit for your transaction message can increase the probability
- * that your transaction will be accepted for processing.
- *
- * If you don't declare a compute unit limit on your transaction, validators will assume an upper
- * limit of 200K compute units (CU) per instruction. Since validators have an incentive to pack as
- * many transactions into each block as possible, they may choose to include transactions that they
- * know will fit into the remaining compute budget for the current block over transactions that
- * might not. For this reason, you should set a compute unit limit on each of your transaction
- * messages, whenever possible.
- *
- * ## Example
- *
- * ```ts
- * import { getSetComputeLimitInstruction } from '@solana-program/compute-budget';
- * import { createSolanaRpc, getComputeUnitEstimateForTransactionMessageFactory, pipe } from '@solana/kit';
- *
- * // Create an estimator function.
- * const rpc = createSolanaRpc('http://127.0.0.1:8899');
- * const getComputeUnitEstimateForTransactionMessage =
- *     getComputeUnitEstimateForTransactionMessageFactory({ rpc });
- *
- * // Create your transaction message.
- * const transactionMessage = pipe(
- *     createTransactionMessage({ version: 'legacy' }),
- *     /* ... *\/
- * );
- *
- * // Request an estimate of the actual compute units this message will consume.
- * const computeUnitsEstimate =
- *     await getComputeUnitEstimateForTransactionMessage(transactionMessage);
- *
- * // Set the transaction message's compute unit budget.
- * const transactionMessageWithComputeUnitLimit = prependTransactionMessageInstruction(
- *     getSetComputeLimitInstruction({ units: computeUnitsEstimate }),
- *     transactionMessage,
- * );
- * ```
- *
- * > [!WARNING]
- * > The compute unit estimate is just that &ndash; an estimate. The compute unit consumption of the
- * > actual transaction might be higher or lower than what was observed in simulation. Unless you
- * > are confident that your particular transaction message will consume the same or fewer compute
- * > units as was estimated, you might like to augment the estimate by either a fixed number of CUs
- * > or a multiplier.
- *
- * > [!NOTE]
- * > If you are preparing an _unsigned_ transaction, destined to be signed and submitted to the
- * > network by a wallet, you might like to leave it up to the wallet to determine the compute unit
- * > limit. Consider that the wallet might have a more global view of how many compute units certain
- * > types of transactions consume, and might be able to make better estimates of an appropriate
- * > compute unit budget.
- */
-export async function getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-    abortSignal,
-    rpc,
-    transactionMessage,
-    ...simulateConfig
-}: ComputeUnitEstimateForTransactionMessageConfig): Promise<number> {
-    /**
-     * STEP 1: Make sure the transaction message will not fail in simulation for lack of a lifetime
-     *         - either a recent blockhash lifetime or a nonce.
-     */
-    const isDurableNonceTransactionMessage = isDurableNonceTransaction(transactionMessage);
-    let compilableTransactionMessage;
-    if (isDurableNonceTransactionMessage || isTransactionMessageWithBlockhashLifetime(transactionMessage)) {
-        compilableTransactionMessage = transactionMessage;
-    } else {
-        compilableTransactionMessage = setTransactionMessageLifetimeUsingBlockhash(
-            INVALID_BUT_SUFFICIENT_FOR_COMPILATION_BLOCKHASH,
-            transactionMessage,
-        );
-    }
-    /**
-     * STEP 2: Ensure that the message has a `SetComputeLimit` instruction. The set compute limit
-     *         instruction itself consumes compute units, so it must be included in the simulation.
-     */
-    const existingSetComputeUnitLimitInstructionIndex =
-        transactionMessage.instructions.findIndex(isSetComputeLimitInstruction);
-    const maxComputeUnitLimitInstruction = createComputeUnitLimitInstruction(1_400_000 /* MAX_COMPUTE_UNIT_LIMIT */);
-    if (existingSetComputeUnitLimitInstructionIndex === -1) {
-        compilableTransactionMessage = appendTransactionMessageInstruction(
-            maxComputeUnitLimitInstruction,
-            compilableTransactionMessage,
-        );
-    } else {
-        const nextInstructions = [...compilableTransactionMessage.instructions];
-        nextInstructions.splice(existingSetComputeUnitLimitInstructionIndex, 1, maxComputeUnitLimitInstruction);
-        compilableTransactionMessage = Object.freeze({
-            ...compilableTransactionMessage,
-            instructions: nextInstructions,
-        } as typeof compilableTransactionMessage);
-    }
-    /**
-     * STEP 3: Simulate the transaction to measure its compute unit consumption.
-     */
-    const compiledTransaction = compileTransaction(compilableTransactionMessage);
-    const wireTransactionBytes = getBase64EncodedWireTransaction(compiledTransaction);
-    try {
-        const {
-            value: { err: transactionError, unitsConsumed },
-        } = await rpc
-            .simulateTransaction(wireTransactionBytes, {
-                ...simulateConfig,
-                encoding: 'base64',
-                replaceRecentBlockhash: !isDurableNonceTransactionMessage,
-                sigVerify: false,
-            })
-            .send({ abortSignal });
-        if (unitsConsumed == null) {
-            // This should never be hit, because all RPCs should support `unitsConsumed` by now.
-            throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT);
-        }
-        // FIXME(https://github.com/anza-xyz/agave/issues/1295): The simulation response returns
-        // compute units as a u64, but the `SetComputeLimit` instruction only accepts a u32. Until
-        // this changes, downcast it.
-        const downcastUnitsConsumed = unitsConsumed > 4_294_967_295n ? 4_294_967_295 : Number(unitsConsumed);
-        if (transactionError) {
-            throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT, {
-                cause: transactionError,
-                unitsConsumed: downcastUnitsConsumed,
-            });
-        }
-        return downcastUnitsConsumed;
-    } catch (e) {
-        if (isSolanaError(e, SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT)) throw e;
-        throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT, {
-            cause: e,
-        });
-    }
-}

+ 0 - 31
packages/gill/src/kit/compute-limit.ts

@@ -1,31 +0,0 @@
-import type { Rpc, SimulateTransactionApi } from '@solana/rpc';
-import type {
-    CompilableTransactionMessage,
-    ITransactionMessageWithFeePayer,
-    TransactionMessage,
-} from '@solana/transaction-messages';
-
-import { getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT } from './compute-limit-internal';
-
-type ComputeUnitEstimateForTransactionMessageFactoryConfig = Readonly<{
-    rpc: Rpc<SimulateTransactionApi>;
-}>;
-type ComputeUnitEstimateForTransactionMessageFunction = (
-    transactionMessage: CompilableTransactionMessage | (ITransactionMessageWithFeePayer & TransactionMessage),
-    config?: Omit<
-        Parameters<typeof getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT>[0],
-        'rpc' | 'transactionMessage'
-    >,
-) => Promise<number>;
-
-export function getComputeUnitEstimateForTransactionMessageFactory({
-    rpc,
-}: ComputeUnitEstimateForTransactionMessageFactoryConfig): ComputeUnitEstimateForTransactionMessageFunction {
-    return async function getComputeUnitEstimateForTransactionMessage(transactionMessage, config) {
-        return await getComputeUnitEstimateForTransactionMessage_INTERNAL_ONLY_DO_NOT_EXPORT({
-            ...config,
-            rpc,
-            transactionMessage,
-        });
-    };
-}

+ 0 - 66
packages/gill/src/kit/decompile-transaction-message-fetching-lookup-tables.ts

@@ -1,66 +0,0 @@
-import {
-    assertAccountsDecoded,
-    assertAccountsExist,
-    type FetchAccountsConfig,
-    fetchJsonParsedAccounts,
-} from '@solana/accounts';
-import type { Address } from '@solana/addresses';
-import type { GetMultipleAccountsApi, Rpc } from '@solana/rpc';
-import {
-    type AddressesByLookupTableAddress,
-    type CompilableTransactionMessage,
-    type CompiledTransactionMessage,
-    decompileTransactionMessage,
-} from '@solana/transaction-messages';
-
-type FetchedAddressLookup = {
-    addresses: Address[];
-};
-
-export async function fetchLookupTables(
-    lookupTableAddresses: Address[],
-    rpc: Rpc<GetMultipleAccountsApi>,
-    config?: FetchAccountsConfig,
-): Promise<AddressesByLookupTableAddress> {
-    const fetchedLookupTables = await fetchJsonParsedAccounts<FetchedAddressLookup[]>(
-        rpc,
-        lookupTableAddresses,
-        config,
-    );
-    assertAccountsDecoded(fetchedLookupTables);
-    assertAccountsExist(fetchedLookupTables);
-
-    return fetchedLookupTables.reduce<AddressesByLookupTableAddress>((acc, lookup) => {
-        return {
-            ...acc,
-            [lookup.address]: lookup.data.addresses,
-        };
-    }, {});
-}
-
-type DecompileTransactionMessageFetchingLookupTablesConfig = FetchAccountsConfig & {
-    lastValidBlockHeight?: bigint;
-};
-
-export async function decompileTransactionMessageFetchingLookupTables(
-    compiledTransactionMessage: CompiledTransactionMessage,
-    rpc: Rpc<GetMultipleAccountsApi>,
-    config?: DecompileTransactionMessageFetchingLookupTablesConfig,
-): Promise<CompilableTransactionMessage> {
-    const lookupTables =
-        'addressTableLookups' in compiledTransactionMessage &&
-        compiledTransactionMessage.addressTableLookups !== undefined &&
-        compiledTransactionMessage.addressTableLookups.length > 0
-            ? compiledTransactionMessage.addressTableLookups
-            : [];
-    const lookupTableAddresses = lookupTables.map(l => l.lookupTableAddress);
-
-    const { lastValidBlockHeight, ...fetchAccountsConfig } = config ?? {};
-    const addressesByLookupTableAddress =
-        lookupTableAddresses.length > 0 ? await fetchLookupTables(lookupTableAddresses, rpc, fetchAccountsConfig) : {};
-
-    return decompileTransactionMessage(compiledTransactionMessage, {
-        addressesByLookupTableAddress,
-        lastValidBlockHeight,
-    });
-}

+ 0 - 11
packages/gill/src/kit/index.ts

@@ -1,11 +0,0 @@
-/**
- * Kit imports taken directly from Anza:
- * https://github.com/anza-xyz/solana-web3.js/tree/main/packages/library
- */
-
-export * from "./airdrop";
-export * from "./compute-limit";
-export * from "./decompile-transaction-message-fetching-lookup-tables";
-export * from "./send-and-confirm-durable-nonce-transaction";
-export * from "./send-and-confirm-transaction";
-export * from "./send-transaction-without-confirming";

+ 0 - 75
packages/gill/src/kit/send-and-confirm-durable-nonce-transaction.ts

@@ -1,75 +0,0 @@
-import type { Signature } from '@solana/keys';
-import type { GetAccountInfoApi, GetSignatureStatusesApi, Rpc, SendTransactionApi } from '@solana/rpc';
-import type { AccountNotificationsApi, RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';
-import {
-    createNonceInvalidationPromiseFactory,
-    createRecentSignatureConfirmationPromiseFactory,
-    waitForDurableNonceTransactionConfirmation,
-} from '@solana/transaction-confirmation';
-import type { FullySignedTransaction, TransactionWithDurableNonceLifetime } from '@solana/transactions';
-
-import { sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT } from './send-transaction-internal';
-
-type SendAndConfirmDurableNonceTransactionFunction = (
-    transaction: FullySignedTransaction & TransactionWithDurableNonceLifetime,
-    config: Omit<
-        Parameters<typeof sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT>[0],
-        'confirmDurableNonceTransaction' | 'rpc' | 'transaction'
-    >,
-) => Promise<Signature>;
-
-type SendAndConfirmDurableNonceTransactionFactoryConfig<TCluster> = {
-    rpc: Rpc<GetAccountInfoApi & GetSignatureStatusesApi & SendTransactionApi> & { '~cluster'?: TCluster };
-    rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi & SignatureNotificationsApi> & { '~cluster'?: TCluster };
-};
-
-export function sendAndConfirmDurableNonceTransactionFactory({
-    rpc,
-    rpcSubscriptions,
-}: SendAndConfirmDurableNonceTransactionFactoryConfig<'devnet'>): SendAndConfirmDurableNonceTransactionFunction;
-export function sendAndConfirmDurableNonceTransactionFactory({
-    rpc,
-    rpcSubscriptions,
-}: SendAndConfirmDurableNonceTransactionFactoryConfig<'testnet'>): SendAndConfirmDurableNonceTransactionFunction;
-export function sendAndConfirmDurableNonceTransactionFactory({
-    rpc,
-    rpcSubscriptions,
-}: SendAndConfirmDurableNonceTransactionFactoryConfig<'mainnet'>): SendAndConfirmDurableNonceTransactionFunction;
-export function sendAndConfirmDurableNonceTransactionFactory({
-    rpc,
-    rpcSubscriptions,
-}: SendAndConfirmDurableNonceTransactionFactoryConfig<'localnet'>): SendAndConfirmDurableNonceTransactionFunction;
-export function sendAndConfirmDurableNonceTransactionFactory<
-    TCluster extends 'devnet' | 'mainnet' | 'testnet' | 'localnet' | void = void,
->({
-    rpc,
-    rpcSubscriptions,
-}: SendAndConfirmDurableNonceTransactionFactoryConfig<TCluster>): SendAndConfirmDurableNonceTransactionFunction {
-    const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({ rpc, rpcSubscriptions } as Parameters<
-        typeof createNonceInvalidationPromiseFactory
-    >[0]);
-    const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({
-        rpc,
-        rpcSubscriptions,
-    } as Parameters<typeof createRecentSignatureConfirmationPromiseFactory>[0]);
-    async function confirmDurableNonceTransaction(
-        config: Omit<
-            Parameters<typeof waitForDurableNonceTransactionConfirmation>[0],
-            'getNonceInvalidationPromise' | 'getRecentSignatureConfirmationPromise'
-        >,
-    ) {
-        await waitForDurableNonceTransactionConfirmation({
-            ...config,
-            getNonceInvalidationPromise,
-            getRecentSignatureConfirmationPromise,
-        });
-    }
-    return async function sendAndConfirmDurableNonceTransaction(transaction, config) {
-        return await sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-            ...config,
-            confirmDurableNonceTransaction,
-            rpc,
-            transaction,
-        });
-    };
-}

+ 0 - 80
packages/gill/src/kit/send-and-confirm-transaction.ts

@@ -1,80 +0,0 @@
-import type { Signature } from '@solana/keys';
-import type { GetEpochInfoApi, GetSignatureStatusesApi, Rpc, SendTransactionApi } from '@solana/rpc';
-import type { RpcSubscriptions, SignatureNotificationsApi, SlotNotificationsApi } from '@solana/rpc-subscriptions';
-import {
-    createBlockHeightExceedencePromiseFactory,
-    createRecentSignatureConfirmationPromiseFactory,
-    waitForRecentTransactionConfirmation,
-} from '@solana/transaction-confirmation';
-import type { FullySignedTransaction, TransactionWithBlockhashLifetime } from '@solana/transactions';
-
-import { sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT } from './send-transaction-internal';
-import type { CompilableTransactionMessage } from '@solana/transaction-messages';
-import { signTransactionMessageWithSigners } from '@solana/signers';
-
-export type SendAndConfirmTransactionWithBlockhashLifetimeFunction = (
-    transaction: (FullySignedTransaction & TransactionWithBlockhashLifetime) | CompilableTransactionMessage,
-    config?: Omit<
-        Parameters<typeof sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT>[0],
-        'confirmRecentTransaction' | 'rpc' | 'transaction'
-    >,
-) => Promise<Signature>;
-
-type SendAndConfirmTransactionWithBlockhashLifetimeFactoryConfig<TCluster> = {
-    rpc: Rpc<GetEpochInfoApi & GetSignatureStatusesApi & SendTransactionApi> & { '~cluster'?: TCluster };
-    rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi & SlotNotificationsApi> & { '~cluster'?: TCluster };
-};
-
-export function sendAndConfirmTransactionFactory({
-    rpc,
-    rpcSubscriptions,
-}: SendAndConfirmTransactionWithBlockhashLifetimeFactoryConfig<'devnet'>): SendAndConfirmTransactionWithBlockhashLifetimeFunction;
-export function sendAndConfirmTransactionFactory({
-    rpc,
-    rpcSubscriptions,
-}: SendAndConfirmTransactionWithBlockhashLifetimeFactoryConfig<'testnet'>): SendAndConfirmTransactionWithBlockhashLifetimeFunction;
-export function sendAndConfirmTransactionFactory({
-    rpc,
-    rpcSubscriptions,
-}: SendAndConfirmTransactionWithBlockhashLifetimeFactoryConfig<'mainnet'>): SendAndConfirmTransactionWithBlockhashLifetimeFunction;
-export function sendAndConfirmTransactionFactory({
-    rpc,
-    rpcSubscriptions,
-}: SendAndConfirmTransactionWithBlockhashLifetimeFactoryConfig<'localnet'>): SendAndConfirmTransactionWithBlockhashLifetimeFunction;
-export function sendAndConfirmTransactionFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | 'localnet' | void = void>({
-    rpc,
-    rpcSubscriptions,
-}: SendAndConfirmTransactionWithBlockhashLifetimeFactoryConfig<TCluster>): SendAndConfirmTransactionWithBlockhashLifetimeFunction {
-    const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({
-        rpc,
-        rpcSubscriptions,
-    } as Parameters<typeof createBlockHeightExceedencePromiseFactory>[0]);
-    const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({
-        rpc,
-        rpcSubscriptions,
-    } as Parameters<typeof createRecentSignatureConfirmationPromiseFactory>[0]);
-    async function confirmRecentTransaction(
-        config: Omit<
-            Parameters<typeof waitForRecentTransactionConfirmation>[0],
-            'getBlockHeightExceedencePromise' | 'getRecentSignatureConfirmationPromise'
-        >,
-    ) {
-        await waitForRecentTransactionConfirmation({
-            ...config,
-            getBlockHeightExceedencePromise,
-            getRecentSignatureConfirmationPromise,
-        });
-    }
-
-    return async function sendAndConfirmTransaction(transaction, config = { commitment: "confirmed" }) {
-        if ("messageBytes" in transaction == false){
-            transaction = await signTransactionMessageWithSigners(transaction) as Readonly<FullySignedTransaction & TransactionWithBlockhashLifetime>;
-        }
-        return await sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT({
-            ...config,
-            confirmRecentTransaction,
-            rpc,
-            transaction,
-        });
-    };
-}

+ 0 - 139
packages/gill/src/kit/send-transaction-internal.ts

@@ -1,139 +0,0 @@
-import type { Signature } from '@solana/keys';
-import type { Rpc, SendTransactionApi } from '@solana/rpc';
-import { type Commitment, commitmentComparator } from '@solana/rpc-types';
-import {
-    waitForDurableNonceTransactionConfirmation,
-    waitForRecentTransactionConfirmation,
-} from '@solana/transaction-confirmation';
-import {
-    type FullySignedTransaction,
-    getBase64EncodedWireTransaction,
-    getSignatureFromTransaction,
-    type TransactionWithBlockhashLifetime,
-    type TransactionWithDurableNonceLifetime,
-} from '@solana/transactions';
-import { debug, getExplorerLink } from '../core';
-
-interface SendAndConfirmDurableNonceTransactionConfig
-    extends SendTransactionBaseConfig,
-        SendTransactionConfigWithoutEncoding {
-    confirmDurableNonceTransaction: (
-        config: Omit<
-            Parameters<typeof waitForDurableNonceTransactionConfirmation>[0],
-            'getNonceInvalidationPromise' | 'getRecentSignatureConfirmationPromise'
-        >,
-    ) => Promise<void>;
-    transaction: FullySignedTransaction & TransactionWithDurableNonceLifetime;
-}
-
-interface SendAndConfirmTransactionWithBlockhashLifetimeConfig
-    extends SendTransactionBaseConfig,
-        SendTransactionConfigWithoutEncoding {
-    confirmRecentTransaction: (
-        config: Omit<
-            Parameters<typeof waitForRecentTransactionConfirmation>[0],
-            'getBlockHeightExceedencePromise' | 'getRecentSignatureConfirmationPromise'
-        >,
-    ) => Promise<void>;
-    transaction: FullySignedTransaction & TransactionWithBlockhashLifetime;
-}
-
-interface SendTransactionBaseConfig extends SendTransactionConfigWithoutEncoding {
-    abortSignal?: AbortSignal;
-    commitment: Commitment;
-    rpc: Rpc<SendTransactionApi>;
-    transaction: FullySignedTransaction;
-}
-
-type SendTransactionConfigWithoutEncoding = Omit<
-    NonNullable<Parameters<SendTransactionApi['sendTransaction']>[1]>,
-    'encoding'
->;
-
-function getSendTransactionConfigWithAdjustedPreflightCommitment(
-    commitment: Commitment,
-    config?: SendTransactionConfigWithoutEncoding,
-): SendTransactionConfigWithoutEncoding | void {
-    if (
-        // The developer has supplied no value for `preflightCommitment`.
-        !config?.preflightCommitment &&
-        // The value of `commitment` is lower than the server default of `preflightCommitment`.
-        commitmentComparator(commitment, 'finalized' /* default value of `preflightCommitment` */) < 0
-    ) {
-        return {
-            ...config,
-            // In the common case, it is unlikely that you want to simulate a transaction at
-            // `finalized` commitment when your standard of commitment for confirming the
-            // transaction is lower. Cap the simulation commitment level to the level of the
-            // confirmation commitment.
-            preflightCommitment: commitment,
-        };
-    }
-    // The commitment at which the developer wishes to confirm the transaction is at least as
-    // high as the commitment at which they want to simulate it. Honour the config as-is.
-    return config;
-}
-
-export async function sendTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-    abortSignal,
-    commitment,
-    rpc,
-    transaction,
-    ...sendTransactionConfig
-}: SendTransactionBaseConfig): Promise<Signature> {
-    debug(`Sending transaction: ${getExplorerLink({transaction: getSignatureFromTransaction(transaction)})}`)
-    const base64EncodedWireTransaction = getBase64EncodedWireTransaction(transaction);
-    debug(`Transaction as base64: ${base64EncodedWireTransaction}`, "debug");
-    return await rpc
-        .sendTransaction(base64EncodedWireTransaction, {
-            ...getSendTransactionConfigWithAdjustedPreflightCommitment(commitment, sendTransactionConfig),
-            encoding: 'base64',
-        })
-        .send({ abortSignal });
-}
-
-export async function sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-    abortSignal,
-    commitment,
-    confirmDurableNonceTransaction,
-    rpc,
-    transaction,
-    ...sendTransactionConfig
-}: SendAndConfirmDurableNonceTransactionConfig): Promise<Signature> {
-    const transactionSignature = await sendTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-        ...sendTransactionConfig,
-        abortSignal,
-        commitment,
-        rpc,
-        transaction,
-    });
-    await confirmDurableNonceTransaction({
-        abortSignal,
-        commitment,
-        transaction,
-    });
-    return transactionSignature;
-}
-
-export async function sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT({
-    abortSignal,
-    commitment,
-    confirmRecentTransaction,
-    rpc,
-    transaction,
-    ...sendTransactionConfig
-}: SendAndConfirmTransactionWithBlockhashLifetimeConfig): Promise<Signature> {
-    const transactionSignature = await sendTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-        ...sendTransactionConfig,
-        abortSignal,
-        commitment,
-        rpc,
-        transaction,
-    });
-    await confirmRecentTransaction({
-        abortSignal,
-        commitment,
-        transaction,
-    });
-    return transactionSignature;
-}

+ 0 - 25
packages/gill/src/kit/send-transaction-without-confirming.ts

@@ -1,25 +0,0 @@
-import type { Rpc, SendTransactionApi } from '@solana/rpc';
-import type { FullySignedTransaction } from '@solana/transactions';
-
-import { sendTransaction_INTERNAL_ONLY_DO_NOT_EXPORT } from './send-transaction-internal';
-
-type SendTransactionWithoutConfirmingFunction = (
-    transaction: FullySignedTransaction,
-    config: Omit<Parameters<typeof sendTransaction_INTERNAL_ONLY_DO_NOT_EXPORT>[0], 'rpc' | 'transaction'>,
-) => Promise<void>;
-
-interface SendTransactionWithoutConfirmingFactoryConfig {
-    rpc: Rpc<SendTransactionApi>;
-}
-
-export function sendTransactionWithoutConfirmingFactory({
-    rpc,
-}: SendTransactionWithoutConfirmingFactoryConfig): SendTransactionWithoutConfirmingFunction {
-    return async function sendTransactionWithoutConfirming(transaction, config) {
-        await sendTransaction_INTERNAL_ONLY_DO_NOT_EXPORT({
-            ...config,
-            rpc,
-            transaction,
-        });
-    };
-}

+ 3 - 3
packages/gill/src/types/rpc.ts

@@ -10,8 +10,8 @@ import type {
   SolanaRpcSubscriptionsApi,
 } from "@solana/rpc-subscriptions";
 import type { DevnetUrl, MainnetUrl, TestnetUrl } from "@solana/rpc-types";
-import type { SendAndConfirmTransactionWithBlockhashLifetimeFunction } from "../kit/send-and-confirm-transaction";
 import type { SimulateTransactionFunction } from "../core/simulate-transaction";
+import { SendAndConfirmTransactionWithSignersFunction } from "../core/send-and-confirm-transaction-with-signers";
 
 /** Solana cluster moniker */
 export type SolanaClusterMoniker = "mainnet" | "devnet" | "testnet" | "localnet";
@@ -42,11 +42,11 @@ export type SolanaClient<TClusterUrl extends ModifiedClusterUrl | string = strin
   /** Used to make RPC websocket calls to your RPC provider */
   rpcSubscriptions: RpcSubscriptions<SolanaRpcSubscriptionsApi> & TClusterUrl;
   /**
-   * Send and confirm a transaction to the network
+   * Send and confirm a transaction to the network (including signing with available Signers)
    *
    * Default commitment level: `confirmed`
    */
-  sendAndConfirmTransaction: SendAndConfirmTransactionWithBlockhashLifetimeFunction;
+  sendAndConfirmTransaction: SendAndConfirmTransactionWithSignersFunction;
   /**
    * Simulate a transaction on the network
    */

+ 54 - 116
pnpm-lock.yaml

@@ -4,20 +4,9 @@ settings:
   autoInstallPeers: true
   excludeLinksFromLockfile: false
 
-overrides:
-  '@solana/web3.js@^2.0.0': npm:gill
-  '@solana/kit': npm:gill
-
 importers:
 
   .:
-    dependencies:
-      '@solana/kit':
-        specifier: npm:gill
-        version: gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
-      '@solana/web3.js':
-        specifier: npm:gill
-        version: gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
     devDependencies:
       '@changesets/changelog-github':
         specifier: ^0.5.0
@@ -123,10 +112,10 @@ importers:
     dependencies:
       '@solana-program/compute-budget':
         specifier: ^0.7.0
-        version: 0.7.0(gill@0.5.0)
+        version: 0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))
       '@solana-program/memo':
         specifier: ^0.7.0
-        version: 0.7.0(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))
+        version: 0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))
       dotenv:
         specifier: ^16.4.5
         version: 16.4.7
@@ -182,16 +171,16 @@ importers:
     dependencies:
       '@solana-program/address-lookup-table':
         specifier: ^0.7.0
-        version: 0.7.0(gill@0.5.0)
+        version: 0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))
       '@solana-program/compute-budget':
         specifier: ^0.7.0
-        version: 0.7.0(gill@0.5.0)
+        version: 0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))
       '@solana-program/system':
         specifier: ^0.7.0
-        version: 0.7.0(gill@0.5.0)
+        version: 0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))
       '@solana-program/token-2022':
         specifier: ^0.4.0
-        version: 0.4.0(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3))(gill@0.5.0)
+        version: 0.4.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3))
       '@solana/accounts':
         specifier: ^2.1.0
         version: 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
@@ -217,8 +206,8 @@ importers:
         specifier: ^2.1.0
         version: 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
       '@solana/kit':
-        specifier: npm:gill
-        version: gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
+        specifier: ^2.1.0
+        version: 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
       '@solana/programs':
         specifier: ^2.1.0
         version: 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
@@ -1392,50 +1381,30 @@ packages:
   '@sinonjs/fake-timers@8.1.0':
     resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==}
 
-  '@solana-program/address-lookup-table@0.6.1':
-    resolution: {integrity: sha512-wWbxkUntnKYrnYCYbxukGwrph5/97JU0jHAwdgl39FMz5dW3u0Q4yriO9rq9bavrz/SqxYlUoVY/Vg0gXOqZCA==}
-    peerDependencies:
-      '@solana/web3.js': npm:gill
-
   '@solana-program/address-lookup-table@0.7.0':
     resolution: {integrity: sha512-dzCeIO5LtiK3bIg0AwO+TPeGURjSG2BKt0c4FRx7105AgLy7uzTktpUzUj6NXAK9SzbirI8HyvHUvw1uvL8O9A==}
     peerDependencies:
-      '@solana/kit': npm:gill
-
-  '@solana-program/compute-budget@0.6.1':
-    resolution: {integrity: sha512-PWcVmRx2gSQ8jd5va5HzSlKqQmR8Q1sYaPcqpCzhOHcApJ4YsVWY6QhaOD5Nx7z1UXkP12vNq3KDsSCZnT3Hkw==}
-    peerDependencies:
-      '@solana/web3.js': npm:gill
+      '@solana/kit': ^2.1.0
 
   '@solana-program/compute-budget@0.7.0':
     resolution: {integrity: sha512-/JJSE1fKO5zx7Z55Z2tLGWBDDi7tUE+xMlK8qqkHlY51KpqksMsIBzQMkG9Dqhoe2Cnn5/t3QK1nJKqW6eHzpg==}
     peerDependencies:
-      '@solana/kit': npm:gill
+      '@solana/kit': ^2.1.0
 
   '@solana-program/memo@0.7.0':
     resolution: {integrity: sha512-3T9iUjWSYtN/5S5jzJuasD2yQfVfFAQ9yTwIE25+P9peWqz4oarn6ZQvRj/FLcBqaMLtSqLhU1hN2cyVBS6hyg==}
     peerDependencies:
-      '@solana/kit': npm:gill
-
-  '@solana-program/system@0.6.2':
-    resolution: {integrity: sha512-q0ZnylK+LISjuP2jH5GWV9IJPtpzQctj5KQwij9XCDRSGkcFr2fpqptNnVupTLQiNL6Q4c1OZuG8WBmyFXVXZw==}
-    peerDependencies:
-      '@solana/web3.js': npm:gill
+      '@solana/kit': ^2.1.0
 
   '@solana-program/system@0.7.0':
     resolution: {integrity: sha512-FKTBsKHpvHHNc1ATRm7SlC5nF/VdJtOSjldhcyfMN9R7xo712Mo2jHIzvBgn8zQO5Kg0DcWuKB7268Kv1ocicw==}
     peerDependencies:
-      '@solana/kit': npm:gill
-
-  '@solana-program/token-2022@0.3.4':
-    resolution: {integrity: sha512-URHA91F9sDibbL6RbuhnKHWGeAONCDcCmHq8tMtpVOhse9/WKp0JOvdLSiGuRkKZqLHo74xF8otmgPVchgVZXQ==}
-    peerDependencies:
-      '@solana/web3.js': npm:gill
+      '@solana/kit': ^2.1.0
 
   '@solana-program/token-2022@0.4.0':
     resolution: {integrity: sha512-rLcYyjeRq/dW62ju9X+gFYqIIRGuD4vXq6EwM9oQBoURFbFzyo12VUi6v0hNh0dRcru+kUx321qVCAfsWWV/ug==}
     peerDependencies:
-      '@solana/kit': npm:gill
+      '@solana/kit': ^2.1.0
       '@solana/sysvars': ^2.1.0
 
   '@solana/accounts@2.1.0':
@@ -1598,6 +1567,12 @@ packages:
     peerDependencies:
       typescript: '>=5'
 
+  '@solana/kit@2.1.0':
+    resolution: {integrity: sha512-vqaHROLKp89xdIbaKVG6BQ44uMN9E6/rSTeltkvquD2qdTObssafGDbAKVFjwZhlNO+sdzHDCLekGabn5VAL6A==}
+    engines: {node: '>=20.18.0'}
+    peerDependencies:
+      typescript: '>=5'
+
   '@solana/options@2.0.0':
     resolution: {integrity: sha512-OVc4KnYosB8oAukQ/htgrxXSxlUP6gUu5Aau6d/BgEkPQzWd/Pr+w91VWw3i3zZuu2SGpedbyh05RoJBe/hSXA==}
     engines: {node: '>=20.18.0'}
@@ -2996,20 +2971,6 @@ packages:
     resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
     engines: {node: '>=10'}
 
-  gill@0.5.0:
-    resolution: {integrity: sha512-g9S7J2upNPOI1IoZ0MLodHO1+e6t/BGkfB4ADDLlSrAzWyv9vixZVRqoIBpZGxJfpW77lIfkUQXhHkd6+O5VbA==}
-    engines: {node: '>=20.18.0'}
-    peerDependencies:
-      '@solana/kit': npm:gill
-      '@solana/web3.js': npm:gill
-      '@solana/web3.js@^2.0.0': '*'
-      typescript: '>=5'
-    peerDependenciesMeta:
-      '@solana/kit':
-        optional: true
-      '@solana/web3.js@^2.0.0':
-        optional: true
-
   glob-parent@5.1.2:
     resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
     engines: {node: '>= 6'}
@@ -5959,41 +5920,25 @@ snapshots:
     dependencies:
       '@sinonjs/commons': 1.8.6
 
-  '@solana-program/address-lookup-table@0.6.1(gill@0.5.0)':
-    dependencies:
-      '@solana/web3.js': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
-
-  '@solana-program/address-lookup-table@0.7.0(gill@0.5.0)':
-    dependencies:
-      '@solana/kit': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
-
-  '@solana-program/compute-budget@0.6.1(gill@0.5.0)':
-    dependencies:
-      '@solana/web3.js': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
-
-  '@solana-program/compute-budget@0.7.0(gill@0.5.0)':
+  '@solana-program/address-lookup-table@0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))':
     dependencies:
-      '@solana/kit': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
+      '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
 
-  '@solana-program/memo@0.7.0(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))':
+  '@solana-program/compute-budget@0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))':
     dependencies:
-      '@solana/kit': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
+      '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
 
-  '@solana-program/system@0.6.2(gill@0.5.0)':
+  '@solana-program/memo@0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))':
     dependencies:
-      '@solana/web3.js': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
+      '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
 
-  '@solana-program/system@0.7.0(gill@0.5.0)':
+  '@solana-program/system@0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))':
     dependencies:
-      '@solana/kit': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
+      '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
 
-  '@solana-program/token-2022@0.3.4(gill@0.5.0)':
+  '@solana-program/token-2022@0.4.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3))':
     dependencies:
-      '@solana/web3.js': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
-
-  '@solana-program/token-2022@0.4.0(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3))(gill@0.5.0)':
-    dependencies:
-      '@solana/kit': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
+      '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
       '@solana/sysvars': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
 
   '@solana/accounts@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)':
@@ -6173,6 +6118,31 @@ snapshots:
     transitivePeerDependencies:
       - fastestsmallesttextencoderdecoder
 
+  '@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))':
+    dependencies:
+      '@solana/accounts': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      '@solana/addresses': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      '@solana/codecs': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      '@solana/errors': 2.1.0(typescript@5.6.3)
+      '@solana/functional': 2.1.0(typescript@5.6.3)
+      '@solana/instructions': 2.1.0(typescript@5.6.3)
+      '@solana/keys': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      '@solana/programs': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      '@solana/rpc': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      '@solana/rpc-parsed-types': 2.1.0(typescript@5.6.3)
+      '@solana/rpc-spec-types': 2.1.0(typescript@5.6.3)
+      '@solana/rpc-subscriptions': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
+      '@solana/rpc-types': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      '@solana/signers': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      '@solana/sysvars': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      '@solana/transaction-confirmation': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
+      '@solana/transaction-messages': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      '@solana/transactions': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
+      typescript: 5.6.3
+    transitivePeerDependencies:
+      - fastestsmallesttextencoderdecoder
+      - ws
+
   '@solana/options@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)':
     dependencies:
       '@solana/codecs-core': 2.0.0(typescript@5.6.3)
@@ -7772,38 +7742,6 @@ snapshots:
 
   get-stream@6.0.1: {}
 
-  gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)):
-    dependencies:
-      '@solana-program/address-lookup-table': 0.6.1(gill@0.5.0)
-      '@solana-program/compute-budget': 0.6.1(gill@0.5.0)
-      '@solana-program/system': 0.6.2(gill@0.5.0)
-      '@solana-program/token-2022': 0.3.4(gill@0.5.0)
-      '@solana/accounts': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/addresses': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/assertions': 2.1.0(typescript@5.6.3)
-      '@solana/codecs': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/errors': 2.1.0(typescript@5.6.3)
-      '@solana/functional': 2.1.0(typescript@5.6.3)
-      '@solana/instructions': 2.1.0(typescript@5.6.3)
-      '@solana/keys': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/programs': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/rpc': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/rpc-parsed-types': 2.1.0(typescript@5.6.3)
-      '@solana/rpc-spec-types': 2.1.0(typescript@5.6.3)
-      '@solana/rpc-subscriptions': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
-      '@solana/rpc-types': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/signers': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/transaction-confirmation': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
-      '@solana/transaction-messages': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/transactions': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.6.3)
-      '@solana/web3.js': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
-      typescript: 5.6.3
-    optionalDependencies:
-      '@solana/kit': gill@0.5.0(fastestsmallesttextencoderdecoder@1.0.22)(gill@0.5.0)(gill@0.5.0(gill@0.5.0)(gill@0.5.0)(typescript@5.6.3))(typescript@5.6.3)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))
-    transitivePeerDependencies:
-      - fastestsmallesttextencoderdecoder
-      - ws
-
   glob-parent@5.1.2:
     dependencies:
       is-glob: 4.0.3