diff --git a/CHANGELOG.md b/CHANGELOG.md index e8e143c..0ee2373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### 0.1.8 - 2021-09-22 +- Fixed parser issue, when extra spaces are present in argument definition + ### 0.1.7 - 2021-09-20 - Added support for Optionals - Added support for multi-line arguments diff --git a/dev-test/test/args.test.js b/dev-test/test/args.test.js index 3aa7775..a754022 100644 --- a/dev-test/test/args.test.js +++ b/dev-test/test/args.test.js @@ -24,6 +24,34 @@ describe("optional arguments", () => { return emulator.stop(); }); + it("failing split", async () => { + const input = ["Hello"]; + const cadence = ` + pub fun main(message: String):String { + return message + } + `; + + const args = () => mapValuesToCode(cadence, input); + const output = await query({ cadence, args }); + + expect(output).toBe(input[0]); + }); + + it("basic - UFix64 and Address", async () => { + const input = [1337, "0x01"]; + const cadence = ` + pub fun main(number: UFix64, address: Address):UFix64{ + return number + } + `; + + const args = () => mapValuesToCode(cadence, input); + const output = await query({ cadence, args }); + + expect(output).toBe(toFixedValue(input[0])); + }); + it("optionals - String? - no value", async () => { const input = null; const cadence = ` diff --git a/package-lock.json b/package-lock.json index a56898d..9837c5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,21 @@ { "name": "flow-cadut", - "version": "0.1.6", + "version": "0.1.7", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.1.6", + "version": "0.1.7", "license": "Apache-2.0", "dependencies": { "@babel/preset-env": "^7.14.5", "@onflow/config": "0.0.2", - "@onflow/fcl": "^0.0.71", + "@onflow/fcl": "^0.0.76", "@onflow/types": "^0.0.4", "esm": "^3.2.25", "handlebars": "^4.7.7", "handlebars-loader": "^1.7.1", + "prettier": "^2.3.0", "rimraf": "^3.0.2", "simple-git": "^2.40.0", "yargs": "^15.4.1" @@ -30,8 +31,7 @@ "eslint-plugin-jest": "^24.3.6", "jest": "^26.6.3", "jest-esm-transformer": "^1.0.0", - "microbundle": "^0.13.0", - "prettier": "^2.3.0" + "microbundle": "^0.13.0" } }, "node_modules/@babel/cli": { @@ -1677,17 +1677,23 @@ } }, "node_modules/@improbable-eng/grpc-web": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.0.tgz", - "integrity": "sha512-ag1PTMWpBZKGi6GrEcZ4lkU5Qag23Xjo10BmnK9qyx4TMmSVcWmQ3rECirfQzm2uogrM9n1M6xfOpFsJP62ivA==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", + "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", "dependencies": { "browser-headers": "^0.4.1" + }, + "peerDependencies": { + "google-protobuf": "^3.14.0" } }, "node_modules/@improbable-eng/grpc-web-node-http-transport": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.14.0.tgz", - "integrity": "sha512-NGZJgY8zTTWM//9oGdJZ+acmCgcgUcqxu3NV3GMFxw35D+3xkdEz599r9O7urg1Vv0+LzXDvfWEg7qg1Ec8x1w==" + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.14.1.tgz", + "integrity": "sha512-ZsCTzI1iKUbmQjB5DNZSI5/hvdliuaPpS2h8mVj1QzynL3IFb5NrNnHVHbfcH1wbm26Ka6Z1CrKFGvKLrmbFIg==", + "peerDependencies": { + "@improbable-eng/grpc-web": ">=0.13.0" + } }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -2570,14 +2576,13 @@ } }, "node_modules/@onflow/fcl": { - "version": "0.0.71", - "resolved": "https://registry.npmjs.org/@onflow/fcl/-/fcl-0.0.71.tgz", - "integrity": "sha512-RMfm8BEt1kMdrQCBOAXPfBk+KPwemtwP78c0rA3PBg6maB3h96KYJSGW7+Fv5jmx/xZHFuvmk2R9nGv29pJ3DQ==", + "version": "0.0.76", + "resolved": "https://registry.npmjs.org/@onflow/fcl/-/fcl-0.0.76.tgz", + "integrity": "sha512-GFD8Pk4k9A6WKoK5CEO5KVZi4b3+KiJVY41NkLG376Wm+nqWLY7XlysU+uX1n+GvoJ7m1W+4BTSKmJRVU/QWjg==", "dependencies": { - "@onflow/config": "0.0.2", "@onflow/interaction": "0.0.11", "@onflow/rlp": "0.0.3", - "@onflow/sdk": "0.0.47", + "@onflow/sdk": "^0.0.53", "@onflow/types": "^0.0.4", "@onflow/util-actor": "0.0.2", "@onflow/util-address": "0.0.0", @@ -2606,6 +2611,9 @@ "integrity": "sha512-uJjgMPngreRTYPBuo6gswMj1gK39Wbqre/RgE0XnSDXJRg6ST7ZhuS53dFE6Vc2CX4jxgl+cO+0B3op8LA4Q0Q==", "dependencies": { "browser-headers": "^0.4.0" + }, + "peerDependencies": { + "google-protobuf": "^3.2.0" } }, "node_modules/@onflow/rlp": { @@ -2614,15 +2622,15 @@ "integrity": "sha512-oAf0VEiMjX8eC6Vd66j1BdGYTHOM6UBaS/sLSScnc7bKX5gICqe2gtEsCeJVE9rUzRk3GD3JqXRnPAW6YFWd/Q==" }, "node_modules/@onflow/sdk": { - "version": "0.0.47", - "resolved": "https://registry.npmjs.org/@onflow/sdk/-/sdk-0.0.47.tgz", - "integrity": "sha512-ouZL5aze9biIJfJeNUzbc4oU54ljTEFFcEXFkR13XBdMkVr3kJ7aA3EkB1T0+iezLEqxV8dkTuDnpCNmMjqJEQ==", + "version": "0.0.53", + "resolved": "https://registry.npmjs.org/@onflow/sdk/-/sdk-0.0.53.tgz", + "integrity": "sha512-arGlf1RSFPMrBzaPjmPKh742fftRCYukTtoUCfihdSskFFip7aNkpSnUUhza+mtkM748vnvSs9xknsB6yg41qQ==", "dependencies": { "@improbable-eng/grpc-web": "^0.14.0", "@improbable-eng/grpc-web-node-http-transport": "^0.14.0", - "@onflow/config": "^0.0.2", "@onflow/protobuf": "^0.1.8", "@onflow/rlp": "^0.0.3", + "@onflow/util-actor": "0.0.2", "@onflow/util-address": "^0.0.0", "@onflow/util-invariant": "^0.0.0", "@onflow/util-template": "0.0.1", @@ -6068,9 +6076,9 @@ "dev": true }, "node_modules/google-protobuf": { - "version": "3.17.2", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.17.2.tgz", - "integrity": "sha512-LlFVMhSkNy6C1MakEjiwbLxq5w+V+Go+mvt2EUoysrp8gXl903ic2W/3BwzM4/WnDMJP+u7UO2efUSl/0CJMzA==" + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.18.0.tgz", + "integrity": "sha512-WlaQWRkUOo/lm9uTgNH6nk9IQt814RggWPzKBfnAVewOFzSzRUSmS1yUWRT6ixW1vS7er5p6tmLSmwzpPpmc8A==" }, "node_modules/graceful-fs": { "version": "4.2.6", @@ -11166,7 +11174,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", - "dev": true, "bin": { "prettier": "bin-prettier.js" }, @@ -15212,17 +15219,18 @@ } }, "@improbable-eng/grpc-web": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.0.tgz", - "integrity": "sha512-ag1PTMWpBZKGi6GrEcZ4lkU5Qag23Xjo10BmnK9qyx4TMmSVcWmQ3rECirfQzm2uogrM9n1M6xfOpFsJP62ivA==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", + "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", "requires": { "browser-headers": "^0.4.1" } }, "@improbable-eng/grpc-web-node-http-transport": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.14.0.tgz", - "integrity": "sha512-NGZJgY8zTTWM//9oGdJZ+acmCgcgUcqxu3NV3GMFxw35D+3xkdEz599r9O7urg1Vv0+LzXDvfWEg7qg1Ec8x1w==" + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.14.1.tgz", + "integrity": "sha512-ZsCTzI1iKUbmQjB5DNZSI5/hvdliuaPpS2h8mVj1QzynL3IFb5NrNnHVHbfcH1wbm26Ka6Z1CrKFGvKLrmbFIg==", + "requires": {} }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -15958,14 +15966,13 @@ } }, "@onflow/fcl": { - "version": "0.0.71", - "resolved": "https://registry.npmjs.org/@onflow/fcl/-/fcl-0.0.71.tgz", - "integrity": "sha512-RMfm8BEt1kMdrQCBOAXPfBk+KPwemtwP78c0rA3PBg6maB3h96KYJSGW7+Fv5jmx/xZHFuvmk2R9nGv29pJ3DQ==", + "version": "0.0.76", + "resolved": "https://registry.npmjs.org/@onflow/fcl/-/fcl-0.0.76.tgz", + "integrity": "sha512-GFD8Pk4k9A6WKoK5CEO5KVZi4b3+KiJVY41NkLG376Wm+nqWLY7XlysU+uX1n+GvoJ7m1W+4BTSKmJRVU/QWjg==", "requires": { - "@onflow/config": "0.0.2", "@onflow/interaction": "0.0.11", "@onflow/rlp": "0.0.3", - "@onflow/sdk": "0.0.47", + "@onflow/sdk": "^0.0.53", "@onflow/types": "^0.0.4", "@onflow/util-actor": "0.0.2", "@onflow/util-address": "0.0.0", @@ -16004,15 +16011,15 @@ "integrity": "sha512-oAf0VEiMjX8eC6Vd66j1BdGYTHOM6UBaS/sLSScnc7bKX5gICqe2gtEsCeJVE9rUzRk3GD3JqXRnPAW6YFWd/Q==" }, "@onflow/sdk": { - "version": "0.0.47", - "resolved": "https://registry.npmjs.org/@onflow/sdk/-/sdk-0.0.47.tgz", - "integrity": "sha512-ouZL5aze9biIJfJeNUzbc4oU54ljTEFFcEXFkR13XBdMkVr3kJ7aA3EkB1T0+iezLEqxV8dkTuDnpCNmMjqJEQ==", + "version": "0.0.53", + "resolved": "https://registry.npmjs.org/@onflow/sdk/-/sdk-0.0.53.tgz", + "integrity": "sha512-arGlf1RSFPMrBzaPjmPKh742fftRCYukTtoUCfihdSskFFip7aNkpSnUUhza+mtkM748vnvSs9xknsB6yg41qQ==", "requires": { "@improbable-eng/grpc-web": "^0.14.0", "@improbable-eng/grpc-web-node-http-transport": "^0.14.0", - "@onflow/config": "^0.0.2", "@onflow/protobuf": "^0.1.8", "@onflow/rlp": "^0.0.3", + "@onflow/util-actor": "0.0.2", "@onflow/util-address": "^0.0.0", "@onflow/util-invariant": "^0.0.0", "@onflow/util-template": "0.0.1", @@ -18836,9 +18843,9 @@ "dev": true }, "google-protobuf": { - "version": "3.17.2", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.17.2.tgz", - "integrity": "sha512-LlFVMhSkNy6C1MakEjiwbLxq5w+V+Go+mvt2EUoysrp8gXl903ic2W/3BwzM4/WnDMJP+u7UO2efUSl/0CJMzA==" + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.18.0.tgz", + "integrity": "sha512-WlaQWRkUOo/lm9uTgNH6nk9IQt814RggWPzKBfnAVewOFzSzRUSmS1yUWRT6ixW1vS7er5p6tmLSmwzpPpmc8A==" }, "graceful-fs": { "version": "4.2.6", @@ -22933,8 +22940,7 @@ "prettier": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", - "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", - "dev": true + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==" }, "pretty-bytes": { "version": "5.6.0", diff --git a/package.json b/package.json index 92d4c6a..ba8f29b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flow-cadut", - "version": "0.1.7", + "version": "0.1.8", "description": "Flow Cadence Template Utilities", "author": "Maksim Daunarovich", "license": "Apache-2.0", @@ -39,15 +39,15 @@ "dependencies": { "@babel/preset-env": "^7.14.5", "@onflow/config": "0.0.2", - "@onflow/fcl": "^0.0.71", + "@onflow/fcl": "^0.0.76", "@onflow/types": "^0.0.4", "esm": "^3.2.25", "handlebars": "^4.7.7", "handlebars-loader": "^1.7.1", + "prettier": "^2.3.0", "rimraf": "^3.0.2", "simple-git": "^2.40.0", - "yargs": "^15.4.1", - "prettier": "^2.3.0" + "yargs": "^15.4.1" }, "devDependencies": { "@babel/cli": "^7.14.3", diff --git a/src/args.js b/src/args.js index a0afe45..c358da3 100644 --- a/src/args.js +++ b/src/args.js @@ -28,6 +28,7 @@ import { isArray, isDictionary, isComplexType, + wrongType, } from "./type-checker"; import { removeSpaces } from "./strings"; @@ -90,6 +91,8 @@ export const reportMissing = (itemType = "items", found, required, prefix = "") export const raw = (type) => type.slice(0, -1); export const resolveBasicType = (type) => { + if (wrongType(type)) return false; + if (type.includes("?")) { return t.Optional(t[raw(type)]); } @@ -141,7 +144,7 @@ export const mapArgument = (type, value) => { } case isAddress(type): { - const prefixedAddress = withPrefix(value) + const prefixedAddress = withPrefix(value); return fcl.arg(prefixedAddress, resolvedType); } diff --git a/src/parser.js b/src/parser.js index d679e05..d6ee41d 100644 --- a/src/parser.js +++ b/src/parser.js @@ -49,11 +49,11 @@ export const extractSigners = (code) => { }; export const extractScriptArguments = (code) => { - return extract(code, `(?:fun\\s+main\\(\\s*)([^\\)]*)(?:\\))`); + return extract(code, `(?:fun\\s+main\\s*\\(\\s*)([^\\)]*)(?:\\))`); }; export const extractTransactionArguments = (code) => { - return extract(code, `(?:transaction\\(\\s*)([^\\)]*)(?:\\))`); + return extract(code, `(?:transaction\\s*\\(\\s*)([^\\)]*)(?:\\))`); }; export const extractContractName = (code) => { diff --git a/src/type-checker.js b/src/type-checker.js index e3c14f7..12b1ef2 100644 --- a/src/type-checker.js +++ b/src/type-checker.js @@ -16,11 +16,15 @@ * limitations under the License. */ +export const wrongType = (type) => !type || typeof type != "string"; + export const isBasicNumType = (type) => { + if (wrongType(type)) return false; return type.startsWith("Int") || type.startsWith("UInt") || type.startsWith("Word"); }; export const isFixedNumType = (type) => { + if (wrongType(type)) return false; return type.startsWith("Fix64") || type.startsWith("UFix64"); }; @@ -30,6 +34,8 @@ export const isBoolean = (type) => type === "Bool"; export const isAddress = (type) => type === "Address" || type === "Address?"; export const isBasicType = (type) => { + if (wrongType(type)) return false; + let fixedType = type.endsWith("?") ? type.slice(0, -1) : type; return ( isBasicNumType(fixedType) || @@ -40,12 +46,15 @@ export const isBasicType = (type) => { }; export const isArray = (type) => { + if (wrongType(type)) return false; + const clearType = type.replace(/\s/g, ""); - const result = clearType.startsWith("[") && clearType.endsWith("]"); - return result; + return clearType.startsWith("[") && clearType.endsWith("]"); }; export const isDictionary = (type) => { + if (wrongType(type)) return false; + const clearType = type.replace(/\s/g, ""); return clearType.startsWith("{") && clearType.endsWith("}"); }; diff --git a/tests/args.test.js b/tests/args.test.js index a7dd2e9..0ae00f1 100644 --- a/tests/args.test.js +++ b/tests/args.test.js @@ -216,7 +216,7 @@ describe("mapArgument", () => { }, ]; const output = mapArgument(type, input); - + expect(output.xform.label).toBe("Array"); expect(output.value.length).toBe(input.length); expect(output.value[0].balance).toBe(input[0].balance); @@ -319,7 +319,7 @@ describe("mapValuesToCode", () => { }); }); -describe("optionals", ()=>{ +describe("optionals", () => { test("Basic Type", async () => { const input = "a: Int?"; const expected = "Int?"; @@ -334,23 +334,23 @@ describe("optionals", ()=>{ expect(output).toBe(expected); }); - test("simple type", async ()=>{ - const type = "String?" - const input = "Cadence" + test("simple type", async () => { + const type = "String?"; + const input = "Cadence"; const output = resolveType(type); const asArgument = output.asArgument(input); expect(asArgument.type).toBe("Optional"); expect(asArgument.value.type).toBe(raw(type)); expect(asArgument.value.value.toString()).toBe(input.toString()); - }) + }); test("Dictionary - as argument", async () => { const type = "{String: String?}"; const input = { name: "James", surname: "Hunter", - middlename: null + middlename: null, }; const output = mapArgument(type, input); @@ -366,4 +366,4 @@ describe("optionals", ()=>{ expect(output.value[2].key).toBe("middlename"); expect(output.value[2].value).toBe(input.middlename); }); -}) +}); diff --git a/tests/parser.test.js b/tests/parser.test.js index ab90396..2943c9a 100644 --- a/tests/parser.test.js +++ b/tests/parser.test.js @@ -5,7 +5,7 @@ import { SCRIPT, TRANSACTION, extractTransactionArguments, - extractScriptArguments + extractScriptArguments, } from "../src/parser"; describe("parser", () => { @@ -79,6 +79,16 @@ describe("parser", () => { const output = extractTransactionArguments(input); expect(output.length).toBe(2); }); + + test("extract transaction arguments - spaces in definition", () => { + const input = ` + transaction ( code: String ) { + prepare( admin: AuthAccount) { } + } + `; + const output = extractTransactionArguments(input); + expect(output.length).toBe(1); + }); }); describe("extract contract name", () => { @@ -166,8 +176,45 @@ describe("template type checker", () => { }); }); -describe("interaction signatures", ()=>{ - test("multi line transaction signature", async ()=>{ +describe("spaces in definitions", ()=>{ + test("spaces in definition - transaction", () => { + const input = ` + transaction ( code: String ) { + prepare( signer: AuthAccount ) {} + } + `; + const { type, signers, args } = getTemplateInfo(input); + expect(type).toBe(TRANSACTION); + expect(signers).toBe(1); + expect(args.length).toBe(1); + }); + + test("spaces in definition - more spaces", () => { + const input = ` + transaction ( code: String ) { + prepare ( signer: AuthAccount ) {} + } + `; + const { type, signers, args } = getTemplateInfo(input); + expect(type).toBe(TRANSACTION); + expect(signers).toBe(1); + expect(args.length).toBe(1); + }); + + test("script", () => { + const input = ` + pub fun main ( code: String ) { + log(code) + } + `; + const { type, args } = getTemplateInfo(input); + expect(type).toBe(SCRIPT); + expect(args.length).toBe(1); + }); +}) + +describe("interaction signatures", () => { + test("multi line transaction signature", async () => { const code = ` // this is some basic transaction we want to send transaction( @@ -176,10 +223,10 @@ describe("interaction signatures", ()=>{ ) { prepare(){} } - ` + `; const args = extractTransactionArguments(code); - expect(args.length).toBe(2) - expect(args[0]).toBe("a:Int") - expect(args[1]).toBe("b:String") - }) -}) \ No newline at end of file + expect(args.length).toBe(2); + expect(args[0]).toBe("a:Int"); + expect(args[1]).toBe("b:String"); + }); +});