Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use schema information when generating client #275

Merged
merged 15 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions examples/ccd-js-gen/wCCD/client-error-message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { credentials } from '@grpc/grpc-js';
import * as SDK from '@concordium/web-sdk';
import { ConcordiumGRPCNodeClient } from '@concordium/web-sdk/nodejs';
import meow from 'meow';
import { parseEndpoint } from '../../shared/util.js';

// The generated module could be imported directly like below,
// but for this example it is imported dynamicly to improve
// the error message when not generated.
// import * as wCCDContractClient from './lib/cis2_wCCD';

const cli = meow(
`
This example uses a generated smart contract client for the wCCD smart contract.

Usage
$ yarn run-example <path-to-this-file> [options]

Required
--index, -i The index of the smart contract. Defaults to 2059, which is wCCD on testnet.

Options
--help, -h Displays this message
--endpoint, -e Specify endpoint of a grpc2 interface of a Concordium node in the format "<scheme>://<address>:<port>". Defaults to 'http://localhost:20000'
--subindex, The subindex of the smart contract. Defaults to 0
`,
{
importMeta: import.meta,
flags: {
endpoint: {
type: 'string',
alias: 'e',
default: 'http://localhost:20000',
},
index: {
type: 'number',
alias: 'i',
default: 2059,
},
subindex: {
type: 'number',
default: 0,
},
},
}
);

const [address, port, scheme] = parseEndpoint(cli.flags.endpoint);
const grpcClient = new ConcordiumGRPCNodeClient(
address,
Number(port),
scheme === 'https' ? credentials.createSsl() : credentials.createInsecure()
);

const contractAddress = SDK.ContractAddress.create(
cli.flags.index,
cli.flags.subindex
);

(async () => {
// Importing the generated smart contract module client.
/* eslint-disable import/no-unresolved */
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const wCCDContractClient = await import('./lib/wCCD_cis2_wCCD.js').catch(
(e) => {
/* eslint-enable import/no-unresolved */
console.error(
'\nFailed to load the generated wCCD module, did you run the `generate` script?\n'
);
throw e;
}
);

const wCCDTokenId = '';
const fromAddress = SDK.AccountAddress.fromBuffer(
new Uint8Array(32).fill(0)
);
const toAddress = SDK.AccountAddress.fromBuffer(new Uint8Array(32).fill(1));
const parameter = [
{
token_id: wCCDTokenId,
amount: 1000,
from: { type: 'Account', content: fromAddress },
to: { type: 'Account', content: toAddress },
data: '',
} as const,
];
const contract = await wCCDContractClient.create(
grpcClient,
contractAddress
);

const unauthorizedInvoker = SDK.AccountAddress.fromBase58(
'357EYHqrmMiJBmUZTVG5FuaMq4soAhgtgz6XNEAJaXHW3NHaUf'
);

const result = await wCCDContractClient.dryRunTransfer(
contract,
parameter,
{
invoker: unauthorizedInvoker,
}
);
const errorMessage = wCCDContractClient.parseErrorMessageTransfer(result);
console.log('Transfer failed with error: ', errorMessage);
})();
113 changes: 113 additions & 0 deletions examples/ccd-js-gen/wCCD/client-events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { credentials } from '@grpc/grpc-js';
import { ConcordiumGRPCNodeClient } from '@concordium/web-sdk/nodejs';
import * as SDK from '@concordium/web-sdk';
import meow from 'meow';
import { parseEndpoint } from '../../shared/util.js';

// The generated module could be imported directly like below,
// but for this example it is imported dynamicly to improve
// the error message when not generated.
// import * as wCCDContractClient from './lib/cis2_wCCD.js';

const cli = meow(
`
This example uses a generated smart contract client for the wCCD smart contract to display events.

Usage
$ yarn run-example <path-to-this-file> [options]

Required
--index, -i The index of the smart contract. Defaults to 2059, which is wCCD on testnet.

Options
--help, -h Displays this message
--endpoint, -e Specify endpoint of a grpc2 interface of a Concordium node in the format "<scheme>://<address>:<port>". Defaults to 'http://localhost:20000'
--subindex, The subindex of the smart contract. Defaults to 0
`,
{
importMeta: import.meta,
flags: {
endpoint: {
type: 'string',
alias: 'e',
default: 'http://localhost:20000',
},
index: {
type: 'number',
alias: 'i',
default: 2059,
},
subindex: {
type: 'number',
default: 0,
},
},
}
);

const [address, port, scheme] = parseEndpoint(cli.flags.endpoint);
const grpcClient = new ConcordiumGRPCNodeClient(
address,
Number(port),
scheme === 'https' ? credentials.createSsl() : credentials.createInsecure()
);

const contractAddress = SDK.ContractAddress.create(
cli.flags.index,
cli.flags.subindex
);

(async () => {
// Importing the generated smart contract module client.
/* eslint-disable import/no-unresolved */
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const wCCDContractClient = await import('./lib/wCCD_cis2_wCCD.js').catch(
(e) => {
/* eslint-enable import/no-unresolved */
console.error(
'\nFailed to load the generated wCCD module, did you run the `generate` script?\n'
);
throw e;
}
);

// The sender of the transaction, i.e the one updating an operator.
const senderAccount = SDK.AccountAddress.fromBase58(
'357EYHqrmMiJBmUZTVG5FuaMq4soAhgtgz6XNEAJaXHW3NHaUf'
);
// The parameter adding the wCCD contract as an operator of sender.
const parameter = [
{
update: { type: 'Add' },
operator: { type: 'Contract', content: contractAddress },
} as const,
];

// The client for the wCCD contract
const contract = await wCCDContractClient.create(
grpcClient,
contractAddress
);

// Dry run the update of operator.
const result = await wCCDContractClient.dryRunUpdateOperator(
contract,
parameter,
{ invoker: senderAccount }
);
if (result.tag !== 'success') {
throw new Error('Unexpected failure');
}
for (const traceEvent of result.events) {
if (
traceEvent.tag === SDK.TransactionEventTag.Updated ||
traceEvent.tag === SDK.TransactionEventTag.Interrupted
) {
for (const contractEvent of traceEvent.events) {
const parsed = wCCDContractClient.parseEvent(contractEvent);
console.log(parsed);
}
}
}
})();
29 changes: 17 additions & 12 deletions examples/ccd-js-gen/wCCD/client-tokenMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,26 +62,31 @@ const contractAddress = SDK.ContractAddress.create(
/* eslint-disable import/no-unresolved */
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const wCCDContractClient = await import('./lib/cis2_wCCD.js').catch((e) => {
/* eslint-enable import/no-unresolved */
console.error(
'\nFailed to load the generated wCCD module, did you run the `generate` script?\n'
);
throw e;
});
const wCCDContractClient = await import('./lib/wCCD_cis2_wCCD.js').catch(
(e) => {
/* eslint-enable import/no-unresolved */
console.error(
'\nFailed to load the generated wCCD module, did you run the `generate` script?\n'
);
throw e;
}
);

const parameter = SDK.Parameter.fromHexString('010000'); // First 2 bytes for number of tokens to query, 1 byte for the token ID.
const wCCDTokenId = '';
const parameter = [wCCDTokenId];
const contract = await wCCDContractClient.create(
grpcClient,
contractAddress
);

const result = await wCCDContractClient.dryRunTokenMetadata(
contract,
SDK.AccountAddress.fromBase58(
'357EYHqrmMiJBmUZTVG5FuaMq4soAhgtgz6XNEAJaXHW3NHaUf'
),
parameter
);
console.log({ result });
const returnValue =
wCCDContractClient.parseReturnValueTokenMetadata(result);
console.log(
'The token metadata for wCCD can be found at: ',
returnValue?.[0].url
);
})();
2 changes: 2 additions & 0 deletions examples/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
This is a collection of scripts/examples that utilizes the SDK. There are
three directories with examples:

- `ccd-js-gen` containing examples with generate and using smart contract clients.
- `client` containing examples that utilize the client to interact with
a Concordium node.
- `cis2` containing examples that helps interact with CIS-2 compliant smart contracts.
- `cis4` containing examples that helps interact with CIS-4 compliant smart contracts.
- `common` that use various general functions from the library.

To run an example call:
Expand Down
3 changes: 1 addition & 2 deletions packages/ccd-js-gen/bin/ccd-js-gen.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env node
// eslint-disable-next-line @typescript-eslint/no-var-requires
#!/usr/bin/env -S node --no-warnings
import { main } from '../lib/src/cli.js';
main();
6 changes: 5 additions & 1 deletion packages/ccd-js-gen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@
"url": "https://concordium.com"
},
"license": "Apache-2.0",
"peerDependencies": {
"@concordium/web-sdk": "6.x"
},
"dependencies": {
"@concordium/web-sdk": "6.4.0",
"@concordium/web-sdk": "6.x",
"buffer": "^6.0.3",
"commander": "^11.0.0",
"sanitize-filename": "^1.6.3",
"ts-morph": "^19.0.0"
},
"devDependencies": {
Expand Down
21 changes: 17 additions & 4 deletions packages/ccd-js-gen/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
This file contains code for building the command line inferface to the ccd-js-gen library.
*/
import { Command } from 'commander';
import packageJson from '../package.json';
import packageJson from '../package.json' assert { type: 'json' };
import * as lib from './lib.js';

/** Type representing the CLI options/arguments and needs to match the options set with commander.js */
Expand All @@ -13,11 +13,11 @@ type Options = {
outDir: string;
};

// Main function, which is called be the executable script in `bin`.
// Main function, which is called in the executable script in `bin`.
export async function main(): Promise<void> {
const program = new Command();
program
.name(packageJson.name)
.name('ccd-js-gen')
.description(packageJson.description)
.version(packageJson.version)
.requiredOption(
Expand All @@ -30,5 +30,18 @@ export async function main(): Promise<void> {
)
limemloh marked this conversation as resolved.
Show resolved Hide resolved
.parse(process.argv);
const options = program.opts<Options>();
await lib.generateContractClientsFromFile(options.module, options.outDir);
console.log('Generating smart contract clients...');

const startTime = Date.now();
await lib.generateContractClientsFromFile(options.module, options.outDir, {
onProgress(update) {
if (update.type === 'Progress') {
console.log(
`[${update.doneItems}/${update.totalItems}] ${update.spentTime}ms`
);
}
},
});

console.log(`Done in ${Date.now() - startTime}ms`);
}
Loading