Skip to content

Commit 2118d21

Browse files
committed
Incorporate initializeCommand in startCompute.
1 parent eaee66c commit 2118d21

6 files changed

Lines changed: 69 additions & 116 deletions

File tree

README.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -287,14 +287,6 @@ npm run cli <command> [options] <arguments>
287287
`-d, --did <did>`
288288
`-f, --folder [destinationFolder]` (Default: `.`)
289289

290-
- **initializeCompute:**
291-
`-d, --datasets <datasetDids>`
292-
`-a, --algo <algoDid>`
293-
`-e, --env <computeEnvId>`
294-
`--validUntil <validUntil>`
295-
`-t, --token <paymentToken>`
296-
`--resources <resources>`
297-
298290
- **startCompute:**
299291
`-d, --datasets <datasetDids>`
300292
`-a, --algo <algoDid>`

src/cli.ts

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { Command } from 'commander';
22
import { Commands } from './commands.js';
33
import { ethers } from 'ethers';
44
import chalk from 'chalk';
5+
import { stdin as input, stdout as output } from 'node:process';
6+
import { createInterface } from 'readline/promises';
57

68
async function initializeSigner() {
79

@@ -174,38 +176,6 @@ export async function createCLI() {
174176
const commands = new Commands(signer, chainId);
175177
await commands.allowAlgo([null, dsDid, aDid, options.encrypt.toString()]);
176178
});
177-
// initializeCommand command
178-
program
179-
.command('initializeCompute')
180-
.description('Initialises provider fees and payment for a compute job')
181-
.argument('<datasetDids>', 'Dataset DIDs (comma-separated) OR (empty array for none)')
182-
.argument('<algoDid>', 'Algorithm DID')
183-
.argument('<computeEnvId>', 'Compute environment ID')
184-
.argument('<computeValidUntil>', 'Valid Until for fees availability')
185-
.argument('<paymentToken>', 'Payment token for compute')
186-
.argument('<resources>', 'Resources of compute environment stringified')
187-
.option('-d, --datasets <datasetDids>', 'Dataset DIDs (comma-separated) OR (empty array for none)')
188-
.option('-a, --algo <algoDid>', 'Algorithm DID')
189-
.option('-e, --env <computeEnvId>', 'Compute environment ID')
190-
.option('--validUntil <validUntil>', 'Compute fees valid until')
191-
.option('-t, --token <paymentToken>', 'Compute payment token')
192-
.option('--resources <resources>', 'Compute resources')
193-
.action(async (datasetDids, algoDid, computeEnvId, computeValidUntil, paymentToken, resources, options) => {
194-
const dsDids = options.datasets || datasetDids;
195-
const aDid = options.algo || algoDid;
196-
const envId = options.env || computeEnvId;
197-
const validUntil = options.validUntil || computeValidUntil;
198-
const token = options.token || paymentToken;
199-
const res = options.resources || resources;
200-
if (!dsDids || !aDid || !envId || !validUntil || !token || !res) {
201-
console.error(chalk.red('Missing required arguments'));
202-
// process.exit(1);
203-
return
204-
}
205-
const { signer, chainId } = await initializeSigner();
206-
const commands = new Commands(signer, chainId);
207-
await commands.initializeCompute([null, dsDids, aDid, envId, validUntil.toString(), token, JSON.stringify(res)]);
208-
});
209179

210180
// startCompute command
211181
program
@@ -222,31 +192,56 @@ export async function createCLI() {
222192
.option('-d, --datasets <datasetDids>', 'Dataset DIDs (comma-separated) OR (empty array for none)')
223193
.option('-a, --algo <algoDid>', 'Algorithm DID')
224194
.option('-e, --env <computeEnvId>', 'Compute environment ID')
225-
.option('--init <initializeResponse>', 'Initialize response')
226195
.option('--maxJobDuration <maxJobDuration>', 'Compute maxJobDuration')
227196
.option('-t, --token <paymentToken>', 'Compute payment token')
228197
.option('--resources <resources>', 'Compute resources')
229198
.option('--amountToDeposit [amountToDeposit]', 'Amount to deposit in escrow')
230-
.action(async (datasetDids, algoDid, computeEnvId, initializeResponse, maxJobDuration, paymentToken, resources, amountToDeposit, options) => {
199+
.option('-y, --yes', 'Accept payment from initialize compute')
200+
.action(async (datasetDids, algoDid, computeEnvId, maxJobDuration, paymentToken, resources, amountToDeposit, options) => {
231201
const dsDids = options.datasets || datasetDids;
232202
const aDid = options.algo || algoDid;
233203
const envId = options.env || computeEnvId;
234-
const initResp = options.init || initializeResponse;
235204
const jobDuration = options.maxJobDuration || maxJobDuration;
236205
const token = options.token || paymentToken;
237206
const res = options.resources || resources;
238207
const amount = options.amountToDeposit || amountToDeposit;
239-
if (!dsDids || !aDid ||!envId || !initResp || !jobDuration || !token || !res) {
208+
if (!dsDids || !aDid ||!envId || !jobDuration || !token || !res) {
240209
console.error(chalk.red('Missing required arguments'));
241210
// process.exit(1);
242211
return
243212
}
244213
const { signer, chainId } = await initializeSigner();
245-
const commands = new Commands(signer, chainId);
246-
const args = [null, dsDids, aDid, envId, JSON.stringify(initResp), jobDuration.toString(), token, JSON.stringify(res)]
247-
if (amount) args.push(amount.toString())
248-
await commands.computeStart(args);
249-
});
214+
const commands = new Commands(signer, chainId);
215+
216+
const initArgs = [null, dsDids, aDid, envId, jobDuration, token, res];
217+
const initResp = await commands.initializeCompute(initArgs);
218+
219+
if (!initResp) {
220+
console.error(chalk.red('Initialization failed. Aborting.'));
221+
return;
222+
}
223+
224+
console.log(chalk.yellow('\n--- Payment Details ---'));
225+
console.log(JSON.stringify(initResp, null, 2));
226+
227+
const proceed = options.yes;
228+
229+
if (!proceed) {
230+
const rl = createInterface({ input, output });
231+
const confirmation = await rl.question(`\nProceed with payment for starting compute job at price ${ethers.BigNumber.from(initResp.payment.amount)} in tokens from address ${initResp.payment.token}? (y/n): `);
232+
rl.close();
233+
if (confirmation.trim().toLowerCase() !== 'y') {
234+
console.log(chalk.red('Compute job canceled by user.'));
235+
return;
236+
}
237+
}
238+
239+
const computeArgs = [null, dsDids, aDid, envId, JSON.stringify(initResp), jobDuration, token, res];
240+
if (amount) computeArgs.push(amount.toString());
241+
242+
await commands.computeStart(computeArgs);
243+
console.log(chalk.green('Compute job started successfully.'));
244+
});
250245

251246
// startFreeCompute command
252247
program

src/commands.ts

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,8 @@ export class Commands {
464464
);
465465
return;
466466
}
467-
468467
console.log(`initialize compute details: ${JSON.stringify(providerInitializeComputeJob)}`)
468+
return providerInitializeComputeJob;
469469

470470
}
471471

@@ -717,31 +717,6 @@ export class Commands {
717717
);
718718
return;
719719
}
720-
const safePaymentDetails =
721-
await ProviderInstance.initializeCompute(
722-
assets,
723-
algo,
724-
computeEnv.id,
725-
paymentToken,
726-
supportedMaxJobDuration,
727-
providerURI,
728-
this.signer, // V1 was this.signer.getAddress()
729-
JSON.parse(resources)
730-
);
731-
732-
const paymentAmount = ethers.BigNumber.from(parsedProviderInitializeComputeJob.payment.amount.toString());
733-
const expectedAmount = ethers.BigNumber.from(safePaymentDetails.payment.amount.toString());
734-
if (paymentAmount.lt(expectedAmount)) {
735-
console.error(
736-
"Error starting compute job dataset DID " +
737-
args[1] +
738-
" and algorithm DID " +
739-
args[2] +
740-
" because payment amount provided is cheaper than the expected one: " +
741-
JSON.stringify(safePaymentDetails.payment)
742-
);
743-
return;
744-
}
745720

746721
let amountToDeposit = args[8];
747722
if (amountToDeposit === '') {
@@ -751,22 +726,22 @@ export class Commands {
751726
" and algorithm DID " +
752727
args[2] +
753728
" because amount to deposit in Escrow contract was not provided, fallback to escrow payment ammount : " +
754-
safePaymentDetails.payment.amount.toString()
729+
parsedProviderInitializeComputeJob.payment.amount.toString()
755730
);
756-
amountToDeposit = safePaymentDetails.payment.amount.toString()
731+
amountToDeposit = parsedProviderInitializeComputeJob.payment.amount.toString()
757732
}
758733

759734
const escrow = new EscrowContract(
760-
ethers.utils.getAddress(safePaymentDetails.payment.escrowAddress),
735+
ethers.utils.getAddress(parsedProviderInitializeComputeJob.payment.escrowAddress),
761736
this.signer
762737
)
763738
console.log("Verifying payment...");
764739
const validationEscrow = await escrow.verifyFundsForEscrowPayment(
765740
paymentToken,
766741
computeEnv.consumerAddress,
767742
await unitsToAmount(this.signer, paymentToken, amountToDeposit),
768-
safePaymentDetails.payment.amount.toString(),
769-
safePaymentDetails.payment.minLockSeconds.toString(),
743+
parsedProviderInitializeComputeJob.payment.amount.toString(),
744+
parsedProviderInitializeComputeJob.payment.minLockSeconds.toString(),
770745
'10'
771746
)
772747
if (validationEscrow.isValid === false) {
@@ -816,7 +791,7 @@ export class Commands {
816791
computeEnv.id,
817792
assets, // assets[0] // only c2d v1,
818793
algo,
819-
maxJobDuration,
794+
supportedMaxJobDuration,
820795
paymentToken,
821796
JSON.parse(resources),
822797
await this.signer.getChainId(),

src/helpers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { hexlify } from "ethers/lib/utils";
2828
import ERC20Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json';
2929

3030

31+
3132
export async function downloadFile(
3233
url: string,
3334
downloadPath: string,

test/paidComputeFlow.test.ts

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,11 @@ describe("Ocean CLI Paid Compute", function() {
154154
console.log(`Fetched Compute Env ID: ${computeEnvId}`);
155155
});
156156

157-
it("should initialize compute on compute dataset and algorithm", async function() {
157+
it("should start paid compute on compute dataset and algorithm", async function() {
158158
const computeEnvs = await ProviderInstance.getComputeEnvironments('http://127.0.0.1:8001');
159159
const env = computeEnvs[0];
160160
expect(env).to.be.an('object').and.to.not.be.null.and.to.not.be.undefined;
161161

162-
console.log(`env: ${JSON.stringify(env)}`)
163162
resources = [
164163
{
165164
id: 'cpu',
@@ -174,22 +173,36 @@ describe("Ocean CLI Paid Compute", function() {
174173
amount: 0
175174
}
176175
]
177-
console.log(`resources: ${JSON.stringify(resources)}`)
178176
const paymentToken = getAddresses().Ocean
179177
const escrow = getAddresses().Escrow;
180-
const output = await runCommand(`npm run cli initializeCompute ${computeDatasetDid} ${jsAlgoDid} ${computeEnvId} 900 ${paymentToken} ${JSON.stringify(resources)}`);
181-
const jsonMatch = output.match(/initialize compute details:\s*([\s\S]*)/);
182-
if (!jsonMatch) {
183-
console.error("Raw output:", output);
184-
throw new Error("Could not find initialize response in the output");
185-
}
186-
const result = jsonMatch[0].split('initialize compute details:')[1]?.trim();
178+
const output = await runCommand(`npm run cli startCompute ${computeDatasetDid} ${jsAlgoDid} ${computeEnvId} 900 ${paymentToken} ${JSON.stringify(resources)} ${providerInitializeResponse.payment.amount} -y`);
179+
const jobIdMatch = output.match(/JobID:\s*([^\s]+)/);
180+
const agreementIdMatch = output.match(/Agreement ID:\s*([^\s]+)/);
181+
const providerInitializeResponseMatch = output.match(/initialize compute details:\s*([\s\S]*)/);
182+
183+
if (!jobIdMatch) {
184+
console.error("Raw output:", output);
185+
throw new Error("Could not find Job ID in the output");
186+
}
187+
188+
if (!agreementIdMatch) {
189+
console.error("Raw output for finding agreement:", output);
190+
throw new Error("Could not find Agreement ID in the output");
191+
}
192+
193+
if (!providerInitializeResponseMatch) {
194+
console.error("Raw output for finding agreement:", output);
195+
throw new Error("Could not find providerInitializeResponseMatch in the output");
196+
}
197+
const result = providerInitializeResponseMatch[1]
187198
try {
188199
providerInitializeResponse = JSON.parse(result);
189200
} catch (error) {
190-
console.error(`Extracted output: ${jsonMatch[0]} and final result: ${result}`);
201+
console.error(`Extracted output: ${providerInitializeResponseMatch[1]} and final result: ${result}`);
191202
throw new Error("Failed to parse the extracted output:\n" + error);
192203
}
204+
expect(computeJobId).to.be.a("string");
205+
expect(agreementId).to.be.a("string");
193206
expect(providerInitializeResponse).to.have.property("payment").that.is.an("object");
194207
expect(providerInitializeResponse.payment).to.have.property("escrowAddress").that.is.a("string").and.that.is.eq(escrow);
195208
expect(providerInitializeResponse.payment).to.have.property("token").that.is.a("string").and.that.is.eq(paymentToken);
@@ -207,24 +220,6 @@ describe("Ocean CLI Paid Compute", function() {
207220
expect(providerInitializeResponse.datasets[0].providerFee).to.have.property("providerFeeAmount").that.is.a("string").and.that.is.eq('0');
208221
expect(providerInitializeResponse.datasets[0].providerFee).to.have.property("providerData").that.is.a("string");
209222

210-
});
211-
212-
it("should start paid compute on compute dataset and algorithm", async function() {
213-
const paymentToken = getAddresses().Ocean
214-
const output = await runCommand(`npm run cli startCompute ${computeDatasetDid} ${jsAlgoDid} ${computeEnvId} ${JSON.stringify(providerInitializeResponse)} 900 ${paymentToken} ${JSON.stringify(resources)} ${providerInitializeResponse.payment.amount}`);
215-
const jobIdMatch = output.match(/JobID:\s*([^\s]+)/);
216-
const agreementIdMatch = output.match(/Agreement ID:\s*([^\s]+)/);
217-
218-
if (!jobIdMatch) {
219-
console.error("Raw output:", output);
220-
throw new Error("Could not find Job ID in the output");
221-
}
222-
223-
if (!agreementIdMatch) {
224-
console.error("Raw output for finding agreement:", output);
225-
throw new Error("Could not find Agreement ID in the output");
226-
}
227-
228223
computeJobId = jobIdMatch[1];
229224
agreementId = agreementIdMatch[1];
230225

@@ -240,9 +235,6 @@ describe("Ocean CLI Paid Compute", function() {
240235
console.error("Agreement ID was empty:", output);
241236
throw new Error("Agreement ID is missing");
242237
}
243-
244-
expect(computeJobId).to.be.a("string");
245-
expect(agreementId).to.be.a("string");
246238
});
247239

248240
it('should delay for compute job', (done) => {

test/setup.test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ describe("Ocean CLI Setup", function() {
3535
expect(stdout).to.contain("Downloads an asset into specified folder");
3636
expect(stdout).to.contain("allowAlgo [options] <datasetDid> <algoDid>");
3737
expect(stdout).to.contain("Approves an algorithm to run on a dataset");
38-
expect(stdout).to.contain("initializeCompute [options] <datasetDids> <algoDid> <computeEnvId> <computeValidUntil> <paymentToken> <resources>");
39-
expect(stdout).to.contain("Initialises provider fees and payment for a compute job");
40-
expect(stdout).to.contain("startCompute [options] <datasetDids> <algoDid> <computeEnvId> <providerInitializeResponse> <maxJobDuration> <paymentToken> <resources> <amountToDeposit>");
38+
expect(stdout).to.contain("startCompute [options] <datasetDids> <algoDid> <computeEnvId> <maxJobDuration> <paymentToken> <resources> <amountToDeposit>");
4139
expect(stdout).to.contain("Starts a compute job");
4240
expect(stdout).to.contain("startFreeCompute [options] <datasetDids> <algoDid> <computeEnvId>");
4341
expect(stdout).to.contain("Starts a FREE compute job");

0 commit comments

Comments
 (0)