diff --git a/src/market/proposal/proposal-properties.ts b/src/market/proposal/proposal-properties.ts index 9503f9830..837c60686 100644 --- a/src/market/proposal/proposal-properties.ts +++ b/src/market/proposal/proposal-properties.ts @@ -20,10 +20,28 @@ export type GenericGolemProtocolPropertyType = Record; + +/** + * Properties defined by GAP-35 + * + * @link https://github.com/golemfactory/golem-architecture/blob/master/gaps/gap-35_gpu_pci_capability/gap-35_gpu_pci_capability.md + */ +export type Gap35GpuSupportProps = Partial<{ + "golem.!exp.gap-35.v1.inf.gpu.model": string; + "golem.!exp.gap-35.v1.inf.gpu.clocks.graphics.mhz": number; + "golem.!exp.gap-35.v1.inf.gpu.clocks.memory.mhz": number; + "golem.!exp.gap-35.v1.inf.gpu.clocks.sm.mhz": number; + "golem.!exp.gap-35.v1.inf.gpu.clocks.video.mhz": number; + "golem.!exp.gap-35.v1.inf.gpu.cuda.cores": number; + "golem.!exp.gap-35.v1.inf.gpu.cuda.enabled": boolean; + "golem.!exp.gap-35.v1.inf.gpu.cuda.version": string; + "golem.!exp.gap-35.v1.inf.gpu.memory.bandwidth.gib": number; + "golem.!exp.gap-35.v1.inf.gpu.memory.total.gib": number; +}>; /** * @link https://github.com/golemfactory/golem-architecture/tree/master/standards/0-commons */ @@ -98,6 +116,7 @@ export type ProposalProperties = StandardComputationPlatformProps & // Attach GAP specific property sets Gap3MidAgreementPaymentProps & + Gap35GpuSupportProps & /** * These are around byt not really specified in any standard * FIXME #yagna - Standardize? diff --git a/src/market/scan/index.ts b/src/market/scan/index.ts index a6e78b177..852270e48 100644 --- a/src/market/scan/index.ts +++ b/src/market/scan/index.ts @@ -1,3 +1,3 @@ export * from "./types"; export * from "./scan-director"; -export * from "./scanned-proposal"; +export * from "./scanned-offer"; diff --git a/src/market/scan/scanned-offer.test.ts b/src/market/scan/scanned-offer.test.ts new file mode 100644 index 000000000..946cfa9d8 --- /dev/null +++ b/src/market/scan/scanned-offer.test.ts @@ -0,0 +1,22 @@ +import { ScannedOffer } from "./scanned-offer"; + +describe("Scanned Offer", () => { + test("Returns payment platform address information", async () => { + const offer = new ScannedOffer({ + offerId: "example-id", + properties: { + "golem.com.payment.platform.erc20-polygon-glm.address": "0xPolygonAddress", + "golem.com.payment.platform.erc20-holesky-tglm.address": "0xHoleskyAddress", + "golem.com.payment.platform.nonsense": "0xNonsense", + "some.other.prop": "with-a-value", + }, + timestamp: new Date().toISOString(), + providerId: "provider-id", + constraints: "", + }); + + expect(offer.paymentPlatformAddresses["erc20-polygon-glm"]).toEqual("0xPolygonAddress"); + expect(offer.paymentPlatformAddresses["erc20-holesky-tglm"]).toEqual("0xHoleskyAddress"); + expect(Object.entries(offer.paymentPlatformAddresses).length).toEqual(2); + }); +}); diff --git a/src/market/scan/scanned-proposal.ts b/src/market/scan/scanned-offer.ts similarity index 57% rename from src/market/scan/scanned-proposal.ts rename to src/market/scan/scanned-offer.ts index c0797b28c..1f1a22726 100644 --- a/src/market/scan/scanned-proposal.ts +++ b/src/market/scan/scanned-offer.ts @@ -4,6 +4,11 @@ import type { MarketApi } from "ya-ts-client"; type ScannedOfferDTO = MarketApi.OfferDTO; +type PaymentPlatformAddressSet = { + /** The payment platform and address map */ + [paymentPlatform: string]: string | undefined; +}; + export class ScannedOffer { constructor(private readonly model: ScannedOfferDTO) {} @@ -51,34 +56,104 @@ export class ScannedOffer { name: this.properties["golem.node.id.name"] || "", }; } + get transferProtocol() { return this.properties["golem.activity.caps.transfer.protocol"]; } + get cpuBrand() { return this.properties["golem.inf.cpu.brand"]; } + + get cpuVendor() { + return this.properties["golem.inf.cpu.vendor"]; + } + get cpuCapabilities() { return this.properties["golem.inf.cpu.capabilities"]; } + get cpuCores() { return this.properties["golem.inf.cpu.cores"]; } + get cpuThreads() { return this.properties["golem.inf.cpu.threads"]; } + + get gpuBrand() { + return this.properties["golem.!exp.gap-35.v1.inf.gpu.model"]; + } + + /** @deprecated Use {@link memoryGib} instead */ get memory() { + return this.memoryGib; + } + + get memoryGib() { return this.properties["golem.inf.mem.gib"]; } + + /** @deprecated Use {@link storageGib} instead */ get storage() { + return this.storageGib; + } + + get storageGib() { return this.properties["golem.inf.storage.gib"]; } + get publicNet() { return this.properties["golem.node.net.is-public"]; } + get runtimeCapabilities() { return this.properties["golem.runtime.capabilities"]; } + get runtimeName() { return this.properties["golem.runtime.name"]; } + + /** + * Get the ID of the offer published by the Provider + * + * Note: + * - this ID will change after the provider refreshes the offer (usually after 1h) + * - this ID will remain unchanged for the same published offer between different scans + */ + get offerId() { + return this.model.offerId; + } + + /** + * The timestamp at which the offer was generated by the Provider + */ + get offerCreateAt() { + return this.model.timestamp; + } + + /** + * Lists down payment addresses on different payment platforms + * + * @example Example return value + * ```json + * { + * "erc20-polygon-glm": "0x8737beea5668595fda9d50e85cae9cad10b4c980", + * "erc20-holesky-tglm:" "0x8737beea5668595fda9d50e85cae9cad10b4c980", + * } + * ``` + */ + get paymentPlatformAddresses(): PaymentPlatformAddressSet { + const propRegex = /golem\.com\.payment\.platform\.([a-z0-9-]+)\.address/; + + const platformAddress = Object.entries(this.model.properties) + .map<[string, string]>(([key, address]) => { + const match = key.match(propRegex); + return [match ? match[1] : "", address]; + }) + .filter(([key]) => !!key); + + return Object.fromEntries(platformAddress); + } }