@nosana/kit 0.1.7 → 1.0.2

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.
Files changed (85) hide show
  1. package/.gitlab-ci.yml +41 -9
  2. package/.prettierignore +17 -0
  3. package/README.md +729 -59
  4. package/dist/config/defaultConfigs.d.ts +1 -1
  5. package/dist/config/defaultConfigs.js +2 -2
  6. package/dist/config/types.d.ts +1 -1
  7. package/dist/config/utils.d.ts +1 -1
  8. package/dist/config/utils.js +5 -5
  9. package/dist/errors/NosanaError.d.ts +1 -1
  10. package/dist/generated_clients/jobs/instructions/assign.d.ts +79 -0
  11. package/dist/generated_clients/jobs/instructions/assign.js +120 -0
  12. package/dist/generated_clients/jobs/instructions/extend.d.ts +9 -6
  13. package/dist/generated_clients/jobs/instructions/extend.js +4 -1
  14. package/dist/generated_clients/jobs/instructions/finish.d.ts +10 -10
  15. package/dist/generated_clients/jobs/instructions/finish.js +6 -6
  16. package/dist/generated_clients/jobs/instructions/index.d.ts +1 -0
  17. package/dist/generated_clients/jobs/instructions/index.js +1 -0
  18. package/dist/generated_clients/jobs/programs/nosanaJobs.d.ts +18 -15
  19. package/dist/generated_clients/jobs/programs/nosanaJobs.js +18 -14
  20. package/dist/generated_clients/staking/accounts/index.d.ts +9 -0
  21. package/dist/generated_clients/staking/accounts/index.js +9 -0
  22. package/dist/generated_clients/staking/accounts/settingsAccount.d.ts +29 -0
  23. package/dist/generated_clients/staking/accounts/settingsAccount.js +55 -0
  24. package/dist/generated_clients/staking/accounts/stakeAccount.d.ts +39 -0
  25. package/dist/generated_clients/staking/accounts/stakeAccount.js +65 -0
  26. package/dist/generated_clients/staking/errors/index.d.ts +8 -0
  27. package/dist/generated_clients/staking/errors/index.js +8 -0
  28. package/dist/generated_clients/staking/errors/nosanaStaking.d.ts +45 -0
  29. package/dist/generated_clients/staking/errors/nosanaStaking.js +62 -0
  30. package/dist/generated_clients/staking/index.d.ts +11 -0
  31. package/dist/generated_clients/staking/index.js +11 -0
  32. package/dist/generated_clients/staking/instructions/close.d.ts +48 -0
  33. package/dist/generated_clients/staking/instructions/close.js +81 -0
  34. package/dist/generated_clients/staking/instructions/extend.d.ts +43 -0
  35. package/dist/generated_clients/staking/instructions/extend.js +73 -0
  36. package/dist/generated_clients/staking/instructions/index.d.ts +17 -0
  37. package/dist/generated_clients/staking/instructions/index.js +17 -0
  38. package/dist/generated_clients/staking/instructions/init.d.ts +45 -0
  39. package/dist/generated_clients/staking/instructions/init.js +82 -0
  40. package/dist/generated_clients/staking/instructions/restake.d.ts +42 -0
  41. package/dist/generated_clients/staking/instructions/restake.js +70 -0
  42. package/dist/generated_clients/staking/instructions/slash.d.ts +55 -0
  43. package/dist/generated_clients/staking/instructions/slash.js +90 -0
  44. package/dist/generated_clients/staking/instructions/stake.d.ts +64 -0
  45. package/dist/generated_clients/staking/instructions/stake.js +106 -0
  46. package/dist/generated_clients/staking/instructions/topup.d.ts +52 -0
  47. package/dist/generated_clients/staking/instructions/topup.js +87 -0
  48. package/dist/generated_clients/staking/instructions/unstake.d.ts +42 -0
  49. package/dist/generated_clients/staking/instructions/unstake.js +70 -0
  50. package/dist/generated_clients/staking/instructions/updateSettings.d.ts +45 -0
  51. package/dist/generated_clients/staking/instructions/updateSettings.js +73 -0
  52. package/dist/generated_clients/staking/instructions/withdraw.d.ts +48 -0
  53. package/dist/generated_clients/staking/instructions/withdraw.js +81 -0
  54. package/dist/generated_clients/staking/programs/index.d.ts +8 -0
  55. package/dist/generated_clients/staking/programs/index.js +8 -0
  56. package/dist/generated_clients/staking/programs/nosanaStaking.d.ts +53 -0
  57. package/dist/generated_clients/staking/programs/nosanaStaking.js +71 -0
  58. package/dist/generated_clients/staking/shared/index.d.ts +49 -0
  59. package/dist/generated_clients/staking/shared/index.js +86 -0
  60. package/dist/index.d.ts +12 -4
  61. package/dist/index.js +18 -136
  62. package/dist/ipfs/IPFS.js +3 -0
  63. package/dist/programs/BaseProgram.d.ts +1 -1
  64. package/dist/programs/BaseProgram.js +3 -7
  65. package/dist/programs/JobsProgram.d.ts +37 -37
  66. package/dist/programs/JobsProgram.js +63 -67
  67. package/dist/programs/StakeProgram.d.ts +29 -0
  68. package/dist/programs/StakeProgram.js +91 -0
  69. package/dist/services/NosService.d.ts +48 -0
  70. package/dist/services/NosService.js +134 -0
  71. package/dist/{solana/SolanaUtils.d.ts → services/SolanaService.d.ts} +5 -5
  72. package/dist/{solana/SolanaUtils.js → services/SolanaService.js} +17 -7
  73. package/dist/utils/index.d.ts +2 -1
  74. package/dist/utils/index.js +2 -0
  75. package/dist/utils/walletConverter.d.ts +9 -0
  76. package/dist/utils/walletConverter.js +141 -0
  77. package/eslint.config.js +49 -0
  78. package/examples/node/README.md +115 -0
  79. package/examples/node/nos-service.ts +117 -0
  80. package/examples/node/package.json +3 -1
  81. package/examples/node/retrieve.ts +2 -2
  82. package/examples/node/stake-program.ts +84 -0
  83. package/package.json +11 -8
  84. package/scripts/generate-clients.ts +20 -7
  85. package/vitest.config.ts +31 -0
package/dist/index.d.ts CHANGED
@@ -1,25 +1,33 @@
1
1
  import { ClientConfig, NosanaNetwork, PartialClientConfig, WalletConfig } from './config/index.js';
2
2
  import { Logger } from './logger/Logger.js';
3
3
  import { JobsProgram } from './programs/JobsProgram.js';
4
- import { SolanaUtils } from './solana/SolanaUtils.js';
4
+ import { StakeProgram } from './programs/StakeProgram.js';
5
+ import { SolanaService } from './services/SolanaService.js';
6
+ import { NosService } from './services/NosService.js';
5
7
  import { IPFS } from './ipfs/IPFS.js';
6
8
  import { KeyPairSigner } from 'gill';
7
9
  export declare class NosanaClient {
8
10
  readonly config: ClientConfig;
9
11
  readonly jobs: JobsProgram;
10
- readonly solana: SolanaUtils;
12
+ readonly stake: StakeProgram;
13
+ readonly solana: SolanaService;
14
+ readonly nos: NosService;
11
15
  readonly ipfs: IPFS;
12
16
  readonly logger: Logger;
13
17
  wallet: KeyPairSigner | undefined;
14
18
  constructor(network?: NosanaNetwork, customConfig?: PartialClientConfig);
15
19
  setWallet(wallet: WalletConfig): Promise<KeyPairSigner | undefined>;
16
- private isValidFilePath;
17
20
  }
18
21
  export * from './config/index.js';
19
22
  export * from './errors/NosanaError.js';
20
23
  export * from './logger/Logger.js';
21
24
  export { JobsProgram, JobState, MarketQueueType } from './programs/JobsProgram.js';
22
25
  export type { Job, Market, Run } from './programs/JobsProgram.js';
26
+ export { StakeProgram } from './programs/StakeProgram.js';
27
+ export type { Stake } from './programs/StakeProgram.js';
23
28
  export * from './ipfs/IPFS.js';
24
- export * from './generated_clients/jobs/index.js';
29
+ export { NosService } from './services/NosService.js';
30
+ export type { TokenAccount, TokenAccountWithBalance } from './services/NosService.js';
31
+ export * as JobsClient from './generated_clients/jobs/index.js';
32
+ export * as StakingClient from './generated_clients/staking/index.js';
25
33
  export * from 'gill';
package/dist/index.js CHANGED
@@ -1,15 +1,11 @@
1
- import { Buffer } from 'buffer';
2
- if (typeof window !== 'undefined' && typeof window.Buffer === 'undefined') {
3
- window.Buffer = Buffer;
4
- }
5
- import { getNosanaConfig, NosanaNetwork } from './config/index.js';
1
+ import { getNosanaConfig, NosanaNetwork, } from './config/index.js';
6
2
  import { Logger } from './logger/Logger.js';
7
3
  import { JobsProgram } from './programs/JobsProgram.js';
8
- import { SolanaUtils } from './solana/SolanaUtils.js';
4
+ import { StakeProgram } from './programs/StakeProgram.js';
5
+ import { SolanaService } from './services/SolanaService.js';
6
+ import { NosService } from './services/NosService.js';
9
7
  import { IPFS } from './ipfs/IPFS.js';
10
- import { createKeyPairSignerFromBytes } from 'gill';
11
- import { NosanaError, ErrorCodes } from './errors/NosanaError.js';
12
- import bs58 from 'bs58';
8
+ import { convertWalletConfigToKeyPairSigner } from './utils/walletConverter.js';
13
9
  export class NosanaClient {
14
10
  constructor(network = NosanaNetwork.MAINNET, customConfig) {
15
11
  this.config = getNosanaConfig(network, customConfig);
@@ -17,134 +13,15 @@ export class NosanaClient {
17
13
  this.setWallet(this.config.wallet);
18
14
  }
19
15
  this.jobs = new JobsProgram(this);
16
+ this.stake = new StakeProgram(this);
20
17
  this.logger = Logger.getInstance();
21
- this.solana = new SolanaUtils(this);
18
+ this.solana = new SolanaService(this);
19
+ this.nos = new NosService(this);
22
20
  this.ipfs = new IPFS(this.config.ipfs);
23
21
  }
24
22
  async setWallet(wallet) {
25
- try {
26
- // Check if we already have a KeyPairSigner type
27
- if (wallet && typeof wallet === 'object' && 'address' in wallet && 'signMessages' in wallet) {
28
- this.wallet = wallet;
29
- return this.wallet;
30
- }
31
- // Check if it's a browser wallet adapter (has publicKey and signTransaction/signMessage)
32
- if (wallet && typeof wallet === 'object' && 'publicKey' in wallet && ('signTransaction' in wallet || 'signMessage' in wallet)) {
33
- // Convert browser wallet adapter to KeyPairSigner-like interface
34
- const browserWallet = wallet;
35
- this.wallet = {
36
- address: browserWallet.publicKey.toString(),
37
- signMessages: async (messages) => {
38
- if (browserWallet.signMessage) {
39
- return Promise.all(messages.map(msg => browserWallet.signMessage(msg)));
40
- }
41
- throw new Error('Browser wallet does not support message signing');
42
- },
43
- signTransactions: async (transactions) => {
44
- if (browserWallet.signTransaction) {
45
- return Promise.all(transactions.map(tx => browserWallet.signTransaction(tx)));
46
- }
47
- throw new Error('Browser wallet does not support transaction signing');
48
- }
49
- };
50
- return this.wallet;
51
- }
52
- // If it's a string, try multiple conversion methods
53
- if (typeof wallet === 'string') {
54
- // Only try file/environment loading in Node.js environment
55
- if (typeof window === 'undefined') {
56
- try {
57
- // Use string concatenation to avoid bundler resolving this import at build time
58
- const nodeModule = 'gill' + '/node';
59
- const { loadKeypairSignerFromFile, loadKeypairSignerFromEnvironment, loadKeypairSignerFromEnvironmentBase58 } = await import(nodeModule);
60
- // Try to load from file path
61
- if (await this.isValidFilePath(wallet)) {
62
- try {
63
- this.wallet = await loadKeypairSignerFromFile(wallet);
64
- return this.wallet;
65
- }
66
- catch (error) {
67
- this.logger.debug(`Failed to load keypair from file: ${error}`);
68
- }
69
- }
70
- // Try to load from environment variable
71
- try {
72
- this.wallet = await loadKeypairSignerFromEnvironment(wallet);
73
- return this.wallet;
74
- }
75
- catch (error) {
76
- this.logger.debug(`Failed to load keypair from environment: ${error}`);
77
- }
78
- // Try to load from environment variable as base58
79
- try {
80
- this.wallet = await loadKeypairSignerFromEnvironmentBase58(wallet);
81
- return this.wallet;
82
- }
83
- catch (error) {
84
- this.logger.debug(`Failed to load keypair from environment base58: ${error}`);
85
- }
86
- }
87
- catch (error) {
88
- this.logger.debug(`Node.js modules not available: ${error}`);
89
- }
90
- }
91
- // Try to parse as JSON array
92
- if (wallet.startsWith('[')) {
93
- try {
94
- const key = JSON.parse(wallet);
95
- this.wallet = await createKeyPairSignerFromBytes(new Uint8Array(key));
96
- return this.wallet;
97
- }
98
- catch (error) {
99
- this.logger.debug(`Failed to parse as JSON array: ${error}`);
100
- }
101
- }
102
- // Try to decode as base58
103
- try {
104
- const key = Buffer.from(bs58.decode(wallet)).toJSON().data;
105
- this.wallet = await createKeyPairSignerFromBytes(new Uint8Array(key));
106
- return this.wallet;
107
- }
108
- catch (error) {
109
- this.logger.debug(`Failed to decode as base58: ${error}`);
110
- }
111
- }
112
- // If it's an array, try to create from bytes
113
- if (Array.isArray(wallet)) {
114
- try {
115
- this.wallet = await createKeyPairSignerFromBytes(new Uint8Array(wallet));
116
- return this.wallet;
117
- }
118
- catch (error) {
119
- this.logger.debug(`Failed to create from byte array: ${error}`);
120
- }
121
- }
122
- // If we get here, none of the conversion methods worked
123
- throw new Error('Unable to convert wallet to KeyPairSigner using any available method');
124
- }
125
- catch (error) {
126
- throw new NosanaError(`Failed to convert wallet to KeyPairSigner: ${error instanceof Error ? error.message : 'Unknown error'}`, ErrorCodes.WALLET_CONVERSION_ERROR, error);
127
- }
128
- }
129
- async isValidFilePath(filePath) {
130
- // Only validate file paths in Node.js environment
131
- if (typeof window !== 'undefined') {
132
- return false; // Browser environment, no file system access
133
- }
134
- try {
135
- const [fs, path] = await Promise.all([
136
- import('fs'),
137
- import('path')
138
- ]);
139
- if (!path.isAbsolute(filePath) && !filePath.startsWith('./') && !filePath.startsWith('../')) {
140
- return false;
141
- }
142
- const stats = await fs.promises.stat(filePath);
143
- return stats.isFile();
144
- }
145
- catch {
146
- return false;
147
- }
23
+ this.wallet = await convertWalletConfigToKeyPairSigner(wallet);
24
+ return this.wallet;
148
25
  }
149
26
  }
150
27
  // Export types and configuration
@@ -153,9 +30,14 @@ export * from './errors/NosanaError.js';
153
30
  export * from './logger/Logger.js';
154
31
  // Export JobsProgram and related types
155
32
  export { JobsProgram, JobState, MarketQueueType } from './programs/JobsProgram.js';
33
+ // Export StakeProgram and related types
34
+ export { StakeProgram } from './programs/StakeProgram.js';
156
35
  // Export IPFS utilities
157
36
  export * from './ipfs/IPFS.js';
158
- // Export all generated client types and functions
159
- export * from './generated_clients/jobs/index.js';
160
- // Export dependencies
37
+ // Export NOS token service
38
+ export { NosService } from './services/NosService.js';
39
+ // Export generated clients under namespaces to avoid naming conflicts
40
+ export * as JobsClient from './generated_clients/jobs/index.js';
41
+ export * as StakingClient from './generated_clients/staking/index.js';
42
+ // Export dependencies
161
43
  export * from 'gill';
package/dist/ipfs/IPFS.js CHANGED
@@ -1,7 +1,9 @@
1
1
  import bs58 from 'bs58';
2
2
  import axios, { AxiosHeaders } from 'axios';
3
3
  // Import form-data dynamically for Node.js environments
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
5
  let FormData;
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
7
  let fs;
6
8
  // Dynamically import Node.js-specific modules
7
9
  const loadNodeModules = async () => {
@@ -80,6 +82,7 @@ export class IPFS {
80
82
  * @param options Additional axios request options
81
83
  * @returns The retrieved data
82
84
  */
85
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
86
  async retrieve(hash, options = {}) {
84
87
  if (typeof hash !== 'string') {
85
88
  const convertedHash = IPFS.solHashToIpfsHash(hash);
@@ -12,7 +12,7 @@ export declare abstract class BaseProgram {
12
12
  /**
13
13
  * Gets the static accounts, initializing them if needed.
14
14
  */
15
- protected getStaticAccounts(): Promise<staticAccounts>;
15
+ getStaticAccounts(): Promise<staticAccounts>;
16
16
  private initializeStaticAccounts;
17
17
  protected readonly sdk: NosanaClient;
18
18
  constructor(sdk: NosanaClient);
@@ -19,14 +19,10 @@ export class BaseProgram {
19
19
  }
20
20
  async initializeStaticAccounts() {
21
21
  return {
22
- rewardsReflection: await this.sdk.solana.pda([
23
- 'reflection',
24
- ], this.sdk.config.programs.rewardsAddress),
25
- rewardsVault: await this.sdk.solana.pda([
26
- this.sdk.config.programs.nosTokenAddress,
27
- ], this.sdk.config.programs.rewardsAddress),
22
+ rewardsReflection: await this.sdk.solana.pda(['reflection'], this.sdk.config.programs.rewardsAddress),
23
+ rewardsVault: await this.sdk.solana.pda([this.sdk.config.programs.nosTokenAddress], this.sdk.config.programs.rewardsAddress),
28
24
  rewardsProgram: this.sdk.config.programs.rewardsAddress,
29
- jobsProgram: this.sdk.config.programs.jobsAddress
25
+ jobsProgram: this.sdk.config.programs.jobsAddress,
30
26
  };
31
27
  }
32
28
  constructor(sdk) {
@@ -1,7 +1,7 @@
1
1
  import { BaseProgram } from './BaseProgram.js';
2
2
  import { Address, Account } from 'gill';
3
3
  import { NosanaClient } from '../index.js';
4
- import * as programClient from "../generated_clients/jobs/index.js";
4
+ import * as programClient from '../generated_clients/jobs/index.js';
5
5
  import { ConvertTypesForDb } from '../utils/index.js';
6
6
  export declare enum JobState {
7
7
  QUEUED = 0,
@@ -37,16 +37,16 @@ export declare class JobsProgram extends BaseProgram {
37
37
  */
38
38
  run(addr: Address): Promise<Run>;
39
39
  /**
40
- * Fetch a run account by address
41
- */
40
+ * Fetch a run account by address
41
+ */
42
42
  market(addr: Address): Promise<Market>;
43
43
  /**
44
- * Fetch multiple job accounts by address
45
- */
44
+ * Fetch multiple job accounts by address
45
+ */
46
46
  multiple(addresses: Address[], checkRuns?: boolean): Promise<Job[]>;
47
47
  /**
48
- * Fetch all job accounts
49
- */
48
+ * Fetch all job accounts
49
+ */
50
50
  all(filters?: {
51
51
  state?: JobState;
52
52
  market?: Address;
@@ -54,15 +54,15 @@ export declare class JobsProgram extends BaseProgram {
54
54
  project?: Address;
55
55
  }, checkRuns?: boolean): Promise<Job[]>;
56
56
  /**
57
- * Fetch all run accounts
58
- */
57
+ * Fetch all run accounts
58
+ */
59
59
  runs(filters?: {
60
60
  node?: Address;
61
61
  job?: Address;
62
62
  }): Promise<Run[]>;
63
63
  /**
64
- * Fetch all market accounts
65
- */
64
+ * Fetch all market accounts
65
+ */
66
66
  markets(): Promise<Market[]>;
67
67
  /**
68
68
  * Post a new job to the marketplace
@@ -76,32 +76,32 @@ export declare class JobsProgram extends BaseProgram {
76
76
  node?: Address;
77
77
  }): Promise<ReturnType<typeof this.client.getListInstruction>>;
78
78
  /**
79
- * Monitor program account updates using callback functions
80
- * Uses WebSocket subscriptions with automatic restart on failure
81
- *
82
- * @example
83
- * ```typescript
84
- * // Example: Monitor job accounts and save to file
85
- * const stopMonitoring = await jobsProgram.monitor({
86
- * onJobAccount: async (jobAccount) => {
87
- * console.log('Job updated:', jobAccount.address.toString());
88
- * // Save to database, file, or process as needed
89
- * },
90
- * onRunAccount: async (runAccount) => {
91
- * console.log('Run updated:', runAccount.address.toString());
92
- * },
93
- * onError: async (error, accountType) => {
94
- * console.error('Error processing account:', error, accountType);
95
- * }
96
- * });
97
- *
98
- * // Stop monitoring when done
99
- * stopMonitoring();
100
- * ```
101
- *
102
- * @param options Configuration options for monitoring
103
- * @returns A function to stop monitoring
104
- */
79
+ * Monitor program account updates using callback functions
80
+ * Uses WebSocket subscriptions with automatic restart on failure
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * // Example: Monitor job accounts and save to file
85
+ * const stopMonitoring = await jobsProgram.monitor({
86
+ * onJobAccount: async (jobAccount) => {
87
+ * console.log('Job updated:', jobAccount.address.toString());
88
+ * // Save to database, file, or process as needed
89
+ * },
90
+ * onRunAccount: async (runAccount) => {
91
+ * console.log('Run updated:', runAccount.address.toString());
92
+ * },
93
+ * onError: async (error, accountType) => {
94
+ * console.error('Error processing account:', error, accountType);
95
+ * }
96
+ * });
97
+ *
98
+ * // Stop monitoring when done
99
+ * stopMonitoring();
100
+ * ```
101
+ *
102
+ * @param options Configuration options for monitoring
103
+ * @returns A function to stop monitoring
104
+ */
105
105
  monitor(options?: {
106
106
  onJobAccount?: (jobAccount: Job) => Promise<void> | void;
107
107
  onMarketAccount?: (marketAccount: Market) => Promise<void> | void;