Using the API with Wallet Authentication
When using the Nosana API with wallet authentication instead of an API key, you gain access to additional features like vault management for funding your deployments directly from your Solana wallet.
Overview
There are two ways to authenticate with the Nosana API:
- API Key Authentication - Simple, uses credits from your account balance
- Wallet Authentication - Uses your Solana wallet, enables vault management
Wallet authentication is required for:
- Creating and managing vaults
- Topping up vaults with SOL or NOS
- Withdrawing funds from vaults
- Getting vault balances
Using with @nosana/kit
The easiest way to use wallet authentication is with the @nosana/kit SDK, which automatically handles wallet signing and authentication.
For all the ways to create and configure a wallet (keypair files, base58 keys, browser wallets), see the Wallet Configuration guide.
Installation
npm install @nosana/kitInitialization
Create the client without an API key and assign a wallet:
import { function createNosanaClient(network: NosanaNetwork | undefined, customConfig: PartialClientConfig & {
connect: ConnectFactoryConfig & {
clientSecret: string;
};
}): NosanaClient & {
connect: ServerConnect;
} (+3 overloads)
createNosanaClient, type NosanaNetwork = "mainnet" | "devnet" | "localnet"
const NosanaNetwork: {
readonly MAINNET: "mainnet";
readonly DEVNET: "devnet";
readonly LOCALNET: "localnet";
}
NosanaNetwork, function loadWalletFromFile(filePath?: string): Promise<Wallet>Load a wallet from a Solana CLI keypair JSON file.
Reads a JSON file containing a byte array (as used by `solana-keygen`)
and creates a wallet from it. Defaults to `~/.config/solana/id.json`
if no path is provided.loadWalletFromFile } from '@nosana/kit';
const const client: NosanaClientclient = function createNosanaClient(network?: NosanaNetwork, customConfig?: PartialClientConfig): NosanaClient (+3 overloads)createNosanaClient(const NosanaNetwork: {
readonly MAINNET: "mainnet";
readonly DEVNET: "devnet";
readonly LOCALNET: "localnet";
}
NosanaNetwork.type MAINNET: "mainnet"MAINNET);
// Load a Solana CLI keypair (defaults to ~/.config/solana/id.json)
const client: NosanaClientclient.NosanaClient.wallet: Wallet | undefinedThe wallet. Must be a Wallet (supports both message and transaction signing).
Set this property directly to configure the wallet.wallet = await function loadWalletFromFile(filePath?: string): Promise<Wallet>Load a wallet from a Solana CLI keypair JSON file.
Reads a JSON file containing a byte array (as used by `solana-keygen`)
and creates a wallet from it. Defaults to `~/.config/solana/id.json`
if no path is provided.loadWalletFromFile();When you use @nosana/kit with a wallet, it automatically:
- Creates
SignerAuthfrom your wallet - Handles message signing for authentication
- Provides Solana functions for vault operations
Creating Deployments with Vault
With a wallet (and no API key) configured, client.api is the signer variant of the API (NosanaApi), whose deployments include a vault:
const const api: NosanaApiapi = const client: NosanaClientclient.NosanaClient.api: NosanaApiClientapi as NosanaApi; // signer variant: deployments include a vault
const const deployment: Deploymentdeployment = await const api: NosanaApiapi.NosanaApi.deployments: DeploymentsApideployments.DeploymentsApi.create: (deploymentBody: CreateDeployment) => Promise<Deployment>create({
name: stringname: 'My Deployment',
market?: string | undefinedmarket: 'CA5pMpqkYFKtme7K31pNB1s62X2SdhEv1nN9RdxKCpuQ',
replicas: numberreplicas: 1,
timeout: numbertimeout: 60,
strategy: "SIMPLE" | "SIMPLE-EXTEND" | "SCHEDULED" | "INFINITE"strategy: 'SIMPLE',
job_definition: JobDefinitionjob_definition: {
version: stringversion: '0.1',
type?: string | undefinedtype: 'container',
meta?: Meta | undefinedmeta: { trigger?: string | undefinedtrigger: 'api' },
ops: Opsops: [
{
type: keyof OperationArgsMaptype: 'container/run',
id: OperationIdid: 'hello-world',
args: ContainerRun | ContainerCreateVolume | VmRunArgsargs: {
cmd: stringcmd: 'echo hello world',
image: stringimage: 'ubuntu',
},
},
],
},
});
// The deployment includes a vault
var console: ConsoleThe `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
```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.log('Vault address:', const deployment: Deploymentdeployment.vault: string & Vaultvault.Vault.address: stringaddress);For detailed information on managing vaults, see the Vault Management guide.
Using @nosana/api Directly
If you're using @nosana/api directly (without @nosana/kit), you need to provide SignerAuth yourself — an identifier (your wallet's public key), a message-signing function, and the Solana functions used for vault operations:
const const signerAuth: SignerAuthsignerAuth: type SignerAuth = {
identifier: string;
generate: SignedHeaderAuth["generate"];
solana: ExternalSolanaFunctions;
}
SignerAuth = {
identifier: stringidentifier: const wallet: {
address: string;
signMessage(message: Uint8Array): Promise<Uint8Array>;
}
wallet.address: stringaddress, // your wallet's public key
generate: (message: string, options?: Pick<GenerateOptions, "skipCache">) => Promise<string>generate: async (message: stringmessage: string) => {
// Sign the message with your wallet and return it base64-encoded
const const signature: Uint8Array<ArrayBufferLike>signature = await const wallet: {
address: string;
signMessage(message: Uint8Array): Promise<Uint8Array>;
}
wallet.function signMessage(message: Uint8Array): Promise<Uint8Array>signMessage(new var TextEncoder: new () => TextEncoderThe **`TextEncoder`** interface takes a stream of code points as input and emits a stream of UTF-8 bytes.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/TextEncoder)
`TextEncoder` class is a global reference for `import { TextEncoder } from 'node:util'`
https://nodejs.org/api/globals.html#textencoderTextEncoder().TextEncoder.encode(input?: string): Uint8Array<ArrayBuffer>The **`TextEncoder.encode()`** method takes a string as input, and returns a Global_Objects/Uint8Array containing the text given in parameters encoded with the specific method for that TextEncoder object.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/TextEncoder/encode)encode(message: stringmessage));
return function btoa(data: string): string (+1 overload)Decodes a string into bytes using Latin-1 (ISO-8859), and encodes those bytes
into a string using Base64.
The `data` may be any JavaScript-value that can be coerced into a string.
**This function is only provided for compatibility with legacy web platform APIs**
**and should never be used in new code, because they use strings to represent**
**binary data and predate the introduction of typed arrays in JavaScript.**
**For code running using Node.js APIs, converting between base64-encoded strings**
**and binary data should be performed using `Buffer.from(str, 'base64')` and `buf.toString('base64')`.**btoa(var String: StringConstructorAllows manipulation and formatting of text strings and determination and location of substrings within strings.String.StringConstructor.fromCharCode(...codes: number[]): stringfromCharCode(...const signature: Uint8Array<ArrayBufferLike>signature));
},
solana: ExternalSolanaFunctionssolana: {
getBalance: (address: string) => Promise<{
SOL: number;
NOS: number;
}>
Gets the balance of SOL and NOS tokens for a given addressgetBalance: async (address: stringaddress) => {
// Fetch the SOL and NOS balances for the address
return { type SOL: numberSOL: 0, type NOS: numberNOS: 0 };
},
transferTokensToRecipient: (recipient: string, tokens: TopupVaultOptions) => Promise<void>Transfers specified amounts of SOL and NOS to the recipient addresstransferTokensToRecipient: async (recipient: stringrecipient, tokens: TopupVaultOptionstokens) => {
// Transfer the tokens from your wallet to the recipient
},
deserializeSignSendAndConfirmTransaction: (transaction: string) => Promise<string>Deserializes, signs, sends, and confirms a Solana transactiondeserializeSignSendAndConfirmTransaction: async (transaction: stringtransaction) => {
// Sign, send, and confirm the serialized transaction
return 'tx-signature';
},
},
};
const const api: NosanaApiapi = function createNosanaApi(environment: NosanaNetwork, signerAuth: SignerAuth, options?: CreateNosanaApiOptions): NosanaApi (+2 overloads)createNosanaApi(const NosanaNetwork: {
readonly MAINNET: "mainnet";
readonly DEVNET: "devnet";
readonly LOCALNET: "localnet";
}
NosanaNetwork.type MAINNET: "mainnet"MAINNET, const signerAuth: SignerAuthsignerAuth);createNosanaApi and the SignerAuth type are also exported from the standalone @nosana/api package. @nosana/kit implements these functions for you from the configured wallet — that's the recommended path.
HTTP API with Wallet Authentication
If you're making direct HTTP requests, you need to:
- Sign a message with your wallet
- Include the signed message in the
Authorizationheader - Include your public key in the
x-user-idheader
Authentication Header Format
Authorization: NosanaApiAuthentication:<base64-encoded-signature>
x-user-id: <your-wallet-public-key>Example Request
# Sign the message "NosanaApiAuthentication" with your wallet
# Then include it in the Authorization header
curl -X POST https://api.nosana.com/deployments/vaults/create \
-H "Authorization: NosanaApiAuthentication:<signed-message>" \
-H "x-user-id: <your-public-key>" \
-H "Content-Type: application/json"For vault management endpoints and operations, see the Vault Management guide.
Differences from API Key Authentication
| Feature | API Key | Wallet Authentication |
|---|---|---|
| Authentication | Bearer <api-key> | NosanaApiAuthentication:<signed-message> |
| Funding | Uses account credits | Uses vault (SOL/NOS) |
| Vault Management | ❌ Not available | ✅ Full vault operations |
| Setup Complexity | Simple | Requires wallet setup |