registry-sdk/src/laconic-client.ts

452 lines
13 KiB
TypeScript

import Long from 'long';
import { GeneratedType, OfflineSigner, Registry } from '@cosmjs/proto-signing';
import {
defaultRegistryTypes,
DeliverTxResponse,
SigningStargateClient,
SigningStargateClientOptions,
StdFee
} from '@cosmjs/stargate';
import { Comet38Client } from '@cosmjs/tendermint-rpc';
import { MsgCancelBondEncodeObject, MsgCreateBondEncodeObject, MsgRefillBondEncodeObject, MsgWithdrawBondEncodeObject, bondTypes, typeUrlMsgCancelBond, typeUrlMsgCreateBond, typeUrlMsgRefillBond, typeUrlMsgWithdrawBond } from './types/cerc/bond/message';
import { Coin } from './proto/cosmos/base/v1beta1/coin';
import { MsgAssociateBondEncodeObject, MsgDeleteNameEncodeObject, MsgDissociateBondEncodeObject, MsgDissociateRecordsEncodeObject, MsgReassociateRecordsEncodeObject, MsgReserveAuthorityEncodeObject, MsgSetAuthorityBondEncodeObject, MsgSetNameEncodeObject, MsgSetRecordEncodeObject, registryTypes, typeUrlMsgAssociateBond, typeUrlMsgDeleteName, typeUrlMsgDissociateBond, typeUrlMsgDissociateRecords, typeUrlMsgReassociateRecords, typeUrlMsgReserveAuthority, typeUrlMsgSetAuthorityBond, typeUrlMsgSetName, typeUrlMsgSetRecord, NAMESERVICE_ERRORS } from './types/cerc/registry/message';
import { MsgCommitBidEncodeObject, MsgCreateAuctionEncodeObject, MsgRevealBidEncodeObject, auctionTypes, typeUrlMsgCommitBid, typeUrlMsgCreateAuction, typeUrlMsgRevealBid } from './types/cerc/auction/message';
import { MsgOnboardParticipantEncodeObject, ONBOARDING_DISABLED_ERROR, onboardingTypes, typeUrlMsgOnboardParticipant } from './types/cerc/onboarding/message';
import { MsgAssociateBondResponse, MsgDeleteNameResponse, MsgDissociateBondResponse, MsgDissociateRecordsResponse, MsgReassociateRecordsResponse, MsgReserveAuthorityResponse, MsgSetAuthorityBondResponse, MsgSetNameResponse, MsgSetRecordResponse, Payload } from './proto/cerc/registry/v1/tx';
import { Record, Signature } from './proto/cerc/registry/v1/registry';
import { Account } from './account';
import { Util } from './util';
import { MsgCommitBidResponse, MsgCreateAuction, MsgCreateAuctionResponse, MsgRevealBidResponse } from './proto/cerc/auction/v1/tx';
import { MsgCancelBondResponse, MsgCreateBondResponse, MsgRefillBondResponse, MsgWithdrawBondResponse } from './proto/cerc/bond/v1/tx';
import { MsgOnboardParticipantResponse } from './proto/cerc/onboarding/v1/tx';
import { bankTypes } from './types/cosmos/bank/message';
import { EthPayload } from './proto/cerc/onboarding/v1/onboarding';
import { Duration } from './proto/google/protobuf/duration';
const DEFAULT_WRITE_ERROR = 'Unable to write to laconicd.';
export const laconicDefaultRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [
...defaultRegistryTypes,
...bondTypes,
...registryTypes,
...auctionTypes,
...bankTypes,
...onboardingTypes
];
function createDefaultRegistry (): Registry {
return new Registry(laconicDefaultRegistryTypes);
}
export class LaconicClient extends SigningStargateClient {
public static async connectWithSigner (
endpoint: string,
signer: OfflineSigner,
options: SigningStargateClientOptions = {}
): Promise<LaconicClient> {
const cometClient = await Comet38Client.connect(endpoint);
return new LaconicClient(cometClient, signer, {
registry: createDefaultRegistry(),
...options
});
}
public async createBond (
signer: string,
denom: string,
amount: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgCreateBondEncodeObject = {
typeUrl: typeUrlMsgCreateBond,
value: {
signer,
coins: [
Coin.fromPartial({
denom,
amount
})
]
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgCreateBondResponse>(response);
}
public async refillBond (
signer: string,
denom: string,
amount: string,
id: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgRefillBondEncodeObject = {
typeUrl: typeUrlMsgRefillBond,
value: {
id,
signer,
coins: [
Coin.fromPartial({
denom,
amount
})
]
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgRefillBondResponse>(response);
}
public async withdrawBond (
signer: string,
denom: string,
amount: string,
id: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgWithdrawBondEncodeObject = {
typeUrl: typeUrlMsgWithdrawBond,
value: {
id,
signer,
coins: [
Coin.fromPartial({
denom,
amount
})
]
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgWithdrawBondResponse>(response);
}
public async cancelBond (
signer: string,
id: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgCancelBondEncodeObject = {
typeUrl: typeUrlMsgCancelBond,
value: {
id,
signer
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgCancelBondResponse>(response);
}
public async associateBond (
signer: string,
recordId: string,
bondId: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgAssociateBondEncodeObject = {
typeUrl: typeUrlMsgAssociateBond,
value: {
recordId,
bondId,
signer
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgAssociateBondResponse>(response);
}
public async dissociateBond (
signer: string,
recordId: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgDissociateBondEncodeObject = {
typeUrl: typeUrlMsgDissociateBond,
value: {
recordId,
signer
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgDissociateBondResponse>(response);
}
public async dissociateRecords (
signer: string,
bondId: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgDissociateRecordsEncodeObject = {
typeUrl: typeUrlMsgDissociateRecords,
value: {
signer,
bondId
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgDissociateRecordsResponse>(response);
}
public async reassociateRecords (
signer: string,
oldBondId: string,
newBondId: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgReassociateRecordsEncodeObject = {
typeUrl: typeUrlMsgReassociateRecords,
value: {
signer,
oldBondId,
newBondId
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgReassociateRecordsResponse>(response);
}
public async reserveAuthority (
signer: string,
name: string,
owner: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgReserveAuthorityEncodeObject = {
typeUrl: typeUrlMsgReserveAuthority,
value: {
name,
signer,
owner
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgReserveAuthorityResponse>(response);
}
public async commitBid (
signer: string,
auctionId: string,
commitHash: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgCommitBidEncodeObject = {
typeUrl: typeUrlMsgCommitBid,
value: {
signer,
auctionId,
commitHash
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgCommitBidResponse>(response);
}
public async revealBid (
signer: string,
auctionId: string,
reveal: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgRevealBidEncodeObject = {
typeUrl: typeUrlMsgRevealBid,
value: {
signer,
auctionId,
reveal
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgRevealBidResponse>(response);
}
public async setRecord (
params: { privateKey: string, record: any, bondId: string },
signer: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const registryRecord = Record.fromPartial({ attributes: Buffer.from(JSON.stringify(params.record), 'binary') });
// Sign record.
const recordSignerAccount = new Account(Buffer.from(params.privateKey, 'hex'));
await recordSignerAccount.init();
const messageToSign = Util.sortJSON(params.record);
const sig = await recordSignerAccount.signRecord(messageToSign);
const signature = Signature.fromJSON({ sig: sig.toString('base64'), pubKey: recordSignerAccount.registryPublicKey });
const payload = Payload.fromJSON({ record: registryRecord, signatures: [signature] });
const createMsg: MsgSetRecordEncodeObject = {
typeUrl: typeUrlMsgSetRecord,
value: {
signer,
bondId: params.bondId,
payload
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgSetRecordResponse>(response);
}
public async setAuthorityBond (
signer: string,
bondId: string,
name: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgSetAuthorityBondEncodeObject = {
typeUrl: typeUrlMsgSetAuthorityBond,
value: {
signer,
bondId,
name
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgSetAuthorityBondResponse>(response);
}
public async setName (
signer: string,
lrn: string,
cid: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgSetNameEncodeObject = {
typeUrl: typeUrlMsgSetName,
value: {
signer,
lrn,
cid
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgSetNameResponse>(response);
}
public async deleteName (
signer: string,
lrn: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createMsg: MsgDeleteNameEncodeObject = {
typeUrl: typeUrlMsgDeleteName,
value: {
signer,
lrn
}
};
const response = await this.signAndBroadcast(signer, [createMsg], fee, memo);
return this.parseResponse<MsgDeleteNameResponse>(response);
}
parseResponse<T> (response: DeliverTxResponse): T {
if (response.code !== 0) {
// Throw error when transaction is not successful.
throw new Error(this.processWriteError(response.rawLog || 'No raw log in response'));
}
return this.registry.decode(response.msgResponses[0]) as T;
}
processWriteError (error: string) {
const errorMessage = [...NAMESERVICE_ERRORS, ONBOARDING_DISABLED_ERROR].find(message => error.includes(message));
if (!errorMessage) {
console.error(error);
}
return `${errorMessage || DEFAULT_WRITE_ERROR}: ${error}`;
}
public async onboardParticipant (
signer: string,
ethPayload: EthPayload,
ethSignature: string,
role: string,
kycId: string,
fee: StdFee | 'auto' | number,
memo = ''
) {
const onboardParticipantMsg: MsgOnboardParticipantEncodeObject = {
typeUrl: typeUrlMsgOnboardParticipant,
value: {
participant: signer,
ethPayload,
ethSignature,
role,
kycId
}
};
const response = await this.signAndBroadcast(signer, [onboardParticipantMsg], fee, memo);
return this.parseResponse<MsgOnboardParticipantResponse>(response);
}
public async createAuction (
signer: string,
kind: string,
commitsDuration: string,
revealsDuration: string,
denom: string,
commitFee: string,
revealFee: string,
minimumBid: string,
maxPrice: string,
numProviders: number,
fee: StdFee | 'auto' | number,
memo = ''
) {
const createAuctionMsg: MsgCreateAuctionEncodeObject = {
typeUrl: typeUrlMsgCreateAuction,
value: {
signer,
kind,
commitsDuration: Duration.fromPartial({ seconds: Long.fromString(commitsDuration) }),
revealsDuration: Duration.fromPartial({ seconds: Long.fromString(revealsDuration) }),
commitFee: Coin.fromPartial({ amount: commitFee, denom }),
revealFee: Coin.fromPartial({ amount: revealFee, denom }),
minimumBid: Coin.fromPartial({ amount: minimumBid, denom }),
maxPrice: Coin.fromPartial({ amount: maxPrice, denom }),
numProviders
}
};
const response = await this.signAndBroadcast(signer, [createAuctionMsg], fee, memo);
return this.parseResponse<MsgCreateAuctionResponse>(response);
}
}