Change in registry constructor (#8)
This commit is contained in:
parent
67819510f7
commit
ea55cbdc7a
@ -21,7 +21,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
address = new Account(Buffer.from(privateKey, 'hex')).getCosmosAddress();
|
address = new Account(Buffer.from(privateKey, 'hex')).getCosmosAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const result = await registry.getAccounts([address]);
|
const result = await registry.getAccounts([address]);
|
||||||
|
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -39,7 +39,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
await ensureDir(outDirPath);
|
await ensureDir(outDirPath);
|
||||||
fs.writeFileSync(revealFilePath, JSON.stringify(reveal, undefined, 2));
|
fs.writeFileSync(revealFilePath, JSON.stringify(reveal, undefined, 2));
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
|
|
||||||
const result = await registry.commitBid({ auctionId, commitHash }, privateKey, fee);
|
const result = await registry.commitBid({ auctionId, commitHash }, privateKey, fee);
|
||||||
|
@ -23,7 +23,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
|
|
||||||
const reveal = fs.readFileSync(path.resolve(filePath));
|
const reveal = fs.readFileSync(path.resolve(filePath));
|
||||||
|
@ -18,7 +18,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const result = await registry.getAuctionsByIds([id as string]);
|
const result = await registry.getAuctionsByIds([id as string]);
|
||||||
|
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -21,7 +21,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.setAuthorityBond({ name, bondId }, privateKey, fee);
|
const result = await registry.setAuthorityBond({ name, bondId }, privateKey, fee);
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -27,7 +27,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.reserveAuthority({ name, owner }, privateKey, fee);
|
const result = await registry.reserveAuthority({ name, owner }, privateKey, fee);
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const result = await registry.lookupAuthorities([name], true);
|
const result = await registry.lookupAuthorities([name], true);
|
||||||
|
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -27,7 +27,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.associateBond({ recordId: id, bondId }, privateKey, fee);
|
const result = await registry.associateBond({ recordId: id, bondId }, privateKey, fee);
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -19,7 +19,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.cancelBond({ id }, privateKey, fee);
|
const result = await registry.cancelBond({ id }, privateKey, fee);
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -32,7 +32,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.createBond({ denom, amount }, privateKey, fee);
|
const result = await registry.createBond({ denom, amount }, privateKey, fee);
|
||||||
console.log(verbose ? JSON.stringify(result, undefined, 2) : result.data);
|
console.log(verbose ? JSON.stringify(result, undefined, 2) : result.data);
|
||||||
|
@ -19,7 +19,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.dissociateBond({ recordId: id }, privateKey, fee);
|
const result = await registry.dissociateBond({ recordId: id }, privateKey, fee);
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -18,7 +18,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
|
|
||||||
const result = await registry.getBondsByIds([id as string]);
|
const result = await registry.getBondsByIds([id as string]);
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -21,7 +21,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
|
|
||||||
const { owner } = argv;
|
const { owner } = argv;
|
||||||
const result = await registry.queryBonds({ owner });
|
const result = await registry.queryBonds({ owner });
|
||||||
|
@ -25,7 +25,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.dissociateRecords({ bondId }, privateKey, fee);
|
const result = await registry.dissociateRecords({ bondId }, privateKey, fee);
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -30,7 +30,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.reassociateRecords({ oldBondId, newBondId }, privateKey, fee);
|
const result = await registry.reassociateRecords({ oldBondId, newBondId }, privateKey, fee);
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -33,7 +33,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.refillBond({ id, denom, amount }, privateKey, fee);
|
const result = await registry.refillBond({ id, denom, amount }, privateKey, fee);
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -33,7 +33,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.withdrawBond({ id, denom, amount }, privateKey, fee);
|
const result = await registry.withdrawBond({ id, denom, amount }, privateKey, fee);
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -19,7 +19,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.deleteName({ crn: name }, privateKey, fee);
|
const result = await registry.deleteName({ crn: name }, privateKey, fee);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const result = await registry.lookupNames([name], argv.history as boolean);
|
const result = await registry.lookupNames([name], argv.history as boolean);
|
||||||
|
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -18,7 +18,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
|
|
||||||
const result = await registry.resolveNames([name]);
|
const result = await registry.resolveNames([name]);
|
||||||
console.log(JSON.stringify(result, undefined, 4));
|
console.log(JSON.stringify(result, undefined, 4));
|
||||||
|
@ -21,7 +21,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(privateKey, 'Invalid Transaction Key.');
|
assert(privateKey, 'Invalid Transaction Key.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.setName({ crn: name, cid: id }, privateKey, fee);
|
const result = await registry.setName({ crn: name, cid: id }, privateKey, fee);
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const result = await registry.getRecordsByIds([id as string]);
|
const result = await registry.getRecordsByIds([id as string]);
|
||||||
|
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -33,7 +33,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
|
|
||||||
const result = await registry.queryRecords({ bondId, type, name }, all as boolean);
|
const result = await registry.queryRecords({ bondId, type, name }, all as boolean);
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -36,7 +36,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { record } = await yaml.load(fs.readFileSync(file, 'utf-8')) as any;
|
const { record } = await yaml.load(fs.readFileSync(file, 'utf-8')) as any;
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
const result = await registry.setRecord({ privateKey: userKey, record, bondId }, txKey as string, fee);
|
const result = await registry.setRecord({ privateKey: userKey, record, bondId }, txKey as string, fee);
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
assert(gqlEndpoint, 'Invalid CNS GQL endpoint.');
|
||||||
assert(chainId, 'Invalid CNS Chain ID.');
|
assert(chainId, 'Invalid CNS Chain ID.');
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
|
|
||||||
const result = await registry.getStatus();
|
const result = await registry.getStatus();
|
||||||
console.log(JSON.stringify(result, undefined, 2));
|
console.log(JSON.stringify(result, undefined, 2));
|
||||||
|
@ -36,7 +36,7 @@ export const handler = async (argv: Arguments) => {
|
|||||||
const account = new Account(Buffer.from(privateKey, 'hex'));
|
const account = new Account(Buffer.from(privateKey, 'hex'));
|
||||||
const fromAddress = account.formattedCosmosAddress;
|
const fromAddress = account.formattedCosmosAddress;
|
||||||
|
|
||||||
const registry = new Registry(restEndpoint, gqlEndpoint, chainId);
|
const registry = new Registry(gqlEndpoint, restEndpoint, chainId);
|
||||||
const fee = getGasAndFees(argv, cnsConfig);
|
const fee = getGasAndFees(argv, cnsConfig);
|
||||||
await registry.sendCoins({ denom, amount, destinationAddress }, privateKey, fee);
|
await registry.sendCoins({ denom, amount, destinationAddress }, privateKey, fee);
|
||||||
const result = await registry.getAccounts([fromAddress, destinationAddress]);
|
const result = await registry.getAccounts([fromAddress, destinationAddress]);
|
||||||
|
@ -1148,9 +1148,9 @@ keccak@^3.0.0:
|
|||||||
node-gyp-build "^4.2.0"
|
node-gyp-build "^4.2.0"
|
||||||
readable-stream "^3.6.0"
|
readable-stream "^3.6.0"
|
||||||
|
|
||||||
"laconic-client@https://github.com/cerc-io/laconic-client.git#dboreham/release":
|
"laconic-sdk@https://github.com/cerc-io/laconic-sdk.git#dboreham/release":
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://github.com/cerc-io/laconic-client.git#9176bb1a5a5ba225f021c9e6cca2ccc5dc24f7f2"
|
resolved "https://github.com/cerc-io/laconic-sdk.git#9176bb1a5a5ba225f021c9e6cca2ccc5dc24f7f2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@cosmjs/amino" "^0.28.1"
|
"@cosmjs/amino" "^0.28.1"
|
||||||
"@cosmjs/crypto" "^0.28.1"
|
"@cosmjs/crypto" "^0.28.1"
|
||||||
|
Loading…
Reference in New Issue
Block a user