Skip to content

Solana Service ​

General Solana utility service for low-level RPC operations, transactions, and PDA derivations.

Methods ​

Build, Sign, and Send (Convenience Method) ​

ts
buildSignAndSend(
  instructions: Instruction | Instruction[],
  options?: {
    feePayer?: TransactionSigner;
    commitment?: 'processed' | 'confirmed' | 'finalized';
  }
): Promise<Signature>

Build Transaction ​

ts
buildTransaction(
  instructions: Instruction | Instruction[],
  options?: { feePayer?: TransactionSigner }
): Promise<TransactionMessage & TransactionMessageWithFeePayer & TransactionMessageWithBlockhashLifetime>

Sign Transaction ​

ts
signTransaction(
  transactionMessage: TransactionMessage & TransactionMessageWithFeePayer & TransactionMessageWithBlockhashLifetime
): Promise<SendableTransaction & Transaction & TransactionWithBlockhashLifetime>

Send Transaction ​

ts
sendTransaction(
  transaction: SendableTransaction & Transaction & TransactionWithBlockhashLifetime,
  options?: { commitment?: 'processed' | 'confirmed' | 'finalized' }
): Promise<Signature>

Get Balance ​

ts
getBalance(address?: Address | string): Promise<bigint>

Get Balance Info ​

ts
getBalanceInfo(address?: Address | string): Promise<SolBalanceInfo>

Derive PDA ​

ts
pda(seeds: Array<Address | string>, programId: Address): Promise<Address>

Get NFT From Collection ​

ts
getNftFromCollection(owner: Address, collection: Address): Promise<Address | undefined>

Returns the mint of the first NFT owner holds (at least one token, classic SPL token program) whose Metaplex metadata has collection as its verified collection, or undefined if there is none. Metadata accounts that are missing or cannot be decoded are skipped. Use it to find a market's access-key NFT before calling jobs.work({ market, nft }).

Transfer SOL ​

ts
transfer(params: {
  to: Address | string;
  amount: number | bigint;
  from?: TransactionSigner;
}): Promise<Instruction> // Returns TransferSolInstruction

Examples ​

ts
import type { type Signature = NominalType<"brand", "Signature"> & NominalType<"stringEncoding", "base58"> & string
A 64-byte Ed25519 signature as a base58-encoded string.
Signature
} from '@solana/kit';
import type { type Address = NominalType<"brand", "Address"> & NominalType<"stringEncoding", "base58"> & string
Represents a string that validates as a Solana address or public key.
@group@solana/kit
Address
} from '@nosana/kit';
// Send a single instruction (convenience method) const const signature: Signaturesignature: type Signature = NominalType<"brand", "Signature"> & NominalType<"stringEncoding", "base58"> & string
A 64-byte Ed25519 signature as a base58-encoded string.
Signature
= await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.
SolanaService.buildSignAndSend(instructions: Instruction | Instruction[], options?: {
    feePayer?: TransactionSigner;
    commitment?: "processed" | "confirmed" | "finalized";
    estimateComputeUnits?: boolean;
}): Promise<Signature>
buildSignAndSend
(const instruction: Instruction<string, readonly (AccountLookupMeta<string, string> | AccountMeta<string>)[]>instruction);
// Send multiple instructions atomically const const signature2: Signaturesignature2: type Signature = NominalType<"brand", "Signature"> & NominalType<"stringEncoding", "base58"> & string
A 64-byte Ed25519 signature as a base58-encoded string.
Signature
= await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.
SolanaService.buildSignAndSend(instructions: Instruction | Instruction[], options?: {
    feePayer?: TransactionSigner;
    commitment?: "processed" | "confirmed" | "finalized";
    estimateComputeUnits?: boolean;
}): Promise<Signature>
buildSignAndSend
([const ix1: Instruction<string, readonly (AccountLookupMeta<string, string> | AccountMeta<string>)[]>ix1, const ix2: Instruction<string, readonly (AccountLookupMeta<string, string> | AccountMeta<string>)[]>ix2, const ix3: Instruction<string, readonly (AccountLookupMeta<string, string> | AccountMeta<string>)[]>ix3]);
// Or build, sign, and send separately for more control const const transactionMessage: TransactionMessage & TransactionMessageWithFeePayer<string> & TransactionMessageWithBlockhashLifetimetransactionMessage = await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.
SolanaService.buildTransaction(instructions: Instruction | Instruction[], options?: {
    feePayer?: TransactionSigner | Address | string;
    estimateComputeUnits?: boolean;
}): Promise<TransactionMessage & TransactionMessageWithFeePayer & TransactionMessageWithBlockhashLifetime>
Build a transaction message from instructions. This function creates a transaction message with fee payer, blockhash, and instructions.
@paraminstructions Single instruction or array of instructions@paramoptions Optional configuration@paramoptions.feePayer Optional custom fee payer. Can be a TransactionSigner (for full signing) or an Address/string (for partial signing where feepayer signs later). Takes precedence over service feePayer and wallet.@paramoptions.estimateComputeUnits If true, estimates and sets the compute unit limit. Default: false.@returnsAn unsigned transaction message ready to be signed
buildTransaction
(const instruction: Instruction<string, readonly (AccountLookupMeta<string, string> | AccountMeta<string>)[]>instruction);
const
const signedTransaction: FullySignedTransaction & TransactionWithinSizeLimit & Readonly<{
    messageBytes: TransactionMessageBytes;
    signatures: SignaturesMap;
}> & TransactionWithBlockhashLifetime
signedTransaction
= await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.SolanaService.signTransaction(transactionMessage: TransactionMessage & TransactionMessageWithFeePayer & TransactionMessageWithBlockhashLifetime): Promise<SendableTransaction & Transaction & TransactionWithBlockhashLifetime>signTransaction(const transactionMessage: TransactionMessage & TransactionMessageWithFeePayer<string> & TransactionMessageWithBlockhashLifetimetransactionMessage);
const const signature3: Signaturesignature3: type Signature = NominalType<"brand", "Signature"> & NominalType<"stringEncoding", "base58"> & string
A 64-byte Ed25519 signature as a base58-encoded string.
Signature
= await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.
SolanaService.sendTransaction(transaction: SendableTransaction & Transaction & TransactionWithBlockhashLifetime, options?: {
    commitment?: "processed" | "confirmed" | "finalized";
}): Promise<Signature>
sendTransaction
(
const signedTransaction: FullySignedTransaction & TransactionWithinSizeLimit & Readonly<{
    messageBytes: TransactionMessageBytes;
    signatures: SignaturesMap;
}> & TransactionWithBlockhashLifetime
signedTransaction
);
// Check account balance const const balance: bigintbalance: bigint = await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.SolanaService.getBalance(addressStr?: string | Address): Promise<bigint>
Get the SOL balance for a specific address.
@paramaddressStr - Optional address to query. If not provided, uses the wallet address.@returnsThe SOL balance in lamports@throws{NosanaError} If neither address nor wallet is provided
getBalance
(address<"address">(putativeAddress: "address"): Address<"address">
Combines _asserting_ that a string is an address with _coercing_ it to the {@link Address } type. It's most useful with untrusted input.
@example```ts import { address } from '@solana/addresses'; await transfer(address(fromAddress), address(toAddress), lamports(100000n)); ``` > [!TIP] > When starting from a known-good address as a string, it's more efficient to typecast it rather than to use the {@link address} helper, because the helper unconditionally performs validation on its input. > > ```ts > import { Address } from '@solana/addresses'; > > const MEMO_PROGRAM_ADDRESS = > 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr' as Address<'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'>; > ```
address
('address'));
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v24.x/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(`Balance: ${const balance: bigintbalance} lamports`);
// Or get exact lamports plus display metadata const const balanceInfo: SolBalanceInfobalanceInfo = await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.SolanaService.getBalanceInfo(addressStr?: string | Address): Promise<SolBalanceInfo>
Get SOL balance metadata for a specific address.
@paramaddressStr - Optional address to query. If not provided, uses the wallet address.@returnsExact lamports plus display-oriented SOL metadata@throws{NosanaError} If neither address nor wallet is provided
getBalanceInfo
(address<"address">(putativeAddress: "address"): Address<"address">
Combines _asserting_ that a string is an address with _coercing_ it to the {@link Address } type. It's most useful with untrusted input.
@example```ts import { address } from '@solana/addresses'; await transfer(address(fromAddress), address(toAddress), lamports(100000n)); ``` > [!TIP] > When starting from a known-good address as a string, it's more efficient to typecast it rather than to use the {@link address} helper, because the helper unconditionally performs validation on its input. > > ```ts > import { Address } from '@solana/addresses'; > > const MEMO_PROGRAM_ADDRESS = > 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr' as Address<'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'>; > ```
address
('address'));
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v24.x/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(`Balance: ${const balanceInfo: SolBalanceInfobalanceInfo.BalanceInfo.uiAmount: numberuiAmount} SOL`);
// Derive PDA const const pda: Addresspda: type Address = NominalType<"brand", "Address"> & NominalType<"stringEncoding", "base58"> & string
Represents a string that validates as a Solana address or public key.
@group@solana/kit
Address
= await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.SolanaService.pda(seeds: Array<Address | string>, programId: Address): Promise<Address>pda(['seed1', 'seed2'], const programAddress: Address<"program-address">programAddress);
// Find the owner's NFT from a verified collection (e.g. a market access key) const const nft: Address | undefinednft: type Address = NominalType<"brand", "Address"> & NominalType<"stringEncoding", "base58"> & string
Represents a string that validates as a Solana address or public key.
@group@solana/kit
Address
| undefined = await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.SolanaService.getNftFromCollection(owner: Address, collection: Address): Promise<Address | undefined>
Find the first NFT of a verified Metaplex collection held by `owner`, e.g. a market's access key to pass as `nft` to `jobs.work`. Looks at the owner's SPL token accounts (classic token program) holding at least one token, decodes each mint's Metaplex metadata account, and returns the first mint whose metadata has `collection` set to the given address with `verified: true`. Metadata accounts that are missing or cannot be decoded are skipped.
@paramowner The address holding the NFT.@paramcollection The collection address (the collection NFT's mint).@returnsThe NFT mint, or `undefined` if the owner holds none from the collection.@throws{NosanaError} If the RPC requests fail.
getNftFromCollection
(
address<"owner-address">(putativeAddress: "owner-address"): Address<"owner-address">
Combines _asserting_ that a string is an address with _coercing_ it to the {@link Address } type. It's most useful with untrusted input.
@example```ts import { address } from '@solana/addresses'; await transfer(address(fromAddress), address(toAddress), lamports(100000n)); ``` > [!TIP] > When starting from a known-good address as a string, it's more efficient to typecast it rather than to use the {@link address} helper, because the helper unconditionally performs validation on its input. > > ```ts > import { Address } from '@solana/addresses'; > > const MEMO_PROGRAM_ADDRESS = > 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr' as Address<'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'>; > ```
address
('owner-address'),
address<"collection-address">(putativeAddress: "collection-address"): Address<"collection-address">
Combines _asserting_ that a string is an address with _coercing_ it to the {@link Address } type. It's most useful with untrusted input.
@example```ts import { address } from '@solana/addresses'; await transfer(address(fromAddress), address(toAddress), lamports(100000n)); ``` > [!TIP] > When starting from a known-good address as a string, it's more efficient to typecast it rather than to use the {@link address} helper, because the helper unconditionally performs validation on its input. > > ```ts > import { Address } from '@solana/addresses'; > > const MEMO_PROGRAM_ADDRESS = > 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr' as Address<'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'>; > ```
address
('collection-address')
); // Get instruction to transfer SOL const const transferSolIx: Instruction<string, readonly (AccountLookupMeta<string, string> | AccountMeta<string>)[]>transferSolIx: interface Instruction<TProgramAddress extends string = string, TAccounts extends readonly (AccountLookupMeta | AccountMeta)[] = readonly (AccountLookupMeta<string, string> | AccountMeta<string>)[]>
An instruction destined for a given program.
@example```ts type StakeProgramInstruction = Instruction<'StakeConfig11111111111111111111111111111111'>; ```
Instruction
= await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.
SolanaService.transfer(params: {
    to: Address | string;
    amount: number | bigint;
    from?: TransactionSigner;
}): Promise<ReturnType<typeof getTransferSolInstruction>>
Get an instruction to transfer SOL from one address to another.
@paramparams Transfer parameters@paramparams.to Recipient address@paramparams.amount Amount in lamports (number or bigint)@paramparams.from Optional sender TransactionSigner. If not provided, uses wallet from client.@returnsAn instruction to transfer SOL
transfer
({
to: string | Addressto: address<"recipient-address">(putativeAddress: "recipient-address"): Address<"recipient-address">
Combines _asserting_ that a string is an address with _coercing_ it to the {@link Address } type. It's most useful with untrusted input.
@example```ts import { address } from '@solana/addresses'; await transfer(address(fromAddress), address(toAddress), lamports(100000n)); ``` > [!TIP] > When starting from a known-good address as a string, it's more efficient to typecast it rather than to use the {@link address} helper, because the helper unconditionally performs validation on its input. > > ```ts > import { Address } from '@solana/addresses'; > > const MEMO_PROGRAM_ADDRESS = > 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr' as Address<'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'>; > ```
address
('recipient-address'),
amount: number | bigintamount: 1000000, // lamports (can be number or bigint) // from is optional - uses wallet if not provided }); // Execute the transfer await const client: NosanaClientclient.NosanaClient.solana: SolanaServicesolana.
SolanaService.buildSignAndSend(instructions: Instruction | Instruction[], options?: {
    feePayer?: TransactionSigner;
    commitment?: "processed" | "confirmed" | "finalized";
    estimateComputeUnits?: boolean;
}): Promise<Signature>
buildSignAndSend
(const transferSolIx: Instruction<string, readonly (AccountLookupMeta<string, string> | AccountMeta<string>)[]>transferSolIx);