Update registry SDK record methods to use cosmjs #2
@ -13,8 +13,6 @@ import { ethToEthermint } from '@tharsis/address-converter';
|
||||
import { encodeSecp256k1Pubkey } from '@cosmjs/amino';
|
||||
import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing';
|
||||
|
||||
import { Payload, Record as RegistryRecord, Signature } from './types';
|
||||
|
||||
const AMINO_PREFIX = 'EB5AE98721';
|
||||
const HDPATH = "m/44'/60'/0'/0";
|
||||
const ACCOUNT_PREFIX = 'laconic';
|
||||
@ -42,7 +40,6 @@ export class Account {
|
||||
_ethAddress!: string;
|
||||
_wallet!: DirectSecp256k1Wallet;
|
||||
_address!: string;
|
||||
_publicKeyLaconic2!: string;
|
||||
|
||||
/**
|
||||
* Generate bip39 mnemonic.
|
||||
@ -98,10 +95,6 @@ export class Account {
|
||||
return this._address;
|
||||
}
|
||||
|
||||
get publicKeyLaconic2 () {
|
||||
return this._publicKeyLaconic2;
|
||||
}
|
||||
|
||||
get wallet () {
|
||||
return this._wallet;
|
||||
}
|
||||
@ -114,7 +107,6 @@ export class Account {
|
||||
|
||||
const [account] = await this._wallet.getAccounts();
|
||||
this._address = account.address;
|
||||
this._publicKeyLaconic2 = Buffer.from(AMINO_PREFIX + toHex(account.pubkey), 'hex').toString('base64');
|
||||
|
||||
// Generate public key.
|
||||
this._publicKey = secp256k1.publicKeyCreate(this._privateKey);
|
||||
@ -127,7 +119,7 @@ export class Account {
|
||||
this._formattedCosmosAddress = ethToEthermint(this._ethAddress);
|
||||
|
||||
// 4. Generate registry formatted public key.
|
||||
const publicKeyInHex = AMINO_PREFIX + toHex(this._publicKey);
|
||||
const publicKeyInHex = AMINO_PREFIX + toHex(account.pubkey);
|
||||
this._registryPublicKey = Buffer.from(publicKeyInHex, 'hex').toString('base64');
|
||||
|
||||
// 5. Generate registry formatted address.
|
||||
@ -169,20 +161,6 @@ export class Account {
|
||||
return Buffer.from(sigObj.signature);
|
||||
}
|
||||
|
||||
async signPayload (payload: Payload) {
|
||||
assert(payload);
|
||||
|
||||
const { record } = payload;
|
||||
const messageToSign = RegistryRecord.getMessageToSign(record);
|
||||
|
||||
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.
|
||||
*/
|
||||
|
69
src/index.ts
69
src/index.ts
@ -4,25 +4,19 @@ import {
|
||||
Chain,
|
||||
Sender,
|
||||
Fee,
|
||||
createMessageSend,
|
||||
MessageSendParams
|
||||
} from '@tharsis/transactions';
|
||||
import { DeliverTxResponse, GasPrice, StdFee } from '@cosmjs/stargate';
|
||||
import { DeliverTxResponse, StdFee } from '@cosmjs/stargate';
|
||||
|
||||
import { RegistryClient } from './registry-client';
|
||||
import { Account } from './account';
|
||||
import { createTransaction } from './txbuilder';
|
||||
import { Payload, Record } from './types';
|
||||
import { Util } from './util';
|
||||
import {
|
||||
createTxMsgAssociateBond,
|
||||
createTxMsgCancelBond,
|
||||
createTxMsgCreateBond,
|
||||
createTxMsgDissociateBond,
|
||||
createTxMsgDissociateRecords,
|
||||
createTxMsgReAssociateRecords,
|
||||
createTxMsgRefillBond,
|
||||
createTxMsgWithdrawBond,
|
||||
MessageMsgAssociateBond,
|
||||
MessageMsgCancelBond,
|
||||
MessageMsgCreateBond,
|
||||
@ -33,22 +27,12 @@ import {
|
||||
MessageMsgWithdrawBond
|
||||
} from './messages/bond';
|
||||
import {
|
||||
createTxMsgDeleteName,
|
||||
createTxMsgReserveAuthority,
|
||||
createTxMsgSetAuthorityBond,
|
||||
createTxMsgSetName,
|
||||
createTxMsgSetRecord,
|
||||
MessageMsgDeleteName,
|
||||
MessageMsgReserveAuthority,
|
||||
MessageMsgSetAuthorityBond,
|
||||
MessageMsgSetName,
|
||||
MessageMsgSetRecord,
|
||||
NAMESERVICE_ERRORS,
|
||||
parseMsgSetRecordResponse
|
||||
NAMESERVICE_ERRORS
|
||||
} from './messages/registry';
|
||||
import {
|
||||
createTxMsgCommitBid,
|
||||
createTxMsgRevealBid,
|
||||
MessageMsgCommitBid,
|
||||
MessageMsgRevealBid
|
||||
} from './messages/auction';
|
||||
@ -487,7 +471,7 @@ export class Registry {
|
||||
);
|
||||
|
||||
// TODO: Parse error response
|
||||
return response;
|
||||
return laconicClient.registry.decode(response.msgResponses[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -511,52 +495,7 @@ export class Registry {
|
||||
);
|
||||
|
||||
// TODO: Parse error response form delete name
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 },
|
||||
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'));
|
||||
const registryRecord = new Record(record);
|
||||
const payload = new Payload(registryRecord);
|
||||
await recordSignerAccount.signPayload(payload);
|
||||
|
||||
// Send record payload Tx.
|
||||
txPrivateKey = txPrivateKey || recordSignerAccount.getPrivateKey();
|
||||
return this._submitRecordPayloadTx({ payload, bondId }, txPrivateKey, fee);
|
||||
}
|
||||
|
||||
async _submitRecordPayloadTx (params: MessageMsgSetRecord, 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 = new Account(Buffer.from(privateKey, 'hex'));
|
||||
const sender = await this._getSender(account);
|
||||
|
||||
const msg = createTxMsgSetRecord(this._chain, sender, fee, '', params);
|
||||
return this._submitTx(msg, privateKey, sender);
|
||||
return laconicClient.registry.decode(response.msgResponses[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@ import { MsgCommitBidEncodeObject, MsgRevealBidEncodeObject, auctionTypes, typeU
|
||||
import { Payload } from './proto2/cerc/registry/v1/tx';
|
||||
import { Record, Signature } from './proto2/cerc/registry/v1/registry';
|
||||
import { Account } from './account';
|
||||
import { Record as RegistryRecord } from './types';
|
||||
import { Util } from './util';
|
||||
|
||||
export const laconicDefaultRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [
|
||||
...defaultRegistryTypes,
|
||||
@ -200,10 +200,10 @@ export class LaconicClient extends SigningStargateClient {
|
||||
// Sign record.
|
||||
const recordSignerAccount = new Account(Buffer.from(params.privateKey, 'hex'));
|
||||
await recordSignerAccount.init();
|
||||
const messageToSign = RegistryRecord.getMessageToSign(params.record);
|
||||
const messageToSign = Util.sortJSON(params.record);
|
||||
const sig = await recordSignerAccount.signRecord(messageToSign);
|
||||
|
||||
const signature = Signature.fromJSON({ sig: sig.toString('base64'), pubKey: recordSignerAccount.publicKeyLaconic2 });
|
||||
const signature = Signature.fromJSON({ sig: sig.toString('base64'), pubKey: recordSignerAccount.registryPublicKey });
|
||||
|
||||
const payload = Payload.fromJSON({ record: registryRecord, signatures: [signature] });
|
||||
|
||||
|
@ -8,9 +8,7 @@ import {
|
||||
} from '@tharsis/transactions';
|
||||
|
||||
import * as registryTx from '../proto/vulcanize/registry/v1beta1/tx';
|
||||
import * as registry from '../proto/vulcanize/registry/v1beta1/registry';
|
||||
import { createTx } from './util';
|
||||
import { Payload } from '../types';
|
||||
|
||||
const MSG_RESERVE_AUTHORITY_TYPES = {
|
||||
MsgValue: [
|
||||
@ -97,11 +95,6 @@ export interface MessageMsgSetName {
|
||||
cid: string
|
||||
}
|
||||
|
||||
export interface MessageMsgSetRecord {
|
||||
bondId: string
|
||||
payload: Payload
|
||||
}
|
||||
|
||||
export interface MessageMsgSetAuthorityBond {
|
||||
name: string
|
||||
bondId: string
|
||||
@ -159,30 +152,6 @@ export function createTxMsgSetName (
|
||||
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,
|
||||
@ -293,51 +262,6 @@ const protoCreateMsgSetName = (
|
||||
};
|
||||
};
|
||||
|
||||
function createMsgSetRecord (
|
||||
bondId: string,
|
||||
payload: Payload,
|
||||
signer: string
|
||||
) {
|
||||
return {
|
||||
type: 'registry/SetRecord',
|
||||
value: {
|
||||
bond_id: bondId,
|
||||
signer,
|
||||
payload: payload.serialize()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const protoCreateMsgSetRecord = (
|
||||
bondId: string,
|
||||
payloadData: Payload,
|
||||
signer: string
|
||||
) => {
|
||||
const record = new registry.vulcanize.registry.v1beta1.Record(payloadData.record.serialize());
|
||||
|
||||
const signatures = payloadData.signatures.map(
|
||||
signature => new registry.vulcanize.registry.v1beta1.Signature(
|
||||
signature.serialize()
|
||||
)
|
||||
);
|
||||
|
||||
const payload = new registryTx.vulcanize.registry.v1beta1.Payload({
|
||||
record,
|
||||
signatures
|
||||
});
|
||||
|
||||
const setNameMessage = new registryTx.vulcanize.registry.v1beta1.MsgSetRecord({
|
||||
bond_id: bondId,
|
||||
signer,
|
||||
payload
|
||||
});
|
||||
|
||||
return {
|
||||
message: setNameMessage,
|
||||
path: 'vulcanize.registry.v1beta1.MsgSetRecord'
|
||||
};
|
||||
};
|
||||
|
||||
function createMsgSetAuthorityBond (
|
||||
name: string,
|
||||
bondId: string,
|
||||
|
@ -95,7 +95,6 @@ const nameserviceExpiryTests = () => {
|
||||
expect(records).toHaveLength(0);
|
||||
});
|
||||
|
||||
// TODO: Check authority not expiring
|
||||
test('Check authority expired without bond balance', async () => {
|
||||
const [authority] = await registry.lookupAuthorities([authorityName]);
|
||||
expect(authority.status).toBe('expired');
|
||||
|
132
src/types.ts
132
src/types.ts
@ -1,132 +0,0 @@
|
||||
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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize record.
|
||||
*/
|
||||
serialize () {
|
||||
return {
|
||||
id: '_',
|
||||
bond_id: '_',
|
||||
create_time: '_',
|
||||
expiry_time: '_',
|
||||
// Setting deleted as false (zero value) throws error in EIP712 signature verification.
|
||||
deleted: true,
|
||||
attributes: this.attributes
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get message to calculate record signature.
|
||||
*/
|
||||
|
||||
// TODO: Replace any type for record
|
||||
static getMessageToSign (record: any) {
|
||||
return Util.sortJSON(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())
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user