@5ive-tech/sdk 1.1.19 → 1.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { PublicKey } from '@solana/web3.js';
1
+ import { SessionClient, canonicalSessionManagerScriptAccount, scopeHashForFunctions, } from '../session/index.js';
2
2
  /**
3
3
  * Lightweight helper around a deployed session-manager script.
4
4
  * Uses normal Five execute flow; no VM opcode/runtime changes required.
@@ -32,66 +32,52 @@ export class SessionManager {
32
32
  }
33
33
  }
34
34
  static resolveCanonicalIdentity(input = {}) {
35
- const vmProgramId = input.vmProgramId || process.env.FIVE_PROGRAM_ID;
35
+ const vmProgramId = input.vmProgramId || process.env.FIVE_PROGRAM_ID || '';
36
36
  if (!vmProgramId) {
37
37
  throw new Error('SessionManager canonical identity requires vmProgramId or FIVE_PROGRAM_ID');
38
38
  }
39
- const vmProgram = new PublicKey(vmProgramId);
40
- const [scriptPda] = PublicKey.findProgramAddressSync([Buffer.from('session_v1', 'utf-8')], vmProgram);
39
+ const scriptPda = canonicalSessionManagerScriptAccount(vmProgramId);
41
40
  const cluster = input.cluster || (process.env.FIVE_VM_CLUSTER || 'localnet');
42
41
  return {
43
42
  cluster,
44
- scriptAccount: input.scriptAccount || scriptPda.toBase58(),
45
- codeHash: input.codeHash || '11111111111111111111111111111111',
43
+ scriptAccount: input.scriptAccount || scriptPda,
46
44
  version: input.version ?? 1,
47
45
  status: input.status || 'active',
48
46
  };
49
47
  }
50
48
  static scopeHashForFunctions(functions) {
51
- const sorted = [...functions].sort();
52
- // Stable v1 hash seed; caller may replace with stronger domain-specific hashing if desired.
53
- let acc = 0n;
54
- for (const ch of sorted.join('|')) {
55
- acc = (acc * 131n + BigInt(ch.charCodeAt(0))) & ((1n << 256n) - 1n);
56
- }
57
- return '0x' + acc.toString(16).padStart(64, '0');
49
+ return scopeHashForFunctions(functions);
58
50
  }
59
51
  async deriveSessionAddress(authority, delegate, targetProgram) {
60
52
  const [pda] = await this.managerProgram.findAddress(['session', authority, delegate, targetProgram], this.managerProgram.getFiveVMProgramId());
61
53
  return pda;
62
54
  }
63
55
  async buildCreateSessionInstruction(params) {
64
- const sessionAddress = await this.deriveSessionAddress(params.authority, params.delegate, params.targetProgram);
65
- const builder = this.managerProgram
66
- .function('create_session')
67
- .accounts({
68
- session: sessionAddress,
56
+ const client = new SessionClient({
57
+ vmProgramId: this.managerProgram.getFiveVMProgramId(),
58
+ managerScriptAccount: this.managerProgram.getScriptAccount(),
59
+ });
60
+ return client.createSessionIx({
69
61
  authority: params.authority,
70
62
  delegate: params.delegate,
71
- })
72
- .args({
73
- target_program: params.targetProgram,
74
- expires_at_slot: params.expiresAtSlot,
75
- scope_hash: params.scopeHash,
76
- bind_account: params.bindAccount || '11111111111111111111111111111111',
77
- nonce: params.nonce || '0x00',
63
+ targetProgram: params.targetProgram,
64
+ expiresAtSlot: params.expiresAtSlot,
65
+ scopeHash: params.scopeHash,
66
+ bindAccount: params.bindAccount,
67
+ nonce: params.nonce ? Number(params.nonce) : 0,
68
+ payer: params.payer,
78
69
  });
79
- if (params.payer) {
80
- builder.payer(params.payer);
81
- }
82
- return builder.instruction();
83
70
  }
84
71
  async buildRevokeSessionInstruction(authority, delegate, targetProgram, payer) {
85
- const sessionAddress = await this.deriveSessionAddress(authority, delegate, targetProgram);
86
- const builder = this.managerProgram
87
- .function('revoke_session')
88
- .accounts({
89
- session: sessionAddress,
72
+ const client = new SessionClient({
73
+ vmProgramId: this.managerProgram.getFiveVMProgramId(),
74
+ managerScriptAccount: this.managerProgram.getScriptAccount(),
75
+ });
76
+ return client.revokeSessionIx({
90
77
  authority,
78
+ delegate,
79
+ targetProgram,
80
+ payer,
91
81
  });
92
- if (payer) {
93
- builder.payer(payer);
94
- }
95
- return builder.instruction();
96
82
  }
97
83
  }
@@ -0,0 +1,56 @@
1
+ import { Keypair, PublicKey, TransactionInstruction, type Connection } from '@solana/web3.js';
2
+ export type SessionExecutionMode = 'auto' | 'direct' | 'session' | 'force-direct' | 'force-session';
3
+ export interface SessionExecutionConfig {
4
+ mode?: SessionExecutionMode;
5
+ sessionAccountByFunction?: Record<string, string>;
6
+ delegateSignerByFunction?: Record<string, any>;
7
+ }
8
+ export interface CreateSessionParams {
9
+ authority: string;
10
+ delegate: string;
11
+ targetProgram: string;
12
+ expiresAtSlot: number;
13
+ scopeHash: string;
14
+ bindAccount?: string;
15
+ nonce?: number;
16
+ payer?: string;
17
+ }
18
+ export interface RevokeSessionParams {
19
+ authority: string;
20
+ delegate: string;
21
+ targetProgram: string;
22
+ payer?: string;
23
+ }
24
+ export interface CreateSessionCompatResult {
25
+ signature: string;
26
+ schema: 'minimal';
27
+ }
28
+ export declare function scopeHashForFunctions(functionNames: string[]): string;
29
+ export declare function canonicalSessionManagerScriptAccount(vmProgramId: string): string;
30
+ export declare class SessionClient {
31
+ readonly vmProgramId: string;
32
+ readonly managerScriptAccount: string;
33
+ constructor(input: {
34
+ vmProgramId: string;
35
+ managerScriptAccount?: string;
36
+ });
37
+ static scopeHashForFunctions(functionNames: string[]): string;
38
+ static canonicalManagerScriptAccount(vmProgramId: string): string;
39
+ deriveSessionAddress(authority: string, delegate: string, targetProgram: string): Promise<string>;
40
+ createSessionIx(params: CreateSessionParams): Promise<TransactionInstruction>;
41
+ createSessionWithCompat(params: CreateSessionParams, send: (ix: TransactionInstruction, schema: 'minimal') => Promise<string>): Promise<CreateSessionCompatResult>;
42
+ revokeSessionIx(params: RevokeSessionParams): Promise<TransactionInstruction>;
43
+ prepareSessionAccountTx(input: {
44
+ connection: Connection;
45
+ payer: PublicKey;
46
+ sessionAccount: PublicKey;
47
+ sessionSpace?: number;
48
+ delegate?: PublicKey;
49
+ delegateMinLamports?: number;
50
+ delegateTopupLamports?: number;
51
+ }): Promise<{
52
+ createIx: TransactionInstruction | null;
53
+ topupIx: TransactionInstruction | null;
54
+ }>;
55
+ }
56
+ export type SessionDelegateSigner = Keypair;
@@ -0,0 +1,153 @@
1
+ import { PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js';
2
+ import { FiveProgram } from '../program/FiveProgram.js';
3
+ const SYSTEM_PROGRAM = '11111111111111111111111111111111';
4
+ const SESSION_MANAGER_ABI_MINIMAL = {
5
+ name: 'SessionManager',
6
+ functions: [
7
+ {
8
+ name: 'create_session',
9
+ index: 0,
10
+ parameters: [
11
+ { name: 'session', type: 'Account', is_account: true, attributes: ['mut'] },
12
+ { name: 'authority', type: 'Account', is_account: true, attributes: ['signer'] },
13
+ { name: 'delegate', type: 'Account', is_account: true, attributes: [] },
14
+ { name: 'target_program', type: 'pubkey', is_account: false, attributes: [] },
15
+ { name: 'expires_at_slot', type: 'u64', is_account: false, attributes: [] },
16
+ { name: 'scope_hash', type: 'u64', is_account: false, attributes: [] },
17
+ { name: 'bind_account', type: 'pubkey', is_account: false, attributes: [] },
18
+ { name: 'nonce', type: 'u64', is_account: false, attributes: [] },
19
+ ],
20
+ return_type: null,
21
+ visibility: 'public',
22
+ is_public: true,
23
+ bytecode_offset: 0,
24
+ },
25
+ {
26
+ name: 'revoke_session',
27
+ index: 1,
28
+ parameters: [
29
+ { name: 'session', type: 'Account', is_account: true, attributes: ['mut'] },
30
+ { name: 'authority', type: 'Account', is_account: true, attributes: ['signer'] },
31
+ ],
32
+ return_type: null,
33
+ visibility: 'public',
34
+ is_public: true,
35
+ bytecode_offset: 0,
36
+ },
37
+ ],
38
+ };
39
+ export function scopeHashForFunctions(functionNames) {
40
+ const sorted = [...functionNames].sort();
41
+ let acc = 0n;
42
+ const mask = (1n << 64n) - 1n;
43
+ for (const ch of sorted.join('|')) {
44
+ acc = (acc * 131n + BigInt(ch.charCodeAt(0))) & mask;
45
+ }
46
+ return acc.toString();
47
+ }
48
+ export function canonicalSessionManagerScriptAccount(vmProgramId) {
49
+ const [scriptPda] = PublicKey.findProgramAddressSync([Buffer.from('session_v1', 'utf-8')], new PublicKey(vmProgramId));
50
+ return scriptPda.toBase58();
51
+ }
52
+ export class SessionClient {
53
+ constructor(input) {
54
+ this.vmProgramId = input.vmProgramId;
55
+ this.managerScriptAccount =
56
+ input.managerScriptAccount || canonicalSessionManagerScriptAccount(input.vmProgramId);
57
+ }
58
+ static scopeHashForFunctions(functionNames) {
59
+ return scopeHashForFunctions(functionNames);
60
+ }
61
+ static canonicalManagerScriptAccount(vmProgramId) {
62
+ return canonicalSessionManagerScriptAccount(vmProgramId);
63
+ }
64
+ async deriveSessionAddress(authority, delegate, targetProgram) {
65
+ const [session] = await FiveProgram.fromABI(this.managerScriptAccount, SESSION_MANAGER_ABI_MINIMAL, {
66
+ fiveVMProgramId: this.vmProgramId,
67
+ }).findAddress(['session', authority, delegate, targetProgram], this.vmProgramId);
68
+ return session;
69
+ }
70
+ async createSessionIx(params) {
71
+ const session = await this.deriveSessionAddress(params.authority, params.delegate, params.targetProgram);
72
+ const program = FiveProgram.fromABI(this.managerScriptAccount, SESSION_MANAGER_ABI_MINIMAL, {
73
+ fiveVMProgramId: this.vmProgramId,
74
+ });
75
+ const argMap = {
76
+ target_program: params.targetProgram,
77
+ expires_at_slot: params.expiresAtSlot,
78
+ scope_hash: params.scopeHash,
79
+ bind_account: params.bindAccount || SYSTEM_PROGRAM,
80
+ nonce: params.nonce ?? 0,
81
+ };
82
+ const builder = program
83
+ .function('create_session')
84
+ .accounts({
85
+ session,
86
+ authority: params.authority,
87
+ delegate: params.delegate,
88
+ })
89
+ .args(argMap);
90
+ builder.payer(params.payer || params.authority);
91
+ const encoded = await builder.instruction();
92
+ return new TransactionInstruction({
93
+ programId: new PublicKey(encoded.programId),
94
+ keys: encoded.keys.map((k) => ({
95
+ pubkey: new PublicKey(k.pubkey),
96
+ isSigner: k.isSigner,
97
+ isWritable: k.isWritable,
98
+ })),
99
+ data: Buffer.from(encoded.data, 'base64'),
100
+ });
101
+ }
102
+ async createSessionWithCompat(params, send) {
103
+ const minimalIx = await this.createSessionIx(params);
104
+ return { signature: await send(minimalIx, 'minimal'), schema: 'minimal' };
105
+ }
106
+ async revokeSessionIx(params) {
107
+ const session = await this.deriveSessionAddress(params.authority, params.delegate, params.targetProgram);
108
+ const program = FiveProgram.fromABI(this.managerScriptAccount, SESSION_MANAGER_ABI_MINIMAL, {
109
+ fiveVMProgramId: this.vmProgramId,
110
+ });
111
+ const builder = program
112
+ .function('revoke_session')
113
+ .accounts({ session, authority: params.authority });
114
+ builder.payer(params.payer || params.authority);
115
+ const encoded = await builder.instruction();
116
+ return new TransactionInstruction({
117
+ programId: new PublicKey(encoded.programId),
118
+ keys: encoded.keys.map((k) => ({
119
+ pubkey: new PublicKey(k.pubkey),
120
+ isSigner: k.isSigner,
121
+ isWritable: k.isWritable,
122
+ })),
123
+ data: Buffer.from(encoded.data, 'base64'),
124
+ });
125
+ }
126
+ async prepareSessionAccountTx(input) {
127
+ const sessionSpace = input.sessionSpace ?? 256;
128
+ const accountInfo = await input.connection.getAccountInfo(input.sessionAccount, 'confirmed');
129
+ let createIx = null;
130
+ if (!accountInfo) {
131
+ const lamports = await input.connection.getMinimumBalanceForRentExemption(sessionSpace);
132
+ createIx = SystemProgram.createAccount({
133
+ fromPubkey: input.payer,
134
+ newAccountPubkey: input.sessionAccount,
135
+ lamports,
136
+ space: sessionSpace,
137
+ programId: new PublicKey(this.vmProgramId),
138
+ });
139
+ }
140
+ let topupIx = null;
141
+ if (input.delegate && input.delegateMinLamports && input.delegateTopupLamports) {
142
+ const delegateBalance = await input.connection.getBalance(input.delegate, 'confirmed');
143
+ if (delegateBalance < input.delegateMinLamports) {
144
+ topupIx = SystemProgram.transfer({
145
+ fromPubkey: input.payer,
146
+ toPubkey: input.delegate,
147
+ lamports: input.delegateTopupLamports,
148
+ });
149
+ }
150
+ }
151
+ return { createIx, topupIx };
152
+ }
153
+ }
@@ -219,7 +219,7 @@ export class AccountTestFixture {
219
219
  else if (spec.type === 'state' || spec.type === 'mutable') {
220
220
  // Create state/mutable account with initial data
221
221
  const space = 1024; // Default space
222
- const owner = options.fiveVMProgramId || new PublicKey('5ive58PJUPaTyAe7tvU1bvBi25o7oieLLTRsJDoQNJst');
222
+ const owner = options.fiveVMProgramId || new PublicKey('5ive5uKDkc3Yhyfu1Sk7i3eVPDQUmG2GmTm2FnUZiTJd');
223
223
  // Serialize state data if provided
224
224
  let initialData;
225
225
  if (spec.state && spec.type === 'state') {
@@ -242,7 +242,7 @@ export class AccountTestFixture {
242
242
  else if (spec.type === 'init') {
243
243
  // Create init account (will be initialized by script)
244
244
  const space = 1024;
245
- const owner = options.fiveVMProgramId || new PublicKey('5ive58PJUPaTyAe7tvU1bvBi25o7oieLLTRsJDoQNJst');
245
+ const owner = options.fiveVMProgramId || new PublicKey('5ive5uKDkc3Yhyfu1Sk7i3eVPDQUmG2GmTm2FnUZiTJd');
246
246
  publicKey = await manager.createAccount(space, owner);
247
247
  if (options.debug) {
248
248
  console.log(` ${spec.name} (init): ${publicKey.toString()}`);
@@ -256,7 +256,7 @@ export class AccountTestFixture {
256
256
  else {
257
257
  // Create readonly account
258
258
  const space = 0;
259
- const owner = options.fiveVMProgramId || new PublicKey('5ive58PJUPaTyAe7tvU1bvBi25o7oieLLTRsJDoQNJst');
259
+ const owner = options.fiveVMProgramId || new PublicKey('5ive5uKDkc3Yhyfu1Sk7i3eVPDQUmG2GmTm2FnUZiTJd');
260
260
  publicKey = await manager.createAccount(space, owner);
261
261
  if (options.debug) {
262
262
  console.log(` ${spec.name} (readonly): ${publicKey.toString()}`);
package/dist/types.d.ts CHANGED
@@ -224,7 +224,7 @@ export interface CLIError extends Error {
224
224
  details?: any;
225
225
  }
226
226
  /** @deprecated Use ProgramIdResolver with explicit config or cluster config instead. */
227
- export declare const FIVE_VM_PROGRAM_ID = "5ive58PJUPaTyAe7tvU1bvBi25o7oieLLTRsJDoQNJst";
227
+ export declare const FIVE_VM_PROGRAM_ID = "5ive5uKDkc3Yhyfu1Sk7i3eVPDQUmG2GmTm2FnUZiTJd";
228
228
  export interface FiveSDKConfig {
229
229
  network?: string;
230
230
  connection?: any;
package/dist/types.js CHANGED
@@ -3,7 +3,7 @@
3
3
  */
4
4
  // ==================== Legacy SDK Types (for compatibility) ====================
5
5
  /** @deprecated Use ProgramIdResolver with explicit config or cluster config instead. */
6
- export const FIVE_VM_PROGRAM_ID = "5ive58PJUPaTyAe7tvU1bvBi25o7oieLLTRsJDoQNJst";
6
+ export const FIVE_VM_PROGRAM_ID = "5ive5uKDkc3Yhyfu1Sk7i3eVPDQUmG2GmTm2FnUZiTJd";
7
7
  export class FiveSDKError extends Error {
8
8
  constructor(message, code, details) {
9
9
  super(message);
@@ -24,10 +24,10 @@ export async function getWasmModule() {
24
24
  './five_vm_wasm.js', // Sibling check
25
25
  ];
26
26
  const bundlerCandidates = [
27
- '../../assets/vm/five_vm_wasm.cjs',
28
- '../assets/vm/five_vm_wasm.cjs',
29
- '../../assets/vm/five_vm_wasm.js',
30
- '../assets/vm/five_vm_wasm.js',
27
+ '../../assets/wasm/five_vm_wasm.cjs',
28
+ '../assets/wasm/five_vm_wasm.cjs',
29
+ '../../assets/wasm/five_vm_wasm.js',
30
+ '../assets/wasm/five_vm_wasm.js',
31
31
  // Fallback for direct import (bundler alias)
32
32
  'five-wasm',
33
33
  'five-vm-wasm'
@@ -45,6 +45,40 @@ export async function getWasmModule() {
45
45
  candidates.push(...nodeCandidates);
46
46
  }
47
47
  const tried = [];
48
+ const tryResolveLoadedModule = async (mod, pathLabel) => {
49
+ if (mod && typeof mod.default === 'function') {
50
+ try {
51
+ const initialized = await mod.default();
52
+ const normalizedInit = resolveEncoderModule(initialized);
53
+ if (normalizedInit) {
54
+ wasmModule = normalizedInit;
55
+ return wasmModule;
56
+ }
57
+ }
58
+ catch (initErr) {
59
+ tried.push({ path: pathLabel, error: initErr });
60
+ }
61
+ }
62
+ const normalized = resolveEncoderModule(mod);
63
+ if (normalized) {
64
+ wasmModule = normalized;
65
+ return wasmModule;
66
+ }
67
+ return null;
68
+ };
69
+ // Browser-first explicit imports so bundlers can statically include wasm modules.
70
+ if (!isNode) {
71
+ try {
72
+ const mod = await import('../assets/wasm/five_vm_wasm.js');
73
+ const resolved = await tryResolveLoadedModule(mod, '../assets/wasm/five_vm_wasm.js');
74
+ if (resolved)
75
+ return resolved;
76
+ tried.push({ path: '../assets/wasm/five_vm_wasm.js', error: 'Module missing ParameterEncoder export' });
77
+ }
78
+ catch (e) {
79
+ tried.push({ path: '../assets/wasm/five_vm_wasm.js', error: e });
80
+ }
81
+ }
48
82
  for (const candidate of candidates) {
49
83
  try {
50
84
  const mod = await import(candidate);
@@ -86,25 +120,9 @@ export async function getWasmModule() {
86
120
  // tried.push({ path: candidate, error: syncErr });
87
121
  }
88
122
  }
89
- // Universal initialization (Browser/Node) if default export is init function
90
- if (mod && typeof mod.default === 'function') {
91
- try {
92
- const initialized = await mod.default();
93
- const normalizedInit = resolveEncoderModule(initialized);
94
- if (normalizedInit) {
95
- wasmModule = normalizedInit;
96
- return wasmModule;
97
- }
98
- }
99
- catch (initErr) {
100
- tried.push({ path: candidate, error: initErr });
101
- }
102
- }
103
- const normalized = resolveEncoderModule(mod);
104
- if (normalized) {
105
- wasmModule = normalized;
106
- return wasmModule;
107
- }
123
+ const resolved = await tryResolveLoadedModule(mod, candidate);
124
+ if (resolved)
125
+ return resolved;
108
126
  tried.push({ path: candidate, error: 'Module missing ParameterEncoder export' });
109
127
  }
110
128
  catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5ive-tech/sdk",
3
- "version": "1.1.19",
3
+ "version": "1.1.20",
4
4
  "description": "Client-agnostic TypeScript SDK for Five VM scripts on Solana",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -33,7 +33,7 @@
33
33
  "sync:wasm": "bash ../scripts/sync-wasm-assets.sh",
34
34
  "sync:wasm:rebuild": "bash ../scripts/sync-wasm-assets.sh --rebuild",
35
35
  "verify:wasm": "bash ../scripts/verify-wasm-sync.sh",
36
- "copy-assets": "mkdir -p dist/assets/vm && COPYFILE_DISABLE=1 cp src/assets/vm/* dist/assets/vm/",
36
+ "copy-assets": "mkdir -p dist/assets/vm dist/assets/wasm && COPYFILE_DISABLE=1 cp src/assets/vm/* dist/assets/vm/ && COPYFILE_DISABLE=1 cp src/assets/wasm/* dist/assets/wasm/",
37
37
  "test": "npm run test:jest --",
38
38
  "test:example": "node src/examples/basic-usage.js",
39
39
  "test:jest": "NODE_OPTIONS=--experimental-vm-modules jest --runInBand",