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

Deploy type file and metadata to attestation registry #74

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
9 changes: 9 additions & 0 deletions lib/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import path from "path";
import { dev } from "./dev";
import { cloneRepository } from "./repository";
import { buildWorkspace, devWorkspace } from "./workspace";
import { deploy_with_metadata } from "./deploy";

const program = new Command();

Expand Down Expand Up @@ -134,6 +135,14 @@ async function run() {
.action((appName) => {
console.log("not yet supported");
});
program
.command("attest")
.description("Deploy the project with metadata")
.argument("[app_name]", "app name")
.argument("[type_file]", "type definition")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the type definition? How is it supposed to be provided?

.action((appName, typeFile) => {
deploy_with_metadata(appName, typeFile);
});

program.parse();
}
Expand Down
109 changes: 109 additions & 0 deletions lib/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { BaseConfig } from "./config";
import { uploadAndPinJson } from '@archetype-org/ribbit';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we moved all of this "deploy_with_metadata" to archetype library?

The attest command can be a direct mapping to ribbit and your contract.

-- although it appears that repo private. We're not sharing builds with a private api.

const { read_bos_config } = require("./config");
const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");

const distFolder = process.env.DIST_FOLDER || "build";

// deploy the app widgets and modules
export async function deployAppCode(src: string, config: BaseConfig) {
Expand All @@ -7,3 +14,105 @@ export async function deployAppCode(src: string, config: BaseConfig) {
// publish data.json to SocialDB
export async function deployAppData(src: string, config: BaseConfig) {
}

// deploy manifest / types to attestation registry
export async function deploy_with_metadata(appFolder, typeFile) {
const config = read_bos_config(appFolder);
const { appAccount, version } = config;

console.log("Uploading package metadata with config:", config);
if (!appAccount) {
console.error(
`App account is not defined for ${appFolder}. Skipping data upload.`,
);
return;
}

const dataJSON = fs.readFileSync(
path.join(distFolder, appFolder, "data.json"),
"utf8",
);

let typeDefinition = {};

if (typeFile) {
typeDefinition = fs.readFileSync(
path.join(distFolder, appFolder, typeFile),
"utf8",
);
}

let content: any = {
data: {
[appAccount]: JSON.parse(dataJSON),
metadata: {},
types: JSON.parse(typeFile)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if no typeFile provided, there isn't a default in the cli

},
};

try {
const metadataJSON = fs.readFileSync(
path.join(distFolder, appFolder, "metadata.json"),
"utf8",
);
content.metadata = JSON.parse(metadataJSON);
} catch (error) {
console.log(error.message);
console.log(`Skipping metadata pinning...`);
}

const formattedContent = [content];
const ipfsHash = await uploadAndPinJson(formattedContent);
try {
console.log(`Uploaded data for ${appFolder} with ipfs hash: ${ipfsHash}`);
} catch (error) {
console.log(
`Error uploading data for ${appFolder} with ipfs hash: ${ipfsHash}`,
);
console.error(`Error uploading data for ${appFolder}:\n${error.message}`);
}

const manifest = {
package_name: `${appFolder}`,
version: `${version ?? ""}`,
content_type: "ipfs",
cid: ipfsHash.toString(),
is_contract: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does is_contract mean?

};

const argsBase64 = Buffer.from(JSON.stringify(manifest)).toString("base64");
const packageRoot = path.resolve(__dirname, "..");
const nearBinaryPath = path.join(packageRoot, "node_modules", ".bin", "near");
const REGISTRY_ADDRESS = "efficacious-mother.testnet";

// TODO: dynamically adjust based on NEAR CLI accounts / signin status / preferences. If signed in, metdata uploads will work, but will throw an error before the contract is called.
const USE_DEFAULT_SIGNER_OPTIONS = true;
const getSignerOptions = () =>
USE_DEFAULT_SIGNER_OPTIONS
? ["sign-as", appAccount, "network-config", "testnet"]
Copy link
Contributor

@elliotBraem elliotBraem Apr 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded testnet, can we have network passed through cli? Fine if it defaults to testnet

: [];

const command = [
nearBinaryPath,
"contract",
"call-function",
"as-transaction",
REGISTRY_ADDRESS,
"create_manifest",
"base64-args",
`'${argsBase64}'`,
"prepaid-gas",
"'300.000 TeraGas'",
...getSignerOptions(),
].join(" ");

try {
execSync(command, {
cwd: path.join(distFolder, appFolder),
stdio: "inherit",
});
console.log(`Uploaded data for ${appFolder}`);
} catch (error) {
console.error(`Error uploading data for ${appFolder}:\n${error.message}`);
}
}
19 changes: 19 additions & 0 deletions lib/ipfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,22 @@ export async function uploadToIPFS(src: SrcType, options: UploadToIPFSOptions):

return cid;
}

async function uploadUsingHelia(content) {
const { createHelia } = await import("helia");
const { json } = await import("@helia/json");

const helia = await createHelia();
const heliaInstance = json(helia);

const cid = await heliaInstance.add(content);
try {
console.log("====================================");
console.log("Added file:", cid);
console.log("Added file:", cid.toString());
console.log("====================================");
return cid;
} catch (e) {
throw new Error(`Error uploading content to IPFS: ${e}`);
}
}
Loading
Loading