Skip to content
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Helpers, plugins, and tools for [`@solana/kit`](https://github.com/anza-xyz/kit)
| [@kit-helpers/jito](./plugins/jito) | Jito bundle plugin — bundle submission, tip accounts, and status polling | 0.1.0 |
| [@kit-helpers/local-validator](./plugins/local-validator) | Solana test validator lifecycle management | 0.1.0 |
| [@kit-helpers/airdrop-token](./plugins/airdrop-token) | Airdrop utility for creating token mints, ATAs, and minting tokens | 0.1.0 |
| [@kit-helpers/surfpool](./plugins/surfpool) | Surfpool/Surfnet cheatcodes — clock, accounts, programs, profiling | 0.1.0 |

> **Note:** The `@kit-helpers/program-system` and `@kit-helpers/program-token` packages have been removed. Their functionality is now provided by the native [`@solana-program/system`](https://www.npmjs.com/package/@solana-program/system) and [`@solana-program/token`](https://www.npmjs.com/package/@solana-program/token) plugins, composed automatically by `@kit-helpers/client` under `client.program.system` and `client.program.token`.

Expand Down
116 changes: 116 additions & 0 deletions plugins/surfpool/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# @kit-helpers/surfpool

[Surfpool](https://www.surfpool.run/) cheatcodes plugin for `@solana/kit` — clock control, account manipulation, program management, profiling, and more.

## Installation

```bash
pnpm add @kit-helpers/surfpool
```

## Usage

### With Plugin

```ts
import { createSolanaClient } from '@solana/kit';
import { surfpool } from '@kit-helpers/surfpool';

const client = createSolanaClient({ ... })
.use(surfpool());

// Time travel to a future epoch
await client.surfnet.timeTravel({ absoluteEpoch: 1000 }).send();

// Set account lamports
await client.surfnet.setAccount(address, { lamports: 5_000_000_000 }).send();

// Pause the clock
await client.surfnet.pauseClock().send();
```

### Without Plugin

```ts
import { createSurfnetCheatcodesRpc } from '@kit-helpers/surfpool';

const surfnet = createSurfnetCheatcodesRpc('http://127.0.0.1:8899');

const clock = await surfnet.timeTravel({ absoluteSlot: 50_000 }).send();
```

## API

### Clock

| Method | Description |
| --------------- | ------------------------------------------ |
| `timeTravel()` | Jump to a future epoch, slot, or timestamp |
| `pauseClock()` | Freeze the clock — slots stop advancing |
| `resumeClock()` | Resume the clock after pausing |

### Accounts

| Method | Description |
| ----------------------- | --------------------------------------------------- |
| `setAccount()` | Set lamports, data, owner, or executable on account |
| `setTokenAccount()` | Set token account balance, delegate, state |
| `resetAccount()` | Reset account to its original state |
| `streamAccount()` | Register an account for streaming |
| `getStreamedAccounts()` | List accounts registered for streaming |

### Programs

| Method | Description |
| ----------------------- | ---------------------------------------- |
| `cloneProgramAccount()` | Clone a program to a new address |
| `setProgramAuthority()` | Set or remove upgrade authority |
| `writeProgram()` | Write data to a program at a byte offset |

### Profiling

| Method | Description |
| -------------------------- | ------------------------------------------ |
| `profileTransaction()` | Profile a transaction's compute unit usage |
| `getTransactionProfile()` | Get detailed profile by signature or UUID |
| `getProfileResultsByTag()` | Get all profile results matching a tag |

### IDL

| Method | Description |
| ---------------- | ------------------------------------- |
| `registerIdl()` | Register an Anchor IDL for a program |
| `getActiveIdl()` | Retrieve the active IDL for a program |

### Network

| Method | Description |
| ------------------ | ---------------------------------------- |
| `getSurfnetInfo()` | Get Surfnet runtime info and runbook log |
| `exportSnapshot()` | Export the current network state |
| `setSupply()` | Override circulating/total supply |
| `resetNetwork()` | Wipe all state and start fresh |

### Scenario

| Method | Description |
| -------------------- | ------------------------------------------ |
| `registerScenario()` | Register a scenario with account overrides |

### Local

| Method | Description |
| ---------------------- | ------------------------------------------ |
| `getLocalSignatures()` | Get recent transaction signatures and logs |

## Configuration

```ts
surfpool({
url: 'http://127.0.0.1:8899', // default
});
```

## License

MIT
79 changes: 79 additions & 0 deletions plugins/surfpool/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"name": "@kit-helpers/surfpool",
"version": "0.1.0",
"description": "Surfpool/Surfnet cheatcodes plugin for @solana/kit",
"exports": {
"types": "./dist/types/index.d.ts",
"react-native": "./dist/index.react-native.mjs",
"browser": {
"import": "./dist/index.browser.mjs",
"require": "./dist/index.browser.cjs"
},
"node": {
"import": "./dist/index.node.mjs",
"require": "./dist/index.node.cjs"
}
},
"browser": {
"./dist/index.node.cjs": "./dist/index.browser.cjs",
"./dist/index.node.mjs": "./dist/index.browser.mjs"
},
"main": "./dist/index.node.cjs",
"module": "./dist/index.node.mjs",
"react-native": "./dist/index.react-native.mjs",
"types": "./dist/types/index.d.ts",
"type": "commonjs",
"files": [
"./dist/types",
"./dist/index.*"
],
"sideEffects": false,
"keywords": [
"solana",
"kit",
"plugin",
"surfpool",
"surfnet",
"cheatcodes"
],
"scripts": {
"build": "rimraf dist && tsup && tsc -p ./tsconfig.declarations.json",
"dev": "vitest --project node",
"lint": "eslint . && prettier --check .",
"lint:fix": "eslint --fix . && prettier --write .",
"test": "pnpm test:types && pnpm test:treeshakability && pnpm test:unit",
"test:treeshakability": "for file in dist/index.*.mjs; do agadoo $file; done",
"test:types": "tsc --noEmit",
"test:unit": "vitest run"
},
"peerDependencies": {
"@solana/kit": "^6.3.0"
},
"dependencies": {
"@solana/rpc": "^6.3.0",
"@solana/rpc-spec-types": "^6.3.0"
},
"devDependencies": {
"@solana/kit": "^6.3.0",
"@types/node": "^25.4.0",
"agadoo": "^3.0.0",
"browserslist-to-esbuild": "^2.1.1",
"happy-dom": "^20.8.3",
"rimraf": "^6.1.3",
"tsup": "^8.5.1",
"vitest": "^4.0.18"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/amilz/kit-helpers",
"directory": "plugins/surfpool"
},
"bugs": {
"url": "https://github.com/amilz/kit-helpers/issues"
},
"browserslist": [
"supports bigint and not dead",
"maintained node versions"
]
}
43 changes: 43 additions & 0 deletions plugins/surfpool/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Plugin
export { surfpool } from './surfpool-plugin';

// RPC factory
export { createSurfnetCheatcodesRpc } from './surfnet-rpc';

// Types
export type { SurfnetCheatcodesApi } from './types';
export type { ClockState, TimeTravelConfig, SurfnetTimeTravelApi } from './methods/clock/time-travel';
export type { SurfnetPauseClockApi } from './methods/clock/pause-clock';
export type { SurfnetResumeClockApi } from './methods/clock/resume-clock';
export type { SetAccountUpdate, SurfnetSetAccountApi } from './methods/accounts/set-account';
export type { SetTokenAccountUpdate, SurfnetSetTokenAccountApi } from './methods/accounts/set-token-account';
export type { ResetAccountConfig, SurfnetResetAccountApi } from './methods/accounts/reset-account';
export type { StreamAccountConfig, SurfnetStreamAccountApi } from './methods/accounts/stream-account';
export type {
StreamedAccountEntry,
StreamedAccountsResult,
SurfnetGetStreamedAccountsApi,
} from './methods/accounts/get-streamed-accounts';
export type { SurfnetCloneProgramAccountApi } from './methods/programs/clone-program-account';
export type { SurfnetSetProgramAuthorityApi } from './methods/programs/set-program-authority';
export type { SurfnetWriteProgramApi } from './methods/programs/write-program';
export type {
ProfileTransactionConfig,
ComputeUnitsProfile,
TransactionProfileResult,
SurfnetProfileTransactionApi,
} from './methods/profiling/profile-transaction';
export type {
TransactionProfileKey,
DetailedTransactionProfile,
SurfnetGetTransactionProfileApi,
} from './methods/profiling/get-transaction-profile';
export type { SurfnetGetProfileResultsByTagApi } from './methods/profiling/get-profile-results-by-tag';
export type { AnchorIdl, IdlMetadata, SurfnetRegisterIdlApi } from './methods/idl/register-idl';
export type { SurfnetGetActiveIdlApi } from './methods/idl/get-active-idl';
export type { SetSupplyUpdate, SurfnetSetSupplyApi } from './methods/network/set-supply';
export type { SurfnetResetNetworkApi } from './methods/network/reset-network';
export type { RunbookExecution, SurfnetInfo, SurfnetGetSurfnetInfoApi } from './methods/network/get-surfnet-info';
export type { ExportSnapshotConfig, SurfnetExportSnapshotApi } from './methods/network/export-snapshot';
export type { ScenarioOverride, Scenario, SurfnetRegisterScenarioApi } from './methods/scenario/register-scenario';
export type { LocalSignatureEntry, SurfnetGetLocalSignaturesApi } from './methods/local/get-local-signatures';
14 changes: 14 additions & 0 deletions plugins/surfpool/src/methods/accounts/get-streamed-accounts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Address } from '@solana/kit';

export type StreamedAccountEntry = Readonly<{
includeOwnedAccounts: boolean;
pubkey: Address;
}>;

export type StreamedAccountsResult = Readonly<{
accounts: readonly StreamedAccountEntry[];
}>;

export type SurfnetGetStreamedAccountsApi = {
getStreamedAccounts(): StreamedAccountsResult;
};
9 changes: 9 additions & 0 deletions plugins/surfpool/src/methods/accounts/reset-account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { Address } from '@solana/kit';

export type ResetAccountConfig = Readonly<{
includeOwnedAccounts?: boolean;
}>;

export type SurfnetResetAccountApi = {
resetAccount(pubkey: Address, config?: ResetAccountConfig): null;
};
13 changes: 13 additions & 0 deletions plugins/surfpool/src/methods/accounts/set-account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Address } from '@solana/kit';

export type SetAccountUpdate = Readonly<{
data?: string;
executable?: boolean;
lamports?: number;
owner?: Address;
rentEpoch?: number;
}>;

export type SurfnetSetAccountApi = {
setAccount(pubkey: Address, update: SetAccountUpdate): null;
};
13 changes: 13 additions & 0 deletions plugins/surfpool/src/methods/accounts/set-token-account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Address } from '@solana/kit';

export type SetTokenAccountUpdate = Readonly<{
amount?: number;
closeAuthority?: Address;
delegate?: Address;
delegatedAmount?: number;
state?: 'frozen' | 'initialized';
}>;

export type SurfnetSetTokenAccountApi = {
setTokenAccount(owner: Address, mint: Address, update: SetTokenAccountUpdate, tokenProgram?: Address): null;
};
9 changes: 9 additions & 0 deletions plugins/surfpool/src/methods/accounts/stream-account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { Address } from '@solana/kit';

export type StreamAccountConfig = Readonly<{
includeOwnedAccounts?: boolean;
}>;

export type SurfnetStreamAccountApi = {
streamAccount(pubkey: Address, config?: StreamAccountConfig): null;
};
5 changes: 5 additions & 0 deletions plugins/surfpool/src/methods/clock/pause-clock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { ClockState } from './time-travel';

export type SurfnetPauseClockApi = {
pauseClock(): ClockState;
};
5 changes: 5 additions & 0 deletions plugins/surfpool/src/methods/clock/resume-clock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { ClockState } from './time-travel';

export type SurfnetResumeClockApi = {
resumeClock(): ClockState;
};
18 changes: 18 additions & 0 deletions plugins/surfpool/src/methods/clock/time-travel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export type TimeTravelConfig = Readonly<{
absoluteEpoch?: number;
absoluteSlot?: number;
absoluteTimestamp?: number;
}>;

export type ClockState = Readonly<{
absoluteSlot: number;
blockHeight: number;
epoch: number;
slotIndex: number;
slotsInEpoch: number;
transactionCount: number;
}>;

export type SurfnetTimeTravelApi = {
timeTravel(config: TimeTravelConfig): ClockState;
};
7 changes: 7 additions & 0 deletions plugins/surfpool/src/methods/idl/get-active-idl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Address } from '@solana/kit';

import type { AnchorIdl } from './register-idl';

export type SurfnetGetActiveIdlApi = {
getActiveIdl(programId: Address, slot?: number): AnchorIdl | null;
};
24 changes: 24 additions & 0 deletions plugins/surfpool/src/methods/idl/register-idl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { Address } from '@solana/kit';

export type IdlMetadata = Readonly<{
description?: string;
name: string;
spec: string;
version: string;
}>;

export type AnchorIdl = Readonly<{
accounts?: readonly unknown[];
address: Address;
constants?: readonly unknown[];
errors?: readonly unknown[];
events?: readonly unknown[];
instructions: readonly unknown[];
metadata: IdlMetadata;
state?: unknown;
types?: readonly unknown[];
}>;

export type SurfnetRegisterIdlApi = {
registerIdl(idl: AnchorIdl, slot?: number): null;
};
9 changes: 9 additions & 0 deletions plugins/surfpool/src/methods/local/get-local-signatures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type LocalSignatureEntry = Readonly<{
err: Readonly<{ errorType: string; message: string }> | null;
logs: readonly string[];
signature: string;
}>;

export type SurfnetGetLocalSignaturesApi = {
getLocalSignatures(limit?: number): readonly LocalSignatureEntry[];
};
13 changes: 13 additions & 0 deletions plugins/surfpool/src/methods/network/export-snapshot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type ExportSnapshotConfig = Readonly<{
filter?: Readonly<{
excludeAccounts?: readonly string[];
includeAccounts?: readonly string[];
includeProgramAccounts?: boolean;
}>;
includeParsedAccounts?: boolean;
scope?: 'network' | 'preTransaction';
}>;

export type SurfnetExportSnapshotApi = {
exportSnapshot(config?: ExportSnapshotConfig): Record<string, unknown>;
};
Loading