diff --git a/README.md b/README.md index cfa4262..1c98b03 100644 --- a/README.md +++ b/README.md @@ -544,103 +544,3 @@ Reassociate records (switch bond): ```bash $ laconic registry bond records reassociate --old-bond-id 5c40abd336ae1561f2a1b55be73b12f5a083080bf879b4c9288d182d238badb0 --new-bond-id 3e11c61f179897e4b12e9b63de35d36f88ac146755e7a28ce0bcdd07cf3a03ae ``` - -## Endpoint Records Demo - -* Create and populate `config.yml` - -* Publish watcher records from [`records/watcher`](./records/watcher): - - ```bash - yarn ts-node src/publish-endponit-records.ts -c config.yml -r records/watcher - ``` - -* Publish watcher deployment records from [`records/watcher-deployments`](./records/watcher-deployments): - - ```bash - yarn ts-node src/publish-endponit-records.ts -c config.yml -r records/watcher-deployments - ``` - -* View the records at laconicd GQL endpoint : - - ```gql - { - queryRecords { - id - bondId - names - attributes { - key - value { - ... on BooleanValue { bool: value } - ... on IntValue { int: value } - ... on FloatValue { float: value } - ... on StringValue { string: value } - ... on BytesValue { bytes: value } - ... on LinkValue { link: value } - ... on ArrayValue { - array: value { - ... on BooleanValue { bool: value } - ... on IntValue { int: value } - ... on FloatValue { float: value } - ... on StringValue { string: value } - ... on BytesValue { bytes: value } - ... on LinkValue { link: value } - } - } - ... on MapValue { map: value { key mapping: value { __typename } } } - } - } - } - } - ``` - -* Query with filters, for example: query all `filecoin` `WatcherRecord`s: - - ```gql - { - queryRecords ( - attributes: [ - { - key: "type", - value: { - string: "WatcherRecord" - } - }, - { - key: "chain", - value: { - string: "filecoin" - } - } - ], - all: true - ) { - id - bondId - names - attributes { - key - value { - ... on BooleanValue { bool: value } - ... on IntValue { int: value } - ... on FloatValue { float: value } - ... on StringValue { string: value } - ... on BytesValue { bytes: value } - ... on LinkValue { link: value } - ... on ArrayValue { - array: value { - ... on BooleanValue { bool: value } - ... on IntValue { int: value } - ... on FloatValue { float: value } - ... on StringValue { string: value } - ... on BytesValue { bytes: value } - ... on LinkValue { link: value } - } - } - ... on MapValue { map: value { key mapping: value { __typename } } } - } - } - } - } - ``` diff --git a/deploy-records.md b/deploy-records.md new file mode 100644 index 0000000..93f0c4d --- /dev/null +++ b/deploy-records.md @@ -0,0 +1,94 @@ +# Records Demo + +* Create and populate `config.yml` + +* Publish watcher records from [`records/watcher`](./records/watcher): + + ```bash + # Publishes records and corresponding 'deployment' records from the given directory + yarn ts-node src/publish-endponit-records.ts -c config.yml -r records/watcher + ``` + +* View the records at laconicd GQL endpoint : + + ```gql + { + queryRecords { + id + bondId + names + attributes { + key + value { + ... on BooleanValue { bool: value } + ... on IntValue { int: value } + ... on FloatValue { float: value } + ... on StringValue { string: value } + ... on BytesValue { bytes: value } + ... on LinkValue { link: value } + ... on ArrayValue { + array: value { + ... on BooleanValue { bool: value } + ... on IntValue { int: value } + ... on FloatValue { float: value } + ... on StringValue { string: value } + ... on BytesValue { bytes: value } + ... on LinkValue { link: value } + } + } + ... on MapValue { map: value { key mapping: value { __typename } } } + } + } + } + } + ``` + +* Query with filters, for example: query all `filecoin` `WatcherRecord`s: + + ```gql + { + queryRecords ( + attributes: [ + { + key: "type", + value: { + string: "WatcherRecord" + } + }, + { + key: "chain", + value: { + string: "filecoin" + } + } + ], + all: true + ) { + id + bondId + names + attributes { + key + value { + ... on BooleanValue { bool: value } + ... on IntValue { int: value } + ... on FloatValue { float: value } + ... on StringValue { string: value } + ... on BytesValue { bytes: value } + ... on LinkValue { link: value } + ... on ArrayValue { + array: value { + ... on BooleanValue { bool: value } + ... on IntValue { int: value } + ... on FloatValue { float: value } + ... on StringValue { string: value } + ... on BytesValue { bytes: value } + ... on LinkValue { link: value } + } + } + ... on MapValue { map: value { key mapping: value { __typename } } } + } + } + } + } + ``` diff --git a/src/publish-endponit-records.ts b/src/publish-endponit-records.ts index 5a0978f..fae97d7 100644 --- a/src/publish-endponit-records.ts +++ b/src/publish-endponit-records.ts @@ -2,6 +2,7 @@ import yargs from 'yargs'; import fs from 'fs'; import path from 'path'; import { hideBin } from 'yargs/helpers'; + import { Registry } from '@cerc-io/registry-sdk'; import { getConfig, getGasAndFees, getConnectionInfo, txOutput } from './util'; @@ -11,42 +12,73 @@ async function main () { const { records: recordsDir, config } = argv; const { services: { registry: registryConfig } } = getConfig(config as string); + + if (registryConfig.userKey == null) { + throw new Error('userKey not set in config'); + } + + if (registryConfig.bondId == null) { + throw new Error('bondId not set in config'); + } + const { rpcEndpoint, gqlEndpoint, userKey, bondId, chainId } = getConnectionInfo(argv, registryConfig); const registry = new Registry(gqlEndpoint, rpcEndpoint, chainId); const fee = getGasAndFees(argv, registryConfig); - await fs.readdir(recordsDir, async (err, files) => { - if (err) { - console.error('Error reading directory:', err); - return; - } + // List record files + const files = fs.readdirSync(recordsDir); + const jsonFiles = files.filter(file => path.extname(file).toLowerCase() === '.json'); - // Filter JSON files - const jsonFiles = files.filter(file => path.extname(file).toLowerCase() === '.json'); + // Read record from each JSON file + for (let i = 0; i < jsonFiles.length; i++) { + const file = jsonFiles[i]; - // Read content of each JSON file - for (let i = 0; i < jsonFiles.length; i++) { - const file = jsonFiles[i]; + const filePath = path.resolve(recordsDir, file); + const record = readRecord(filePath); - const filePath = path.resolve(recordsDir, file); + // Publish record + const result = await registry.setRecord({ privateKey: userKey, record, bondId }, userKey, fee); - let record; - try { - const data = fs.readFileSync(filePath, 'utf8'); - record = JSON.parse(data); - } catch (error) { - console.error(`Error reading file ${file}:`, err); + console.log(`Published record from ${file}`); + txOutput(result, JSON.stringify(result, undefined, 2), argv.output, argv.verbose); + + // Find the deployment record using filename + const deploymentRecordsDir = path.resolve(recordsDir, 'deployments'); + + if (fs.statSync(deploymentRecordsDir).isDirectory()) { + const recordName = path.basename(file, path.extname(file)); + const deploymentRecordFile = `${recordName}Deployment.json`; + const deploymentRecordFilePath = path.resolve(deploymentRecordsDir, deploymentRecordFile); + + // Check if deployment record exists + if (fs.existsSync(deploymentRecordFilePath)) { + console.log(`Deployment record ${deploymentRecordFile} found`); + const deploymentRecord = readRecord(deploymentRecordFilePath); + + // Set watcher field to watcher record id + deploymentRecord.watcher = result.id; + + // Publish deployment record + const deploymentResult = await registry.setRecord({ privateKey: userKey, record: deploymentRecord, bondId }, userKey, fee); + + console.log(`Published deployment record from ${deploymentRecordFile}`); + txOutput(deploymentResult, JSON.stringify(deploymentResult, undefined, 2), argv.output, argv.verbose); } - - // TODO: validate the records using a schema - - const result = await registry.setRecord({ privateKey: userKey, record, bondId }, userKey, fee); - - console.log(`Published record ${file}`); - txOutput(result, JSON.stringify(result, undefined, 2), argv.output, argv.verbose); } - }); + } +} + +function readRecord (filePath: string): any { + let record; + try { + const data = fs.readFileSync(filePath, 'utf8'); + record = JSON.parse(data); + } catch (err) { + console.error(`Error reading file ${filePath}:`, err); + } + + return record; } function getArgs (): any {