Skip to content

feat: support @solana/web3js #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: feat/solana
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"test:watch": "bun test --watch",
"changeset": "changeset",
"changeset:release": "bash remove-type.sh && bun run build && changeset publish && bash restore-type.sh && bun run format",
"changeset:version": "changeset version && bun install --lockfile-only"
"changeset:version": "changeset version && bun install --lockfile-only",
"typecheck": "tsc --noEmit"
},
"exports": {
".": {
Expand Down
20 changes: 8 additions & 12 deletions src/actions/getCAB.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import type { Address as SolanaAddress, TransactionSigner } from "@solana/kit";
import type { Address as SolanaAddress } from "@solana/kit";
import { AccountNotFoundError } from "@zerodev/sdk";
import type {
Address as EvmAddress,
Chain,
Client,
Hex,
Transport,
} from "viem";
import type { Address as EvmAddress, Chain, Hex, Transport } from "viem";
import type { SmartAccount } from "viem/account-abstraction";
import type { CombinedIntentRpcSchema } from "../client/intentClient.js";
import type {
BaseIntentClient,
CombinedIntentRpcSchema,
} from "../client/intentClient.js";

export type NetworkType = "mainnet" | "testnet";

Expand Down Expand Up @@ -97,13 +94,12 @@ export async function getCAB<
chain extends Chain | undefined = Chain | undefined,
account extends SmartAccount | undefined = SmartAccount | undefined,
>(
client: Client<transport, chain, account, CombinedIntentRpcSchema>,
client: BaseIntentClient<transport, chain, account, CombinedIntentRpcSchema>,
parameters: GetCABParameters,
solanaSigner: TransactionSigner | undefined,
): Promise<GetCABResult> {
const { account: account_ = client.account } = parameters;
const evmAddress = parameters.evmAddress ?? account_?.address;
const solanaAddress = parameters.solanaAddress ?? solanaSigner?.address;
const solanaAddress = parameters.solanaAddress ?? client?.solana?.address;
if (!evmAddress && !solanaAddress) throw new AccountNotFoundError();

const result = await client.request({
Expand Down
18 changes: 7 additions & 11 deletions src/actions/getIntent.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import type {
Address as SolanaAddress,
Rpc,
SolanaRpcApi,
TransactionSigner,
} from "@solana/kit";
import type { Chain, Client, Hex, RpcErrorType, Transport } from "viem";
import type { Address as SolanaAddress } from "@solana/kit";
import type { Chain, Hex, RpcErrorType, Transport } from "viem";
import type { SmartAccount } from "viem/account-abstraction";
import type { CombinedIntentRpcSchema } from "../client/intentClient.js";
import type {
BaseIntentClient,
CombinedIntentRpcSchema,
} from "../client/intentClient.js";
import type { INTENT_VERSION_TYPE } from "../types/intent.js";
import { deepHexlify } from "../utils/deepHexlify.js";

Expand Down Expand Up @@ -87,11 +85,9 @@ export async function getIntent<
chain extends Chain | undefined = Chain | undefined,
account extends SmartAccount | undefined = SmartAccount | undefined,
>(
client: Client<transport, chain, account, CombinedIntentRpcSchema>,
client: BaseIntentClient<transport, chain, account, CombinedIntentRpcSchema>,
parameters: GetIntentParameters,
version: INTENT_VERSION_TYPE,
_solanaSigner: TransactionSigner | undefined,
_solanaRpc: Rpc<SolanaRpcApi> | undefined,
): Promise<GetIntentReturnType> {
const { gasToken, ...rest } = parameters;
const parametersWithVersion = {
Expand Down
103 changes: 34 additions & 69 deletions src/actions/prepareUserIntent.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,11 @@
import type {
Address as SolanaAddress,
IInstruction,
Rpc,
SolanaRpcApi,
TransactionSigner,
} from "@solana/kit";
import {
appendTransactionMessageInstructions,
compileTransactionMessage,
createTransactionMessage,
getCompiledTransactionMessageEncoder,
pipe,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
} from "@solana/kit";
import type { Address as SolanaAddress, ReadonlyUint8Array } from "@solana/kit";
import {
AccountNotFoundError,
type KernelSmartAccountImplementation,
} from "@zerodev/sdk";
import type {
Address,
Chain,
Client,
ContractFunctionParameters,
Hex,
Transport,
Expand All @@ -33,7 +17,10 @@ import type {
UserOperationCall,
} from "viem/account-abstraction";
import { parseAccount } from "viem/utils";
import type { CombinedIntentRpcSchema } from "../client/intentClient.js";
import type {
BaseIntentClient,
CombinedIntentRpcSchema,
} from "../client/intentClient.js";
import type { INTENT_VERSION_TYPE } from "../types/intent.js";
import { SOLANA_CHAIN_ID } from "../utils/constants.js";
import type { GetIntentReturnType } from "./getIntent.js";
Expand All @@ -55,12 +42,6 @@ export type PrepareUserIntentParameters<
account extends SmartAccount | undefined = SmartAccount | undefined,
accountOverride extends SmartAccount | undefined = SmartAccount | undefined,
calls extends readonly unknown[] = readonly unknown[],
solanaRpc extends Rpc<SolanaRpcApi> | undefined =
| Rpc<SolanaRpcApi>
| undefined,
solanaSigner extends TransactionSigner | undefined =
| TransactionSigner
| undefined,
> = PrepareUserOperationParametersWithOptionalCalls<
account,
accountOverride,
Expand All @@ -76,11 +57,13 @@ export type PrepareUserIntentParameters<
amount: bigint;
chainId: number;
}>;
instructions?: IInstruction[];
/**
* Prepared and encoded transactions for solana
* Built using : `getCompiledTransactionMessageEncoder().encode(compiledTransactionMessage)`
*/
solTransaction?: ReadonlyUint8Array;
gasToken?: "SPONSORED" | "NATIVE";
chainId?: number;
solanaRpc?: solanaRpc;
solanaSigner?: solanaSigner;
};

export type PrepareUserIntentResult = GetIntentReturnType;
Expand Down Expand Up @@ -134,30 +117,34 @@ export type PrepareUserIntentResult = GetIntentReturnType;
* chainId: 10n
* }]
* })
*
* // Using solana transaction
* const result = await intentClient.sendUserIntent({
* inputTokens: [
* {
* chainId: 1n,
* address: '0x...',
* }
* ],
* outputTokens: [
* {
* chainId: 10n,
* address: '0x...',
* amount: 900000n,
* }
* ],
* solTransaction: encodedTransactionMessage,
* })
*/
export async function prepareUserIntent<
account extends SmartAccount | undefined = SmartAccount | undefined,
chain extends Chain | undefined = Chain | undefined,
accountOverride extends SmartAccount | undefined = undefined,
calls extends readonly unknown[] = readonly unknown[],
SolanaRpc extends Rpc<SolanaRpcApi> | undefined =
| Rpc<SolanaRpcApi>
| undefined,
SolanaSigner extends TransactionSigner | undefined =
| TransactionSigner
| undefined,
>(
client: Client<Transport, chain, account, CombinedIntentRpcSchema>,
parameters: PrepareUserIntentParameters<
account,
accountOverride,
calls,
SolanaRpc,
SolanaSigner
>,
client: BaseIntentClient<Transport, chain, account, CombinedIntentRpcSchema>,
parameters: PrepareUserIntentParameters<account, accountOverride, calls>,
version: INTENT_VERSION_TYPE,
solanaSigner: TransactionSigner | undefined,
solanaRpc: Rpc<SolanaRpcApi> | undefined,
): Promise<PrepareUserIntentResult> {
const { account: account_ = client.account } = parameters;
if (!account_) throw new AccountNotFoundError();
Expand Down Expand Up @@ -192,29 +179,9 @@ export async function prepareUserIntent<

// get instructionData
const instructionData = await (async () => {
const instructions = parameters.instructions;
if (instructions) {
if (!solanaSigner || !solanaRpc)
throw new Error("please provide solanaSigner and solanaRpc");
const { value: latestBlockhash } = await solanaRpc
.getLatestBlockhash()
.send();
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(message) =>
setTransactionMessageFeePayer(solanaSigner.address, message),
(message) =>
setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message),
(message) =>
appendTransactionMessageInstructions(instructions, message),
);
const compiledTransactionMessage =
compileTransactionMessage(transactionMessage);
const encodedTransactionMessage =
getCompiledTransactionMessageEncoder().encode(
compiledTransactionMessage,
);
return toHex(new Uint8Array(encodedTransactionMessage));
// If we got a provided solana transaction, return it
if (parameters.solTransaction) {
return toHex(new Uint8Array(parameters.solTransaction));
}
return "0x";
})();
Expand All @@ -231,7 +198,7 @@ export async function prepareUserIntent<
}
const recipient =
BigInt(desinationChainId) === SOLANA_CHAIN_ID
? solanaSigner?.address
? client.solana?.address
: account.address;
if (!recipient) throw new Error("please provide solanaSigner");

Expand All @@ -250,7 +217,5 @@ export async function prepareUserIntent<
initData,
},
version,
solanaSigner,
solanaRpc,
);
}
Loading