@nosana/kit 0.1.1 → 0.1.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 (71) hide show
  1. package/.gitlab-ci.yml +6 -5
  2. package/dist/config/defaultConfigs.js +15 -18
  3. package/dist/config/index.js +3 -19
  4. package/dist/config/types.d.ts +1 -3
  5. package/dist/config/types.js +4 -7
  6. package/dist/config/utils.js +8 -13
  7. package/dist/errors/NosanaError.d.ts +1 -0
  8. package/dist/errors/NosanaError.js +3 -6
  9. package/dist/generated_clients/jobs/accounts/index.js +3 -19
  10. package/dist/generated_clients/jobs/accounts/jobAccount.js +46 -59
  11. package/dist/generated_clients/jobs/accounts/marketAccount.js +45 -57
  12. package/dist/generated_clients/jobs/accounts/runAccount.js +36 -49
  13. package/dist/generated_clients/jobs/errors/index.js +1 -17
  14. package/dist/generated_clients/jobs/errors/nosanaJobs.js +43 -48
  15. package/dist/generated_clients/jobs/index.js +5 -21
  16. package/dist/generated_clients/jobs/instructions/claim.js +17 -26
  17. package/dist/generated_clients/jobs/instructions/clean.js +17 -26
  18. package/dist/generated_clients/jobs/instructions/cleanAdmin.js +17 -26
  19. package/dist/generated_clients/jobs/instructions/close.js +17 -26
  20. package/dist/generated_clients/jobs/instructions/closeAdmin.js +17 -26
  21. package/dist/generated_clients/jobs/instructions/complete.js +21 -30
  22. package/dist/generated_clients/jobs/instructions/delist.js +17 -26
  23. package/dist/generated_clients/jobs/instructions/end.js +17 -26
  24. package/dist/generated_clients/jobs/instructions/extend.js +21 -30
  25. package/dist/generated_clients/jobs/instructions/finish.js +21 -30
  26. package/dist/generated_clients/jobs/instructions/index.js +18 -34
  27. package/dist/generated_clients/jobs/instructions/list.js +23 -32
  28. package/dist/generated_clients/jobs/instructions/open.js +29 -38
  29. package/dist/generated_clients/jobs/instructions/quit.js +17 -26
  30. package/dist/generated_clients/jobs/instructions/quitAdmin.js +17 -26
  31. package/dist/generated_clients/jobs/instructions/recover.js +17 -26
  32. package/dist/generated_clients/jobs/instructions/stop.js +17 -26
  33. package/dist/generated_clients/jobs/instructions/update.js +29 -38
  34. package/dist/generated_clients/jobs/instructions/work.js +17 -26
  35. package/dist/generated_clients/jobs/programs/index.js +1 -17
  36. package/dist/generated_clients/jobs/programs/nosanaJobs.js +29 -34
  37. package/dist/generated_clients/jobs/shared/index.js +13 -21
  38. package/dist/generated_clients/jobs/types/index.js +3 -19
  39. package/dist/generated_clients/jobs/types/jobState.js +9 -15
  40. package/dist/generated_clients/jobs/types/jobType.js +9 -15
  41. package/dist/generated_clients/jobs/types/queueType.js +9 -15
  42. package/dist/index.d.ts +5 -1
  43. package/dist/index.js +149 -35
  44. package/dist/ipfs/IPFS.js +5 -12
  45. package/dist/logger/Logger.js +1 -5
  46. package/dist/programs/BaseProgram.js +1 -5
  47. package/dist/programs/JobsProgram.d.ts +2 -3
  48. package/dist/programs/JobsProgram.js +35 -99
  49. package/dist/solana/SolanaUtils.d.ts +15 -1
  50. package/dist/solana/SolanaUtils.js +81 -14
  51. package/dist/utils/index.js +1 -4
  52. package/examples/browser/.gitlab-ci.yml +78 -0
  53. package/examples/browser/FEATURES.md +141 -0
  54. package/examples/browser/QUICK_START.md +76 -0
  55. package/examples/browser/README.md +182 -0
  56. package/examples/browser/app.vue +1840 -0
  57. package/examples/browser/assets/css/main.css +7 -0
  58. package/examples/browser/nuxt.config.ts +24 -0
  59. package/examples/browser/package-lock.json +11855 -0
  60. package/examples/browser/package.json +31 -0
  61. package/examples/browser/public/favicon.ico +0 -0
  62. package/examples/browser/public/robots.txt +2 -0
  63. package/examples/browser/start.sh +38 -0
  64. package/examples/browser/tailwind.config.js +26 -0
  65. package/examples/node/README.md +146 -0
  66. package/examples/node/example-keypair.json +1 -0
  67. package/examples/node/package-lock.json +500 -156
  68. package/examples/node/package.json +5 -3
  69. package/examples/node/post-job.ts +160 -0
  70. package/examples/node/set-wallet.ts +87 -0
  71. package/package.json +3 -1
@@ -1,51 +1,12 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.JobsProgram = void 0;
40
- const BaseProgram_js_1 = require("./BaseProgram.js");
41
- const gill_1 = require("gill");
42
- const index_js_1 = require("../index.js");
43
- const programClient = __importStar(require("../generated_clients/jobs/index.js"));
44
- const token_1 = require("@solana-program/token");
45
- const bs58_1 = __importDefault(require("bs58"));
46
- const IPFS_js_1 = require("../ipfs/IPFS.js");
47
- const index_js_2 = require("../utils/index.js");
48
- class JobsProgram extends BaseProgram_js_1.BaseProgram {
1
+ import { BaseProgram } from './BaseProgram.js';
2
+ import { generateKeyPairSigner, parseBase64RpcAccount } from 'gill';
3
+ import { ErrorCodes, NosanaError } from '../index.js';
4
+ import * as programClient from "../generated_clients/jobs/index.js";
5
+ import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
6
+ import bs58 from 'bs58';
7
+ import { IPFS } from '../ipfs/IPFS.js';
8
+ import { convertBigIntToNumber } from '../utils/index.js';
9
+ export class JobsProgram extends BaseProgram {
49
10
  constructor(sdk) {
50
11
  super(sdk);
51
12
  this.client = programClient;
@@ -144,7 +105,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
144
105
  extraGPAFilters.push({
145
106
  memcmp: {
146
107
  offset: BigInt(208),
147
- bytes: bs58_1.default.encode(Buffer.from([filters.state])),
108
+ bytes: bs58.encode(Buffer.from([filters.state])),
148
109
  encoding: "base58",
149
110
  },
150
111
  });
@@ -184,7 +145,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
184
145
  {
185
146
  memcmp: {
186
147
  offset: BigInt(0),
187
- bytes: bs58_1.default.encode(Buffer.from(programClient.JOB_ACCOUNT_DISCRIMINATOR)),
148
+ bytes: bs58.encode(Buffer.from(programClient.JOB_ACCOUNT_DISCRIMINATOR)),
188
149
  encoding: "base58",
189
150
  },
190
151
  },
@@ -195,7 +156,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
195
156
  const jobs = getProgramAccountsResponse
196
157
  .map((result) => {
197
158
  try {
198
- const jobAccount = programClient.decodeJobAccount((0, gill_1.parseBase64RpcAccount)(result.pubkey, result.account));
159
+ const jobAccount = programClient.decodeJobAccount(parseBase64RpcAccount(result.pubkey, result.account));
199
160
  return this.transformJobAccount(jobAccount);
200
161
  }
201
162
  catch (err) {
@@ -257,7 +218,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
257
218
  {
258
219
  memcmp: {
259
220
  offset: BigInt(0),
260
- bytes: bs58_1.default.encode(Buffer.from(programClient.RUN_ACCOUNT_DISCRIMINATOR)),
221
+ bytes: bs58.encode(Buffer.from(programClient.RUN_ACCOUNT_DISCRIMINATOR)),
261
222
  encoding: "base58",
262
223
  },
263
224
  },
@@ -267,7 +228,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
267
228
  const runAccounts = getProgramAccountsResponse
268
229
  .map((result) => {
269
230
  try {
270
- const runAccount = programClient.decodeRunAccount((0, gill_1.parseBase64RpcAccount)(result.pubkey, result.account));
231
+ const runAccount = programClient.decodeRunAccount(parseBase64RpcAccount(result.pubkey, result.account));
271
232
  return this.transformRunAccount(runAccount);
272
233
  }
273
234
  catch (err) {
@@ -295,7 +256,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
295
256
  {
296
257
  memcmp: {
297
258
  offset: BigInt(0),
298
- bytes: bs58_1.default.encode(Buffer.from(programClient.MARKET_ACCOUNT_DISCRIMINATOR)),
259
+ bytes: bs58.encode(Buffer.from(programClient.MARKET_ACCOUNT_DISCRIMINATOR)),
299
260
  encoding: "base58",
300
261
  },
301
262
  },
@@ -305,7 +266,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
305
266
  const marketAccounts = getProgramAccountsResponse
306
267
  .map((result) => {
307
268
  try {
308
- const marketAccount = programClient.decodeMarketAccount((0, gill_1.parseBase64RpcAccount)(result.pubkey, result.account));
269
+ const marketAccount = programClient.decodeMarketAccount(parseBase64RpcAccount(result.pubkey, result.account));
309
270
  return this.transformMarketAccount(marketAccount);
310
271
  }
311
272
  catch (err) {
@@ -327,15 +288,12 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
327
288
  * @returns The transaction signature
328
289
  */
329
290
  async post(params) {
330
- if (!this.sdk.config.wallet) {
331
- throw new index_js_1.NosanaError('No wallet found', index_js_1.ErrorCodes.NO_WALLET);
332
- }
333
- const jobKey = await (0, gill_1.generateKeyPairSigner)();
334
- const runKey = await (0, gill_1.generateKeyPairSigner)();
335
- const [associatedTokenAddress] = await (0, token_1.findAssociatedTokenPda)({
291
+ const jobKey = await generateKeyPairSigner();
292
+ const runKey = await generateKeyPairSigner();
293
+ const [associatedTokenAddress] = await findAssociatedTokenPda({
336
294
  mint: this.sdk.config.programs.nosTokenAddress,
337
- owner: this.sdk.config.wallet.signer.address,
338
- tokenProgram: token_1.TOKEN_PROGRAM_ADDRESS
295
+ owner: this.sdk.wallet.address,
296
+ tokenProgram: TOKEN_PROGRAM_ADDRESS
339
297
  });
340
298
  try {
341
299
  const staticAccounts = await this.getStaticAccounts();
@@ -349,41 +307,20 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
349
307
  params.market,
350
308
  this.sdk.config.programs.nosTokenAddress,
351
309
  ], staticAccounts.jobsProgram),
352
- payer: this.sdk.config.wallet.signer,
310
+ payer: this.sdk.wallet,
353
311
  rewardsReflection: staticAccounts.rewardsReflection,
354
312
  rewardsVault: staticAccounts.rewardsVault,
355
- authority: this.sdk.config.wallet.signer,
313
+ authority: this.sdk.wallet,
356
314
  rewardsProgram: staticAccounts.rewardsProgram,
357
- ipfsJob: bs58_1.default.decode(params.ipfsHash).subarray(2),
315
+ ipfsJob: bs58.decode(params.ipfsHash).subarray(2),
358
316
  timeout: params.timeout
359
317
  });
360
- if (params.instructionOnly)
361
- return instruction;
362
- // Create the transaction
363
- const transaction = (0, gill_1.createTransaction)({
364
- instructions: [instruction],
365
- feePayer: this.sdk.config.wallet.signer,
366
- latestBlockhash: await this.sdk.solana.getLatestBlockhash(),
367
- version: 0,
368
- });
369
- // Sign the transaction with all required signers
370
- const signedTransaction = await (0, gill_1.signTransactionMessageWithSigners)(transaction);
371
- // Get the transaction signature for logging
372
- const signature = (0, gill_1.getSignatureFromTransaction)(signedTransaction);
373
- // Log the transaction explorer link
374
- const explorerLink = (0, gill_1.getExplorerLink)({
375
- cluster: this.sdk.config.solana.cluster,
376
- transaction: signature
377
- });
378
- this.sdk.logger.info(`Sending list job transaction: ${explorerLink}`);
379
- // Send and confirm the transaction
380
- await this.sdk.solana.sendAndConfirmTransaction(signedTransaction);
381
- this.sdk.logger.info("Job listing transaction confirmed!");
382
- return signature;
318
+ return instruction;
383
319
  }
384
320
  catch (err) {
385
- this.sdk.logger.error(`Failed to list job: ${err instanceof Error ? err.message : String(err)}`);
386
- throw new Error(`Failed to list job: ${err instanceof Error ? err.message : String(err)}`);
321
+ const errorMessage = `Failed to create list instruction: ${err instanceof Error ? err.message : String(err)}`;
322
+ this.sdk.logger.error(errorMessage);
323
+ throw new Error(errorMessage);
387
324
  }
388
325
  }
389
326
  /**
@@ -462,7 +399,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
462
399
  }
463
400
  catch (error) {
464
401
  this.sdk.logger.error(`Failed to start monitoring job program accounts: ${error}`);
465
- throw new index_js_1.NosanaError('Failed to start monitoring job program accounts', index_js_1.ErrorCodes.RPC_ERROR, error);
402
+ throw new NosanaError('Failed to start monitoring job program accounts', ErrorCodes.RPC_ERROR, error);
466
403
  }
467
404
  }
468
405
  /**
@@ -519,9 +456,9 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
519
456
  const { discriminator: _, ...jobAccountData } = jobAccount.data;
520
457
  return {
521
458
  address: jobAccount.address,
522
- ...(0, index_js_2.convertBigIntToNumber)(jobAccountData),
523
- ipfsJob: IPFS_js_1.IPFS.solHashToIpfsHash(jobAccountData.ipfsJob),
524
- ipfsResult: IPFS_js_1.IPFS.solHashToIpfsHash(jobAccountData.ipfsResult),
459
+ ...convertBigIntToNumber(jobAccountData),
460
+ ipfsJob: IPFS.solHashToIpfsHash(jobAccountData.ipfsJob),
461
+ ipfsResult: IPFS.solHashToIpfsHash(jobAccountData.ipfsResult),
525
462
  };
526
463
  }
527
464
  transformRunAccount(runAccount) {
@@ -529,7 +466,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
529
466
  const { discriminator: _, ...runAccountData } = runAccount.data;
530
467
  return {
531
468
  address: runAccount.address,
532
- ...(0, index_js_2.convertBigIntToNumber)(runAccountData),
469
+ ...convertBigIntToNumber(runAccountData),
533
470
  };
534
471
  }
535
472
  transformMarketAccount(marketAccount) {
@@ -537,7 +474,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
537
474
  const { discriminator: _, ...marketAccountData } = marketAccount.data;
538
475
  return {
539
476
  address: marketAccount.address,
540
- ...(0, index_js_2.convertBigIntToNumber)(marketAccountData),
477
+ ...convertBigIntToNumber(marketAccountData),
541
478
  };
542
479
  }
543
480
  /**
@@ -546,7 +483,7 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
546
483
  async handleAccountUpdate(accountData, options, isMonitoring) {
547
484
  try {
548
485
  const { account, pubkey } = accountData;
549
- const encodedAccount = (0, gill_1.parseBase64RpcAccount)(pubkey, account);
486
+ const encodedAccount = parseBase64RpcAccount(pubkey, account);
550
487
  const accountType = programClient.identifyNosanaJobsAccount(encodedAccount);
551
488
  switch (accountType) {
552
489
  case programClient.NosanaJobsAccount.JobAccount:
@@ -608,4 +545,3 @@ class JobsProgram extends BaseProgram_js_1.BaseProgram {
608
545
  this.sdk.logger.debug(`Processed run account ${runAccount.address.toString()}`);
609
546
  }
610
547
  }
611
- exports.JobsProgram = JobsProgram;
@@ -1,4 +1,4 @@
1
- import { Address, SolanaClient } from 'gill';
1
+ import { Address, SolanaClient, Signature, IInstruction, TransactionMessageWithBlockhashLifetime, CompilableTransactionMessage, FullySignedTransaction, TransactionWithBlockhashLifetime } from 'gill';
2
2
  import { NosanaClient } from '../index.js';
3
3
  export declare class SolanaUtils {
4
4
  private readonly sdk;
@@ -12,4 +12,18 @@ export declare class SolanaUtils {
12
12
  blockhash: import("gill").Blockhash;
13
13
  lastValidBlockHeight: bigint;
14
14
  }>>;
15
+ /**
16
+ * Type guard to check if the input is a transaction
17
+ */
18
+ private isTransaction;
19
+ /**
20
+ * Type guard to check if the input is a signed transaction
21
+ */
22
+ private isSignedTransaction;
23
+ /**
24
+ * Create, sign, and send a transaction with proper logging and error handling
25
+ * @param instructionsOrTransaction Single instruction, array of instructions, or pre-built transaction
26
+ * @returns The transaction signature
27
+ */
28
+ send(instructionsOrTransaction: IInstruction | IInstruction[] | CompilableTransactionMessage & TransactionMessageWithBlockhashLifetime | FullySignedTransaction & TransactionWithBlockhashLifetime): Promise<Signature>;
15
29
  }
@@ -1,22 +1,19 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SolanaUtils = void 0;
4
- const gill_1 = require("gill");
5
- const NosanaError_js_1 = require("../errors/NosanaError.js");
6
- class SolanaUtils {
1
+ import { createSolanaClient, address, getProgramDerivedAddress, getAddressEncoder, generateKeyPairSigner, createTransaction, signTransactionMessageWithSigners, getExplorerLink, getSignatureFromTransaction } from 'gill';
2
+ import { NosanaError, ErrorCodes } from '../errors/NosanaError.js';
3
+ export class SolanaUtils {
7
4
  constructor(sdk) {
8
5
  this.sdk = sdk;
9
6
  const rpcEndpoint = this.sdk.config.solana.rpcEndpoint;
10
7
  if (!rpcEndpoint)
11
- throw new NosanaError_js_1.NosanaError('RPC URL is required', NosanaError_js_1.ErrorCodes.INVALID_CONFIG);
12
- const { rpc, rpcSubscriptions, sendAndConfirmTransaction } = (0, gill_1.createSolanaClient)({ urlOrMoniker: rpcEndpoint });
8
+ throw new NosanaError('RPC URL is required', ErrorCodes.INVALID_CONFIG);
9
+ const { rpc, rpcSubscriptions, sendAndConfirmTransaction } = createSolanaClient({ urlOrMoniker: rpcEndpoint });
13
10
  this.rpc = rpc;
14
11
  this.rpcSubscriptions = rpcSubscriptions;
15
12
  this.sendAndConfirmTransaction = sendAndConfirmTransaction;
16
13
  }
17
14
  async pda(seeds, programId) {
18
- const addressEncoder = (0, gill_1.getAddressEncoder)();
19
- const [pda] = await (0, gill_1.getProgramDerivedAddress)({
15
+ const addressEncoder = getAddressEncoder();
16
+ const [pda] = await getProgramDerivedAddress({
20
17
  programAddress: programId,
21
18
  seeds: seeds.map(seed => typeof seed !== 'string' ? addressEncoder.encode(seed) : seed),
22
19
  });
@@ -25,24 +22,94 @@ class SolanaUtils {
25
22
  async getBalance(addressStr) {
26
23
  try {
27
24
  this.sdk.logger.debug(`Getting balance for address: ${addressStr}`);
28
- const addr = (0, gill_1.address)(addressStr);
25
+ const addr = address(addressStr);
29
26
  const balance = await this.rpc.getBalance(addr).send();
30
27
  return balance.value;
31
28
  }
32
29
  catch (error) {
33
30
  this.sdk.logger.error(`Failed to get balance: ${error}`);
34
- throw new NosanaError_js_1.NosanaError('Failed to get balance', NosanaError_js_1.ErrorCodes.RPC_ERROR, error);
31
+ throw new NosanaError('Failed to get balance', ErrorCodes.RPC_ERROR, error);
35
32
  }
36
33
  }
37
34
  async getLatestBlockhash() {
35
+ console.log('testing gen key..');
36
+ const jobKey = await generateKeyPairSigner();
37
+ console.log('test', jobKey);
38
38
  try {
39
39
  const { value: blockhash } = await this.rpc.getLatestBlockhash().send();
40
40
  return blockhash;
41
41
  }
42
42
  catch (error) {
43
43
  this.sdk.logger.error(`Failed to get latest blockhash: ${error}`);
44
- throw new NosanaError_js_1.NosanaError('Failed to get latest blockhash', NosanaError_js_1.ErrorCodes.RPC_ERROR, error);
44
+ throw new NosanaError('Failed to get latest blockhash', ErrorCodes.RPC_ERROR, error);
45
+ }
46
+ }
47
+ /**
48
+ * Type guard to check if the input is a transaction
49
+ */
50
+ isTransaction(input) {
51
+ return 'instructions' in input && 'version' in input && !('programAddress' in input);
52
+ }
53
+ /**
54
+ * Type guard to check if the input is a signed transaction
55
+ */
56
+ isSignedTransaction(input) {
57
+ return 'signatures' in input && input.signatures && input.signatures.length > 0;
58
+ }
59
+ /**
60
+ * Create, sign, and send a transaction with proper logging and error handling
61
+ * @param instructionsOrTransaction Single instruction, array of instructions, or pre-built transaction
62
+ * @returns The transaction signature
63
+ */
64
+ async send(instructionsOrTransaction) {
65
+ if (!this.sdk.wallet) {
66
+ throw new NosanaError('No wallet found', ErrorCodes.NO_WALLET);
67
+ }
68
+ try {
69
+ let signedTransaction;
70
+ // Check if it's already a transaction or if we need to create one from instructions
71
+ if (this.isTransaction(instructionsOrTransaction)) {
72
+ // Check if it's already signed
73
+ if (this.isSignedTransaction(instructionsOrTransaction)) {
74
+ // Already signed, use it directly
75
+ signedTransaction = instructionsOrTransaction;
76
+ }
77
+ else {
78
+ // Not signed yet, sign it
79
+ signedTransaction = await signTransactionMessageWithSigners(instructionsOrTransaction);
80
+ }
81
+ }
82
+ else {
83
+ // It's instructions, create and sign a transaction
84
+ const instructions = Array.isArray(instructionsOrTransaction)
85
+ ? instructionsOrTransaction
86
+ : [instructionsOrTransaction];
87
+ const transaction = createTransaction({
88
+ instructions,
89
+ feePayer: this.sdk.wallet,
90
+ latestBlockhash: await this.getLatestBlockhash(),
91
+ version: 0,
92
+ });
93
+ // Sign the transaction with all required signers
94
+ signedTransaction = await signTransactionMessageWithSigners(transaction);
95
+ }
96
+ // Get the transaction signature for logging
97
+ const signature = getSignatureFromTransaction(signedTransaction);
98
+ // Log the transaction explorer link
99
+ const explorerLink = getExplorerLink({
100
+ cluster: this.sdk.config.solana.cluster,
101
+ transaction: signature
102
+ });
103
+ this.sdk.logger.info(`Sending transaction: ${explorerLink}`);
104
+ // Send and confirm the transaction
105
+ await this.sendAndConfirmTransaction(signedTransaction);
106
+ this.sdk.logger.info('Transaction confirmed!');
107
+ return signature;
108
+ }
109
+ catch (err) {
110
+ const errorMessage = `Failed to send transaction: ${err instanceof Error ? err.message : String(err)}`;
111
+ this.sdk.logger.error(errorMessage);
112
+ throw new Error(errorMessage);
45
113
  }
46
114
  }
47
115
  }
48
- exports.SolanaUtils = SolanaUtils;
@@ -1,12 +1,9 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertBigIntToNumber = convertBigIntToNumber;
4
1
  /**
5
2
  * Helper function to convert bigint values to numbers in an object
6
3
  * @param obj Object that may contain bigint values
7
4
  * @returns Object with all bigint values converted to numbers
8
5
  */
9
- function convertBigIntToNumber(obj) {
6
+ export function convertBigIntToNumber(obj) {
10
7
  const result = { ...obj };
11
8
  for (const [key, value] of Object.entries(result)) {
12
9
  if (typeof value === 'bigint') {
@@ -0,0 +1,78 @@
1
+ include:
2
+ - project: nosana-ci/tools/cicd/gitlab-ci
3
+ file: templates/semver.yml
4
+ - project: nosana-ci/tools/cicd/gitlab-ci
5
+ file: templates/cacheflush.yml
6
+
7
+ variables:
8
+ NODE_VERSION: 22
9
+ OUTPUT_DIR: examples/browser/.output/public
10
+ PURGE_FILE: examples/browser/purge.json
11
+
12
+ .npm:
13
+ image: node:$NODE_VERSION
14
+ cache:
15
+ key:
16
+ files:
17
+ - examples/browser/package-lock.json
18
+ paths:
19
+ - examples/browser/node_modules
20
+ - examples/browser/.npm
21
+
22
+ build:
23
+ extends: .npm
24
+ stage: build
25
+ before_script:
26
+ - cd examples/browser
27
+ script: npm ci --cache .npm --prefer-offline
28
+ rules:
29
+ - if: $CI_MERGE_REQUEST_ID # merge requests
30
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # main
31
+ - if: $DEPLOYMENT_BRANCH && $CI_COMMIT_BRANCH == $DEPLOYMENT_BRANCH # optional deployment branch
32
+
33
+ pages:
34
+ extends: .npm
35
+ stage: deploy
36
+ before_script:
37
+ - cd examples/browser
38
+ script:
39
+ - NODE_OPTIONS=--max_old_space_size=25384 npm run generate
40
+ - |
41
+ if [ -z ${SKIP_CACHEFLUSH} ] && [ -n ${FQDN} ]
42
+ then
43
+ apt update
44
+ apt install -y jq
45
+ find $OUTPUT_DIR -type f | sed "s/${OUTPUT_DIR//\//\\/}/https:\/\/$FQDN/g" | jq -R -s -c 'split("\n")[:-1]' > $PURGE_FILE
46
+ fi
47
+ - mv $OUTPUT_DIR public
48
+ artifacts:
49
+ paths:
50
+ - public
51
+ - $PURGE_FILE
52
+ rules:
53
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $AUTO_DEPLOY != null # main
54
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $AUTO_DEPLOY == null # main
55
+ when: manual
56
+ - if: $DEPLOYMENT_BRANCH && $CI_COMMIT_BRANCH == $DEPLOYMENT_BRANCH && $AUTO_DEPLOY != null # deployment branch
57
+ - if: $DEPLOYMENT_BRANCH && $CI_COMMIT_BRANCH == $DEPLOYMENT_BRANCH && $AUTO_DEPLOY == null # deployment branch
58
+ when: manual
59
+
60
+ release:
61
+ extends: .release
62
+ stage: .post
63
+ rules:
64
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # main
65
+ - if: $DEPLOYMENT_BRANCH && $CI_COMMIT_BRANCH == $DEPLOYMENT_BRANCH # optional deployment branch
66
+
67
+ gitlab-release:
68
+ extends: .gitlab-release
69
+ stage: .post
70
+
71
+ cacheflush:
72
+ extends: .cacheflush
73
+ stage: .post
74
+ rules:
75
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # main
76
+ - if: $DEPLOYMENT_BRANCH && $CI_COMMIT_BRANCH == $DEPLOYMENT_BRANCH # optional deployment branch
77
+
78
+
@@ -0,0 +1,141 @@
1
+ # Nosana SDK Browser Playground - Features
2
+
3
+ This interactive documentation site provides a comprehensive testing environment for the Nosana SDK with the following features:
4
+
5
+ ## 🎯 Core Features
6
+
7
+ ### 1. **Interactive SDK Testing**
8
+ - Test all major SDK functions through a user-friendly web interface
9
+ - No need to write code - just click buttons and see results
10
+ - Perfect for developers learning the SDK or testing specific functionality
11
+
12
+ ### 2. **Network Management**
13
+ - **Mainnet/Devnet Switching**: Easily switch between networks with a dropdown
14
+ - **Connection Status**: Real-time connection indicator
15
+ - **Automatic Reinitialization**: SDK automatically reinitializes when switching networks
16
+
17
+ ### 3. **Job Operations**
18
+ - **Individual Job Retrieval**: Get detailed information about specific jobs by address
19
+ - **Bulk Job Fetching**: Retrieve multiple jobs with optional filtering
20
+ - **State Filtering**: Filter jobs by state (Queued, Running, Stopped, Done)
21
+ - **Limit Control**: Control how many jobs to fetch (1-100)
22
+
23
+ ### 4. **Market Operations**
24
+ - **Market Discovery**: Retrieve all available markets
25
+ - **Market Details**: View pricing, timeouts, and configuration
26
+ - **Market Monitoring**: Real-time updates for market changes
27
+
28
+ ### 5. **Real-time Monitoring**
29
+ - **WebSocket Subscriptions**: Live updates for account changes
30
+ - **Multi-Account Types**: Monitor jobs, runs, and markets simultaneously
31
+ - **Automatic Reconnection**: Handles connection failures gracefully
32
+ - **Error Reporting**: Clear error messages and recovery
33
+
34
+ ## 🖥️ User Interface Features
35
+
36
+ ### 1. **Terminal-style Output**
37
+ - **Color-coded Logs**: Different colors for info, success, error, and warning messages
38
+ - **Timestamps**: Every log entry includes a timestamp
39
+ - **Auto-scroll**: Optional automatic scrolling to latest entries
40
+ - **Log Management**: Clear logs button for fresh starts
41
+
42
+ ### 2. **Responsive Design**
43
+ - **Mobile-friendly**: Works on phones, tablets, and desktops
44
+ - **Grid Layout**: Adaptive layout that works on all screen sizes
45
+ - **Modern UI**: Clean, professional interface using Tailwind CSS
46
+
47
+ ### 3. **Interactive Controls**
48
+ - **Form Validation**: Input validation and error handling
49
+ - **Loading States**: Visual feedback during operations
50
+ - **Disabled States**: Buttons disabled during loading to prevent conflicts
51
+ - **Status Indicators**: Visual indicators for connection and monitoring status
52
+
53
+ ## 🔧 Technical Features
54
+
55
+ ### 1. **Modern Web Technologies**
56
+ - **Nuxt 3**: Latest Vue.js framework for optimal performance
57
+ - **Vue 3 Composition API**: Modern reactive programming
58
+ - **TypeScript Support**: Full type safety and IntelliSense
59
+ - **Hot Module Replacement**: Instant updates during development
60
+
61
+ ### 2. **Blockchain Integration**
62
+ - **Solana SDK Integration**: Full compatibility with Solana blockchain
63
+ - **WASM Support**: WebAssembly support for cryptographic operations
64
+ - **Address Validation**: Proper Solana address handling
65
+ - **Error Handling**: Comprehensive blockchain error handling
66
+
67
+ ### 3. **Development Experience**
68
+ - **Fast Builds**: Optimized build process with Vite
69
+ - **Development Server**: Hot reload for rapid development
70
+ - **Dependency Optimization**: Pre-bundled dependencies for faster loading
71
+ - **SSR Disabled**: Client-side rendering for better SDK compatibility
72
+
73
+ ## 📊 Monitoring Capabilities
74
+
75
+ ### 1. **Account Monitoring**
76
+ - **Job Accounts**: Monitor job state changes, node assignments, and completion
77
+ - **Run Accounts**: Track job execution and node performance
78
+ - **Market Accounts**: Watch for pricing and configuration changes
79
+
80
+ ### 2. **Real-time Updates**
81
+ - **Live Data**: Updates appear immediately as they happen on-chain
82
+ - **Detailed Information**: Full account data with formatted display
83
+ - **Historical View**: All updates are logged and preserved during session
84
+
85
+ ### 3. **Error Handling**
86
+ - **Connection Recovery**: Automatic reconnection on WebSocket failures
87
+ - **Error Classification**: Different error types with appropriate handling
88
+ - **User Feedback**: Clear error messages and recovery suggestions
89
+
90
+ ## 🎨 User Experience Features
91
+
92
+ ### 1. **Intuitive Interface**
93
+ - **Logical Grouping**: Related functions grouped in clear sections
94
+ - **Progressive Disclosure**: Advanced options available but not overwhelming
95
+ - **Visual Hierarchy**: Clear information hierarchy with proper typography
96
+
97
+ ### 2. **Helpful Defaults**
98
+ - **Example Data**: Pre-filled example job addresses for testing
99
+ - **Sensible Limits**: Default limits that work well for most use cases
100
+ - **Network Selection**: Starts with devnet for safer testing
101
+
102
+ ### 3. **Documentation Integration**
103
+ - **Inline Help**: Helpful descriptions and tooltips
104
+ - **Example Usage**: Clear examples of how to use each feature
105
+ - **Troubleshooting**: Built-in error handling and user guidance
106
+
107
+ ## 🚀 Performance Features
108
+
109
+ ### 1. **Optimized Loading**
110
+ - **Dynamic Imports**: SDK loaded only when needed
111
+ - **Code Splitting**: Efficient bundle splitting for faster initial load
112
+ - **Dependency Optimization**: Pre-bundled common dependencies
113
+
114
+ ### 2. **Efficient Updates**
115
+ - **Reactive State**: Efficient state management with Vue 3 reactivity
116
+ - **Minimal Re-renders**: Optimized component updates
117
+ - **Memory Management**: Proper cleanup of WebSocket connections
118
+
119
+ ### 3. **Browser Compatibility**
120
+ - **Modern Browsers**: Optimized for Chrome, Firefox, Safari, Edge
121
+ - **WebSocket Support**: Fallback handling for connection issues
122
+ - **WASM Support**: WebAssembly for cryptographic operations
123
+
124
+ ## 📱 Accessibility Features
125
+
126
+ ### 1. **Keyboard Navigation**
127
+ - **Tab Order**: Logical tab order through interface elements
128
+ - **Keyboard Shortcuts**: Standard keyboard interactions
129
+ - **Focus Management**: Clear focus indicators
130
+
131
+ ### 2. **Screen Reader Support**
132
+ - **Semantic HTML**: Proper HTML structure for screen readers
133
+ - **ARIA Labels**: Appropriate ARIA labels for interactive elements
134
+ - **Status Updates**: Screen reader announcements for status changes
135
+
136
+ ### 3. **Visual Accessibility**
137
+ - **Color Contrast**: High contrast colors for readability
138
+ - **Font Sizes**: Readable font sizes across all devices
139
+ - **Visual Indicators**: Multiple ways to convey information (not just color)
140
+
141
+ This playground serves as both a learning tool for developers new to the Nosana SDK and a testing environment for experienced developers working with the platform.