@sogni-ai/sogni-client 3.0.0-alpha.3 → 3.0.0-alpha.31

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 (61) hide show
  1. package/CHANGELOG.md +218 -0
  2. package/README.md +3 -1
  3. package/dist/Account/CurrentAccount.d.ts +3 -3
  4. package/dist/Account/CurrentAccount.js +14 -4
  5. package/dist/Account/CurrentAccount.js.map +1 -1
  6. package/dist/Account/index.d.ts +9 -5
  7. package/dist/Account/index.js +21 -10
  8. package/dist/Account/index.js.map +1 -1
  9. package/dist/Account/types.d.ts +15 -0
  10. package/dist/ApiClient/WebSocketClient/events.d.ts +21 -7
  11. package/dist/ApiClient/WebSocketClient/index.js +14 -4
  12. package/dist/ApiClient/WebSocketClient/index.js.map +1 -1
  13. package/dist/ApiGroup.d.ts +0 -3
  14. package/dist/ApiGroup.js +0 -1
  15. package/dist/ApiGroup.js.map +1 -1
  16. package/dist/Projects/Job.d.ts +43 -0
  17. package/dist/Projects/Job.js +76 -0
  18. package/dist/Projects/Job.js.map +1 -1
  19. package/dist/Projects/Project.d.ts +1 -1
  20. package/dist/Projects/Project.js +22 -19
  21. package/dist/Projects/Project.js.map +1 -1
  22. package/dist/Projects/createJobRequestMessage.js +2 -2
  23. package/dist/Projects/createJobRequestMessage.js.map +1 -1
  24. package/dist/Projects/index.d.ts +7 -2
  25. package/dist/Projects/index.js +50 -12
  26. package/dist/Projects/index.js.map +1 -1
  27. package/dist/Projects/types/ControlNetParams.d.ts +7 -2
  28. package/dist/Projects/types/events.d.ts +6 -0
  29. package/dist/Projects/types/index.d.ts +16 -3
  30. package/dist/Projects/utils.d.ts +2 -0
  31. package/dist/Projects/utils.js +14 -0
  32. package/dist/Projects/utils.js.map +1 -0
  33. package/dist/Stats/types.d.ts +1 -1
  34. package/dist/index.d.ts +3 -6
  35. package/dist/index.js +3 -12
  36. package/dist/index.js.map +1 -1
  37. package/dist/types/token.d.ts +1 -0
  38. package/dist/types/token.js +3 -0
  39. package/dist/types/token.js.map +1 -0
  40. package/dist/version.d.ts +1 -1
  41. package/dist/version.js +2 -1
  42. package/dist/version.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/Account/CurrentAccount.ts +16 -6
  45. package/src/Account/index.ts +35 -18
  46. package/src/Account/types.ts +19 -0
  47. package/src/ApiClient/WebSocketClient/events.ts +25 -8
  48. package/src/ApiClient/WebSocketClient/index.ts +14 -4
  49. package/src/ApiGroup.ts +0 -4
  50. package/src/Projects/Job.ts +98 -0
  51. package/src/Projects/Project.ts +24 -20
  52. package/src/Projects/createJobRequestMessage.ts +4 -2
  53. package/src/Projects/index.ts +51 -11
  54. package/src/Projects/types/ControlNetParams.ts +8 -2
  55. package/src/Projects/types/events.ts +6 -0
  56. package/src/Projects/types/index.ts +17 -3
  57. package/src/Projects/utils.ts +12 -0
  58. package/src/Stats/types.ts +2 -0
  59. package/src/index.ts +6 -16
  60. package/src/types/token.ts +1 -0
  61. package/src/version.ts +2 -1
package/src/ApiGroup.ts CHANGED
@@ -1,23 +1,19 @@
1
- import { AbstractProvider } from 'ethers';
2
1
  import ApiClient from './ApiClient';
3
2
  import EIP712Helper from './lib/EIP712Helper';
4
3
  import TypedEventEmitter, { EventMap } from './lib/TypedEventEmitter';
5
4
 
6
5
  export interface ApiConfig {
7
6
  client: ApiClient;
8
- provider: AbstractProvider;
9
7
  eip712: EIP712Helper;
10
8
  }
11
9
 
12
10
  abstract class ApiGroup<E extends EventMap = {}> extends TypedEventEmitter<E> {
13
11
  protected client: ApiClient;
14
- protected provider: AbstractProvider;
15
12
  protected eip712: EIP712Helper;
16
13
 
17
14
  constructor(config: ApiConfig) {
18
15
  super();
19
16
  this.client = config.client;
20
- this.provider = config.provider;
21
17
  this.eip712 = config.eip712;
22
18
  }
23
19
  }
@@ -4,6 +4,24 @@ import { RawJob, RawProject } from './types/RawProject';
4
4
  import ProjectsApi from './index';
5
5
  import { Logger } from '../lib/DefaultLogger';
6
6
  import getUUID from '../lib/getUUID';
7
+ import { EnhancementStrength } from './types';
8
+ import Project from './Project';
9
+ import { SupernetType } from '../ApiClient/WebSocketClient/types';
10
+ import { getEnhacementStrength } from './utils';
11
+ import { TokenType } from '../types/token';
12
+
13
+ export const enhancementDefaults = {
14
+ network: 'fast' as SupernetType,
15
+ modelId: 'flux1-schnell-fp8',
16
+ positivePrompt: '',
17
+ negativePrompt: '',
18
+ stylePrompt: '',
19
+ startingImageStrength: 0.5,
20
+ steps: 5,
21
+ guidance: 1,
22
+ numberOfImages: 1,
23
+ numberOfPreviews: 0
24
+ };
7
25
 
8
26
  export type JobStatus =
9
27
  | 'pending'
@@ -40,6 +58,9 @@ export interface JobData {
40
58
  previewUrl?: string;
41
59
  resultUrl?: string | null;
42
60
  error?: ErrorData;
61
+ positivePrompt?: string;
62
+ negativePrompt?: string;
63
+ jobIndex?: number;
43
64
  }
44
65
 
45
66
  export interface JobEventMap extends EntityEvents {
@@ -51,6 +72,7 @@ export interface JobEventMap extends EntityEvents {
51
72
  export interface JobOptions {
52
73
  api: ProjectsApi;
53
74
  logger: Logger;
75
+ project: Project;
54
76
  }
55
77
 
56
78
  class Job extends DataEntity<JobData, JobEventMap> {
@@ -72,14 +94,18 @@ class Job extends DataEntity<JobData, JobEventMap> {
72
94
 
73
95
  private readonly _api: ProjectsApi;
74
96
  private readonly _logger: Logger;
97
+ private readonly _project: Project;
98
+ private _enhancementProject: Project | null = null;
75
99
 
76
100
  constructor(data: JobData, options: JobOptions) {
77
101
  super(data);
78
102
 
79
103
  this._api = options.api;
80
104
  this._logger = options.logger;
105
+ this._project = options.project;
81
106
 
82
107
  this.on('updated', this.handleUpdated.bind(this));
108
+ this.handleEnhancementUpdate = this.handleEnhancementUpdate.bind(this);
83
109
  }
84
110
 
85
111
  get id() {
@@ -152,6 +178,25 @@ class Job extends DataEntity<JobData, JobEventMap> {
152
178
  return this.data.error;
153
179
  }
154
180
 
181
+ get hasResultImage() {
182
+ return this.status === 'completed' && !this.isNSFW;
183
+ }
184
+
185
+ get enhancedImage() {
186
+ if (!this._enhancementProject) {
187
+ return null;
188
+ }
189
+ const project = this._enhancementProject;
190
+ const job = project.jobs[0];
191
+ return {
192
+ status: project.status,
193
+ progress: project.progress,
194
+ result: job?.resultUrl || null,
195
+ error: project.error,
196
+ getResultUrl: () => job?.getResultUrl()
197
+ };
198
+ }
199
+
155
200
  /**
156
201
  * Get the result URL of the job. This method will make a request to the API to get signed URL.
157
202
  * IMPORTANT: URL expires after 30 minutes, so make sure to download the image as soon as possible.
@@ -225,6 +270,59 @@ class Job extends DataEntity<JobData, JobEventMap> {
225
270
  this.emit('failed', this.data.error!);
226
271
  }
227
272
  }
273
+
274
+ private handleEnhancementUpdate() {
275
+ this.emit('updated', ['enhancedImage']);
276
+ }
277
+
278
+ async getResultData() {
279
+ if (!this.hasResultImage) {
280
+ throw new Error('No result image available');
281
+ }
282
+ const url = await this.getResultUrl();
283
+ const response = await fetch(url);
284
+ if (!response.ok) {
285
+ throw new Error(`Failed to fetch image: ${response.statusText}`);
286
+ }
287
+ return response.blob();
288
+ }
289
+
290
+ /**
291
+ * Enhance the image using the Flux model. This method will create a new project with the
292
+ * enhancement parameters and use the result image of the current job as the starting image.
293
+ * @param strength - how much freedom the model has to change the image.
294
+ * @param overrides - optional parameters to override original prompt, style or token type.
295
+ */
296
+ async enhance(
297
+ strength: EnhancementStrength,
298
+ overrides: { positivePrompt?: string; stylePrompt?: string; tokenType?: TokenType } = {}
299
+ ) {
300
+ if (this.status !== 'completed') {
301
+ throw new Error('Job is not completed yet');
302
+ }
303
+ if (this.isNSFW) {
304
+ throw new Error('Job did not pass NSFW filter');
305
+ }
306
+ if (this._enhancementProject) {
307
+ this._enhancementProject.off('updated', this.handleEnhancementUpdate);
308
+ this._enhancementProject = null;
309
+ }
310
+ const imageData = await this.getResultData();
311
+ const project = await this._api.create({
312
+ ...enhancementDefaults,
313
+ positivePrompt: overrides.positivePrompt || this._project.params.positivePrompt,
314
+ stylePrompt: overrides.stylePrompt || this._project.params.stylePrompt,
315
+ tokenType: overrides.tokenType || this._project.params.tokenType,
316
+ seed: this.seed || this._project.params.seed,
317
+ startingImage: imageData,
318
+ startingImageStrength: 1 - getEnhacementStrength(strength),
319
+ sizePreset: this._project.params.sizePreset
320
+ });
321
+ this._enhancementProject = project;
322
+ this._enhancementProject.on('updated', this.handleEnhancementUpdate);
323
+ const images = await project.waitForCompletion();
324
+ return images[0];
325
+ }
228
326
  }
229
327
 
230
328
  export default Job;
@@ -1,4 +1,4 @@
1
- import Job, { JobData, JobStatus } from './Job';
1
+ import Job, { JobData } from './Job';
2
2
  import DataEntity, { EntityEvents } from '../lib/DataEntity';
3
3
  import { ProjectParams } from './types';
4
4
  import cloneDeep from 'lodash/cloneDeep';
@@ -50,6 +50,7 @@ export interface ProjectEventMap extends EntityEvents {
50
50
  progress: number;
51
51
  completed: string[];
52
52
  failed: ErrorData;
53
+ jobStarted: Job;
53
54
  jobCompleted: Job;
54
55
  jobFailed: Job;
55
56
  }
@@ -209,48 +210,47 @@ class Project extends DataEntity<ProjectData, ProjectEventMap> {
209
210
  */
210
211
  _addJob(data: JobData | Job) {
211
212
  const job =
212
- data instanceof Job ? data : new Job(data, { api: this._api, logger: this._logger });
213
+ data instanceof Job
214
+ ? data
215
+ : new Job(data, { api: this._api, logger: this._logger, project: this });
213
216
  this._jobs.push(job);
214
217
  job.on('updated', () => {
215
218
  this.lastUpdated = new Date();
216
219
  this.emit('updated', ['jobs']);
217
220
  });
221
+ this.emit('jobStarted', job);
218
222
  job.on('completed', () => {
219
223
  this.emit('jobCompleted', job);
220
- this._handleJobFinished(job);
221
224
  });
222
225
  job.on('failed', () => {
223
226
  this.emit('jobFailed', job);
224
- this._handleJobFinished(job);
225
227
  });
226
228
  return job;
227
229
  }
228
230
 
229
- private _handleJobFinished(job: Job) {
230
- const finalStatus: JobStatus[] = ['completed', 'failed', 'canceled'];
231
- const allJobsDone = this.jobs.every((job) => finalStatus.includes(job.status));
232
- // If all jobs are done and project is not already failed or completed, update the project status
233
- if (allJobsDone && this.status !== 'failed' && this.status !== 'completed') {
234
- const allJobsFailed = this.jobs.every((job) => job.status === 'failed');
235
- if (allJobsFailed) {
236
- this._update({ status: 'failed' });
237
- } else {
238
- this._update({ status: 'completed' });
239
- }
240
- }
241
- }
242
-
243
231
  private _checkForTimeout() {
244
232
  if (this.lastUpdated.getTime() + PROJECT_TIMEOUT < Date.now()) {
245
233
  this._syncToServer().catch((error) => {
246
234
  this._logger.error(error);
247
235
  this._failedSyncAttempts++;
248
- if (this._failedSyncAttempts > MAX_FAILED_SYNC_ATTEMPTS) {
236
+ if (this._failedSyncAttempts >= MAX_FAILED_SYNC_ATTEMPTS) {
249
237
  this._logger.error(
250
238
  `Failed to sync project data after ${MAX_FAILED_SYNC_ATTEMPTS} attempts. Stopping further attempts.`
251
239
  );
252
240
  clearInterval(this._timeout!);
253
241
  this._timeout = null;
242
+ this.jobs.forEach((job) => {
243
+ if (!job.finished) {
244
+ job._update({
245
+ status: 'failed',
246
+ error: { code: 0, message: 'Job timed out' }
247
+ });
248
+ }
249
+ });
250
+ this._update({
251
+ status: 'failed',
252
+ error: { code: 0, message: 'Project timed out. Please try again or contact support.' }
253
+ });
254
254
  }
255
255
  });
256
256
  }
@@ -286,7 +286,11 @@ class Project extends DataEntity<ProjectData, ProjectEventMap> {
286
286
  // If there are any jobs left in jobData, it means they are new jobs that are not in the project yet
287
287
  if (Object.keys(jobData).length) {
288
288
  for (const job of Object.values(jobData)) {
289
- const jobInstance = Job.fromRaw(data, job, { api: this._api, logger: this._logger });
289
+ const jobInstance = Job.fromRaw(data, job, {
290
+ api: this._api,
291
+ logger: this._logger,
292
+ project: this
293
+ });
290
294
  this._addJob(jobInstance);
291
295
  }
292
296
  }
@@ -119,7 +119,8 @@ function createJobRequestMessage(id: string, params: ProjectParams) {
119
119
  keyFrames: [
120
120
  {
121
121
  ...template.keyFrames[0],
122
- scheduler: params.scheduler,
122
+ scheduler: params.scheduler || null,
123
+ timeStepSpacing: params.timeStepSpacing || null,
123
124
  steps: params.steps,
124
125
  guidanceScale: params.guidance,
125
126
  modelID: params.modelId,
@@ -138,7 +139,8 @@ function createJobRequestMessage(id: string, params: ProjectParams) {
138
139
  previews: params.numberOfPreviews || 0,
139
140
  numberOfImages: params.numberOfImages,
140
141
  jobID: id,
141
- disableSafety: !!params.disableNSFWFilter
142
+ disableSafety: !!params.disableNSFWFilter,
143
+ tokenType: params.tokenType
142
144
  };
143
145
  if (params.network) {
144
146
  jobRequest.network = params.network;
@@ -1,6 +1,7 @@
1
1
  import ApiGroup, { ApiConfig } from '../ApiGroup';
2
2
  import {
3
3
  AvailableModel,
4
+ EnhancementStrength,
4
5
  EstimateRequest,
5
6
  ImageUrlParams,
6
7
  ProjectParams,
@@ -24,9 +25,12 @@ import { RawProject } from './types/RawProject';
24
25
  import ErrorData from '../types/ErrorData';
25
26
  import { SupernetType } from '../ApiClient/WebSocketClient/types';
26
27
  import Cache from '../lib/Cache';
28
+ import { enhancementDefaults } from './Job';
29
+ import { getEnhacementStrength } from './utils';
30
+ import { TokenType } from '../types/token';
27
31
 
28
32
  const sizePresetCache = new Cache<SizePreset[]>(10 * 60 * 1000);
29
- const GARBAGE_COLLECT_TIMEOUT = 10000;
33
+ const GARBAGE_COLLECT_TIMEOUT = 30000;
30
34
  const MODELS_REFRESH_INTERVAL = 1000 * 60 * 60 * 24; // 24 hours
31
35
 
32
36
  function mapErrorCodes(code: string): number {
@@ -67,7 +71,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
67
71
  this.client.socket.on('jobProgress', this.handleJobProgress.bind(this));
68
72
  this.client.socket.on('jobError', this.handleJobError.bind(this));
69
73
  this.client.socket.on('jobResult', this.handleJobResult.bind(this));
70
- // Listen to server disconnect event
74
+ // Listen to the server disconnect event
71
75
  this.client.on('disconnected', this.handleServerDisconnected.bind(this));
72
76
  // Listen to project and job events and update project and job instances
73
77
  this.on('project', this.handleProjectEvent.bind(this));
@@ -115,7 +119,10 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
115
119
  type: 'initiating',
116
120
  projectId: data.jobID,
117
121
  jobId: data.imgID,
118
- workerName: data.workerName
122
+ workerName: data.workerName,
123
+ positivePrompt: data.positivePrompt,
124
+ negativePrompt: data.negativePrompt,
125
+ jobIndex: data.jobIndex
119
126
  });
120
127
  return;
121
128
  case 'jobStarted': {
@@ -123,7 +130,10 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
123
130
  type: 'started',
124
131
  projectId: data.jobID,
125
132
  jobId: data.imgID,
126
- workerName: data.workerName
133
+ workerName: data.workerName,
134
+ positivePrompt: data.positivePrompt,
135
+ negativePrompt: data.negativePrompt,
136
+ jobIndex: data.jobIndex
127
137
  });
128
138
  return;
129
139
  }
@@ -241,7 +251,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
241
251
  this.client.logger.error(e);
242
252
  });
243
253
  setTimeout(() => {
244
- this.projects = this.projects.filter((p) => p.id !== event.projectId);
254
+ this.projects = this.projects.filter((p) => !p.finished);
245
255
  }, GARBAGE_COLLECT_TIMEOUT);
246
256
  }
247
257
  }
@@ -263,15 +273,30 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
263
273
  }
264
274
  switch (event.type) {
265
275
  case 'initiating':
266
- job._update({ status: 'initiating', workerName: event.workerName });
276
+ // positivePrompt and negativePrompt are only received if a Dynamic Prompt was used for the project creating a different prompt for each job
277
+ job._update({
278
+ status: 'initiating',
279
+ workerName: event.workerName,
280
+ positivePrompt: event.positivePrompt,
281
+ negativePrompt: event.negativePrompt,
282
+ jobIndex: event.jobIndex
283
+ });
267
284
  break;
268
285
  case 'started':
269
- job._update({ status: 'processing', workerName: event.workerName });
286
+ // positivePrompt and negativePrompt are only received if a Dynamic Prompt was used for the project creating a different prompt for each job
287
+ job._update({
288
+ status: 'processing',
289
+ workerName: event.workerName,
290
+ positivePrompt: event.positivePrompt,
291
+ negativePrompt: event.negativePrompt,
292
+ jobIndex: event.jobIndex
293
+ });
270
294
  break;
271
295
  case 'progress':
272
296
  job._update({
273
297
  status: 'processing',
274
- step: event.step,
298
+ // Jus in case event comes out of order
299
+ step: Math.max(event.step, job.step),
275
300
  stepCount: event.stepCount
276
301
  });
277
302
  if (project.status !== 'processing') {
@@ -337,10 +362,10 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
337
362
  */
338
363
  async create(data: ProjectParams): Promise<Project> {
339
364
  const project = new Project({ ...data }, { api: this, logger: this.client.logger });
340
- if (data.startingImage) {
365
+ if (data.startingImage && data.startingImage !== true) {
341
366
  await this.uploadGuideImage(project.id, data.startingImage);
342
367
  }
343
- if (data.controlNet?.image) {
368
+ if (data.controlNet?.image && data.controlNet.image !== true) {
344
369
  await this.uploadCNImage(project.id, data.controlNet.image);
345
370
  }
346
371
  const request = createJobRequestMessage(project.id, data);
@@ -441,6 +466,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
441
466
  */
442
467
  async estimateCost({
443
468
  network,
469
+ tokenType,
444
470
  model,
445
471
  imageCount,
446
472
  stepCount,
@@ -452,6 +478,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
452
478
  sizePreset
453
479
  }: EstimateRequest) {
454
480
  const pathParams = [
481
+ tokenType || 'sogni',
455
482
  network,
456
483
  model,
457
484
  imageCount,
@@ -471,7 +498,7 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
471
498
  pathParams.push(width, height);
472
499
  }
473
500
  const r = await this.client.socket.get<EstimationResponse>(
474
- `/api/v1/job/estimate/${pathParams.join('/')}`
501
+ `/api/v2/job/estimate/${pathParams.join('/')}`
475
502
  );
476
503
  return {
477
504
  token: r.quote.project.costInToken,
@@ -479,6 +506,19 @@ class ProjectsApi extends ApiGroup<ProjectApiEvents> {
479
506
  };
480
507
  }
481
508
 
509
+ async estimateEnhancementCost(strength: EnhancementStrength, tokenType: TokenType = 'sogni') {
510
+ return this.estimateCost({
511
+ network: enhancementDefaults.network,
512
+ tokenType,
513
+ model: enhancementDefaults.modelId,
514
+ imageCount: 1,
515
+ stepCount: enhancementDefaults.steps,
516
+ previewCount: 0,
517
+ cnEnabled: false,
518
+ startingImageStrength: getEnhacementStrength(strength)
519
+ });
520
+ }
521
+
482
522
  /**
483
523
  * Get upload URL for image
484
524
  * @internal
@@ -16,7 +16,8 @@ export type ControlNetName =
16
16
  | 'segmentation'
17
17
  | 'shuffle'
18
18
  | 'softedge'
19
- | 'tile';
19
+ | 'tile'
20
+ | 'instantid';
20
21
 
21
22
  /**
22
23
  * Raw ControlNet parameters passed to the API
@@ -53,8 +54,13 @@ export interface ControlNetParams {
53
54
  name: ControlNetName;
54
55
  /**
55
56
  * ControlNet input image
57
+ * Supported types:
58
+ * `File` - file object from input[type=file]
59
+ * `Buffer` - Node.js buffer object with image data
60
+ * `Blob` - blob object with image data
61
+ * `true` - indicates that the image is already uploaded to the server
56
62
  */
57
- image?: File | Buffer | Blob;
63
+ image?: File | Buffer | Blob | boolean;
58
64
  /**
59
65
  * ControlNet strength 0 to 1. 0 full control to prompt, 1 full control to ControlNet
60
66
  */
@@ -29,11 +29,17 @@ export interface JobEventBase {
29
29
  export interface JobInitiating extends JobEventBase {
30
30
  type: 'initiating';
31
31
  workerName: string;
32
+ positivePrompt?: string;
33
+ negativePrompt?: string;
34
+ jobIndex?: number;
32
35
  }
33
36
 
34
37
  export interface JobStarted extends JobEventBase {
35
38
  type: 'started';
36
39
  workerName: string;
40
+ positivePrompt?: string;
41
+ negativePrompt?: string;
42
+ jobIndex?: number;
37
43
  }
38
44
 
39
45
  export interface JobProgress extends JobEventBase {
@@ -1,5 +1,6 @@
1
1
  import { SupernetType } from '../../ApiClient/WebSocketClient/types';
2
2
  import { ControlNetParams } from './ControlNetParams';
3
+ import { TokenType } from '../../types/token';
3
4
 
4
5
  export interface SupportedModel {
5
6
  id: string;
@@ -102,12 +103,14 @@ export interface ProjectParams {
102
103
  */
103
104
  numberOfImages: number;
104
105
  /**
105
- * Generate images based on starting image.
106
+ * Generate images based on the starting image.
107
+ * Supported types:
106
108
  * `File` - file object from input[type=file]
107
- * `Buffer` - buffer object with image data
109
+ * `Buffer` - Node.js buffer object with image data
108
110
  * `Blob` - blob object with image data
111
+ * `true` - indicates that the image is already uploaded to the server
109
112
  */
110
- startingImage?: File | Buffer | Blob;
113
+ startingImage?: File | Buffer | Blob | boolean;
111
114
  /**
112
115
  * How strong effect of starting image should be. From 0 to 1, default 0.5
113
116
  */
@@ -141,6 +144,11 @@ export interface ProjectParams {
141
144
  * ControlNet model parameters
142
145
  */
143
146
  controlNet?: ControlNetParams;
147
+ /**
148
+ * Select which tokens to use for the project.
149
+ * If not specified, the Sogni token will be used.
150
+ */
151
+ tokenType?: TokenType;
144
152
  }
145
153
 
146
154
  export type ImageUrlParams = {
@@ -156,6 +164,10 @@ export interface EstimateRequest {
156
164
  * Network to use. Can be 'fast' or 'relaxed'
157
165
  */
158
166
  network: SupernetType;
167
+ /**
168
+ * Token type
169
+ */
170
+ tokenType?: TokenType;
159
171
  /**
160
172
  * Model ID
161
173
  */
@@ -195,3 +207,5 @@ export interface EstimateRequest {
195
207
  */
196
208
  height?: number;
197
209
  }
210
+
211
+ export type EnhancementStrength = 'light' | 'medium' | 'heavy';
@@ -0,0 +1,12 @@
1
+ import { EnhancementStrength } from './types';
2
+
3
+ export function getEnhacementStrength(strength: EnhancementStrength): number {
4
+ switch (strength) {
5
+ case 'light':
6
+ return 0.15;
7
+ case 'heavy':
8
+ return 0.49;
9
+ default:
10
+ return 0.35;
11
+ }
12
+ }
@@ -4,7 +4,9 @@ export type LeaderboardType =
4
4
  | 'renderSecCompleteWorker'
5
5
  | 'renderSecCompleteArtist'
6
6
  | 'renderTokenCompleteWorker'
7
+ | 'renderTokenCompleteWorker2'
7
8
  | 'renderTokenCompleteArtist'
9
+ | 'renderTokenCompleteArtist2'
8
10
  | 'jobCompleteWorker'
9
11
  | 'jobCompleteArtist'
10
12
  | 'projectCompleteArtist'
package/src/index.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { AbstractProvider, JsonRpcProvider, getDefaultProvider } from 'ethers';
2
1
  // Account API
3
2
  import AccountApi from './Account';
4
3
  import CurrentAccount from './Account/CurrentAccount';
@@ -18,6 +17,7 @@ import { AvailableModel, ProjectParams, Scheduler, TimeStepSpacing } from './Pro
18
17
  import StatsApi from './Stats';
19
18
  // Base Types
20
19
  import ErrorData from './types/ErrorData';
20
+ import { TokenType } from './types/token';
21
21
 
22
22
  export type {
23
23
  AvailableModel,
@@ -29,7 +29,8 @@ export type {
29
29
  ProjectStatus,
30
30
  Scheduler,
31
31
  SupernetType,
32
- TimeStepSpacing
32
+ TimeStepSpacing,
33
+ TokenType
33
34
  };
34
35
 
35
36
  export { ApiError, CurrentAccount, Job, Project };
@@ -62,10 +63,6 @@ export interface SogniClientConfig {
62
63
  * @default 'warn'
63
64
  **/
64
65
  logLevel?: LogLevel;
65
- /**
66
- * If provided, the client will connect to this JSON-RPC endpoint to interact with the blockchain
67
- */
68
- jsonRpcUrl?: string;
69
66
  /**
70
67
  * If true, the client will connect to the testnet. Ignored if jsonRpcUrl is provided
71
68
  */
@@ -92,7 +89,7 @@ export class SogniClient {
92
89
  }
93
90
 
94
91
  /**
95
- * Instance creation may involve async operations, so we use a static method
92
+ * Create client instance, with default configuration
96
93
  * @param config
97
94
  */
98
95
  static async createInstance(config: SogniClientConfig): Promise<SogniClient> {
@@ -103,18 +100,11 @@ export class SogniClient {
103
100
  const isTestnet = config.testnet !== undefined ? config.testnet : true;
104
101
 
105
102
  const client = new ApiClient(restEndpoint, socketEndpoint, config.appId, network, logger);
106
- let provider: AbstractProvider;
107
- if ('jsonRpcUrl' in config) {
108
- provider = new JsonRpcProvider(config.jsonRpcUrl);
109
- } else {
110
- provider = getDefaultProvider(isTestnet ? 84532 : 8453);
111
- }
112
- const chainId = await provider.getNetwork().then((network) => network.chainId);
113
103
  const eip712 = new EIP712Helper({
114
104
  name: 'Sogni-testnet',
115
105
  version: '1',
116
- chainId: chainId.toString()
106
+ chainId: isTestnet ? '84532' : '8453'
117
107
  });
118
- return new SogniClient({ client, provider, eip712 });
108
+ return new SogniClient({ client, eip712 });
119
109
  }
120
110
  }
@@ -0,0 +1 @@
1
+ export type TokenType = 'sogni' | 'spark';
package/src/version.ts CHANGED
@@ -1 +1,2 @@
1
- export const LIB_VERSION = "1.0.0-alpha.4";
1
+ import { version } from '../package.json';
2
+ export const LIB_VERSION = version;