diff --git a/config.example.json b/config.example.json index 1cec000..e90dad1 100644 --- a/config.example.json +++ b/config.example.json @@ -4,7 +4,7 @@ "accessToken": "" }, "blockchain": { - "rpcUrl": "https://polygon.superprotocol.com", + "rpcUrl": "https://opbnb.superprotocol.com", "smartContractAddress": "0x3C69ea105Fc716C1Dcb41859281Aa817D0A0B279", "accountPrivateKey": "" }, diff --git a/package-lock.json b/package-lock.json index b5a9027..bacd06c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,20 @@ { "name": "@super-protocol/ctl", - "version": "0.10.11", + "version": "0.10.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@super-protocol/ctl", - "version": "0.10.11", + "version": "0.10.12", "license": "MIT", "dependencies": { "@amplitude/node": "^1.10.2", "@iarna/toml": "^2.2.5", "@super-protocol/distributed-secrets": "1.0.2", "@super-protocol/dto-js": "1.1.2", - "@super-protocol/sdk-js": "3.3.3-update.1", - "@super-protocol/sp-files-addon": "^0.9.0", + "@super-protocol/sdk-js": "^3.5.0-beta.2", + "@super-protocol/sp-files-addon": "^0.9.6", "@types/tar-stream": "^3.1.3", "axios": "1.6.2", "bip39": "^3.1.0", @@ -4741,6 +4741,7 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz", "integrity": "sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==", + "license": "ISC", "engines": { "node": ">= 10" } @@ -5723,6 +5724,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@super-protocol/dto-js/-/dto-js-1.1.2.tgz", "integrity": "sha512-6L9kv9JfKbZ5H05v3OetqHXTenoCS3WssmP9Si4I2b9HFJESaCXQXnA1izonkJGCYliKEp+BtK9bEHFDgpGhHQ==", + "license": "MIT", "dependencies": { "@sinclair/typebox": "0.33.17", "iso-639-3": "^2.2.0" @@ -5752,26 +5754,25 @@ } }, "node_modules/@super-protocol/pki-common": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@super-protocol/pki-common/-/pki-common-1.5.4.tgz", - "integrity": "sha512-zO2GwDak1zULJj67QbNcTYm4I0Xk1Xotb+BGcTWI0d3eLsBoEIrbx9oKWZtWkNVzpo5CAqoh21Vx9Sj7LoIk0w==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@super-protocol/pki-common/-/pki-common-1.6.1.tgz", + "integrity": "sha512-v7P5UBcF+KmiAactTkyZf/gs3FmxyEOnrxEmhsUDdiyfwZzjTrFDju6pUTYFOJnQ2V5OMX8L0+SRj+XskPTp+Q==", "dependencies": { "hi-base32": "^0.5.1", "node-forge": "^1.3.1" } }, "node_modules/@super-protocol/sdk-js": { - "version": "3.3.3-update.1", - "resolved": "https://registry.npmjs.org/@super-protocol/sdk-js/-/sdk-js-3.3.3-update.1.tgz", - "integrity": "sha512-TU4qPo9MufBJzZ0LsPvD8QoLhxgVTyYJpAKw+UfgOE21xQkxcZBk9u29xcFd7d5sppVn0TYrqza1ZmDksC+BBQ==", + "version": "3.5.0-beta.2", + "resolved": "https://registry.npmjs.org/@super-protocol/sdk-js/-/sdk-js-3.5.0-beta.2.tgz", + "integrity": "sha512-rWmtIQRCbg3Wy8nMicz+LBOJu7vjHx6/bqdd+uxFCH50o+ZPqs08wlKedoH69obKGJqCE1Gkp68NlbEUvV6VBw==", "dependencies": { "@aws-sdk/client-s3": "^3.470.0", "@fidm/x509": "^1.2.1", "@msgpack/msgpack": "^2.8.0", "@sinclair/typebox": "0.33.17", - "@super-protocol/dto-js": "1.1.2", - "@super-protocol/pki-common": "1.5.4", - "@super-protocol/tee-lib": "^0.1.2", + "@super-protocol/dto-js": "1.1.3", + "@super-protocol/pki-common": "1.6.1", "@super-protocol/uplink-nodejs": "^1.2.20", "asn1js": "^3.0.5", "axios": "^1.5.1", @@ -5786,7 +5787,7 @@ "object-hash": "^3.0.0", "p-queue": "6.6.2", "pino": "^7.2.0", - "pkijs": "^3.0.15", + "pkijs": "^3.2.4", "protobufjs": "^6.11.2", "ua-parser-js": "^1.0.37", "uuid": "^9.0.1", @@ -5801,29 +5802,38 @@ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.33.17.tgz", "integrity": "sha512-75232GRx3wp3P7NP+yc4nRK3XUAnaQShxTAzapgmQrgs0QvSq0/mOJGoZXRpH15cFCKyys+4laCPbBselqJ5Ag==" }, + "node_modules/@super-protocol/sdk-js/node_modules/@super-protocol/dto-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@super-protocol/dto-js/-/dto-js-1.1.3.tgz", + "integrity": "sha512-j1K04a7DK+SlLjNkAhCuM//oX9XoDEAvSTZxtxewfvXaiFagXARUj4d+d9QYuxlK8P1qAimrK2hpaUB2CZ4c4w==", + "dependencies": { + "@sinclair/typebox": "0.33.17", + "iso-639-3": "^2.2.0" + } + }, "node_modules/@super-protocol/sdk-js/node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/@super-protocol/sp-files-addon": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon/-/sp-files-addon-0.9.0.tgz", - "integrity": "sha512-LqK8DDa1VHbvRi03/j6m8xUNDuvgCOs4lNiWkKvl6wDOIS6kpY09npuayPD2mWhvf05r1Vds+50sbnWm/u3GUw==", + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon/-/sp-files-addon-0.9.6.tgz", + "integrity": "sha512-tXNQdMg8+9wqolHF3WX1R3sfqsqBfu/z89dqj/LSEKydMPVvGmNkUzMmEnCRNhhgdnlV2EnkEu95Hv9aU8Bq5A==", "license": "MIT", "engines": { "node": ">= 16" }, "optionalDependencies": { - "@super-protocol/sp-files-addon-darwin-arm64": "0.9.0", - "@super-protocol/sp-files-addon-darwin-x64": "0.9.0", - "@super-protocol/sp-files-addon-linux-x64-gnu": "0.9.0" + "@super-protocol/sp-files-addon-darwin-arm64": "0.9.6", + "@super-protocol/sp-files-addon-darwin-x64": "0.9.6", + "@super-protocol/sp-files-addon-linux-x64-gnu": "0.9.6" } }, "node_modules/@super-protocol/sp-files-addon-darwin-arm64": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-darwin-arm64/-/sp-files-addon-darwin-arm64-0.9.0.tgz", - "integrity": "sha512-YmoYnzpAg2gJawYn8278ijCPj1urCM98VvZzl14WUWA8Pb8ZdiPx6Hl8F2a2crKeXf7ShREpdVJ7mGUsxopiSw==", + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-darwin-arm64/-/sp-files-addon-darwin-arm64-0.9.6.tgz", + "integrity": "sha512-oIcnHr7D+LOjkC+72V1odH0PYPwPgWEKSmDzl9pp9frhFS9toqqkCgugcvfejGGgNEaqw51JHDpbHxnO5gQQ8A==", "cpu": [ "arm64" ], @@ -5837,9 +5847,9 @@ } }, "node_modules/@super-protocol/sp-files-addon-darwin-x64": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-darwin-x64/-/sp-files-addon-darwin-x64-0.9.0.tgz", - "integrity": "sha512-XSHJJSpzBGT7Upnqi1DtnxxXv2cryCWWZnAOquz34vJAIWnbW8M0i/lUva/W5/8qsQU/CPMCtsxYrLAv5sK6Fw==", + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-darwin-x64/-/sp-files-addon-darwin-x64-0.9.6.tgz", + "integrity": "sha512-bS7aDvzvRgQVPaW+JQBOdCw3fwRz9SqwzqRcPBUmtgqiSE8WyF+AkxQ8/x89euiNVpQFG06efLv6JGq8aHD5Cg==", "cpu": [ "x64" ], @@ -5853,9 +5863,9 @@ } }, "node_modules/@super-protocol/sp-files-addon-linux-x64-gnu": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-linux-x64-gnu/-/sp-files-addon-linux-x64-gnu-0.9.0.tgz", - "integrity": "sha512-DxLzhM+WOXoM1i3H9tdvR44/pxAeGo3JTsse+5jig7GAFCQS+YmmPufdeL33JYR0NS06OAW83VO6KFsoXF38sg==", + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-linux-x64-gnu/-/sp-files-addon-linux-x64-gnu-0.9.6.tgz", + "integrity": "sha512-sqHgERzvJikLhTDZkOYVmYNvD9LR6mQxniOAn1zoljXm7bnqPUCIeQnwVl7bidb8cDfpTINGWNwjKVRWCPo0jQ==", "cpu": [ "x64" ], @@ -5868,20 +5878,6 @@ "node": ">= 16" } }, - "node_modules/@super-protocol/tee-lib": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@super-protocol/tee-lib/-/tee-lib-0.1.3.tgz", - "integrity": "sha512-1ysktkTWchqJUWk+AQejg/WWrdQ6TpA04jlQNkuJeCQFmyB0sZGxvuHjGL7WVooW/PsgatPqYO0pbqBXP+puTQ==", - "dependencies": { - "@msgpack/msgpack": "^2.7.1", - "buffer": "^6.0.3", - "gzip-js": "^0.3.2" - }, - "engines": { - "node": ">=14.0", - "npm": ">=6.0" - } - }, "node_modules/@super-protocol/uplink-nodejs": { "version": "1.2.20", "resolved": "https://registry.npmjs.org/@super-protocol/uplink-nodejs/-/uplink-nodejs-1.2.20.tgz", @@ -7039,29 +7035,6 @@ "node-int64": "^0.4.0" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -7660,17 +7633,6 @@ "node": ">=0.8" } }, - "node_modules/crc32": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/crc32/-/crc32-0.2.2.tgz", - "integrity": "sha512-PFZEGbDUeoNbL2GHIEpJRQGheXReDody/9axKTxhXtQqIL443wnNigtVZO9iuCIMPApKZRv7k2xr8euXHqNxQQ==", - "bin": { - "crc32": "bin/runner.js" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -7848,18 +7810,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/deflate-js": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/deflate-js/-/deflate-js-0.2.3.tgz", - "integrity": "sha512-r5KgHJ/yTiWQs23nVeQz5dSL/kmW0MBszsssNyEqDCjjFDj4XG/c6QUN/I0JtY3ZHwwcaNBtGE8s+oV33acTfQ==", - "bin": { - "deflate-js": "bin/deflate.js", - "inflate-js": "bin/inflate.js" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -9502,22 +9452,6 @@ "graphql": ">=0.11 <=16" } }, - "node_modules/gzip-js": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/gzip-js/-/gzip-js-0.3.2.tgz", - "integrity": "sha512-BFTiwtEN12koJsnhVo77SzW+u6VANzhaK0HEtdwFwgFzFOq1WQJ8eSPEyGAueUfs1C/WqdgtuYnUwCRuRm1A5Q==", - "dependencies": { - "crc32": ">= 0.2.2", - "deflate-js": ">= 0.2.2" - }, - "bin": { - "gunzip-js": "bin/gunzip.js", - "gzip-js": "bin/gzip.js" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", diff --git a/package.json b/package.json index dccd5ce..f92bdee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@super-protocol/ctl", - "version": "0.10.11", + "version": "0.10.12", "description": "A tool for publishing values in a secure and reliable way.", "main": "./build/index.js", "type": "commonjs", @@ -36,8 +36,8 @@ "@iarna/toml": "^2.2.5", "@super-protocol/distributed-secrets": "1.0.2", "@super-protocol/dto-js": "1.1.2", - "@super-protocol/sdk-js": "3.3.3-update.1", - "@super-protocol/sp-files-addon": "^0.9.0", + "@super-protocol/sdk-js": "^3.5.0-beta.2", + "@super-protocol/sp-files-addon": "^0.9.6", "@types/tar-stream": "^3.1.3", "axios": "1.6.2", "bip39": "^3.1.0", diff --git a/src/commands/filesUpload.addon.ts b/src/commands/filesUpload.addon.ts index d2fc484..a700292 100644 --- a/src/commands/filesUpload.addon.ts +++ b/src/commands/filesUpload.addon.ts @@ -176,6 +176,17 @@ export default async (params: FilesUploadParams): Promise => { return; } + const outputPath = preparePath(params.outputPath); + + try { + await fs.stat(outputPath); + throw new Error('Output path already exists'); + } catch (err) { + if (err instanceof Error && 'code' in err && err.code !== 'ENOENT') { + throw err; + } + } + let metadata: Partial> = {}; if (params.metadataPath) { @@ -271,7 +282,6 @@ export default async (params: FilesUploadParams): Promise => { ...uploadResult, }; - const outputPath = preparePath(params.outputPath); await fs.writeFile(outputPath, JSON.stringify(result, null, 2)); Printer.print(`Resource file was created in ${outputPath}`); diff --git a/src/commands/offersCreate.ts b/src/commands/offersCreate.ts index 5864f2a..9c56b54 100644 --- a/src/commands/offersCreate.ts +++ b/src/commands/offersCreate.ts @@ -24,6 +24,7 @@ export type OffersCreateParams = { enableAutoDeposit: boolean; storageConfig: Config['storage']; configurationPath?: string; + enabled?: boolean; }; export default async (params: OffersCreateParams): Promise => { @@ -56,7 +57,7 @@ export default async (params: OffersCreateParams): Promise => { break; } case 'value': { - const offerInfo = await readValueOfferInfo({ + const { version, ...offerInfo } = await readValueOfferInfo({ path: params.offerInfoPath, isPartialContent: false, }); @@ -93,6 +94,8 @@ export default async (params: OffersCreateParams): Promise => { contractAddress: params.blockchainConfig.contractAddress, enableAutoDeposit: params.enableAutoDeposit, offerInfo, + versionInfo: version.info, + enabled: params.enabled ?? true, }); break; } diff --git a/src/commands/offersGetInfo.ts b/src/commands/offersGetInfo.ts index 304f611..66021a8 100644 --- a/src/commands/offersGetInfo.ts +++ b/src/commands/offersGetInfo.ts @@ -1,9 +1,10 @@ -import { OfferInfo, TeeOfferInfo } from '@super-protocol/sdk-js'; +import { OfferInfo, OfferVersion, TeeOfferInfo } from '@super-protocol/sdk-js'; import { promises as fs } from 'fs'; import path from 'path'; import Printer from '../printer'; +import fetchOffers, { OfferItem } from '../services/fetchOffers'; import fetchTeeOffers from '../services/fetchTeeOffers'; -import fetchOffers from '../services/fetchOffers'; +import { selectLastValueOfferVersion } from '../services/offerValueVersionHelper'; export type OffersGetInfoParams = { backendUrl: string; @@ -14,9 +15,9 @@ export type OffersGetInfoParams = { }; export default async (params: OffersGetInfoParams): Promise => { - let offer: OfferInfo | TeeOfferInfo | undefined; + let offer: (OfferInfo & { version?: OfferVersion }) | TeeOfferInfo | undefined; switch (params.type) { - case 'tee': + case 'tee': { offer = await fetchTeeOffers({ backendUrl: params.backendUrl, accessToken: params.accessToken, @@ -24,15 +25,28 @@ export default async (params: OffersGetInfoParams): Promise => { filter: { id: params.id }, }).then(({ list }) => list[0]?.teeOfferInfo); break; - case 'value': + } + case 'value': { + const convert = (offer?: OfferItem): (OfferInfo & { version?: OfferVersion }) | undefined => { + if (!offer) { + return; + } + + const version = selectLastValueOfferVersion(offer.versions as OfferVersion[]); + + return { + ...(offer.offerInfo as OfferInfo), + ...(version && { version: version as OfferVersion }), + }; + }; offer = await fetchOffers({ backendUrl: params.backendUrl, accessToken: params.accessToken, limit: 1, id: params.id, - }).then(({ list }) => list[0]?.offerInfo); + }).then(({ list }) => convert(list[0])); break; - + } default: throw new Error(`Unknown offer type ${params.type} provided`); } diff --git a/src/commands/offersUpdateSlot.ts b/src/commands/offersUpdateSlot.ts index 9f0acb1..817e85c 100644 --- a/src/commands/offersUpdateSlot.ts +++ b/src/commands/offersUpdateSlot.ts @@ -44,6 +44,7 @@ export default async (params: OffersAddSlotParams) => { valueOfferSlot.info, valueOfferSlot.option, valueOfferSlot.usage, + valueOfferSlot.metadata, ); break; } diff --git a/src/commands/ordersCreate.ts b/src/commands/ordersCreate.ts index 5190b4a..604d2f7 100644 --- a/src/commands/ordersCreate.ts +++ b/src/commands/ordersCreate.ts @@ -18,7 +18,7 @@ import { Encryption, EncryptionKey } from '@super-protocol/dto-js'; import Printer from '../printer'; import { checkFetchedOffers, - FethchedOffer, + FetchedOffer, getFetchedOffers, getHoldDeposit, } from '../services/workflowHelpers'; @@ -68,8 +68,8 @@ const getCheckedOfferById = async (params: { offerId: OrderCreateParams['offerId']; slotId: string; options?: Partial; -}): Promise => { - const offers: FethchedOffer[] = await getFetchedOffers({ +}): Promise => { + const offers: FetchedOffer[] = await getFetchedOffers({ backendUrl: params.backendUrl, accessToken: params.accessToken, limit: 1, @@ -80,7 +80,7 @@ const getCheckedOfferById = async (params: { throw Error(`Offer ${params.offerId} does not exist`); } - const offer: FethchedOffer = offers[0]; + const offer: FetchedOffer = offers[0]; if (offer.offerInfo.offerType === OfferType.TeeOffer) { throw Error(`Unsupported offer type: ${getObjectKey(offer.offerInfo.offerType, OfferType)}`); } @@ -98,7 +98,7 @@ const getCheckedOfferById = async (params: { checkFetchedOffers( [{ id: params.offerId, slotId: params.slotId }], - new Map(offers.map((o) => [o.id, o])), + new Map(offers.map((o) => [o.id, o])), offer.offerInfo.offerType as OfferType, ); @@ -241,7 +241,7 @@ export default async (params: OrderCreateParams): Promise => slotId = result[0].slotId; } - const offer: FethchedOffer = await getCheckedOfferById({ + const offer: FetchedOffer = await getCheckedOfferById({ ...params, slotId, }); diff --git a/src/commands/secrets/storage/command-builders.ts b/src/commands/secrets/storage/command-builders.ts index ed5d1e3..5acb43d 100644 --- a/src/commands/secrets/storage/command-builders.ts +++ b/src/commands/secrets/storage/command-builders.ts @@ -19,7 +19,7 @@ export const buildRegisterStorageCommand = ( STORAGE_COMMAND, REGISTER_COMMAND, offerId, - options.version ? `--version ${options.version}` : '', + options.offerVersion ? `--version ${options.offerVersion}` : '', `--storage-offer ${options.storageOffer}`, `--storage-slot ${options.storageSlot}`, `--min-rent ${options.minRent}`, @@ -40,7 +40,7 @@ export const buildUpdateStorageCommand = ( STORAGE_COMMAND, UPDATE_COMMAND, offerId, - options.version ? `--version ${options.version}` : '', + options.offerVersion ? `--version ${options.offerVersion}` : '', `--storage-offer ${options.storageOffer}`, `--storage-slot ${options.storageSlot}`, `--min-rent ${options.minRent}`, @@ -53,7 +53,7 @@ export const buildUpdateStorageCommand = ( export const buildStatusCommand = ( offerId: string, - options: { version?: number; config: string }, + options: { offerVersion: number; config: string }, ): string => { return [ SPCTL_COMMAND, @@ -61,7 +61,7 @@ export const buildStatusCommand = ( STORAGE_COMMAND, STATUS_COMMAND, offerId, - options.version ? `--version ${options.version}` : '', + `--offer-version ${options.offerVersion}`, options.config ? `--config ${options.config}` : '', ] .filter(Boolean) diff --git a/src/commands/secrets/storage/register/action.ts b/src/commands/secrets/storage/register/action.ts index f5782a8..b760968 100644 --- a/src/commands/secrets/storage/register/action.ts +++ b/src/commands/secrets/storage/register/action.ts @@ -4,10 +4,10 @@ import Printer from '../../../../printer'; import initBlockchainConnector from '../../../../services/initBlockchainConnector'; import { buildStatusCommand, buildUpdateStorageCommand } from '../command-builders'; import { checkParamsToRegisterStorage, registerStorage, RegisterStorageParams } from '../service'; -import { findAllocatedOrderId, findRequestOrderId } from '../../utils'; +import { findAllocatedOrderId, findLastOfferVersion, findRequestOrderId } from '../../utils'; export type RegisterActionOptions = { - version?: number; + offerVersion?: number; storageOffer: string; storageSlot: string; minRent: number; @@ -37,13 +37,16 @@ export const registerAction = async ( await checkParamsToRegisterStorage({ offerId, + offerVersion: options.offerVersion, storageOfferId: options.storageOffer, storageSlotId: options.storageSlot, }); const params: RegisterStorageParams = { offerId, - offerVersion: options.version, + offerVersion: options.offerVersion + ? options.offerVersion + : await findLastOfferVersion({ offerId }), copyPreviousData: false, // (!) replicationFactor: options.replicationFactor, storageOfferId: options.storageOffer, @@ -71,7 +74,10 @@ export const registerAction = async ( if (id) { Printer.print(`Storage is registered (orderId=${id})`); } else { - const statusCommand = buildStatusCommand(offerId, options); + const statusCommand = buildStatusCommand(offerId, { + offerVersion: params.offerVersion, + config: options.config, + }); const msg = [ `The resource has not yet met the replication target.`, `Please check back later using the command:\n\n ${statusCommand}`, @@ -85,7 +91,7 @@ export const registerAction = async ( }; export const findStorageOrderId = async ( - params: Pick, + params: Pick, 'offerId' | 'offerVersion'>, ): Promise => { const allocatedOrderId = await findAllocatedOrderId(params); if (allocatedOrderId) { diff --git a/src/commands/secrets/storage/register/command.ts b/src/commands/secrets/storage/register/command.ts index d953ebc..4f20de8 100644 --- a/src/commands/secrets/storage/register/command.ts +++ b/src/commands/secrets/storage/register/command.ts @@ -5,7 +5,7 @@ import { registerAction } from './action'; export const registerCommand = new Command(REGISTER_COMMAND) .description('Register secrets storage') .argument('offer-id', 'Solution offer id') - .option('--version ', 'Solution offer version') + .option('--offer-version ', 'Solution offer version') .requiredOption('--storage-offer ', 'Storage offer id') .requiredOption('--storage-slot ', 'Storage slot id') .requiredOption('--min-rent ', 'Min rent time in hours') diff --git a/src/commands/secrets/storage/service.ts b/src/commands/secrets/storage/service.ts index 61b8d66..dcac848 100644 --- a/src/commands/secrets/storage/service.ts +++ b/src/commands/secrets/storage/service.ts @@ -20,7 +20,7 @@ import Printer from '../../../printer'; export type RegisterStorageParams = CalculateStorageOrderDepositParams & { offerId: BlockchainId; - offerVersion?: number; + offerVersion: number; copyPreviousData: boolean; retryCount: number; retryInterval: number; @@ -29,6 +29,7 @@ export type RegisterStorageParams = CalculateStorageOrderDepositParams & { export const checkParamsToRegisterStorage = async (params: { offerId: string; + offerVersion?: number; storageOfferId: string; storageSlotId: string; }): Promise => { @@ -37,6 +38,18 @@ export const checkParamsToRegisterStorage = async (params: { throw Error(`Invalid solution offer id ${params.offerId}`); } + if (params.offerVersion === undefined) { + const versionCount = await new Offer(params.offerId).getVersionCount(); + if (versionCount === 0) { + throw Error(`Offer ${params.offerId} has no versions`); + } + } else if (params.offerVersion < 0) { + throw Error(`Offer version number must be greater than or equal to 0`); + } else { + // checks if version exists + await new Offer(params.offerId).getVersion(params.offerVersion); + } + const offerStorage = new Offer(params.storageOfferId); const offerStorageType = await offerStorage.getOfferType(); if (offerStorageType !== OfferType.Storage) { @@ -56,7 +69,7 @@ export const registerStorage = async ( const { offerId, offerVersion, retryCount, retryInterval } = params; const { replicationFactor } = await setOfferStorageRequest({ ...params, - offerVersion: 0, + offerVersion, }); const orderId = await doWithRetries( @@ -121,10 +134,7 @@ const setOfferStorageRequest = async (params: { teeOfferIssuerId, storageOfferId, storageSlotId, - replicationFactor: calculateReplicationFactor({ - activeTeeOfferIds, - replicationFactor, - }), + replicationFactor, deposit: await calculateStorageOrderDeposit(params), copyPreviousData, }); diff --git a/src/commands/secrets/storage/status/action.ts b/src/commands/secrets/storage/status/action.ts index 92d556c..7fd8da1 100644 --- a/src/commands/secrets/storage/status/action.ts +++ b/src/commands/secrets/storage/status/action.ts @@ -2,9 +2,10 @@ import Printer from '../../../../printer'; import { getStorageRegistrationStatus, StorageRegistrationStatus } from './service'; import initBlockchainConnector from '../../../../services/initBlockchainConnector'; import ConfigLoader from '../../../../config'; +import { findLastOfferVersion } from '../../utils'; export type StatusActionOptions = { - version?: number; + offerVersion?: number; config: string; }; @@ -24,7 +25,9 @@ export const statusAction = async ( const registrationStatus = await getStorageRegistrationStatus({ offerId, - offerVersion: options.version, + offerVersion: options.offerVersion + ? options.offerVersion + : await findLastOfferVersion({ offerId }), }); displayStatus(registrationStatus); diff --git a/src/commands/secrets/storage/status/command.ts b/src/commands/secrets/storage/status/command.ts index 8fe6e1c..22723bc 100644 --- a/src/commands/secrets/storage/status/command.ts +++ b/src/commands/secrets/storage/status/command.ts @@ -5,5 +5,5 @@ import { statusAction } from './action'; export const statusCommand = new Command(STATUS_COMMAND) .description('Show storage registration status') .argument('offer-id', 'Solution offer id') - .option('--version ', 'Solution offer version') + .option('--offer-version ', 'Solution offer version') .action(statusAction); diff --git a/src/commands/secrets/storage/status/service.ts b/src/commands/secrets/storage/status/service.ts index f35323e..c2bc757 100644 --- a/src/commands/secrets/storage/status/service.ts +++ b/src/commands/secrets/storage/status/service.ts @@ -12,7 +12,7 @@ import { getObjectKey } from '../../../../utils'; type GetStorageRegistrationStatusParams = { offerId: BlockchainId; - offerVersion?: number; + offerVersion: number; }; export type StorageRegistrationStatus = { diff --git a/src/commands/secrets/storage/update/action.ts b/src/commands/secrets/storage/update/action.ts index fa1aca0..77db409 100644 --- a/src/commands/secrets/storage/update/action.ts +++ b/src/commands/secrets/storage/update/action.ts @@ -4,7 +4,7 @@ import initBlockchainConnector from '../../../../services/initBlockchainConnecto import ConfigLoader from '../../../../config'; import { RegisterActionOptions } from '../register/action'; import { buildRegisterStorageCommand, buildStatusCommand } from '../command-builders'; -import { findAllocatedOrderId } from '../../utils'; +import { findAllocatedOrderId, findLastOfferVersion } from '../../utils'; export type UpdateActionOptions = RegisterActionOptions; @@ -34,7 +34,9 @@ export const updateAction = async ( const params: RegisterStorageParams = { offerId, - offerVersion: options.version, + offerVersion: options.offerVersion + ? options.offerVersion + : await findLastOfferVersion({ offerId }), copyPreviousData: true, // (!) replicationFactor: options.replicationFactor, storageOfferId: options.storageOffer, @@ -62,7 +64,10 @@ export const updateAction = async ( if (id) { Printer.print(`Storage is updated (orderId=${id})`); } else { - const statusCommand = buildStatusCommand(offerId, options); + const statusCommand = buildStatusCommand(offerId, { + offerVersion: params.offerVersion, + config: options.config, + }); const msg = [ `The resource has not yet met the replication target.`, ` Please check back later using the command:\n\n ${statusCommand}`, diff --git a/src/commands/secrets/utils.ts b/src/commands/secrets/utils.ts index 5fac911..3f17400 100644 --- a/src/commands/secrets/utils.ts +++ b/src/commands/secrets/utils.ts @@ -5,10 +5,11 @@ import { } from '@super-protocol/distributed-secrets'; import { BlockchainId, - LoaderSecretPublicKey, - LoaderSecretsPublicKeys, + LoaderSecretAccessPublicKey, + LoaderSecretsAccessPublicKeys, LoaderSession, LoaderSessions, + Offer, OfferResources, OffersStorageAllocated, OffersStorageRequests, @@ -18,7 +19,7 @@ import { export const validateKeys = async ( keys: { session?: LoaderSession; - secret?: LoaderSecretPublicKey; + secret?: LoaderSecretAccessPublicKey; }, pccsServiceApiUrl: string, ): Promise => { @@ -45,7 +46,7 @@ export const getMostRecentlyActiveTeeOfferIds = (params: { async verifyOffer(offerId) { const [session, secret] = await Promise.all([ LoaderSessions.get(offerId), - LoaderSecretsPublicKeys.get(offerId), + LoaderSecretsAccessPublicKeys.get(offerId), ]); return validateKeys({ session, secret }, pccsServiceApiUrl); @@ -57,7 +58,7 @@ const parseOrderId = (orderId: string | undefined): string | undefined => orderId === '0' ? undefined : orderId; export const findAllocatedOrderId = async ( - params: Pick, + params: Pick, 'offerId' | 'offerVersion'>, ): Promise => { const { offerId, offerVersion } = params; const allocated = await OffersStorageAllocated.getByOfferVersion(offerId, offerVersion); @@ -76,7 +77,7 @@ export const findAllocatedOrderId = async ( }; export const findRequestOrderId = async ( - params: Pick, + params: Pick, 'offerId' | 'offerVersion'>, ): Promise => { const { offerId, offerVersion } = params; const request = await OffersStorageRequests.getByOfferVersion(offerId, offerVersion); @@ -86,3 +87,15 @@ export const findRequestOrderId = async ( return; }; + +export const findLastOfferVersion = async ( + params: Pick, +): Promise => { + const { offerId } = params; + const lastVersionNumber = await new Offer(offerId).getLastVersionNumber(); + if (lastVersionNumber === null) { + throw Error(`Last version number for offer ${offerId} not found`); + } + + return lastVersionNumber; +}; diff --git a/src/commands/tokensBalance.ts b/src/commands/tokensBalance.ts index 15c21a6..5af96a4 100644 --- a/src/commands/tokensBalance.ts +++ b/src/commands/tokensBalance.ts @@ -1,5 +1,5 @@ import { Wallet } from 'ethers'; -import getMaticBalanceService from '../services/getMaticBalance'; +import getBnbBalanceService from '../services/getBnbBalance'; import getTeeBalanceService from '../services/getTeeBalance'; import Printer from '../printer'; import { Config as BlockchainConfig, getTokensInfo } from '@super-protocol/sdk-js'; @@ -26,7 +26,7 @@ export default async (params: TokensBalanceParams): Promise => { Printer.print(`Balance of ${address}: ${weiToEther(balance)} ${token.symbol}`); } - Printer.print('\nFetching POL tokens balance'); - const balanceMatic = await getMaticBalanceService({ address }); - Printer.print(`Balance of ${address}: ${weiToEther(balanceMatic)} POL`); + Printer.print('\nFetching BNB tokens balance'); + const balanceBnb = await getBnbBalanceService({ address }); + Printer.print(`Balance of ${address}: ${weiToEther(balanceBnb)} BNB`); }; diff --git a/src/commands/tokensRequest.ts b/src/commands/tokensRequest.ts index 8e5a305..04b1c0d 100644 --- a/src/commands/tokensRequest.ts +++ b/src/commands/tokensRequest.ts @@ -1,8 +1,8 @@ import { Wallet } from 'ethers'; import requestTeeService from '../services/requestTee'; -import requestCustomMaticService from '../services/requestCustomMatic'; +import requestCustomBnbService from '../services/requestCustomBnb'; import requestCustomTeeService from '../services/requestCustomTee'; -import requestMaticService from '../services/requestMatic'; +import requestBnbService from '../services/requestBnb'; import Printer from '../printer'; import { program } from 'commander'; @@ -10,15 +10,15 @@ export type TokensRequestParams = { actionAccountPrivateKey: string; backendUrl: string; accessToken: string; - requestMatic?: boolean; + requestBnb?: boolean; requestTee?: boolean; customAccountPrivateKey?: string; }; export default async (params: TokensRequestParams): Promise => { - if (!params.requestTee && !params.requestMatic) { + if (!params.requestTee && !params.requestBnb) { Printer.print( - 'No token type was specified, please add --tee or --matic flag to request specific tokens', + 'No token type was specified, please add --tee or --bnb flag to request specific tokens', ); program.help(); } @@ -41,13 +41,13 @@ export default async (params: TokensRequestParams): Promise => { Printer.print(`TEE tokens will be transferred to ${address} shortly`); } - if (params.requestMatic) { - Printer.print(`Requesting Polygon MATIC tokens for ${address}`); + if (params.requestBnb) { + Printer.print(`Requesting opBNB tokens for ${address}`); if (params.customAccountPrivateKey) { - await requestCustomMaticService(requestParams); + await requestCustomBnbService(requestParams); } else { - await requestMaticService(requestParams); + await requestBnbService(requestParams); } - Printer.print(`MATIC tokens will be transferred to ${address} shortly`); + Printer.print(`BNB tokens will be transferred to ${address} shortly`); } }; diff --git a/src/commands/workflowsCreate.ts b/src/commands/workflowsCreate.ts index 765d8a3..7f70718 100644 --- a/src/commands/workflowsCreate.ts +++ b/src/commands/workflowsCreate.ts @@ -40,7 +40,7 @@ import { checkFetchedOffers, checkSlot, divideImagesAndSolutions, - FethchedOffer, + FetchedOffer, getFetchedOffers, getHoldDeposit, } from '../services/workflowHelpers'; @@ -165,7 +165,7 @@ const workflowCreate = async (params: WorkflowCreateCommandParams): Promise(fetchedValueOffers.map((o) => [o.id, o])); + const offersMap = new Map(fetchedValueOffers.map((o) => [o.id, o])); checkFetchedOffers([storage], offersMap, OfferType.Storage); checkFetchedOffers(solutions.offers, offersMap, OfferType.Solution); @@ -480,8 +480,8 @@ const workflowCreate = async (params: WorkflowCreateCommandParams): Promise; stats?: Maybe; + versions?: Maybe>; }; export type OfferConfiguration = { @@ -8479,6 +8480,8 @@ export type OfferFilter = { providerActionAccounts?: InputMaybe>; /** filter by offerInfo -> restrictions -> offers */ restrictions?: InputMaybe>; + /** Search by id or name */ + search?: InputMaybe; /** get only compatible with selected offers */ selectedOfferIds?: InputMaybe>; /** filter by offerInfo -> subType */ @@ -8501,10 +8504,7 @@ export type OfferInfo = { * */ group: Scalars['String']; - hardwareContext?: Maybe; - hash: Scalars['String']; input: Scalars['String']; - metadata: Scalars['String']; name: Scalars['String']; /** * The supported offers type. @@ -8522,7 +8522,6 @@ export type OfferInfo = { output: Scalars['String']; restrictions?: Maybe; resultResource: Scalars['String']; - signatureKeyHash?: Maybe; subType: Scalars['String']; }; @@ -8541,10 +8540,7 @@ export type OfferInfoInput = { * */ group: Scalars['String']; - hardwareContext?: InputMaybe; - hash: Scalars['String']; input: Scalars['String']; - metadata: Scalars['String']; name: Scalars['String']; /** * The supported offers type. @@ -8562,7 +8558,6 @@ export type OfferInfoInput = { output: Scalars['String']; restrictions?: InputMaybe; resultResource: Scalars['String']; - signatureKeyHash?: InputMaybe; subType: Scalars['String']; }; @@ -8575,6 +8570,7 @@ export type OfferInputType = { providerInfo: ProviderInformationInput; slots: Array; stats?: InputMaybe; + versions?: InputMaybe>; }; export type OfferPageInfo = { @@ -8654,6 +8650,48 @@ export enum OfferType { TeeOffer = 'TeeOffer' } +export type OfferVersion = { + __typename?: 'OfferVersion'; + info: OfferVersionInfo; + /** + * The supported version status. + * + * New = '0', + * + * Deleted = '1' + * + */ + status: Scalars['String']; + version: Scalars['Float']; +}; + +export type OfferVersionInfo = { + __typename?: 'OfferVersionInfo'; + hash?: Maybe; + metadata?: Maybe; + signatureKeyHash?: Maybe; +}; + +export type OfferVersionInfoInput = { + hash?: InputMaybe; + metadata?: InputMaybe; + signatureKeyHash?: InputMaybe; +}; + +export type OfferVersionInput = { + info: OfferVersionInfoInput; + /** + * The supported version status. + * + * New = '0', + * + * Deleted = '1' + * + */ + status: Scalars['String']; + version: Scalars['Float']; +}; + export type OptionInfo = { __typename?: 'OptionInfo'; bandwidth: Scalars['Float']; @@ -9150,6 +9188,8 @@ export type ProviderEdge = { }; export type ProviderFilter = { + /** filter by id */ + _id?: InputMaybe; /** filter by address */ address?: InputMaybe; }; @@ -9225,6 +9265,8 @@ export type Query = { getMinimalConfiguration: OfferConfiguration; /** Get all pipeline types used in the system */ getUsedPipelineTypes: Array; + /** Get all pipelines types used by concrete engines */ + getUsedPipelineTypesByEngines: Array; listErc20: ListErc20Response; offer: Offer; offerType: OfferType; @@ -9305,6 +9347,12 @@ export type QueryGetUsedPipelineTypesArgs = { }; +export type QueryGetUsedPipelineTypesByEnginesArgs = { + filter?: InputMaybe; + pipelineTypeSource: ValueOfferSubtype; +}; + + export type QueryListErc20Args = { filter?: InputMaybe; pagination: ConnectionArgs; @@ -9357,7 +9405,7 @@ export type QueryOrdersStatusesStatisticArgs = { export type QueryProviderArgs = { - _id: Scalars['String']; + filter: ProviderFilter; }; @@ -9710,6 +9758,8 @@ export type TeeOfferFilter = { providerActionAccounts?: InputMaybe>; /** filter by teeOfferInfo.hardwareInfo.slotInfo → ram */ ram?: InputMaybe>; + /** Search by id or name */ + search?: InputMaybe; /** filter by teeOfferInfo -> subType */ subType?: InputMaybe; /** filter by teeOfferInfo.hardwareInfo.optionInfo → traffic */ @@ -9882,7 +9932,6 @@ export type ValueObject = { staking?: Maybe; superpro?: Maybe; teeOfferSecDeposit?: Maybe; - teeRewardPerEpoch?: Maybe; token?: Maybe; tokenReceiverAddress?: Maybe; }; @@ -9895,7 +9944,6 @@ export type ValueObjectType = { staking?: InputMaybe; superpro?: InputMaybe; teeOfferSecDeposit?: InputMaybe; - teeRewardPerEpoch?: InputMaybe; token?: InputMaybe; tokenReceiverAddress?: InputMaybe; }; @@ -9988,7 +10036,7 @@ export type OffersQueryVariables = Exact<{ }>; -export type OffersQuery = { __typename?: 'Query', result: { __typename?: 'ListOffersResponse', pageData?: { __typename?: 'PageDataDto', count: number, limit: number, offset: number } | null, page: { __typename?: 'OfferConnection', pageInfo?: { __typename?: 'OfferPageInfo', endCursor?: string | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null } | null, edges?: Array<{ __typename?: 'OfferEdge', cursor?: string | null, node?: { __typename?: 'Offer', _id: string, id: string, authority?: string | null, configuration?: any | null, enabled: boolean, offerInfo: { __typename?: 'OfferInfo', name: string, group: string, offerType: string, cancelable: boolean, description: string, metadata: string, input: string, output: string, allowedArgs?: string | null, allowedAccounts: Array, argsPublicKey: string, resultResource: string, hash: string, signatureKeyHash?: any | null, hardwareContext?: any | null, subType: string, restrictions?: { __typename?: 'OfferRestrictions', offers?: Array | null, types?: Array | null, versions?: Array | null } | null }, slots: Array<{ __typename?: 'OfferSlot', id: string, info: { __typename?: 'SlotInfo', cpuCores: number, gpuCores: number, diskUsage: number, ram: number, vram: number }, usage: { __typename?: 'SlotUsage', maxTimeMinutes: number, minTimeMinutes: number, price: string, priceType: PriceType }, option: { __typename?: 'OptionInfo', bandwidth: number, externalPort: number, traffic: number } }>, origins?: { __typename?: 'Origins', createdBy: string, createdDate: number, modifiedBy: string, modifiedDate: number } | null, providerInfo: { __typename?: 'ProviderInformation', actionAccount: string, description: string, metadata: string, name: string, tokenReceiver: string } } | null }> | null } } }; +export type OffersQuery = { __typename?: 'Query', result: { __typename?: 'ListOffersResponse', pageData?: { __typename?: 'PageDataDto', count: number, limit: number, offset: number } | null, page: { __typename?: 'OfferConnection', pageInfo?: { __typename?: 'OfferPageInfo', endCursor?: string | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null } | null, edges?: Array<{ __typename?: 'OfferEdge', cursor?: string | null, node?: { __typename?: 'Offer', _id: string, id: string, authority?: string | null, configuration?: any | null, enabled: boolean, offerInfo: { __typename?: 'OfferInfo', name: string, group: string, offerType: string, cancelable: boolean, description: string, input: string, output: string, allowedArgs?: string | null, allowedAccounts: Array, argsPublicKey: string, resultResource: string, subType: string, restrictions?: { __typename?: 'OfferRestrictions', offers?: Array | null, types?: Array | null, versions?: Array | null } | null }, slots: Array<{ __typename?: 'OfferSlot', id: string, info: { __typename?: 'SlotInfo', cpuCores: number, gpuCores: number, diskUsage: number, ram: number, vram: number }, usage: { __typename?: 'SlotUsage', maxTimeMinutes: number, minTimeMinutes: number, price: string, priceType: PriceType }, option: { __typename?: 'OptionInfo', bandwidth: number, externalPort: number, traffic: number } }>, origins?: { __typename?: 'Origins', createdBy: string, createdDate: number, modifiedBy: string, modifiedDate: number } | null, providerInfo: { __typename?: 'ProviderInformation', actionAccount: string, description: string, metadata: string, name: string, tokenReceiver: string }, versions?: Array<{ __typename?: 'OfferVersion', version: number, status: string, info: { __typename?: 'OfferVersionInfo', hash?: any | null, metadata?: any | null, signatureKeyHash?: any | null } }> | null } | null }> | null } } }; export type OffersSelectQueryVariables = Exact<{ pagination: ConnectionArgs; @@ -10175,16 +10223,12 @@ export const OffersDocument = gql` types versions } - metadata input output allowedArgs allowedAccounts argsPublicKey resultResource - hash - signatureKeyHash - hardwareContext subType } enabled @@ -10222,6 +10266,15 @@ export const OffersDocument = gql` name tokenReceiver } + versions { + version + status + info { + hash + metadata + signatureKeyHash + } + } } cursor } diff --git a/src/gql/schemas/offers.graphql b/src/gql/schemas/offers.graphql index 293ebd2..1fe690a 100644 --- a/src/gql/schemas/offers.graphql +++ b/src/gql/schemas/offers.graphql @@ -27,16 +27,12 @@ query Offers($pagination: ConnectionArgs!, $filter: OfferFilter) { types versions } - metadata input output allowedArgs allowedAccounts argsPublicKey resultResource - hash - signatureKeyHash - hardwareContext subType } enabled @@ -74,6 +70,15 @@ query Offers($pagination: ConnectionArgs!, $filter: OfferFilter) { name tokenReceiver } + versions { + version + status + info { + hash + metadata + signatureKeyHash + } + } } cursor } diff --git a/src/index.ts b/src/index.ts index da38fdc..f882389 100644 --- a/src/index.ts +++ b/src/index.ts @@ -749,7 +749,7 @@ async function main(): Promise { tokensCommand .command('request') .description('Request tokens for the account') - .option('--matic', 'Request Polygon MATIC tokens', false) + .option('--bnb', 'Request opBNB tokens', false) .option('--tee', 'Request Super Protocol TEE tokens', false) .option('--debug', 'Display debug information', false) .addOption( @@ -766,7 +766,7 @@ async function main(): Promise { backendUrl: backend.url, accessToken: backend.accessToken, actionAccountPrivateKey: blockchain.accountPrivateKey, - requestMatic: options.matic, + requestBnb: options.bnb, requestTee: options.tee, customAccountPrivateKey: options.customKey, }; @@ -778,7 +778,7 @@ async function main(): Promise { eventName: AnalyticEvent.TEE_TOKENS_REPLENISHED, }); } - if (options.matic) { + if (options.bnb) { await analytics?.trackSuccessEventCatched({ eventName: AnalyticEvent.MATIC_TOKENS_REPLENISHED, }); @@ -792,7 +792,7 @@ async function main(): Promise { err, ); } - if (options.matic) { + if (options.bnb) { await analytics?.trackErrorEventCatched( { eventName: AnalyticEvent.MATIC_TOKENS_REPLENISHED, diff --git a/src/services/addValueOfferVersion.ts b/src/services/addValueOfferVersion.ts new file mode 100644 index 0000000..0de703f --- /dev/null +++ b/src/services/addValueOfferVersion.ts @@ -0,0 +1,52 @@ +import { + BlockchainConnector, + BlockchainId, + NotFoundError, + Offer, + OfferVersion, + OfferVersionInfo, +} from '@super-protocol/sdk-js'; +import Printer from '../printer'; + +export type AddOfferVersionParams = { + action: string; + offerId: BlockchainId; + version?: number; + versionInfo: OfferVersionInfo; +}; + +export default async (params: AddOfferVersionParams): Promise => { + const actionAddress = await BlockchainConnector.getInstance().initializeActionAccount( + params.action, + ); + if (params.version !== undefined && params.version < 0) { + throw new Error('Offer version number must be greater than or equal to 0'); + } + + Printer.print('Adding new value offer version'); + const offer = new Offer(params.offerId); + const versionCount = await offer.getVersionCount(); + if (versionCount) { + if (params.version !== undefined) { + let version: OfferVersion | null = null; + try { + version = await offer.getVersion(params.version); + } catch (err) { + if (!(err instanceof NotFoundError)) { + throw err; + } + } + if (version) { + throw new Error(`Version number ${params.version} is already exists`); + } + } + } + const newVersionNumber = params.version ?? versionCount + 1; + + await offer.setNewVersion(newVersionNumber, params.versionInfo, { + from: actionAddress, + }); + Printer.print(`Value offer version has been created (version=${newVersionNumber})`); + + return newVersionNumber; +}; diff --git a/src/services/calcWorkflowDeposit.ts b/src/services/calcWorkflowDeposit.ts index 9f4eea5..9540b6e 100644 --- a/src/services/calcWorkflowDeposit.ts +++ b/src/services/calcWorkflowDeposit.ts @@ -7,7 +7,7 @@ import { } from '@super-protocol/sdk-js'; import { BigNumber } from 'ethers'; import { TeeOfferParams, ValueOfferParams } from './createWorkflow'; -import { FethchedOffer } from './workflowHelpers'; +import { FetchedOffer } from './workflowHelpers'; import { TeeOfferItem } from './fetchTeeOffers'; import { PriceType, SlotUsage } from '../gql'; import { MINUTES_IN_HOUR } from '../constants'; @@ -18,7 +18,7 @@ export type CalcWorkflowDepositParams = { solutions: ValueOfferParams[]; data: ValueOfferParams[]; teeOffer: TeeOfferItem; - valueOffers: Map; + valueOffers: Map; minRentMinutes: number; }; diff --git a/src/services/createValueOffer.ts b/src/services/createValueOffer.ts index 25c8fa7..405467b 100644 --- a/src/services/createValueOffer.ts +++ b/src/services/createValueOffer.ts @@ -1,15 +1,25 @@ -import { BlockchainConnector, BlockchainId, OfferInfo, Offers } from '@super-protocol/sdk-js'; +import { + BlockchainConnector, + BlockchainId, + Offer, + OfferInfo, + Offers, + OfferVersionInfo, +} from '@super-protocol/sdk-js'; import Printer from '../printer'; import doWithRetries from './doWithRetries'; import checkBalanceToCreateOffer from './checkBalanceToCreateOffer'; import { generateExternalId } from '../utils'; +import addValueOfferVersion from './addValueOfferVersion'; export type CreateOfferParams = { authority: string; action: string; offerInfo: OfferInfo; + versionInfo: OfferVersionInfo; contractAddress: string; enableAutoDeposit: boolean; + enabled: boolean; }; export default async (params: CreateOfferParams): Promise => { @@ -20,8 +30,6 @@ export default async (params: CreateOfferParams): Promise => { const authorityAddress = await BlockchainConnector.getInstance().initializeActionAccount( params.authority, ); - // TODO: make as option parameter with possibility to enable/disable by update command - const enable = true; await checkBalanceToCreateOffer({ contractAddress: params.contractAddress, @@ -34,8 +42,11 @@ export default async (params: CreateOfferParams): Promise => { Printer.print('Creating value offer'); const currentBlock = await BlockchainConnector.getInstance().getLastBlockInfo(); - await Offers.create(authorityAddress, params.offerInfo, externalId, enable, { - from: actionAddress, + await Offers.create({ + providerAuthorityAccount: authorityAddress, + offerInfo: params.offerInfo, + externalId, + transactionOptions: { from: actionAddress }, }); const offerLoaderFn = (): Promise => @@ -51,6 +62,20 @@ export default async (params: CreateOfferParams): Promise => { }); const offerId = await doWithRetries(offerLoaderFn, 10, 5000); + await addValueOfferVersion({ + action: params.action, + offerId, + versionInfo: params.versionInfo, + version: 1, + }); + + if (params.enabled) { + const offer = new Offer(offerId); + const isEnabled = await offer.isEnabled(); + if (!isEnabled) { + await new Offer(offerId).enable({ from: actionAddress }); + } + } return offerId; }; diff --git a/src/services/createWorkflow.ts b/src/services/createWorkflow.ts index c1d304c..3cb53f0 100644 --- a/src/services/createWorkflow.ts +++ b/src/services/createWorkflow.ts @@ -178,7 +178,6 @@ export default async (params: CreateWorkflowParams): Promise => { subOrdersSlots, params.holdDeposit, { - gas: BigInt(10_000_000), from: params.consumerAddress, }, ); diff --git a/src/services/getMaticBalance.ts b/src/services/getBnbBalance.ts similarity index 74% rename from src/services/getMaticBalance.ts rename to src/services/getBnbBalance.ts index 24a2538..b168fd2 100644 --- a/src/services/getMaticBalance.ts +++ b/src/services/getBnbBalance.ts @@ -5,9 +5,9 @@ export type GetMumbaiBalanceParams = { address: string; }; -const getMaticBalance = async (params: GetMumbaiBalanceParams) => { +const getBnbBalance = async (params: GetMumbaiBalanceParams) => { const weiString = await BlockchainConnector.getInstance().getBalance(params.address); return BigNumber.from(weiString); }; -export default getMaticBalance; +export default getBnbBalance; diff --git a/src/services/offerValueVersionHelper.ts b/src/services/offerValueVersionHelper.ts new file mode 100644 index 0000000..d11568a --- /dev/null +++ b/src/services/offerValueVersionHelper.ts @@ -0,0 +1,17 @@ +import { OfferVersion, OfferVersionStatus } from '@super-protocol/sdk-js'; + +export const selectLastValueOfferVersion = ( + versions?: OfferVersion[], +): OfferVersion | undefined => { + const version = versions + ?.filter((v) => v.status === OfferVersionStatus.New) + .reduce((max, current) => (current.version > max.version ? current : max), { + version: Number.MIN_SAFE_INTEGER, + info: {}, + status: OfferVersionStatus.New, + }); + + if (version?.version !== Number.MIN_SAFE_INTEGER) { + return version; + } +}; diff --git a/src/services/readValueOfferInfo.ts b/src/services/readValueOfferInfo.ts index 74bb2d9..ff6f682 100644 --- a/src/services/readValueOfferInfo.ts +++ b/src/services/readValueOfferInfo.ts @@ -1,5 +1,10 @@ /* eslint-disable prettier/prettier */ -import {OfferGroup, OfferInfo, OfferType, ValueOfferSubtype} from '@super-protocol/sdk-js'; +import { + OfferGroup, + OfferInfo, + OfferType, OfferVersion, + ValueOfferSubtype +} from '@super-protocol/sdk-js'; import z, { ZodError } from 'zod'; import readJsonFile from './readJsonFile'; import {EncryptionValidator, HashValidator, ResourceValidator} from './readResourceFile'; @@ -10,55 +15,61 @@ export type ReadValueOfferInfoFileParams = { isPartialContent?: boolean; }; -const OfferInfoRestrictionsValidator = z.object({ +const OfferInfoRestrictionsSchema = z.object({ offers: z.array(z.string()), versions: z.array(z.number()), types: z.array(z.nativeEnum(OfferType)), }); -const OfferInfoFileValidator = z.object({ +const OfferVersionInfoSchema = z.object({ + metadata: z.object({}).catchall(z.unknown()).optional(), + signatureKeyHash: HashValidator.optional(), + hash: HashValidator.optional(), +}); +const OfferVersionSchema = z.object({ + version: z.number(), + info: OfferVersionInfoSchema, +}); +const OfferInfoSchema = z.object({ name: z.string(), group: z.nativeEnum(OfferGroup), offerType: z.nativeEnum(OfferType), cancelable: z.boolean(), description: z.string(), - restrictions: OfferInfoRestrictionsValidator, - metadata: z.string(), + restrictions: OfferInfoRestrictionsSchema, input: z.string(), output: z.string(), allowedArgs: z.string(), allowedAccounts: z.array(z.string()), argsPublicKey: z.string(), resultResource: z.string(), - hash: z.string(), subType: z.nativeEnum(ValueOfferSubtype), - signatureKeyHash: HashValidator.nullable().optional(), - hardwareContext: z - .object({ - mrEnclave: HashValidator.optional(), - }) - .catchall(z.unknown()) - .nullable() - .optional(), + version: OfferVersionSchema.partial({ version: true }), }); -const OptionalOfferInfoFileValidator = OfferInfoFileValidator.extend({ - restrictions: OfferInfoRestrictionsValidator.partial(), -}).partial(); +const OfferInfoFileSchema = OfferInfoSchema; + +const OptionalOfferInfoFileValidator = OfferInfoSchema + .omit({ version: true }) + .extend({ restrictions: OfferInfoRestrictionsSchema.partial()}) + .partial(); + +type OfferInfoFileType = OfferInfo & { version: OfferVersion }; +type OptionalOfferInfoFileType = Partial; export async function readValueOfferInfo( params: ReadValueOfferInfoFileParams & { isPartialContent: false }, -): Promise; +): Promise; export async function readValueOfferInfo( params: ReadValueOfferInfoFileParams & { isPartialContent: true }, -): Promise>; +): Promise; export async function readValueOfferInfo({ path, isPartialContent = false, - }: ReadValueOfferInfoFileParams): Promise> { + }: ReadValueOfferInfoFileParams): Promise { const offerInfo = await readJsonFile({ path, - validator: isPartialContent ? OptionalOfferInfoFileValidator : OfferInfoFileValidator, + validator: isPartialContent ? OptionalOfferInfoFileValidator : OfferInfoFileSchema, }); if (offerInfo.argsPublicKey) { diff --git a/src/services/readValueOfferSlot.ts b/src/services/readValueOfferSlot.ts index 5d56f93..85041cd 100644 --- a/src/services/readValueOfferSlot.ts +++ b/src/services/readValueOfferSlot.ts @@ -12,6 +12,7 @@ const ValueOfferSlotFileValidator = z.object({ info: SlotInfoValidator, usage: SlotUsageValidator, option: OptionInfoValidator, + metadata: z.string().default(''), }); export default async (params: ReadFileParams): Promise => { diff --git a/src/services/requestMatic.ts b/src/services/requestBnb.ts similarity index 90% rename from src/services/requestMatic.ts rename to src/services/requestBnb.ts index fb636e9..97f199a 100644 --- a/src/services/requestMatic.ts +++ b/src/services/requestBnb.ts @@ -22,7 +22,7 @@ export default async (params: RequestTeeParams) => { ); } catch (error: any) { throw ErrorWithCustomMessage( - error?.response?.errors[0]?.message || 'MATIC tokens request error', + error?.response?.errors[0]?.message || 'BNB tokens request error', error, ); } diff --git a/src/services/requestCustomMatic.ts b/src/services/requestCustomBnb.ts similarity index 90% rename from src/services/requestCustomMatic.ts rename to src/services/requestCustomBnb.ts index 9438a6b..06031f7 100644 --- a/src/services/requestCustomMatic.ts +++ b/src/services/requestCustomBnb.ts @@ -22,7 +22,7 @@ export default async (params: RequestTeeParams): Promise => { ); } catch (error: any) { throw ErrorWithCustomMessage( - error?.response?.errors[0]?.message || 'MATIC tokens request error', + error?.response?.errors[0]?.message || 'BNB tokens request error', error, ); } diff --git a/src/services/workflowHelpers.ts b/src/services/workflowHelpers.ts index 7872a1d..37b21c9 100644 --- a/src/services/workflowHelpers.ts +++ b/src/services/workflowHelpers.ts @@ -1,5 +1,5 @@ import { ValueOfferParams } from './createWorkflow'; -import { OfferType } from '@super-protocol/sdk-js'; +import { OfferType, OfferVersion } from '@super-protocol/sdk-js'; import { ErrorWithCustomMessage, Token, @@ -13,18 +13,20 @@ import { BigNumber } from 'ethers'; import Printer from '../printer'; import { MINUTES_IN_HOUR } from '../constants'; import getTeeBalance from './getTeeBalance'; +import { selectLastValueOfferVersion } from './offerValueVersionHelper'; import { ParsedInputResource } from './parseInputResources'; import { SolutionResourceFileValidator } from './readResourceFile'; import { ZodError } from 'zod'; -export type FethchedOffer = { +export type FetchedOffer = { id: NonNullable['id']; offerInfo: NonNullable['offerInfo']; + version?: OfferVersion; slots: NonNullable['slots']; }; export function calculateValueOffersMinTimeMinutes( offersWithSlot: ValueOfferParams[], - allOffers: Map, + allOffers: Map, ): number { return offersWithSlot.reduce((greatestMinTimeMinutes: number, valueOffer: ValueOfferParams) => { const valueOfferSlot = allOffers @@ -65,7 +67,7 @@ export const checkSlot = ( export const checkFetchedOffers = ( ids: Array<{ id: string; slotId: string }>, - offers: Map, + offers: Map, type: OfferType, ): void => { ids.forEach(({ id, slotId }) => { @@ -96,15 +98,16 @@ export const getFetchedOffers = async (params: { accessToken: string; limit: number; ids: string[]; -}): Promise => { +}): Promise => { const result = await fetchOffers(params); - return result.list + return result.list .filter((item) => Boolean(item)) .map((item) => ({ offerInfo: item?.offerInfo || {}, slots: item?.slots || [], id: item?.id, + version: selectLastValueOfferVersion(item?.versions as OfferVersion[]), })); };