Implement setRecord and add test for setAutorityBond

This commit is contained in:
nabarun 2022-04-08 10:59:03 +05:30 committed by Ashwin Phatak
parent 48507ca46a
commit 9de3c59c19
17 changed files with 901 additions and 53 deletions

View File

@ -9,6 +9,7 @@
"devDependencies": {
"@types/is-url": "^1.2.30",
"@types/jest": "^27.4.1",
"@types/semver": "^7.3.9",
"dotenv": "^16.0.0",
"jest": "^27.5.1",
"protoc-gen-ts": "^0.8.2",
@ -23,10 +24,16 @@
"axios": "^0.26.1",
"bip32": "^3.0.1",
"bip39": "^3.0.4",
"canonical-json": "^0.0.4",
"evmosjs": "^0.2.5",
"graphql.js": "^0.6.8",
"ipld-dag-cbor": "^1.0.1",
"is-url": "^1.2.4",
"js-sha256": "^0.9.0",
"js-yaml": "^4.1.0",
"jsonschema": "^1.4.0",
"node-yaml": "^4.0.1",
"semver": "^7.3.5",
"tiny-secp256k1": "^2.2.1"
},
"scripts": {

View File

@ -68,21 +68,17 @@ message Record {
string bond_id = 2 [
(gogoproto.moretags) = "json:\"bondId\" yaml:\"bondId\""
];
google.protobuf.Timestamp create_time = 3 [
(gogoproto.stdtime) = true,
(gogoproto.nullable) = false,
string create_time = 3 [
(gogoproto.moretags) = "json:\"createTime\" yaml:\"createTime\""
];
google.protobuf.Timestamp expiry_time = 4 [
(gogoproto.stdtime) = true,
(gogoproto.nullable) = false,
string expiry_time = 4 [
(gogoproto.moretags) = "json:\"expiryTime\" yaml:\"expiryTime\""
];
bool deleted = 5;
repeated string owners = 6 [
(gogoproto.moretags) = "json:\"owners\" yaml:\"owners\""
];
bytes attributes = 7 [
string attributes = 7 [
(gogoproto.moretags) = "json:\"attributes\" yaml:\"attributes\""
];
}

View File

@ -2,11 +2,17 @@ import assert from 'assert';
import BIP32Factory from 'bip32';
import * as ecc from 'tiny-secp256k1';
import * as bip39 from 'bip39';
import canonicalStringify from 'canonical-json';
import secp256k1 from 'secp256k1';
import { MessageTypes, signTypedData, SignTypedDataVersion } from '@metamask/eth-sig-util';
import { Ripemd160, Secp256k1 } from "@cosmjs/crypto";
import { toBech32 } from '@cosmjs/encoding';
import { fromHex, toBech32, toHex } from '@cosmjs/encoding';
import { rawSecp256k1PubkeyToRawAddress } from "@cosmjs/amino";
import { Payload, Signature } from './types';
import { sha256 } from 'js-sha256';
const AMINO_PREFIX = 'EB5AE98721';
const HDPATH = "m/44'/60'/0'/0";
const bip32 = BIP32Factory(ecc);
@ -27,6 +33,8 @@ export class Account {
_publicKey?: Uint8Array
_cosmosAddress?: string
_formattedCosmosAddress?: string
_registryPublicKey?: string
_registryAddress?: string
/**
* Generate bip39 mnemonic.
@ -67,6 +75,14 @@ export class Account {
return this._formattedCosmosAddress;
}
get registryPublicKey() {
return this._registryPublicKey;
}
get registryAddress() {
return this._registryAddress;
}
async init () {
// Generate public key.
const keypair = await Secp256k1.makeKeypair(this._privateKey);
@ -75,11 +91,18 @@ export class Account {
this._publicKey = compressed
// 2. Generate cosmos-sdk address.
// let publicKeySha256 = sha256(this._publicKey);
this._cosmosAddress = new Ripemd160().update(keypair.pubkey).digest().toString();
// 3. Generate cosmos-sdk formatted address.
this._formattedCosmosAddress = toBech32('ethm', rawSecp256k1PubkeyToRawAddress(this._publicKey));
// 4. Generate registry formatted public key.
const publicKeyInHex = AMINO_PREFIX + toHex(this._publicKey);
this._registryPublicKey = Buffer.from(publicKeyInHex, 'hex').toString('base64');
// 5. Generate registry formatted address.
let publicKeySha256 = sha256(Buffer.from(publicKeyInHex, 'hex'));
this._registryAddress = new Ripemd160().update(fromHex(publicKeySha256)).digest().toString();
}
/**
@ -89,6 +112,41 @@ export class Account {
return this._privateKey.toString('hex');
}
/**
* Get record signature.
* @param {object} record
*/
async signRecord(record: any) {
assert(record);
const recordAsJson = canonicalStringify(record);
// Double sha256.
const recordBytesToSign = Buffer.from(sha256(Buffer.from(sha256(Buffer.from(recordAsJson)), 'hex')), 'hex');
// Sign message
assert(recordBytesToSign);
const messageToSignSha256 = sha256(recordBytesToSign);
const messageToSignSha256InBytes = Buffer.from(messageToSignSha256, 'hex');
const sigObj = secp256k1.ecdsaSign(messageToSignSha256InBytes, this.privateKey);
return Buffer.from(sigObj.signature);
}
async signPayload(payload: Payload) {
assert(payload);
const { record } = payload;
const messageToSign = record.getMessageToSign();
const sig = await this.signRecord(messageToSign);
assert(this.registryPublicKey)
const signature = new Signature(this.registryPublicKey, sig.toString('base64'));
payload.addSignature(signature);
return signature;
}
/**
* Sign message.
*/

View File

@ -1,8 +1,6 @@
import { Registry } from './index';
import { getConfig } from './testing/helper';
const TX_WAIT_TIME = 5000; // in milliseconds.
const { chainId, restEndpoint, gqlEndpoint, privateKey, accountAddress, fee } = getConfig();
jest.setTimeout(90 * 1000);

3
src/decs.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
declare module 'graphql.js'
declare module 'node-yaml'
declare module 'canonical-json'

1
src/graphql.d.ts vendored
View File

@ -1 +0,0 @@
declare module 'graphql.js'

View File

@ -14,7 +14,8 @@ import { createTxMsgCancelBond, createTxMsgCreateBond, createTxMsgRefillBond, cr
import { RegistryClient } from "./registry-client";
import { Account } from "./account";
import { createTransaction } from "./txbuilder";
import { createTxMsgReserveAuthority, MessageMsgReserveAuthority } from './messages/nameservice';
import { createTxMsgReserveAuthority, createTxMsgSetAuthorityBond, createTxMsgSetName, createTxMsgSetRecord, MessageMsgReserveAuthority, MessageMsgSetAuthorityBond, MessageMsgSetName, MessageMsgSetRecord } from './messages/nameservice';
import { Payload, Record } from './types';
const DEFAULT_WRITE_ERROR = 'Unable to write to chiba-clonk.';
@ -51,6 +52,7 @@ export class Registry {
path: [ 'submit' ]
}g
*/
console.error(error)
const message = JSON.parse(error.message);
return message.log || DEFAULT_WRITE_ERROR;
}
@ -80,6 +82,28 @@ export class Registry {
return this._client.getAccount(address);
}
/**
* Publish record.
* @param transactionPrivateKey - private key in HEX to sign transaction.
*/
async setRecord(
params: { privateKey: string, record: any, bondId: string },
senderAddress: string,
transactionPrivateKey: string,
fee: Fee
) {
let result;
try {
result = await this._submitRecordTx(params, senderAddress, transactionPrivateKey, fee);
} catch (err: any) {
const error = err[0] || err;
throw new Error(Registry.processWriteError(error));
}
return parseTxResponse(result);
}
/**
* Send coins.
*/
@ -247,7 +271,7 @@ export class Registry {
/**
* Reserve authority.
*/
async reserveAuthority(params: MessageMsgReserveAuthority, senderAddress: string, privateKey: string, fee: Fee) {
async reserveAuthority(params: MessageMsgReserveAuthority, senderAddress: string, privateKey: string, fee: Fee) {
let result;
try {
@ -270,13 +294,125 @@ export class Registry {
return parseTxResponse(result);
}
/**
* Set authority bond.
* @param {string} name
* @param {string} bondId
* @param {string} privateKey
* @param {object} fee
*/
async setAuthorityBond(params: MessageMsgSetAuthorityBond, senderAddress: string, privateKey: string, fee: Fee) {
let result;
try {
const { account: { base_account: accountInfo } } = await this.getAccount(senderAddress);
const sender = {
accountAddress: accountInfo.address,
sequence: accountInfo.sequence,
accountNumber: accountInfo.account_number,
pubkey: accountInfo.pub_key.key,
}
const msg = createTxMsgSetAuthorityBond(this._chain, sender, fee, '', params)
result = await this._submitTx(msg, privateKey, sender);
} catch (err: any) {
const error = err[0] || err;
throw new Error(Registry.processWriteError(error));
}
return parseTxResponse(result);
}
/**
* Lookup authorities by names.
*/
async lookupAuthorities(names: string[], auction = false) {
async lookupAuthorities(names: string[], auction = false) {
return this._client.lookupAuthorities(names, auction);
}
/**
* Set name (WRN) to record ID (CID).
* @param {string} wrn
* @param {string} id
* @param {string} privateKey
* @param {object} fee
*/
async setName(params: MessageMsgSetName, senderAddress: string, privateKey: string, fee: Fee) {
let result;
try {
const { account: { base_account: accountInfo } } = await this.getAccount(senderAddress);
const sender = {
accountAddress: accountInfo.address,
sequence: accountInfo.sequence,
accountNumber: accountInfo.account_number,
pubkey: accountInfo.pub_key.key,
}
const msg = createTxMsgSetName(this._chain, sender, fee, '', params)
result = await this._submitTx(msg, privateKey, sender);
} catch (err: any) {
const error = err[0] || err;
throw new Error(Registry.processWriteError(error));
}
return parseTxResponse(result);
}
/**
* Submit record transaction.
* @param privateKey - private key in HEX to sign message.
* @param txPrivateKey - private key in HEX to sign transaction.
*/
async _submitRecordTx(
{ privateKey, record, bondId }: { privateKey: string, record: any, bondId: string },
senderAddress: string,
txPrivateKey: string,
fee: Fee
) {
if (!isKeyValid(privateKey)) {
throw new Error('Registry privateKey should be a hex string.');
}
if (!isKeyValid(bondId)) {
throw new Error(`Invalid bondId: ${bondId}.`);
}
// Sign record.
const recordSignerAccount = new Account(Buffer.from(privateKey, 'hex'));
await recordSignerAccount.init();
const registryRecord = new Record(record);
const payload = new Payload(registryRecord);
await recordSignerAccount.signPayload(payload);
// Send record payload Tx.
return this._submitRecordPayloadTx({ payload, bondId }, senderAddress, txPrivateKey, fee);
}
async _submitRecordPayloadTx(params: MessageMsgSetRecord, senderAddress: string, privateKey: string, fee: Fee) {
if (!isKeyValid(privateKey)) {
throw new Error('Registry privateKey should be a hex string.');
}
if (!isKeyValid(params.bondId)) {
throw new Error(`Invalid bondId: ${params.bondId}.`);
}
const { account: { base_account: accountInfo } } = await this.getAccount(senderAddress);
const sender = {
accountAddress: accountInfo.address,
sequence: accountInfo.sequence,
accountNumber: accountInfo.account_number,
pubkey: accountInfo.pub_key.key,
}
const msg = createTxMsgSetRecord(this._chain, sender, fee, '', params)
return this._submitTx(msg, privateKey, sender);
}
/**
* Submit a generic Tx to the chain.
*/

View File

@ -8,7 +8,9 @@ import {
} from '@tharsis/transactions'
import * as nameserviceTx from '../proto/vulcanize/nameservice/v1beta1/tx'
import * as nameservice from '../proto/vulcanize/nameservice/v1beta1/nameservice'
import { createTx } from './util'
import { Payload } from '../types'
const MSG_RESERVE_AUTHORITY_TYPES = {
MsgValue: [
@ -18,11 +20,66 @@ const MSG_RESERVE_AUTHORITY_TYPES = {
],
}
const MSG_SET_NAME_TYPES = {
MsgValue: [
{ name: 'wrn', type: 'string' },
{ name: 'cid', type: 'string' },
{ name: 'signer', type: 'string' },
],
}
const MSG_SET_RECORD_TYPES = {
MsgValue: [
{ name: 'bond_id', type: 'string' },
{ name: 'signer', type: 'string' },
{ name: 'payload', type: 'TypePayload' },
],
TypePayload: [
{ name: 'record', type: 'TypePayloadRecord' },
{ name: 'signatures', type: 'TypePayloadSignatures[]' },
],
TypePayloadRecord: [
{ name: 'id', type: 'string' },
{ name: 'bond_id', type: 'string' },
{ name: 'create_time', type: 'string' },
{ name: 'expiry_time', type: 'string' },
{ name: 'deleted', type: 'bool' },
{ name: 'attributes', type: 'string' },
],
TypePayloadSignatures: [
{ name: 'sig', type: 'string' },
{ name: 'pub_key', type: 'string' }
],
}
const MSG_SET_AUTHORITY_BOND_TYPES = {
MsgValue: [
{ name: 'name', type: 'string' },
{ name: 'bond_id', type: 'string' },
{ name: 'signer', type: 'string' },
],
}
export interface MessageMsgReserveAuthority {
name: string
owner: string
}
export interface MessageMsgSetName {
wrn: string
cid: string
}
export interface MessageMsgSetRecord {
bondId: string
payload: Payload
}
export interface MessageMsgSetAuthorityBond {
name: string
bondId: string
}
export function createTxMsgReserveAuthority(
chain: Chain,
sender: Sender,
@ -47,6 +104,78 @@ export function createTxMsgReserveAuthority(
return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
}
export function createTxMsgSetName(
chain: Chain,
sender: Sender,
fee: Fee,
memo: string,
params: MessageMsgSetName,
) {
const types = generateTypes(MSG_SET_NAME_TYPES)
const msg = createMsgSetName(
params.wrn,
params.cid,
sender.accountAddress
)
const msgCosmos = protoCreateMsgSetName(
params.wrn,
params.cid,
sender.accountAddress
)
return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
}
export function createTxMsgSetRecord(
chain: Chain,
sender: Sender,
fee: Fee,
memo: string,
params: MessageMsgSetRecord,
) {
const types = generateTypes(MSG_SET_RECORD_TYPES)
const msg = createMsgSetRecord(
params.bondId,
params.payload,
sender.accountAddress
)
const msgCosmos = protoCreateMsgSetRecord(
params.bondId,
params.payload,
sender.accountAddress
)
return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
}
export function createTxMsgSetAuthorityBond(
chain: Chain,
sender: Sender,
fee: Fee,
memo: string,
params: MessageMsgSetAuthorityBond,
) {
const types = generateTypes(MSG_SET_AUTHORITY_BOND_TYPES)
const msg = createMsgSetAuthorityBond(
params.name,
params.bondId,
sender.accountAddress
)
const msgCosmos = protoCreateMsgSetAuthorityBond(
params.name,
params.bondId,
sender.accountAddress
)
return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
}
function createMsgReserveAuthority(
name: string,
signer: string,
@ -78,3 +207,112 @@ const protoCreateMsgReserveAuthority = (
path: 'vulcanize.nameservice.v1beta1.MsgReserveAuthority',
}
}
function createMsgSetName(
wrn: string,
cid: string,
signer: string
) {
return {
type: 'nameservice/SetName',
value: {
wrn,
cid,
signer
},
}
}
const protoCreateMsgSetName = (
wrn: string,
cid: string,
signer: string
) => {
const setNameMessage = new nameserviceTx.vulcanize.nameservice.v1beta1.MsgSetName({
wrn,
cid,
signer,
})
return {
message: setNameMessage,
path: 'vulcanize.nameservice.v1beta1.MsgSetName',
}
}
function createMsgSetRecord(
bondId: string,
payload: Payload,
signer: string
) {
return {
type: 'nameservice/SetRecord',
value: {
bond_id: bondId,
signer,
payload: payload.serialize()
},
}
}
const protoCreateMsgSetRecord = (
bondId: string,
payloadData: Payload,
signer: string
) => {
const record = new nameservice.vulcanize.nameservice.v1beta1.Record(payloadData.record.serialize())
const signatures = payloadData.signatures.map(
signature => new nameservice.vulcanize.nameservice.v1beta1.Signature(
signature.serialize()
)
)
const payload = new nameserviceTx.vulcanize.nameservice.v1beta1.Payload({
record,
signatures
})
const setNameMessage = new nameserviceTx.vulcanize.nameservice.v1beta1.MsgSetRecord({
bond_id: bondId,
signer,
payload
})
return {
message: setNameMessage,
path: 'vulcanize.nameservice.v1beta1.MsgSetRecord',
}
}
function createMsgSetAuthorityBond(
name: string,
bondId: string,
signer: string
) {
return {
type: 'nameservice/SetAuthorityBond',
value: {
name,
bond_id: bondId,
signer
},
}
}
const protoCreateMsgSetAuthorityBond = (
name: string,
bondId: string,
signer: string
) => {
const setAuthorityBondMessage = new nameserviceTx.vulcanize.nameservice.v1beta1.MsgSetAuthorityBond({
name,
bond_id: bondId,
signer,
})
return {
message: setAuthorityBondMessage,
path: 'vulcanize.nameservice.v1beta1.MsgSetAuthorityBond',
}
}

View File

@ -1,8 +1,12 @@
import assert from 'assert';
import path from 'path';
import { Account } from './account';
import { Registry } from './index';
import { getConfig } from './testing/helper';
import { ensureUpdatedConfig, getConfig } from './testing/helper';
const WATCHER_ID = 'bafyreibmr47ksukoadck2wigevb2jp5j5oubfadeyzb6zi57ydjsvjmmby'
const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml');
jest.setTimeout(120 * 1000);
@ -10,10 +14,11 @@ const { chainId, restEndpoint, gqlEndpoint, privateKey, accountAddress, fee } =
const namingTests = () => {
let registry: Registry;
let bondId: string;
let watcher: any;
let watcherId: string;
let authorityName: string;
let wrn: string;
beforeAll(async () => {
registry = new Registry(restEndpoint, gqlEndpoint, chainId);
@ -21,6 +26,23 @@ const namingTests = () => {
// Create bond.
bondId = await registry.getNextBondId(accountAddress);
await registry.createBond({ denom: 'aphoton', amount: '1000000000' }, accountAddress, privateKey, fee);
// Create bot.
watcher = await ensureUpdatedConfig(WATCHER_YML_PATH);
const result = await registry.setRecord(
{
privateKey,
bondId,
record: watcher.record
},
accountAddress,
privateKey,
fee
)
// TODO: Get id from setRecord response.
// watcherId = result.data;
watcherId = WATCHER_ID;
});
test('Reserve authority.', async () => {
@ -84,6 +106,16 @@ const namingTests = () => {
expect(record.ownerPublicKey).toBeDefined();
expect(Number(record.height)).toBeGreaterThan(0);
});
xtest('Set name for unbonded authority', async () => {
wrn = `wrn://${authorityName}/app/test`;
assert(watcherId)
await expect(registry.setName({ wrn, cid: watcherId }, accountAddress, privateKey, fee)).rejects.toThrow('Authority bond not found.');
});
test('Set authority bond', async () => {
await registry.setAuthorityBond({ name: authorityName, bondId }, accountAddress, privateKey, fee);
});
};
if (process.env.AUCTIONS_ENABLED) {

View File

@ -311,11 +311,11 @@ export namespace vulcanize.nameservice.v1beta1 {
constructor(data?: any[] | {
id?: string;
bond_id?: string;
create_time?: dependency_2.google.protobuf.Timestamp;
expiry_time?: dependency_2.google.protobuf.Timestamp;
create_time?: string;
expiry_time?: string;
deleted?: boolean;
owners?: string[];
attributes?: Uint8Array;
attributes?: string;
}) {
super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [6], []);
@ -356,16 +356,16 @@ export namespace vulcanize.nameservice.v1beta1 {
pb_1.Message.setField(this, 2, value);
}
get create_time() {
return pb_1.Message.getWrapperField(this, dependency_2.google.protobuf.Timestamp, 3) as dependency_2.google.protobuf.Timestamp;
return pb_1.Message.getField(this, 3) as string;
}
set create_time(value: dependency_2.google.protobuf.Timestamp) {
pb_1.Message.setWrapperField(this, 3, value);
set create_time(value: string) {
pb_1.Message.setField(this, 3, value);
}
get expiry_time() {
return pb_1.Message.getWrapperField(this, dependency_2.google.protobuf.Timestamp, 4) as dependency_2.google.protobuf.Timestamp;
return pb_1.Message.getField(this, 4) as string;
}
set expiry_time(value: dependency_2.google.protobuf.Timestamp) {
pb_1.Message.setWrapperField(this, 4, value);
set expiry_time(value: string) {
pb_1.Message.setField(this, 4, value);
}
get deleted() {
return pb_1.Message.getField(this, 5) as boolean;
@ -380,19 +380,19 @@ export namespace vulcanize.nameservice.v1beta1 {
pb_1.Message.setField(this, 6, value);
}
get attributes() {
return pb_1.Message.getField(this, 7) as Uint8Array;
return pb_1.Message.getField(this, 7) as string;
}
set attributes(value: Uint8Array) {
set attributes(value: string) {
pb_1.Message.setField(this, 7, value);
}
static fromObject(data: {
id?: string;
bond_id?: string;
create_time?: ReturnType<typeof dependency_2.google.protobuf.Timestamp.prototype.toObject>;
expiry_time?: ReturnType<typeof dependency_2.google.protobuf.Timestamp.prototype.toObject>;
create_time?: string;
expiry_time?: string;
deleted?: boolean;
owners?: string[];
attributes?: Uint8Array;
attributes?: string;
}) {
const message = new Record({});
if (data.id != null) {
@ -402,10 +402,10 @@ export namespace vulcanize.nameservice.v1beta1 {
message.bond_id = data.bond_id;
}
if (data.create_time != null) {
message.create_time = dependency_2.google.protobuf.Timestamp.fromObject(data.create_time);
message.create_time = data.create_time;
}
if (data.expiry_time != null) {
message.expiry_time = dependency_2.google.protobuf.Timestamp.fromObject(data.expiry_time);
message.expiry_time = data.expiry_time;
}
if (data.deleted != null) {
message.deleted = data.deleted;
@ -422,11 +422,11 @@ export namespace vulcanize.nameservice.v1beta1 {
const data: {
id?: string;
bond_id?: string;
create_time?: ReturnType<typeof dependency_2.google.protobuf.Timestamp.prototype.toObject>;
expiry_time?: ReturnType<typeof dependency_2.google.protobuf.Timestamp.prototype.toObject>;
create_time?: string;
expiry_time?: string;
deleted?: boolean;
owners?: string[];
attributes?: Uint8Array;
attributes?: string;
} = {};
if (this.id != null) {
data.id = this.id;
@ -435,10 +435,10 @@ export namespace vulcanize.nameservice.v1beta1 {
data.bond_id = this.bond_id;
}
if (this.create_time != null) {
data.create_time = this.create_time.toObject();
data.create_time = this.create_time;
}
if (this.expiry_time != null) {
data.expiry_time = this.expiry_time.toObject();
data.expiry_time = this.expiry_time;
}
if (this.deleted != null) {
data.deleted = this.deleted;
@ -459,16 +459,16 @@ export namespace vulcanize.nameservice.v1beta1 {
writer.writeString(1, this.id);
if (typeof this.bond_id === "string" && this.bond_id.length)
writer.writeString(2, this.bond_id);
if (this.create_time !== undefined)
writer.writeMessage(3, this.create_time, () => this.create_time.serialize(writer));
if (this.expiry_time !== undefined)
writer.writeMessage(4, this.expiry_time, () => this.expiry_time.serialize(writer));
if (typeof this.create_time === "string" && this.create_time.length)
writer.writeString(3, this.create_time);
if (typeof this.expiry_time === "string" && this.expiry_time.length)
writer.writeString(4, this.expiry_time);
if (this.deleted !== undefined)
writer.writeBool(5, this.deleted);
if (this.owners !== undefined)
writer.writeRepeatedString(6, this.owners);
if (this.attributes !== undefined)
writer.writeBytes(7, this.attributes);
if (typeof this.attributes === "string" && this.attributes.length)
writer.writeString(7, this.attributes);
if (!w)
return writer.getResultBuffer();
}
@ -485,10 +485,10 @@ export namespace vulcanize.nameservice.v1beta1 {
message.bond_id = reader.readString();
break;
case 3:
reader.readMessage(message.create_time, () => message.create_time = dependency_2.google.protobuf.Timestamp.deserialize(reader));
message.create_time = reader.readString();
break;
case 4:
reader.readMessage(message.expiry_time, () => message.expiry_time = dependency_2.google.protobuf.Timestamp.deserialize(reader));
message.expiry_time = reader.readString();
break;
case 5:
message.deleted = reader.readBool();
@ -497,7 +497,7 @@ export namespace vulcanize.nameservice.v1beta1 {
pb_1.Message.addToRepeatedField(message, 6, reader.readString());
break;
case 7:
message.attributes = reader.readBytes();
message.attributes = reader.readString();
break;
default: reader.skipField();
}

5
src/schema/record.json Normal file
View File

@ -0,0 +1,5 @@
{
"$schema": "http://json-schema.org/schema#",
"id": "/Record",
"type": "object"
}

View File

@ -0,0 +1,6 @@
record:
type: watcher
name: ERC20 Watcher
version: 1.0.0
protocol:
/: QmdeazkS38aCrqG6qKwaio2fQnShE6RGpmNdqStLkkZcQN

View File

@ -1,4 +1,14 @@
import assert from 'assert';
import yaml from 'node-yaml';
import semver from 'semver';
export const ensureUpdatedConfig = async (path: string) => {
const conf = await yaml.read(path);
conf.record.version = semver.inc(conf.record.version, 'patch');
await yaml.write(path, conf);
return conf;
};
export const getConfig = () => {
assert(process.env.PRIVATE_KEY);

132
src/types.ts Normal file
View File

@ -0,0 +1,132 @@
import assert from 'assert';
import { Validator } from 'jsonschema';
import RecordSchema from './schema/record.json';
import { Util } from './util';
/**
* Record.
*/
export class Record {
_record: any
/**
* New Record.
*/
constructor(record: any) {
assert(record);
const validator = new Validator();
const result = validator.validate(record, RecordSchema);
if (!result.valid) {
result.errors.map(console.error);
throw new Error('Invalid record input.');
}
this._record = record;
}
get attributes() {
return Buffer.from(JSON.stringify(this._record), 'binary').toString('base64')
}
/**
* Serialize record.
*/
serialize() {
// return Util.sortJSON({
// });
return {
'id': '_',
'bond_id': '_',
'create_time': '_',
'expiry_time': '_',
'deleted': true,
'attributes': this.attributes,
// 'owners': [],
}
}
/**
* Get message to calculate record signature.
*/
getMessageToSign() {
return Util.sortJSON(this._record);
}
}
/**
* Record Signature.
*/
export class Signature {
_pubKey: string
_sig: string
/**
* New Signature.
*/
constructor(pubKey: string, sig: string) {
assert(pubKey);
assert(sig);
this._pubKey = pubKey;
this._sig = sig;
}
/**
* Serialize Signature.
*/
serialize() {
return Util.sortJSON({
'pub_key': this._pubKey,
'sig': this._sig
});
}
}
/**
* Message Payload.
*/
export class Payload {
_record: Record
_signatures: Signature[]
/**
* New Payload.
*/
constructor(record: Record, ...signatures: Signature[]) {
assert(record);
this._record = record;
this._signatures = signatures;
}
get record() {
return this._record;
}
get signatures() {
return this._signatures;
}
/**
* Add message signature to payload.
*/
addSignature(signature: any) {
assert(signature);
this._signatures.push(signature);
}
/**
* Serialize Payload.
*/
serialize() {
// return Util.sortJSON({
// });
return {
'record': this._record.serialize(),
'signatures': this._signatures.map(s => s.serialize())
}
}
}

View File

@ -1,3 +1,5 @@
import dagCBOR from 'ipld-dag-cbor';
/**
* Utils
*/
@ -76,4 +78,15 @@ export class Util {
return res;
}
/**
* Get record content ID.
*/
static async getContentId(record: any) {
console.log(record)
const content = dagCBOR.util.serialize(record);
const cid = await dagCBOR.util.cid(content);
return cid.toString();
}
}

View File

@ -33,7 +33,7 @@
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "resolveJsonModule": true, /* Enable importing .json files */
"resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */

223
yarn.lock
View File

@ -551,11 +551,21 @@
tweetnacl "^1.0.3"
tweetnacl-util "^0.15.1"
"@multiformats/base-x@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121"
integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw==
"@noble/hashes@^1":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae"
integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg==
"@octetstream/promisify@2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@octetstream/promisify/-/promisify-2.0.2.tgz#29ac3bd7aefba646db670227f895d812c1a19615"
integrity sha512-7XHoRB61hxsz8lBQrjC1tq/3OEIgpvGWg6DKAdwi7WRzruwkmsdwmOoUXbU4Dtd4RSOMDwed0SkP3y8UlMt1Bg==
"@sinonjs/commons@^1.7.0":
version "1.8.3"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
@ -570,6 +580,11 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
"@sovpro/delimited-stream@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@sovpro/delimited-stream/-/delimited-stream-1.1.0.tgz#4334bba7ee241036e580fdd99c019377630d26b4"
integrity sha512-kQpk267uxB19X3X2T1mvNMjyvIEonpNSHrMlK5ZaBU6aZxw7wPbpgKJOjHN3+/GPVpXgAV9soVT2oyHpLkLtyw==
"@tharsis/address-converter@^0.1.7":
version "0.1.7"
resolved "https://registry.yarnpkg.com/@tharsis/address-converter/-/address-converter-0.1.7.tgz#c13c4d09f30a5b908e795626a5c4c92f8120d954"
@ -743,6 +758,11 @@
dependencies:
"@types/node" "*"
"@types/semver@^7.3.9":
version "7.3.9"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc"
integrity sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==
"@types/stack-utils@^2.0.0":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
@ -841,6 +861,11 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@ -946,6 +971,11 @@ big-integer@1.6.36:
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.36.tgz#78631076265d4ae3555c04f85e7d9d2f3a071a36"
integrity sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==
bignumber.js@^9.0.0:
version "9.0.2"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673"
integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==
bip32@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/bip32/-/bip32-3.0.1.tgz#1d1121469cce6e910e0ec3a5a1990dd62687e2a3"
@ -983,6 +1013,19 @@ bn.js@^5.2.0:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
borc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/borc/-/borc-3.0.0.tgz#49ada1be84de86f57bb1bb89789f34c186dfa4fe"
integrity sha512-ec4JmVC46kE0+layfnwM3l15O70MlFiEbmQHY/vpqIKiUtPVntv4BY4NVnz3N4vb21edV3mY97XVckFvYHWF9g==
dependencies:
bignumber.js "^9.0.0"
buffer "^6.0.3"
commander "^2.15.0"
ieee754 "^1.1.13"
iso-url "^1.1.5"
json-text-sequence "~0.3.0"
readable-stream "^3.6.0"
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@ -1071,7 +1114,7 @@ buffer-xor@^1.0.3:
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
buffer@6.0.3:
buffer@6.0.3, buffer@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
@ -1099,6 +1142,11 @@ caniuse-lite@^1.0.30001317:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001319.tgz#eb4da4eb3ecdd409f7ba1907820061d56096e88f"
integrity sha512-xjlIAFHucBRSMUo1kb5D4LYgcN1M45qdKP++lhqowDpwJwGkpIRTt5qQqnhxjj1vHcI7nrJxWhCC1ATrCEBTcw==
canonical-json@^0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/canonical-json/-/canonical-json-0.0.4.tgz#6579c072c3db5c477ec41dc978fbf2b8f41074a3"
integrity sha1-ZXnAcsPbXEd+xB3JePvyuPQQdKM=
chalk@^2.0.0, chalk@^2.4.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@ -1126,6 +1174,16 @@ ci-info@^3.2.0:
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2"
integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==
cids@^1.0.0, cids@^1.1.6:
version "1.1.9"
resolved "https://registry.yarnpkg.com/cids/-/cids-1.1.9.tgz#402c26db5c07059377bcd6fb82f2a24e7f2f4a4f"
integrity sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==
dependencies:
multibase "^4.0.1"
multicodec "^3.0.1"
multihashes "^4.0.1"
uint8arrays "^3.0.0"
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
@ -1148,7 +1206,7 @@ cliui@^7.0.2:
strip-ansi "^6.0.0"
wrap-ansi "^7.0.0"
co@^4.6.0:
co@4.6.0, co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
@ -1189,6 +1247,11 @@ combined-stream@^1.0.8:
dependencies:
delayed-stream "~1.0.0"
commander@^2.15.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@ -1354,6 +1417,11 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
err-code@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/err-code/-/err-code-3.0.1.tgz#a444c7b992705f2b120ee320b09972eef331c920"
integrity sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
@ -1702,7 +1770,7 @@ iconv-lite@0.4.24:
dependencies:
safer-buffer ">= 2.1.2 < 3"
ieee754@^1.2.1:
ieee754@^1.1.13, ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
@ -1733,16 +1801,43 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
interface-ipld-format@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/interface-ipld-format/-/interface-ipld-format-1.0.1.tgz#bee39c70c584a033e186ff057a2be89f215963e3"
integrity sha512-WV/ar+KQJVoQpqRDYdo7YPGYIUHJxCuOEhdvsRpzLqoOIVCqPKdMMYmsLL1nCRsF3yYNio+PAJbCKiv6drrEAg==
dependencies:
cids "^1.1.6"
multicodec "^3.0.1"
multihashes "^4.0.2"
interpret@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
ipld-dag-cbor@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ipld-dag-cbor/-/ipld-dag-cbor-1.0.1.tgz#1e07cb289aec26e393508e99d2a51ff624d876a1"
integrity sha512-PZh8rHnRETX5bj60i73W2oq6BXoZnIvYCBDwIffYVJgxMr7BEVd5PycAARBiT6daORJ/4zbqEFR5CcrjeCtm/A==
dependencies:
borc "^3.0.0"
cids "^1.0.0"
interface-ipld-format "^1.0.0"
is-circular "^1.0.2"
multicodec "^3.0.1"
multihashing-async "^2.0.0"
uint8arrays "^2.1.3"
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-circular@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-circular/-/is-circular-1.0.2.tgz#2e0ab4e9835f4c6b0ea2b9855a84acd501b8366c"
integrity sha512-YttjnrswnUYRVJvxCvu8z+PGMUSzC2JttP0OEXezlAEdp3EXzhf7IZ3j0gRAybJBQupedIZFhY61Tga6E0qASA==
is-core-module@^2.8.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
@ -1795,6 +1890,11 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
iso-url@^1.1.5:
version "1.2.1"
resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-1.2.1.tgz#db96a49d8d9a64a1c889fc07cc525d093afb1811"
integrity sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==
istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3"
@ -2247,6 +2347,11 @@ js-sha256@^0.9.0:
resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966"
integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==
js-sha3@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@ -2260,6 +2365,13 @@ js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
dependencies:
argparse "^2.0.1"
jsdom@^16.6.0:
version "16.7.0"
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710"
@ -2303,11 +2415,28 @@ json-parse-even-better-errors@^2.3.0:
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
json-text-sequence@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.3.0.tgz#6603e0ee45da41f949669fd18744b97fb209e6ce"
integrity sha512-7khKIYPKwXQem4lWXfpIN/FEnhztCeRPSxH4qm3fVlqulwujrRDD54xAwDDn/qVKpFtV550+QAkcWJcufzqQuA==
dependencies:
"@sovpro/delimited-stream" "^1.1.0"
json5@2.x, json5@^2.1.2:
version "2.2.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
jsonschema@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2"
integrity sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==
junk@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1"
integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==
keccak@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0"
@ -2468,6 +2597,52 @@ ms@2.1.2:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
multibase@^4.0.1:
version "4.0.6"
resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.6.tgz#6e624341483d6123ca1ede956208cb821b440559"
integrity sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==
dependencies:
"@multiformats/base-x" "^4.0.1"
multicodec@^3.0.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-3.2.1.tgz#82de3254a0fb163a107c1aab324f2a91ef51efb2"
integrity sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==
dependencies:
uint8arrays "^3.0.0"
varint "^6.0.0"
multiformats@^9.4.2:
version "9.6.4"
resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.6.4.tgz#5dce1f11a407dbb69aa612cb7e5076069bb759ca"
integrity sha512-fCCB6XMrr6CqJiHNjfFNGT0v//dxOBMrOMqUIzpPc/mmITweLEyhvMpY9bF+jZ9z3vaMAau5E8B68DW77QMXkg==
multihashes@^4.0.1, multihashes@^4.0.2:
version "4.0.3"
resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-4.0.3.tgz#426610539cd2551edbf533adeac4c06b3b90fb05"
integrity sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==
dependencies:
multibase "^4.0.1"
uint8arrays "^3.0.0"
varint "^5.0.2"
multihashing-async@^2.0.0:
version "2.1.4"
resolved "https://registry.yarnpkg.com/multihashing-async/-/multihashing-async-2.1.4.tgz#26dce2ec7a40f0e7f9e732fc23ca5f564d693843"
integrity sha512-sB1MiQXPSBTNRVSJc2zM157PXgDtud2nMFUEIvBrsq5Wv96sUclMRK/ecjoP1T/W61UJBqt4tCTwMkUpt2Gbzg==
dependencies:
blakejs "^1.1.0"
err-code "^3.0.0"
js-sha3 "^0.8.0"
multihashes "^4.0.1"
murmurhash3js-revisited "^3.0.0"
uint8arrays "^3.0.0"
murmurhash3js-revisited@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz#6bd36e25de8f73394222adc6e41fa3fac08a5869"
integrity sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@ -2493,6 +2668,15 @@ node-releases@^2.0.2:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01"
integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==
node-yaml@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/node-yaml/-/node-yaml-4.0.1.tgz#3675d27c275fbea9c02e2b0faa18bb1699444cb3"
integrity sha512-ZPKi3OexXdiklsRW9g4P7jAxHAhoBRZCFmIDMQ89clLhMz+MTJuCM9y5f1R7Ru75H84hWJouwpxVOq1SdRTe7A==
dependencies:
co "4.6.0"
junk "3.1.0"
promise-fs "2.1.1"
normalize-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
@ -2637,6 +2821,13 @@ pretty-format@^27.0.0, pretty-format@^27.5.1:
ansi-styles "^5.0.0"
react-is "^17.0.1"
promise-fs@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/promise-fs/-/promise-fs-2.1.1.tgz#0b725a592c165ff16157d1f13640ba390637e557"
integrity sha512-43p7e4QzAQ3w6eyN0+gbBL7jXiZFWLWYITg9wIObqkBySu/a5K1EDcQ/S6UyB/bmiZWDA4NjTbcopKLTaKcGSw==
dependencies:
"@octetstream/promisify" "2.0.2"
prompts@^2.0.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
@ -2787,7 +2978,7 @@ secp256k1@^4.0.1:
node-addon-api "^2.0.0"
node-gyp-build "^4.2.0"
semver@7.x, semver@^7.3.2:
semver@7.x, semver@^7.3.2, semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
@ -3115,6 +3306,20 @@ uint8array-tools@0.0.7:
resolved "https://registry.yarnpkg.com/uint8array-tools/-/uint8array-tools-0.0.7.tgz#a7a2bb5d8836eae2fade68c771454e6a438b390d"
integrity sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==
uint8arrays@^2.1.3:
version "2.1.10"
resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a"
integrity sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A==
dependencies:
multiformats "^9.4.2"
uint8arrays@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.0.0.tgz#260869efb8422418b6f04e3fac73a3908175c63b"
integrity sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==
dependencies:
multiformats "^9.4.2"
universalify@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
@ -3134,6 +3339,16 @@ v8-to-istanbul@^8.1.0:
convert-source-map "^1.6.0"
source-map "^0.7.3"
varint@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4"
integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==
varint@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0"
integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==
w3c-hr-time@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"