quantumcoin 7.0.1 → 7.0.3

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.
Files changed (43) hide show
  1. package/.gitignore +3 -0
  2. package/README-SDK.md +64 -10
  3. package/README.md +27 -4
  4. package/SPEC.md +3843 -0
  5. package/examples/AllSolidityTypes.sol +184 -0
  6. package/examples/SimpleIERC20.sol +74 -0
  7. package/examples/example-generator-sdk-js.js +95 -0
  8. package/examples/example-generator-sdk-ts.js +95 -0
  9. package/examples/example.js +2 -2
  10. package/examples/offline-signing.js +73 -0
  11. package/examples/package-lock.json +10 -1103
  12. package/examples/package.json +1 -2
  13. package/examples/read-operations.js +1 -2
  14. package/examples/sdk-generator-erc20.inline.json +251 -0
  15. package/examples/solidity-types.ts +43 -0
  16. package/generate-sdk.js +689 -87
  17. package/package.json +30 -9
  18. package/src/abi/interface.d.ts +18 -0
  19. package/src/abi/interface.js +247 -9
  20. package/src/abi/js-abi-coder.js +474 -0
  21. package/src/contract/contract-factory.d.ts +1 -1
  22. package/src/contract/contract-factory.js +14 -2
  23. package/src/contract/contract.d.ts +10 -1
  24. package/src/contract/contract.js +42 -0
  25. package/src/generator/index.js +1041 -63
  26. package/src/index.d.ts +16 -0
  27. package/src/providers/provider.d.ts +20 -11
  28. package/src/providers/provider.js +12 -0
  29. package/src/types/index.d.ts +462 -0
  30. package/src/types/index.js +9 -0
  31. package/test/e2e/all-solidity-types.dynamic.test.js +200 -0
  32. package/test/e2e/all-solidity-types.fixtures.js +231 -0
  33. package/test/e2e/all-solidity-types.generated-sdks.e2e.test.js +368 -0
  34. package/test/e2e/simple-erc20.generated-sdks.e2e.test.js +151 -0
  35. package/test/e2e/transactional.test.js +4 -4
  36. package/test/e2e/typed-generator.e2e.test.js +8 -6
  37. package/test/integration/ws-provider.test.js +1 -1
  38. package/test/unit/generate-contract-cli.test.js +2 -1
  39. package/test/unit/generate-sdk-artifacts-json.test.js +45 -0
  40. package/test/unit/generator.test.js +1 -0
  41. package/test/unit/populate-transaction.test.js +62 -0
  42. package/test/unit/solidity-types.test.js +46 -0
  43. package/test/unit/utils.test.js +1 -1
@@ -26,6 +26,9 @@ describe("generate-sdk.js --artifacts-json", () => {
26
26
  const betaAbi = [
27
27
  { type: "function", name: "set", stateMutability: "nonpayable", inputs: [{ name: "value", type: "uint256" }], outputs: [] },
28
28
  ];
29
+ const gammaAbi = [
30
+ { type: "function", name: "ping", stateMutability: "pure", inputs: [], outputs: [{ name: "", type: "bool" }] },
31
+ ];
29
32
 
30
33
  fs.writeFileSync(path.join(tmp, "Alpha.abi.json"), JSON.stringify(alphaAbi, null, 2), "utf8");
31
34
  fs.writeFileSync(path.join(tmp, "Alpha.bin"), "0x6000", "utf8");
@@ -39,6 +42,8 @@ describe("generate-sdk.js --artifacts-json", () => {
39
42
  [
40
43
  { abi: "./Alpha.abi.json", bin: "./Alpha.bin" },
41
44
  { abi: "./Beta.abi.json", bin: "./Beta.bin" },
45
+ // Inline string form: abi is a JSON string; bin is inline bytecode (string).
46
+ { name: "Gamma", abi: JSON.stringify(gammaAbi), bin: "6000" },
42
47
  ],
43
48
  null,
44
49
  2,
@@ -60,6 +65,46 @@ describe("generate-sdk.js --artifacts-json", () => {
60
65
  assert.ok(fs.existsSync(path.join(outDir, "Alpha__factory.ts")));
61
66
  assert.ok(fs.existsSync(path.join(outDir, "Beta.ts")));
62
67
  assert.ok(fs.existsSync(path.join(outDir, "Beta__factory.ts")));
68
+ assert.ok(fs.existsSync(path.join(outDir, "Gamma.ts")));
69
+ assert.ok(fs.existsSync(path.join(outDir, "Gamma__factory.ts")));
70
+ });
71
+
72
+ it("supports --lang js (generates JS source + .d.ts types)", () => {
73
+ const repoRoot = path.resolve(__dirname, "..", "..");
74
+ const cli = path.join(repoRoot, "generate-sdk.js");
75
+
76
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "qcgen-artjson-js-"));
77
+ const outDir = path.join(tmp, "out");
78
+
79
+ const alphaAbi = [
80
+ { type: "function", name: "get", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "uint256" }] },
81
+ ];
82
+ fs.writeFileSync(path.join(tmp, "Alpha.abi.json"), JSON.stringify(alphaAbi, null, 2), "utf8");
83
+ fs.writeFileSync(path.join(tmp, "Alpha.bin"), "0x6000", "utf8");
84
+
85
+ const artifactsJsonPath = path.join(tmp, "artifacts.json");
86
+ fs.writeFileSync(artifactsJsonPath, JSON.stringify([{ abi: "./Alpha.abi.json", bin: "./Alpha.bin" }], null, 2), "utf8");
87
+
88
+ const res = spawnSync(
89
+ process.execPath,
90
+ [cli, "--lang", "js", "--artifacts-json", artifactsJsonPath, "--out", outDir, "--non-interactive"],
91
+ { cwd: repoRoot, encoding: "utf8", stdio: "pipe", shell: false, windowsHide: true },
92
+ );
93
+
94
+ assert.equal(res.status, 0, `generator failed:\n${res.stdout}\n${res.stderr}`);
95
+
96
+ assert.ok(fs.existsSync(path.join(outDir, "types.js")));
97
+ assert.ok(fs.existsSync(path.join(outDir, "types.d.ts")));
98
+ assert.ok(fs.existsSync(path.join(outDir, "index.js")));
99
+ assert.ok(fs.existsSync(path.join(outDir, "index.d.ts")));
100
+ assert.ok(fs.existsSync(path.join(outDir, "Alpha.js")));
101
+ assert.ok(fs.existsSync(path.join(outDir, "Alpha.d.ts")));
102
+ assert.ok(fs.existsSync(path.join(outDir, "Alpha__factory.js")));
103
+ assert.ok(fs.existsSync(path.join(outDir, "Alpha__factory.d.ts")));
104
+
105
+ // Ensure generated types re-export core Solidity types (no local re-definition).
106
+ const typesDts = fs.readFileSync(path.join(outDir, "types.d.ts"), "utf8");
107
+ assert.ok(typesDts.includes('from "quantumcoin/types"'), "expected generated types.d.ts to reference quantumcoin/types");
63
108
  });
64
109
  });
65
110
 
@@ -53,6 +53,7 @@ describe("typed contract generator", () => {
53
53
  assert.ok(contractSrc.includes("export class TestToken"));
54
54
  assert.ok(contractSrc.includes("async balanceOf"));
55
55
  assert.ok(contractSrc.includes("async transfer"));
56
+ assert.ok(contractSrc.includes("populateTransaction"));
56
57
 
57
58
  const factorySrc = fs.readFileSync(res.factoryFile, "utf8");
58
59
  assert.ok(factorySrc.includes("export class TestToken__factory"));
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @testCategory unit
3
+ * @blockchainRequired false
4
+ * @transactional false
5
+ * @description populateTransaction namespace and sendRawTransaction API
6
+ */
7
+
8
+ const { describe, it } = require("node:test");
9
+ const assert = require("node:assert/strict");
10
+
11
+ const { Initialize } = require("../../config");
12
+ const qc = require("../../index");
13
+
14
+ describe("populateTransaction + sendRawTransaction", () => {
15
+ it("contract.populateTransaction.<fn> builds tx request without provider/signer", async () => {
16
+ await Initialize(null);
17
+
18
+ const abi = [
19
+ {
20
+ type: "function",
21
+ name: "setValue",
22
+ stateMutability: "nonpayable",
23
+ inputs: [{ name: "value", type: "uint256" }],
24
+ outputs: [],
25
+ },
26
+ ];
27
+
28
+ const addr = "0x" + "11".repeat(32);
29
+ const contract = new qc.Contract(addr, abi);
30
+
31
+ const tx = await contract.populateTransaction.setValue(123, { gasLimit: 50000 });
32
+ assert.equal(tx.to, addr);
33
+ assert.equal(typeof tx.data, "string");
34
+ assert.ok(tx.data.startsWith("0x") && tx.data.length > 10);
35
+ assert.equal(tx.gasLimit, 50000);
36
+ });
37
+
38
+ it("provider.sendRawTransaction exists and forwards to eth_sendRawTransaction", async () => {
39
+ await Initialize(null);
40
+
41
+ class TestProvider extends qc.AbstractProvider {
42
+ constructor() {
43
+ super();
44
+ this.calls = [];
45
+ }
46
+ async _perform(method, params) {
47
+ this.calls.push({ method, params });
48
+ if (method === "eth_sendRawTransaction") return "0x" + "aa".repeat(32);
49
+ if (method === "eth_getTransactionByHash") return null;
50
+ return null;
51
+ }
52
+ }
53
+
54
+ const p = new TestProvider();
55
+ const raw = "0xdeadbeef";
56
+ const resp = await p.sendRawTransaction(raw);
57
+ assert.ok(resp && typeof resp.hash === "string");
58
+ assert.equal(p.calls[0].method, "eth_sendRawTransaction");
59
+ assert.deepEqual(p.calls[0].params, [raw]);
60
+ });
61
+ });
62
+
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @testCategory unit
3
+ * @blockchainRequired false
4
+ * @transactional false
5
+ * @description Core Solidity type exports exist and are wired via package exports.
6
+ */
7
+
8
+ const { describe, it } = require("node:test");
9
+ const assert = require("node:assert/strict");
10
+ const fs = require("node:fs");
11
+ const path = require("node:path");
12
+
13
+ describe("core solidity types", () => {
14
+ it("has src/types/index.d.ts with expected exports", () => {
15
+ const repoRoot = path.resolve(__dirname, "..", "..");
16
+ const dts = path.join(repoRoot, "src", "types", "index.d.ts");
17
+ assert.ok(fs.existsSync(dts), "missing src/types/index.d.ts");
18
+ const src = fs.readFileSync(dts, "utf8");
19
+
20
+ for (const needle of [
21
+ "export type AddressLike",
22
+ "export type BytesLike",
23
+ "export type BigNumberish",
24
+ "export type SolidityTypeName",
25
+ "export type SolidityInputValue",
26
+ "export type SolidityOutputValue",
27
+ ]) {
28
+ assert.ok(src.includes(needle), `expected types module to include: ${needle}`);
29
+ }
30
+ });
31
+
32
+ it("exports ./types via package.json exports map", () => {
33
+ const repoRoot = path.resolve(__dirname, "..", "..");
34
+ const pkgPath = path.join(repoRoot, "package.json");
35
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
36
+
37
+ assert.equal(pkg.types, "src/index.d.ts");
38
+ assert.ok(pkg.typesVersions && pkg.typesVersions["*"], "package.json missing typesVersions");
39
+
40
+ assert.ok(pkg.exports, "package.json missing exports");
41
+ assert.ok(pkg.exports["./types"], "package.json exports missing ./types");
42
+ assert.equal(pkg.exports["./types"].types, "./src/types/index.d.ts");
43
+ assert.equal(pkg.exports["./types"].default, "./src/types/index.js");
44
+ });
45
+ });
46
+
@@ -31,7 +31,7 @@ describe("Utils", () => {
31
31
  assert.equal(qc.toUtf8String(out), "hello world");
32
32
  });
33
33
 
34
- it("RLP encode/decode roundtrip (ethers-style bytes)", () => {
34
+ it("RLP encode/decode roundtrip (hex bytes)", () => {
35
35
  const value = ["0x68656c6c6f", "0x7b", "0x01"];
36
36
  const encoded = qc.encodeRlp(value);
37
37
  assert.ok(typeof encoded === "string" && encoded.startsWith("0x"));