Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement predicates/scripts CLI deploy #3254

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion nodemon.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"**/out/release/**",
"apps/demo-typegen/src/contract-types/**",
"apps/demo-typegen/src/predicate-types/**",
"apps/demo-typegen/src/script-types/**"
"apps/demo-typegen/src/script-types/**",
"packages/fuels/src/cli/commands/deploy/proxy/types/**"
]
}
18 changes: 14 additions & 4 deletions packages/contract/src/contract-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,16 +376,21 @@
return { waitForResult, contractId, waitForTransactionId };
}

async deployAsBlobTxForScript(configurableConstants: { [name: string]: unknown } = {}): Promise<{

Check warning on line 379 in packages/contract/src/contract-factory.ts

View workflow job for this annotation

GitHub Actions / Lint

'configurableConstants' is assigned a value but never used
waitForResult: () => Promise<{
transactionResult: TransactionResult<TransactionType.Blob>;
loaderBytecode: string;
}>;
blobId: string;
loaderBytecode: Uint8Array;
loaderBytecodeHexlified: string;
}> {
const account = this.getAccount();
if (configurableConstants) {
this.setConfigurableConstants(configurableConstants);
}

// TODO: We think that we should not be setting configurable constants here, but rather when we try to call the script.
// if (configurableConstants) {
// this.setConfigurableConstants(configurableConstants);
// }

// Generate the associated create tx for the loader contract
const blobId = hash(this.bytecode);
Expand Down Expand Up @@ -444,7 +449,12 @@
return { transactionResult: result, loaderBytecode: hexlify(loaderBytecode) };
};

return { waitForResult };
return {
waitForResult,
blobId,
loaderBytecode,
loaderBytecodeHexlified: hexlify(loaderBytecode),
};
}

/**
Expand Down
55 changes: 20 additions & 35 deletions packages/fuels/src/cli/commands/deploy/deployScripts.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import type { WalletUnlocked } from '@fuel-ts/account';
import type { DeployContractOptions } from '@fuel-ts/contract';
import { ContractFactory } from '@fuel-ts/contract';
import { debug, log } from 'console';
import { readFileSync } from 'fs';

import type { ForcToml } from '../../config/forcUtils';
import {
getClosestForcTomlDir,
getBinaryPath,
getABIPath,
getStorageSlotsPath,
getContractName,
readForcToml,
} from '../../config/forcUtils';
import { getBinaryPath, getABIPath, getContractName } from '../../config/forcUtils';
import type { FuelsConfig, DeployedScript } from '../../types';

import { createWallet } from './createWallet';
Expand All @@ -21,24 +16,23 @@
wallet: WalletUnlocked,
binaryPath: string,
abiPath: string,
storageSlotsPath: string,
scriptPath: string,
tomlContents: ForcToml
configurableConstants?: DeployContractOptions['configurableConstants']
) {
debug(`Deploying script for ABI: ${abiPath}`);

// Implement script deploy
await Promise.resolve({
wallet,
binaryPath,
abiPath,
storageSlotsPath,
scriptPath,
tomlContents,
});
const bytecode = readFileSync(binaryPath);
const abi = JSON.parse(readFileSync(abiPath, 'utf-8'));
const factory = new ContractFactory(bytecode, abi, wallet);

// TODO: implement me
return 'deployed-blob-id';
const { waitForResult, blobId, loaderBytecode, loaderBytecodeHexlified } =
await factory.deployAsBlobTxForScript(configurableConstants);
await waitForResult();

return {
blobId,
loaderBytecode,
loaderBytecodeHexlified,
};
}

/**
Expand All @@ -51,36 +45,27 @@

log(`Deploying scripts to: ${wallet.provider.url}`);

const scriptsLen = config.scripts.length;

Check failure on line 48 in packages/fuels/src/cli/commands/deploy/deployScripts.ts

View workflow job for this annotation

GitHub Actions / node@18

packages/fuels/src/cli/commands/deploy/index.test.ts > deploy > should call onDeploy callback

Error: ENOENT: no such file or directory, open '/home/runner/work/fuels-ts/fuels-ts/packages/fuels/test/fixtures/workspace/scripts/script/out/debug/script-true.bin' ❯ deployScript packages/fuels/src/cli/commands/deploy/deployScripts.ts:48:9 ❯ Module.deployScripts packages/fuels/src/cli/commands/deploy/deployScripts.ts:373:42 ❯ Module.deploy packages/fuels/src/cli/commands/deploy/index.ts:148:45 ❯ packages/fuels/src/cli/commands/deploy/index.test.ts:37:5 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { errno: -2, syscall: 'open', code: 'ENOENT', path: '/home/runner/work/fuels-ts/fuels-ts/packages/fuels/test/fixtures/workspace/scripts/script/out/debug/script-true.bin' }

Check failure on line 48 in packages/fuels/src/cli/commands/deploy/deployScripts.ts

View workflow job for this annotation

GitHub Actions / node@20

packages/fuels/src/cli/commands/deploy/index.test.ts > deploy > should call onDeploy callback

Error: ENOENT: no such file or directory, open '/home/runner/work/fuels-ts/fuels-ts/packages/fuels/test/fixtures/workspace/scripts/script/out/debug/script-true.bin' ❯ deployScript packages/fuels/src/cli/commands/deploy/deployScripts.ts:48:9 ❯ Module.deployScripts packages/fuels/src/cli/commands/deploy/deployScripts.ts:373:42 ❯ Module.deploy packages/fuels/src/cli/commands/deploy/index.ts:148:45 ❯ packages/fuels/src/cli/commands/deploy/index.test.ts:37:5 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { errno: -2, code: 'ENOENT', syscall: 'open', path: '/home/runner/work/fuels-ts/fuels-ts/packages/fuels/test/fixtures/workspace/scripts/script/out/debug/script-true.bin' }

Check failure on line 48 in packages/fuels/src/cli/commands/deploy/deployScripts.ts

View workflow job for this annotation

GitHub Actions / node@22

packages/fuels/src/cli/commands/deploy/index.test.ts > deploy > should call onDeploy callback

Error: ENOENT: no such file or directory, open '/home/runner/work/fuels-ts/fuels-ts/packages/fuels/test/fixtures/workspace/scripts/script/out/debug/script-true.bin' ❯ deployScript packages/fuels/src/cli/commands/deploy/deployScripts.ts:48:9 ❯ Module.deployScripts packages/fuels/src/cli/commands/deploy/deployScripts.ts:373:42 ❯ Module.deploy packages/fuels/src/cli/commands/deploy/index.ts:148:45 ❯ packages/fuels/src/cli/commands/deploy/index.test.ts:37:5 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { errno: -2, code: 'ENOENT', syscall: 'open', path: '/home/runner/work/fuels-ts/fuels-ts/packages/fuels/test/fixtures/workspace/scripts/script/out/debug/script-true.bin' }

for (let i = 0; i < scriptsLen; i++) {
const scriptPath = config.scripts[i];
const forcTomlPath = getClosestForcTomlDir(scriptPath);
const binaryPath = getBinaryPath(scriptPath, config);
const abiPath = getABIPath(scriptPath, config);
const storageSlotsPath = getStorageSlotsPath(scriptPath, config);
const projectName = getContractName(scriptPath);
// const scriptName = getContractCamelCase(scriptPath);
const tomlContents = readForcToml(forcTomlPath);

const blobId = await deployScript(
const { blobId, loaderBytecode, loaderBytecodeHexlified } = await deployScript(
wallet,
binaryPath,
abiPath,
storageSlotsPath,
scriptPath,
tomlContents
abiPath
);

// TODO: implement me
const loaderBytecode = `0x${blobId}`;

debug(`Script deployed: ${projectName} - ${blobId}`);

scripts.push({
path: scriptPath,
blobId,
loaderBytecode,
loaderBytecodeHexlified,
});
}

Expand Down
2 changes: 1 addition & 1 deletion packages/fuels/src/cli/commands/deploy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* After saving the script files, we need to
* re-generate types for them.
*
* This time, the script will have to binaries:
* This time, the script will have two binaries:
* - the original one
* - the loader one (after deploy)
*
Expand All @@ -32,7 +32,7 @@
*
* This would look like:
*
* import { MyScript, MyScriptDeployed } from './generated-types';

Check warning on line 35 in packages/fuels/src/cli/commands/deploy/index.ts

View workflow job for this annotation

GitHub Actions / Lint

tsdoc-malformed-inline-tag: Expecting a TSDoc tag starting with "{@"

Check warning on line 35 in packages/fuels/src/cli/commands/deploy/index.ts

View workflow job for this annotation

GitHub Actions / Lint

tsdoc-escape-right-brace: The "}" character should be escaped using a backslash to avoid confusion with a TSDoc inline tag
*
*/

Expand Down
12 changes: 12 additions & 0 deletions packages/fuels/src/cli/commands/deploy/saveScriptFiles.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { writeFileSync } from 'fs';

import { getScriptName } from '../../config/forcUtils';
import type { DeployedScript, FuelsConfig } from '../../types';

export async function saveScriptFiles(scripts: DeployedScript[], _config: FuelsConfig) {
Expand All @@ -9,6 +12,15 @@ export async function saveScriptFiles(scripts: DeployedScript[], _config: FuelsC
* - Hash file for scripts
* - Root file for predicates
*/
const scriptName = getScriptName(path);
const buildMode = _config.buildMode;

const scriptBlobIdPath = `${path}/out/${buildMode}/${scriptName}-deployed-bin-hash`;
writeFileSync(scriptBlobIdPath, blobId);

const loaderBytecodePath = `${path}/out/${buildMode}/${scriptName}-deployed.bin`;
writeFileSync(loaderBytecodePath, loaderBytecode);

await Promise.resolve({ path, blobId, loaderBytecode });
}
}
5 changes: 5 additions & 0 deletions packages/fuels/src/cli/config/forcUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ export function getContractName(contractPath: string) {
return project.name;
}

export function getScriptName(scriptPath: string) {
const { project } = readForcToml(scriptPath);
return project.name;
}

export function getContractCamelCase(contractPath: string) {
const projectName = getContractName(contractPath);
return camelCase(projectName);
Expand Down
3 changes: 2 additions & 1 deletion packages/fuels/src/cli/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export type DeployedContract = {
export type DeployedScript = {
path: string;
blobId: string;
loaderBytecode: string;
loaderBytecode: Uint8Array;
loaderBytecodeHexlified: string;
};

export type ContractDeployOptions = {
Expand Down
Loading