Add a script to publish records from a given directory #62

Merged
ashwin merged 20 commits from deep-stack/laconic-registry-cli:pm-endpoint-records into laconic2 2024-05-09 10:35:55 +00:00
3 changed files with 151 additions and 125 deletions
Showing only changes of commit 7a49cfe0bb - Show all commits

100
README.md
View File

@ -544,103 +544,3 @@ Reassociate records (switch bond):
```bash ```bash
$ laconic registry bond records reassociate --old-bond-id 5c40abd336ae1561f2a1b55be73b12f5a083080bf879b4c9288d182d238badb0 --new-bond-id 3e11c61f179897e4b12e9b63de35d36f88ac146755e7a28ce0bcdd07cf3a03ae $ 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 <http://localhost:9473>:
```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 } } }
}
}
}
}
```

94
deploy-records.md Normal file
View File

@ -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 <http://localhost:9473>:
```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 } } }
}
}
}
}
```

View File

@ -2,6 +2,7 @@ import yargs from 'yargs';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { hideBin } from 'yargs/helpers'; import { hideBin } from 'yargs/helpers';
import { Registry } from '@cerc-io/registry-sdk'; import { Registry } from '@cerc-io/registry-sdk';
import { getConfig, getGasAndFees, getConnectionInfo, txOutput } from './util'; import { getConfig, getGasAndFees, getConnectionInfo, txOutput } from './util';
@ -11,42 +12,73 @@ async function main () {
const { records: recordsDir, config } = argv; const { records: recordsDir, config } = argv;
const { services: { registry: registryConfig } } = getConfig(config as string); 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 { rpcEndpoint, gqlEndpoint, userKey, bondId, chainId } = getConnectionInfo(argv, registryConfig);
const registry = new Registry(gqlEndpoint, rpcEndpoint, chainId); const registry = new Registry(gqlEndpoint, rpcEndpoint, chainId);
const fee = getGasAndFees(argv, registryConfig); const fee = getGasAndFees(argv, registryConfig);
await fs.readdir(recordsDir, async (err, files) => { // List record files
if (err) { const files = fs.readdirSync(recordsDir);
console.error('Error reading directory:', err); const jsonFiles = files.filter(file => path.extname(file).toLowerCase() === '.json');
return;
}
// Filter JSON files // Read record from each JSON file
const jsonFiles = files.filter(file => path.extname(file).toLowerCase() === '.json'); for (let i = 0; i < jsonFiles.length; i++) {
const file = jsonFiles[i];
// Read content of each JSON file const filePath = path.resolve(recordsDir, file);
for (let i = 0; i < jsonFiles.length; i++) { const record = readRecord(filePath);
const file = jsonFiles[i];
const filePath = path.resolve(recordsDir, file); // Publish record
const result = await registry.setRecord({ privateKey: userKey, record, bondId }, userKey, fee);
let record; console.log(`Published record from ${file}`);
try { txOutput(result, JSON.stringify(result, undefined, 2), argv.output, argv.verbose);
const data = fs.readFileSync(filePath, 'utf8');
record = JSON.parse(data); // Find the deployment record using filename
} catch (error) { const deploymentRecordsDir = path.resolve(recordsDir, 'deployments');
console.error(`Error reading file ${file}:`, err);
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 { function getArgs (): any {