@cosmwasm/ts-codegen 0.16.5 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,118 @@
1
+ import { resolve, join, dirname, basename, extname } from 'path';
2
+ import { sync as mkdirp } from 'mkdirp';
3
+ import { sync as glob } from 'glob';
4
+ import { sync as rimraf } from 'rimraf';
5
+ import { exec } from 'shelljs';
6
+ import { prompt } from '../utils/prompt';
7
+ import { parse } from 'parse-package-name';
8
+ import { tmpdir } from 'os';
9
+ import { readFileSync, writeFileSync } from 'fs';
10
+
11
+ const TMPDIR = tmpdir();
12
+ const rnd = () =>
13
+ Math.random().toString(36).substring(2, 15) +
14
+ Math.random().toString(36).substring(2, 15);
15
+
16
+ const getPackages = (names) => {
17
+ return names.map(pkg => {
18
+ const { name, version } = parse(pkg);
19
+ return `${name}@${version}`
20
+ }).join(' ');
21
+ };
22
+
23
+ export default async (argv) => {
24
+
25
+ // don't prompt if we got this...
26
+ if (argv._.length) {
27
+ argv.pkg = argv._;
28
+ }
29
+
30
+ // current dir/package
31
+ const cur = process.cwd();
32
+ let thisPackage;
33
+ try {
34
+ thisPackage = JSON.parse(readFileSync(join(cur, 'package.json'), 'utf-8'));
35
+ } catch (e) {
36
+ throw new Error('make sure you are inside of a telescope package!');
37
+ }
38
+
39
+ // what are we installing?
40
+ let { pkg } = await prompt([
41
+ {
42
+ type: 'checkbox',
43
+ name: 'pkg',
44
+ message:
45
+ 'which chain contracts do you want to support?',
46
+ choices: [
47
+ 'stargaze-base-factory',
48
+ 'stargaze-base-minter',
49
+ 'stargaze-sg721-base',
50
+ 'stargaze-sg721-metdata-onchain',
51
+ 'stargaze-sg721-nt',
52
+ 'stargaze-splits',
53
+ 'stargaze-vending-factory',
54
+ 'stargaze-vending-minter',
55
+ 'stargaze-whitelist',
56
+ 'wasmswap'
57
+ ].map(name => {
58
+ return {
59
+ name,
60
+ value: `@cosmjson/${name}`
61
+ }
62
+ })
63
+ }
64
+ ], argv);
65
+
66
+ // install
67
+ if (!Array.isArray(pkg)) pkg = [pkg];
68
+ const tmp = join(TMPDIR, rnd());
69
+ mkdirp(tmp);
70
+ process.chdir(tmp);
71
+ exec(`npm install ${getPackages(pkg)} --production --prefix ./smart-contracts`);
72
+
73
+ // protos
74
+ const pkgs = glob('./smart-contracts/**/package.json');
75
+ const cmds = pkgs
76
+ .filter((f) => { return f !== './smart-contracts/package.json' })
77
+ .map((f) => resolve(join(tmp, f)))
78
+ .map((conf) => {
79
+ const extDir = dirname(conf);
80
+ const dir = extDir.split('node_modules/')[1];
81
+ const dst = basename(dir);
82
+
83
+ const files = glob(`${extDir}/**/*`, { nodir: true });
84
+ files.forEach(f => {
85
+ if (extname(f) === '.json'
86
+ || f === 'package.json'
87
+ || /license/i.test(f)
88
+ || /readme/i.test(f)) return;
89
+ rimraf(f);
90
+ });
91
+ return [extDir, resolve(join(cur, 'contracts', dst)), dir];
92
+ });
93
+
94
+ // move protos
95
+ for (const [src, dst, pkg] of cmds) {
96
+ rimraf(dst);
97
+ console.log(`installing ${pkg}...`);
98
+ mkdirp(dirname(dst));
99
+ exec(`mv ${src} ${dst}`);
100
+ }
101
+
102
+ // package
103
+ const packageInfo = JSON.parse(readFileSync('./smart-contracts/package.json', 'utf-8'));
104
+ const deps = packageInfo.dependencies ?? {};
105
+ thisPackage.devDependencies = thisPackage.devDependencies ?? {};
106
+ thisPackage.devDependencies = {
107
+ ...thisPackage.devDependencies,
108
+ ...deps
109
+ };
110
+
111
+ thisPackage.devDependencies = Object.fromEntries(Object.entries(thisPackage.devDependencies).sort());
112
+
113
+ writeFileSync(join(cur, 'package.json'), JSON.stringify(thisPackage, null, 2));
114
+
115
+ // cleanup
116
+ rimraf(tmp);
117
+ process.chdir(cur);
118
+ };
package/src/file.js ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ import { prompt } from './utils/prompt';
3
+ import { cli } from './cli';
4
+ import { readFileSync } from 'fs';
5
+ const argv = require('minimist')(process.argv.slice(2));
6
+
7
+ const question = [
8
+ {
9
+ _: true,
10
+ type: 'string',
11
+ name: 'file',
12
+ message: 'file'
13
+ }
14
+ ];
15
+
16
+ (async () => {
17
+ const { file } = await prompt(question, argv);
18
+ const argvv = JSON.parse(readFileSync(file, 'utf-8'));
19
+ await cli(argvv);
20
+ })();
@@ -0,0 +1,108 @@
1
+ import { pascal } from "case";
2
+ import { header } from '../utils/header';
3
+ import { join } from "path";
4
+ import { sync as mkdirp } from "mkdirp";
5
+ import * as w from 'wasm-ast-types';
6
+ import * as t from '@babel/types';
7
+ import { writeFileSync } from 'fs';
8
+ import generate from "@babel/generator";
9
+ import { ContractInfo, getMessageProperties } from "wasm-ast-types";
10
+ import { findAndParseTypes, findExecuteMsg, findQueryMsg } from '../utils';
11
+ import { RenderContext, TSClientOptions } from "wasm-ast-types";
12
+ import { BuilderFile } from "../builder";
13
+
14
+ export default async (
15
+ name: string,
16
+ contractInfo: ContractInfo,
17
+ outPath: string,
18
+ tsClientOptions?: TSClientOptions
19
+ ): Promise<BuilderFile[]> => {
20
+
21
+ const { schemas } = contractInfo;
22
+ const context = new RenderContext(contractInfo, {
23
+ client: tsClientOptions ?? {}
24
+ });
25
+ // const options = context.options.client;
26
+
27
+ const localname = pascal(name) + '.client.ts';
28
+ const TypesFile = pascal(name) + '.types'
29
+ const QueryMsg = findQueryMsg(schemas);
30
+ const ExecuteMsg = findExecuteMsg(schemas);
31
+ const typeHash = await findAndParseTypes(schemas);
32
+
33
+ let Client = null;
34
+ let Instance = null;
35
+ let QueryClient = null;
36
+ let ReadOnlyInstance = null;
37
+
38
+ const body = [];
39
+
40
+ body.push(
41
+ w.importStmt(Object.keys(typeHash), `./${TypesFile}`)
42
+ );
43
+
44
+ // query messages
45
+ if (QueryMsg) {
46
+
47
+ QueryClient = pascal(`${name}QueryClient`);
48
+ ReadOnlyInstance = pascal(`${name}ReadOnlyInterface`);
49
+
50
+ body.push(
51
+ w.createQueryInterface(context, ReadOnlyInstance, QueryMsg)
52
+ );
53
+ body.push(
54
+ w.createQueryClass(context, QueryClient, ReadOnlyInstance, QueryMsg)
55
+ );
56
+ }
57
+
58
+ // execute messages
59
+ if (ExecuteMsg) {
60
+ const children = getMessageProperties(ExecuteMsg);
61
+ if (children.length > 0) {
62
+ Client = pascal(`${name}Client`);
63
+ Instance = pascal(`${name}Interface`);
64
+
65
+ body.push(
66
+ w.createExecuteInterface(
67
+ context,
68
+ Instance,
69
+ ReadOnlyInstance,
70
+ ExecuteMsg
71
+ )
72
+ );
73
+ body.push(
74
+ w.createExecuteClass(
75
+ context,
76
+ Client,
77
+ Instance,
78
+ QueryClient,
79
+ ExecuteMsg
80
+ )
81
+ );
82
+ }
83
+ }
84
+
85
+ if (typeHash.hasOwnProperty('Coin')) {
86
+ // @ts-ignore
87
+ delete context.utils.Coin;
88
+ }
89
+ const imports = context.getImports();
90
+ const code = header + generate(
91
+ t.program([
92
+ ...imports,
93
+ ...body
94
+ ])
95
+ ).code;
96
+
97
+ mkdirp(outPath);
98
+ writeFileSync(join(outPath, localname), code);
99
+
100
+ return [
101
+ {
102
+ type: 'client',
103
+ contract: name,
104
+ localname,
105
+ filename: join(outPath, localname),
106
+ }
107
+ ]
108
+ };
@@ -0,0 +1,86 @@
1
+ import { pascal } from "case";
2
+ import { header } from '../utils/header';
3
+ import { join } from "path";
4
+ import { sync as mkdirp } from "mkdirp";
5
+ import * as w from 'wasm-ast-types';
6
+ import * as t from '@babel/types';
7
+ import { writeFileSync } from 'fs';
8
+ import generate from "@babel/generator";
9
+ import { ContractInfo, getMessageProperties } from "wasm-ast-types";
10
+ import { findAndParseTypes, findExecuteMsg } from "../utils";
11
+ import { RenderContext, MessageComposerOptions } from "wasm-ast-types";
12
+ import { BuilderFile } from "../builder";
13
+
14
+ export default async (
15
+ name: string,
16
+ contractInfo: ContractInfo,
17
+ outPath: string,
18
+ messageComposerOptions?: MessageComposerOptions
19
+ ): Promise<BuilderFile[]> => {
20
+
21
+ const { schemas } = contractInfo;
22
+ const context = new RenderContext(contractInfo, {
23
+ messageComposer: messageComposerOptions ?? {}
24
+ });
25
+ // const options = context.options.messageComposer;
26
+
27
+ const localname = pascal(name) + '.message-composer.ts';
28
+ const TypesFile = pascal(name) + '.types';
29
+ const ExecuteMsg = findExecuteMsg(schemas);
30
+ const typeHash = await findAndParseTypes(schemas);
31
+
32
+ const body = [];
33
+
34
+ body.push(
35
+ w.importStmt(Object.keys(typeHash), `./${TypesFile}`)
36
+ );
37
+
38
+ // execute messages
39
+ if (ExecuteMsg) {
40
+ const children = getMessageProperties(ExecuteMsg);
41
+ if (children.length > 0) {
42
+ const TheClass = pascal(`${name}MessageComposer`);
43
+ const Interface = pascal(`${name}Message`);
44
+
45
+ body.push(
46
+ w.createMessageComposerInterface(
47
+ context,
48
+ Interface,
49
+ ExecuteMsg
50
+ )
51
+ );
52
+ body.push(
53
+ w.createMessageComposerClass(
54
+ context,
55
+ TheClass,
56
+ Interface,
57
+ ExecuteMsg
58
+ )
59
+ );
60
+ }
61
+ }
62
+
63
+ if (typeHash.hasOwnProperty('Coin')) {
64
+ // @ts-ignore
65
+ delete context.utils.Coin;
66
+ }
67
+ const imports = context.getImports();
68
+ const code = header + generate(
69
+ t.program([
70
+ ...imports,
71
+ ...body
72
+ ])
73
+ ).code;
74
+
75
+ mkdirp(outPath);
76
+ writeFileSync(join(outPath, localname), code);
77
+
78
+ return [
79
+ {
80
+ type: 'message-composer',
81
+ contract: name,
82
+ localname,
83
+ filename: join(outPath, localname),
84
+ }
85
+ ]
86
+ };
@@ -0,0 +1,102 @@
1
+ import { pascal } from "case";
2
+ import { header } from '../utils/header';
3
+ import { join } from "path";
4
+ import { sync as mkdirp } from "mkdirp";
5
+ import * as w from 'wasm-ast-types';
6
+ import { RenderContext } from 'wasm-ast-types';
7
+ import * as t from '@babel/types';
8
+ import { writeFileSync } from 'fs';
9
+ import generate from "@babel/generator";
10
+ import { findAndParseTypes, findExecuteMsg, findQueryMsg } from '../utils';
11
+ import { getMessageProperties, ReactQueryOptions, ContractInfo } from "wasm-ast-types";
12
+ import { BuilderFile } from "../builder";
13
+
14
+ export default async (
15
+ contractName: string,
16
+ contractInfo: ContractInfo,
17
+ outPath: string,
18
+ reactQueryOptions?: ReactQueryOptions
19
+ ): Promise<BuilderFile[]> => {
20
+ const { schemas } = contractInfo;
21
+ const context = new RenderContext(contractInfo, {
22
+ reactQuery: reactQueryOptions ?? {}
23
+ });
24
+ const options = context.options.reactQuery;
25
+
26
+ const localname = pascal(`${contractName}`) + '.react-query.ts';
27
+ const ContractFile = pascal(`${contractName}`) + '.client';
28
+ const TypesFile = pascal(`${contractName}`) + '.types';
29
+
30
+ const QueryMsg = findQueryMsg(schemas);
31
+ const ExecuteMsg = findExecuteMsg(schemas);
32
+ const typeHash = await findAndParseTypes(schemas);
33
+
34
+ const ExecuteClient = pascal(`${contractName}Client`);
35
+ const QueryClient = pascal(`${contractName}QueryClient`);
36
+
37
+ const body = [];
38
+
39
+ const clientImports = []
40
+
41
+ QueryMsg && clientImports.push(QueryClient)
42
+
43
+ // check that there are commands within the exec msg
44
+ const shouldGenerateMutationHooks = ExecuteMsg && options?.version === 'v4' && options?.mutations && getMessageProperties(ExecuteMsg).length > 0
45
+
46
+ if (shouldGenerateMutationHooks) {
47
+ clientImports.push(ExecuteClient)
48
+ }
49
+
50
+ // general contract imports
51
+ body.push(w.importStmt(Object.keys(typeHash), `./${TypesFile}`));
52
+
53
+ // client imports
54
+ body.push(w.importStmt(clientImports, `./${ContractFile}`));
55
+
56
+ // query messages
57
+ if (QueryMsg) {
58
+ [].push.apply(body,
59
+ w.createReactQueryHooks({
60
+ context,
61
+ queryMsg: QueryMsg,
62
+ contractName: contractName,
63
+ QueryClient
64
+ })
65
+ );
66
+ }
67
+
68
+ if (shouldGenerateMutationHooks) {
69
+ [].push.apply(body,
70
+ w.createReactQueryMutationHooks({
71
+ context,
72
+ execMsg: ExecuteMsg,
73
+ contractName: contractName,
74
+ ExecuteClient
75
+ })
76
+ );
77
+ }
78
+
79
+ if (typeHash.hasOwnProperty('Coin')) {
80
+ // @ts-ignore
81
+ delete context.utils.Coin;
82
+ }
83
+ const imports = context.getImports();
84
+ const code = header + generate(
85
+ t.program([
86
+ ...imports,
87
+ ...body
88
+ ])
89
+ ).code;
90
+
91
+ mkdirp(outPath);
92
+ writeFileSync(join(outPath, localname), code);
93
+
94
+ return [
95
+ {
96
+ type: 'react-query',
97
+ contract: contractName,
98
+ localname,
99
+ filename: join(outPath, localname),
100
+ }
101
+ ]
102
+ };
@@ -0,0 +1,92 @@
1
+ import { pascal } from "case";
2
+ import { header } from '../utils/header';
3
+ import { join } from "path";
4
+ import { sync as mkdirp } from "mkdirp";
5
+ import * as w from 'wasm-ast-types';
6
+ import * as t from '@babel/types';
7
+ import { writeFileSync } from 'fs';
8
+ import generate from "@babel/generator";
9
+ import { findAndParseTypes, findQueryMsg } from "../utils";
10
+ import { ContractInfo, RenderContext, RecoilOptions } from "wasm-ast-types";
11
+ import { BuilderFile } from "../builder";
12
+
13
+ export default async (
14
+ name: string,
15
+ contractInfo: ContractInfo,
16
+ outPath: string,
17
+ recoilOptions?: RecoilOptions
18
+ ): Promise<BuilderFile[]> => {
19
+
20
+ const { schemas } = contractInfo;
21
+ const context = new RenderContext(contractInfo, {
22
+ recoil: recoilOptions ?? {}
23
+ });
24
+ const options = context.options.recoil;
25
+
26
+ const localname = pascal(name) + '.recoil.ts';
27
+ const ContractFile = pascal(name) + '.client';
28
+ const TypesFile = pascal(name) + '.types';
29
+
30
+ const QueryMsg = findQueryMsg(schemas);
31
+ const typeHash = await findAndParseTypes(schemas);
32
+
33
+ let QueryClient = null;
34
+ let ReadOnlyInstance = null;
35
+
36
+ const body = [];
37
+
38
+ body.push(
39
+ w.importStmt(['cosmWasmClient'], './chain')
40
+ );
41
+
42
+ body.push(
43
+ w.importStmt(Object.keys(typeHash), `./${TypesFile}`)
44
+ );
45
+
46
+ // query messages
47
+ if (QueryMsg) {
48
+
49
+ QueryClient = pascal(`${name}QueryClient`);
50
+ ReadOnlyInstance = pascal(`${name}ReadOnlyInterface`);
51
+
52
+ body.push(
53
+ w.importStmt([QueryClient], `./${ContractFile}`)
54
+ );
55
+
56
+ body.push(w.createRecoilQueryClientType());
57
+ body.push(w.createRecoilQueryClient(
58
+ context,
59
+ name,
60
+ QueryClient
61
+ ));
62
+
63
+ [].push.apply(body,
64
+ w.createRecoilSelectors(context, name, QueryClient, QueryMsg)
65
+ );
66
+
67
+ }
68
+
69
+ if (typeHash.hasOwnProperty('Coin')) {
70
+ // @ts-ignore
71
+ delete context.utils.Coin;
72
+ }
73
+ const imports = context.getImports();
74
+ const code = header + generate(
75
+ t.program([
76
+ ...imports,
77
+ ...body
78
+ ])
79
+ ).code;
80
+
81
+ mkdirp(outPath);
82
+ writeFileSync(join(outPath, localname), code);
83
+
84
+ return [
85
+ {
86
+ type: 'recoil',
87
+ contract: name,
88
+ localname,
89
+ filename: join(outPath, localname),
90
+ }
91
+ ]
92
+ };
@@ -0,0 +1,72 @@
1
+ import { pascal } from "case";
2
+ import { header } from '../utils/header';
3
+ import { join } from "path";
4
+ import { sync as mkdirp } from "mkdirp";
5
+ import * as t from '@babel/types';
6
+ import { writeFileSync } from 'fs';
7
+ import generate from "@babel/generator";
8
+ import { clean } from "../utils/clean";
9
+ import { findAndParseTypes, findExecuteMsg } from '../utils';
10
+ import { ContractInfo, RenderContext, TSTypesOptions } from "wasm-ast-types";
11
+ import { BuilderFile } from "../builder";
12
+
13
+ export default async (
14
+ name: string,
15
+ contractInfo: ContractInfo,
16
+ outPath: string,
17
+ tsTypesOptions?: TSTypesOptions
18
+ ): Promise<BuilderFile[]> => {
19
+
20
+ const { schemas } = contractInfo;
21
+ const context = new RenderContext(contractInfo, {
22
+ types: tsTypesOptions ?? {}
23
+ });
24
+ const options = context.options.types;
25
+
26
+ const localname = pascal(name) + '.types.ts';
27
+ const ExecuteMsg = findExecuteMsg(schemas);
28
+ const typeHash = await findAndParseTypes(schemas);
29
+
30
+ const body = [];
31
+
32
+ // TYPES
33
+ Object.values(typeHash).forEach((type: t.Node) => {
34
+ body.push(
35
+ clean(type)
36
+ )
37
+ });
38
+
39
+ // alias the ExecuteMsg
40
+ if (options.aliasExecuteMsg && ExecuteMsg) {
41
+ body.push(
42
+ t.exportNamedDeclaration(
43
+ t.tsTypeAliasDeclaration(
44
+ t.identifier(`${name}ExecuteMsg`),
45
+ null,
46
+ t.tsTypeReference(t.identifier('ExecuteMsg'))
47
+ )
48
+ )
49
+ );
50
+ }
51
+
52
+ const imports = context.getImports();
53
+ const code = header + generate(
54
+ t.program([
55
+ ...imports,
56
+ ...body
57
+ ])
58
+ ).code;
59
+
60
+ mkdirp(outPath);
61
+ const filename = join(outPath, localname);
62
+ writeFileSync(filename, code);
63
+
64
+ return [
65
+ {
66
+ type: 'type',
67
+ contract: name,
68
+ localname,
69
+ filename,
70
+ }
71
+ ]
72
+ };
package/src/index.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { TSBuilder, TSBuilderInput } from './builder';
2
+
3
+ export { default as generateTypes } from './generators/types';
4
+ export { default as generateClient } from './generators/client';
5
+ export { default as generateMessageComposer } from './generators/message-composer';
6
+ export { default as generateReactQuery } from './generators/react-query';
7
+ export { default as generateRecoil } from './generators/recoil';
8
+
9
+ export * from './utils';
10
+ export * from './builder';
11
+ export * from './bundler';
12
+
13
+ export default async (input: TSBuilderInput) => {
14
+ const builder = new TSBuilder(input);
15
+ await builder.build();
16
+ };
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { cli } from './cli';
3
+ var argv = require('minimist')(process.argv.slice(2));
4
+
5
+ (async () => {
6
+ await cli(argv);
7
+ })();
@@ -0,0 +1,45 @@
1
+ export const clean = (obj) => {
2
+ var copy;
3
+ // Handle the 3 simple types, and null or undefined
4
+ if (null == obj || 'object' != typeof obj) return obj;
5
+
6
+ // Handle Date
7
+ if (obj instanceof Date) {
8
+ copy = new Date();
9
+ copy.setTime(obj.getTime());
10
+ return copy;
11
+ }
12
+
13
+ // Handle Array
14
+ if (obj instanceof Array) {
15
+ copy = [];
16
+ for (var i = 0, len = obj.length; i < len; i++) {
17
+ copy[i] = clean(obj[i]);
18
+ }
19
+ return copy;
20
+ }
21
+
22
+ // Handle Object
23
+ if (obj instanceof Object || typeof obj === 'object') {
24
+ copy = {};
25
+ for (var attr in obj) {
26
+ if (obj.hasOwnProperty(attr)) {
27
+ switch (attr) {
28
+ case 'leadingComments':
29
+ case 'trailingComments':
30
+ case 'loc':
31
+ case 'start':
32
+ case 'end':
33
+ break;
34
+ default:
35
+ copy[attr] = clean(obj[attr]);
36
+ }
37
+ } else {
38
+ copy[attr] = clean(obj[attr]);
39
+ }
40
+ }
41
+ return copy;
42
+ }
43
+
44
+ throw new Error("Unable to copy obj! Its type isn't supported.");
45
+ };