Skip to content

Commit

Permalink
Merge pull request #275 from Concordium/ccd-js-gen-schema-param
Browse files Browse the repository at this point in the history
Use schema information when generating client
  • Loading branch information
limemloh authored Oct 12, 2023
2 parents ad93b49 + d340b75 commit 5285fa1
Show file tree
Hide file tree
Showing 31 changed files with 2,430 additions and 418 deletions.
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> {
)
.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

0 comments on commit 5285fa1

Please sign in to comment.