@openzeppelin/wizard-stellar 0.5.0 → 0.6.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.
Files changed (92) hide show
  1. package/dist/add-upgradeable.d.ts.map +1 -1
  2. package/dist/add-upgradeable.js +15 -14
  3. package/dist/add-upgradeable.js.map +1 -1
  4. package/dist/api.d.ts +5 -2
  5. package/dist/api.d.ts.map +1 -1
  6. package/dist/api.js +7 -1
  7. package/dist/api.js.map +1 -1
  8. package/dist/build-generic.d.ts +4 -0
  9. package/dist/build-generic.d.ts.map +1 -1
  10. package/dist/build-generic.js +3 -0
  11. package/dist/build-generic.js.map +1 -1
  12. package/dist/contract.d.ts +3 -0
  13. package/dist/contract.d.ts.map +1 -1
  14. package/dist/contract.js +4 -0
  15. package/dist/contract.js.map +1 -1
  16. package/dist/fungible.d.ts +1 -0
  17. package/dist/fungible.d.ts.map +1 -1
  18. package/dist/fungible.js +74 -25
  19. package/dist/fungible.js.map +1 -1
  20. package/dist/generate/fungible.d.ts.map +1 -1
  21. package/dist/generate/fungible.js +1 -0
  22. package/dist/generate/fungible.js.map +1 -1
  23. package/dist/generate/governor.d.ts +3 -0
  24. package/dist/generate/governor.d.ts.map +1 -0
  25. package/dist/generate/governor.js +24 -0
  26. package/dist/generate/governor.js.map +1 -0
  27. package/dist/generate/non-fungible.d.ts.map +1 -1
  28. package/dist/generate/non-fungible.js +1 -0
  29. package/dist/generate/non-fungible.js.map +1 -1
  30. package/dist/generate/sources.d.ts.map +1 -1
  31. package/dist/generate/sources.js +6 -0
  32. package/dist/generate/sources.js.map +1 -1
  33. package/dist/generate/stablecoin.d.ts.map +1 -1
  34. package/dist/generate/stablecoin.js +1 -0
  35. package/dist/generate/stablecoin.js.map +1 -1
  36. package/dist/governor.d.ts +17 -0
  37. package/dist/governor.d.ts.map +1 -0
  38. package/dist/governor.js +378 -0
  39. package/dist/governor.js.map +1 -0
  40. package/dist/index.d.ts +2 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +5 -3
  43. package/dist/index.js.map +1 -1
  44. package/dist/kind.js +1 -0
  45. package/dist/kind.js.map +1 -1
  46. package/dist/non-fungible.d.ts +1 -0
  47. package/dist/non-fungible.d.ts.map +1 -1
  48. package/dist/non-fungible.js +68 -7
  49. package/dist/non-fungible.js.map +1 -1
  50. package/dist/print.d.ts.map +1 -1
  51. package/dist/print.js +6 -1
  52. package/dist/print.js.map +1 -1
  53. package/dist/stablecoin.d.ts.map +1 -1
  54. package/dist/stablecoin.js +7 -0
  55. package/dist/stablecoin.js.map +1 -1
  56. package/dist/test.js +3 -0
  57. package/dist/test.js.map +1 -1
  58. package/dist/utils/compile-test.d.ts +2 -2
  59. package/dist/utils/compile-test.d.ts.map +1 -1
  60. package/dist/utils/compile-test.js +54 -3
  61. package/dist/utils/compile-test.js.map +1 -1
  62. package/dist/utils/version.d.ts +4 -4
  63. package/dist/utils/version.js +3 -3
  64. package/dist/zip-rust.d.ts.map +1 -1
  65. package/dist/zip-rust.js +3 -2
  66. package/dist/zip-rust.js.map +1 -1
  67. package/dist/zip-shared.d.ts +3 -4
  68. package/dist/zip-shared.d.ts.map +1 -1
  69. package/dist/zip-shared.js +20 -7
  70. package/dist/zip-shared.js.map +1 -1
  71. package/package.json +1 -1
  72. package/src/add-upgradeable.ts +15 -16
  73. package/src/api.ts +15 -2
  74. package/src/build-generic.ts +6 -0
  75. package/src/contract.ts +6 -0
  76. package/src/fungible.ts +93 -25
  77. package/src/generate/fungible.ts +1 -0
  78. package/src/generate/governor.ts +24 -0
  79. package/src/generate/non-fungible.ts +1 -0
  80. package/src/generate/sources.ts +7 -0
  81. package/src/generate/stablecoin.ts +1 -0
  82. package/src/governor.ts +425 -0
  83. package/src/index.ts +2 -0
  84. package/src/kind.ts +1 -0
  85. package/src/non-fungible.ts +73 -3
  86. package/src/print.ts +6 -1
  87. package/src/stablecoin.ts +8 -0
  88. package/src/test.ts +4 -0
  89. package/src/utils/compile-test.ts +84 -5
  90. package/src/utils/version.ts +3 -3
  91. package/src/zip-rust.ts +4 -2
  92. package/src/zip-shared.ts +17 -6
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.workspaceCargo = exports.createRustLibFile = exports.printContractCargo = exports.addDependenciesWith = exports.allDependencies = exports.libDependencies = exports.printRustNameTest = exports.contractOptionsToContractName = void 0;
3
+ exports.workspaceCargo = exports.createRustLibFile = exports.printContractCargo = exports.addDependenciesWith = exports.printRustNameTest = exports.contractOptionsToContractName = void 0;
4
4
  exports.getAddressArgs = getAddressArgs;
5
+ exports.getRequiredLibDependencies = getRequiredLibDependencies;
5
6
  const version_1 = require("./utils/version");
6
7
  function pascalToSnakeCase(string) {
7
8
  return string
@@ -38,16 +39,27 @@ fn initial_state() {
38
39
  // Add more tests bellow
39
40
  `;
40
41
  exports.printRustNameTest = printRustNameTest;
41
- exports.libDependencies = [
42
+ const libDependencies = [
42
43
  'stellar-tokens',
43
44
  'stellar-access',
44
45
  'stellar-contract-utils',
46
+ 'stellar-governance',
45
47
  'stellar-macros',
46
48
  ];
47
- exports.allDependencies = [...exports.libDependencies, 'soroban-sdk'];
49
+ // Derives required lib crate dependencies from the contract's use clauses.
50
+ // Each use clause has a containerPath like "stellar_tokens::fungible::Base".
51
+ // We extract the first segment (the crate name), convert underscores to hyphens
52
+ // to match Cargo naming (e.g., stellar_tokens -> stellar-tokens), then filter
53
+ // libDependencies to include only crates the contract actually references.
54
+ // Filtering against the known list preserves stable ordering and ignores
55
+ // non-lib crates like soroban_sdk (which is always added separately).
56
+ function getRequiredLibDependencies(c) {
57
+ const usedCrates = new Set(c.useClauses.map(uc => uc.containerPath.split('::')[0].replace(/_/g, '-')));
58
+ return libDependencies.filter(dep => usedCrates.has(dep));
59
+ }
48
60
  const addDependenciesWith = (dependencyValue, dependenciesToAdd) => `${dependenciesToAdd.map(dependency => `${dependency} = ${dependencyValue}\n`).join('')}`;
49
61
  exports.addDependenciesWith = addDependenciesWith;
50
- const printContractCargo = (scaffoldContractName) => `[package]
62
+ const printContractCargo = (scaffoldContractName, requiredLibDeps) => `[package]
51
63
  name = "${scaffoldContractName.replace(/_/, '-')}-contract"
52
64
  edition.workspace = true
53
65
  license.workspace = true
@@ -62,7 +74,7 @@ crate-type = ["cdylib"]
62
74
  doctest = false
63
75
 
64
76
  [dependencies]
65
- ${(0, exports.addDependenciesWith)('{ workspace = true }', [...exports.allDependencies])}
77
+ ${(0, exports.addDependenciesWith)('{ workspace = true }', [...requiredLibDeps, 'soroban-sdk'])}
66
78
  [dev-dependencies]
67
79
  ${(0, exports.addDependenciesWith)('{ workspace = true, features = ["testutils"] }', ['soroban-sdk'])}`;
68
80
  exports.printContractCargo = printContractCargo;
@@ -72,7 +84,7 @@ exports.createRustLibFile = `#![no_std]
72
84
  mod contract;
73
85
  mod test;
74
86
  `;
75
- exports.workspaceCargo = `[workspace]
87
+ const workspaceCargo = (requiredLibDeps) => `[workspace]
76
88
  resolver = "2"
77
89
  members = ["contracts/*"]
78
90
 
@@ -83,7 +95,7 @@ license = "Apache-2.0"
83
95
  version = "0.0.1"
84
96
 
85
97
  [workspace.dependencies]
86
- ${(0, exports.addDependenciesWith)(`"${version_1.compatibleSorobanVersion}"`, ['soroban-sdk'])}${(0, exports.addDependenciesWith)(`"=${version_1.contractsVersion}"`, [...exports.libDependencies])}
98
+ ${(0, exports.addDependenciesWith)(`"${version_1.compatibleSorobanVersion}"`, ['soroban-sdk'])}${(0, exports.addDependenciesWith)(`"=${version_1.contractsVersion}"`, [...requiredLibDeps])}
87
99
 
88
100
  [profile.release]
89
101
  opt-level = "z"
@@ -99,4 +111,5 @@ lto = true
99
111
  inherits = "release"
100
112
  debug-assertions = true
101
113
  `;
114
+ exports.workspaceCargo = workspaceCargo;
102
115
  //# sourceMappingURL=zip-shared.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"zip-shared.js","sourceRoot":"","sources":["../src/zip-shared.ts"],"names":[],"mappings":";;;AAYA,wCAIC;AAfD,6CAA6E;AAE7E,SAAS,iBAAiB,CAAC,MAAc;IACvC,OAAO,MAAM;SACV,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;SAC1B,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;SACjB,WAAW,EAAE,CAAC;AACnB,CAAC;AAEY,QAAA,6BAA6B,GAAG,iBAAiB,CAAC;AAE/D,SAAgB,cAAc,CAAC,CAAoC;IACjE,OAAO,CAAC,CAAC,CAAC,eAAe,IAAI,EAAE,CAAC;SAC7B,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,SAAS,CAAC;SACnE,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC;AAEM,MAAM,iBAAiB,GAAG,CAAC,CAA6C,EAAE,EAAE,CAAC;;;;qBAI/D,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,EAAE;;yBAEhE,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;;;;;;uCAMH,CAAC,CAAC,IAAI,MAAM,cAAc,CAAC,CAAC,CAAC;KAC7D,GAAG,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC;KACpC,IAAI,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;mBACzC,CAAC,CAAC,IAAI;;wDAE+B,CAAC,CAAC,IAAI;;;;CAI7D,CAAC;AArBW,QAAA,iBAAiB,qBAqB5B;AAEW,QAAA,eAAe,GAAG;IAC7B,gBAAgB;IAChB,gBAAgB;IAChB,wBAAwB;IACxB,gBAAgB;CACR,CAAC;AAEE,QAAA,eAAe,GAAG,CAAC,GAAG,uBAAe,EAAE,aAAa,CAAU,CAAC;AAErE,MAAM,mBAAmB,GAAG,CAAC,eAAuB,EAAE,iBAA2B,EAAE,EAAE,CAC1F,GAAG,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,UAAU,MAAM,eAAe,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;AAD/E,QAAA,mBAAmB,uBAC4D;AAErF,MAAM,kBAAkB,GAAG,CAAC,oBAA4B,EAAE,EAAE,CAAC;UAC1D,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;;;;;;;;;;;;;;EAc9C,IAAA,2BAAmB,EAAC,sBAAsB,EAAE,CAAC,GAAG,uBAAe,CAAC,CAAC;;EAEjE,IAAA,2BAAmB,EAAC,gDAAgD,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;AAjB9E,QAAA,kBAAkB,sBAiB4D;AAE9E,QAAA,iBAAiB,GAAG;;;;;CAKhC,CAAC;AAEW,QAAA,cAAc,GAAG;;;;;;;;;;;EAW5B,IAAA,2BAAmB,EAAC,IAAI,kCAAwB,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,GAAG,IAAA,2BAAmB,EAAC,KAAK,0BAAgB,GAAG,EAAE,CAAC,GAAG,uBAAe,CAAC,CAAC;;;;;;;;;;;;;;;CAe5I,CAAC"}
1
+ {"version":3,"file":"zip-shared.js","sourceRoot":"","sources":["../src/zip-shared.ts"],"names":[],"mappings":";;;AAYA,wCAIC;AAwCD,gEAGC;AA1DD,6CAA6E;AAE7E,SAAS,iBAAiB,CAAC,MAAc;IACvC,OAAO,MAAM;SACV,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;SAC1B,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;SACjB,WAAW,EAAE,CAAC;AACnB,CAAC;AAEY,QAAA,6BAA6B,GAAG,iBAAiB,CAAC;AAE/D,SAAgB,cAAc,CAAC,CAAoC;IACjE,OAAO,CAAC,CAAC,CAAC,eAAe,IAAI,EAAE,CAAC;SAC7B,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,SAAS,CAAC;SACnE,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC;AAEM,MAAM,iBAAiB,GAAG,CAAC,CAA6C,EAAE,EAAE,CAAC;;;;qBAI/D,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,EAAE;;yBAEhE,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;;;;;;uCAMH,CAAC,CAAC,IAAI,MAAM,cAAc,CAAC,CAAC,CAAC;KAC7D,GAAG,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC;KACpC,IAAI,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;mBACzC,CAAC,CAAC,IAAI;;wDAE+B,CAAC,CAAC,IAAI;;;;CAI7D,CAAC;AArBW,QAAA,iBAAiB,qBAqB5B;AAEF,MAAM,eAAe,GAAG;IACtB,gBAAgB;IAChB,gBAAgB;IAChB,wBAAwB;IACxB,oBAAoB;IACpB,gBAAgB;CACR,CAAC;AAEX,2EAA2E;AAC3E,6EAA6E;AAC7E,gFAAgF;AAChF,8EAA8E;AAC9E,2EAA2E;AAC3E,yEAAyE;AACzE,sEAAsE;AACtE,SAAgB,0BAA0B,CAAC,CAA+B;IACxE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACxG,OAAO,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5D,CAAC;AAEM,MAAM,mBAAmB,GAAG,CAAC,eAAuB,EAAE,iBAA2B,EAAE,EAAE,CAC1F,GAAG,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,UAAU,MAAM,eAAe,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;AAD/E,QAAA,mBAAmB,uBAC4D;AAErF,MAAM,kBAAkB,GAAG,CAAC,oBAA4B,EAAE,eAAkC,EAAE,EAAE,CAAC;UAC9F,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;;;;;;;;;;;;;;EAc9C,IAAA,2BAAmB,EAAC,sBAAsB,EAAE,CAAC,GAAG,eAAe,EAAE,aAAa,CAAC,CAAC;;EAEhF,IAAA,2BAAmB,EAAC,gDAAgD,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;AAjB9E,QAAA,kBAAkB,sBAiB4D;AAE9E,QAAA,iBAAiB,GAAG;;;;;CAKhC,CAAC;AAEK,MAAM,cAAc,GAAG,CAAC,eAAkC,EAAE,EAAE,CAAC;;;;;;;;;;;EAWpE,IAAA,2BAAmB,EAAC,IAAI,kCAAwB,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,GAAG,IAAA,2BAAmB,EAAC,KAAK,0BAAgB,GAAG,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC;;;;;;;;;;;;;;;CAe5I,CAAC;AA1BW,QAAA,cAAc,kBA0BzB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openzeppelin/wizard-stellar",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "A boilerplate generator to get started with OpenZeppelin Stellar Soroban Contracts",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": "https://github.com/OpenZeppelin/contracts-wizard",
@@ -6,31 +6,30 @@ import { defineFunctions } from './utils/define-functions';
6
6
 
7
7
  export function addUpgradeable(c: ContractBuilder, access: Access, explicitImplementations: boolean) {
8
8
  const functions = defineFunctions({
9
- _require_auth: {
10
- args: [getSelfArg(), { name: 'operator', type: '&Address' }],
11
- code: ['operator.require_auth();'],
9
+ upgrade: {
10
+ args: [getSelfArg(), { name: 'new_wasm_hash', type: 'BytesN<32>' }, { name: 'operator', type: 'Address' }],
11
+ code: ['upgradeable::upgrade(e, &new_wasm_hash)'],
12
12
  },
13
- _require_auth_unused_operator: {
14
- name: '_require_auth',
15
- args: [getSelfArg(), { name: '_operator', type: '&Address' }],
16
- code: [],
13
+ upgrade_unused_operator: {
14
+ name: 'upgrade',
15
+ args: [getSelfArg(), { name: 'new_wasm_hash', type: 'BytesN<32>' }, { name: '_operator', type: 'Address' }],
16
+ code: ['upgradeable::upgrade(e, &new_wasm_hash)'],
17
17
  },
18
18
  });
19
19
 
20
- c.addUseClause('stellar_contract_utils::upgradeable', 'UpgradeableInternal');
21
- c.addUseClause('stellar_macros', 'Upgradeable');
22
-
23
- c.addDerives('Upgradeable');
20
+ c.addUseClause('soroban_sdk', 'Address');
21
+ c.addUseClause('soroban_sdk', 'BytesN');
22
+ c.addUseClause('stellar_contract_utils::upgradeable', 'self', { alias: 'upgradeable' });
23
+ c.addUseClause('stellar_contract_utils::upgradeable', 'Upgradeable');
24
24
 
25
25
  const upgradeableTrait = {
26
- traitName: 'UpgradeableInternal',
26
+ traitName: 'Upgradeable',
27
27
  structName: c.name,
28
- tags: [],
28
+ tags: ['contractimpl'],
29
29
  section: 'Utils',
30
30
  };
31
31
 
32
- const upgradeFn: BaseFunction =
33
- access === 'ownable' ? functions._require_auth_unused_operator : functions._require_auth;
32
+ const upgradeFn: BaseFunction = access === 'ownable' ? functions.upgrade_unused_operator : functions.upgrade;
34
33
 
35
34
  c.addTraitFunction(upgradeableTrait, upgradeFn);
36
35
 
@@ -40,7 +39,7 @@ export function addUpgradeable(c: ContractBuilder, access: Access, explicitImple
40
39
  upgradeFn,
41
40
  access,
42
41
  {
43
- useMacro: false,
42
+ useMacro: true,
44
43
  role: 'upgrader',
45
44
  caller: 'operator',
46
45
  },
package/src/api.ts CHANGED
@@ -1,5 +1,6 @@
1
- import type { CommonContractOptions } from './common-options';
1
+ import type { CommonContractOptions, CommonOptions } from './common-options';
2
2
  import type { FungibleOptions } from './fungible';
3
+ import type { GovernorOptions } from './governor';
3
4
  import type { NonFungibleOptions } from './non-fungible';
4
5
  import type { StablecoinOptions } from './stablecoin';
5
6
  import {
@@ -12,13 +13,18 @@ import {
12
13
  defaults as fungibledefaults,
13
14
  isAccessControlRequired as fungibleIsAccessControlRequired,
14
15
  } from './fungible';
16
+ import {
17
+ printGovernor,
18
+ defaults as governorDefaults,
19
+ isAccessControlRequired as governorIsAccessControlRequired,
20
+ } from './governor';
15
21
  import {
16
22
  printNonFungible,
17
23
  defaults as nonFungibledefaults,
18
24
  isAccessControlRequired as nonFungibleIsAccessControlRequired,
19
25
  } from './non-fungible';
20
26
 
21
- export interface WizardContractAPI<Options extends CommonContractOptions> {
27
+ export interface WizardContractAPI<Options extends CommonOptions> {
22
28
  /**
23
29
  * Returns a string representation of a contract generated using the provided options. If opts is not provided, uses `defaults`.
24
30
  */
@@ -39,6 +45,7 @@ export interface AccessControlAPI<Options extends CommonContractOptions> {
39
45
  }
40
46
 
41
47
  export type Fungible = WizardContractAPI<FungibleOptions> & AccessControlAPI<FungibleOptions>;
48
+ export type Governor = WizardContractAPI<GovernorOptions> & AccessControlAPI<GovernorOptions>;
42
49
  export type NonFungible = WizardContractAPI<NonFungibleOptions> & AccessControlAPI<NonFungibleOptions>;
43
50
  export type Stablecoin = WizardContractAPI<StablecoinOptions> & AccessControlAPI<StablecoinOptions>;
44
51
 
@@ -48,6 +55,12 @@ export const fungible: Fungible = {
48
55
  isAccessControlRequired: fungibleIsAccessControlRequired,
49
56
  };
50
57
 
58
+ export const governor: Governor = {
59
+ print: printGovernor,
60
+ defaults: governorDefaults,
61
+ isAccessControlRequired: governorIsAccessControlRequired,
62
+ };
63
+
51
64
  export const nonFungible: NonFungible = {
52
65
  print: printNonFungible,
53
66
  defaults: nonFungibledefaults,
@@ -1,5 +1,7 @@
1
1
  import type { FungibleOptions } from './fungible';
2
2
  import { buildFungible } from './fungible';
3
+ import type { GovernorOptions } from './governor';
4
+ import { buildGovernor } from './governor';
3
5
  import type { NonFungibleOptions } from './non-fungible';
4
6
  import { buildNonFungible } from './non-fungible';
5
7
  import type { StablecoinOptions } from './stablecoin';
@@ -7,6 +9,7 @@ import { buildStablecoin } from './stablecoin';
7
9
 
8
10
  export interface KindedOptions {
9
11
  Fungible: { kind: 'Fungible' } & FungibleOptions;
12
+ Governor: { kind: 'Governor' } & GovernorOptions;
10
13
  NonFungible: { kind: 'NonFungible' } & NonFungibleOptions;
11
14
  Stablecoin: { kind: 'Stablecoin' } & StablecoinOptions;
12
15
  }
@@ -18,6 +21,9 @@ export function buildGeneric(opts: GenericOptions) {
18
21
  case 'Fungible':
19
22
  return buildFungible(opts);
20
23
 
24
+ case 'Governor':
25
+ return buildGovernor(opts);
26
+
21
27
  case 'NonFungible':
22
28
  return buildNonFungible(opts);
23
29
 
package/src/contract.ts CHANGED
@@ -10,6 +10,7 @@ export interface Contract {
10
10
  constructorArgs: Argument[];
11
11
  implementedTraits: TraitImplBlock[];
12
12
  freeFunctions: ContractFunction[];
13
+ topLevelDeclarations: string[][];
13
14
  variables: Variable[];
14
15
  errors: Error[];
15
16
  ownable: boolean;
@@ -81,6 +82,7 @@ export class ContractBuilder implements Contract {
81
82
 
82
83
  readonly constructorArgs: Argument[] = [];
83
84
  readonly constructorCode: string[] = [];
85
+ readonly topLevelDeclarations: string[][] = [];
84
86
 
85
87
  private implementedTraitsMap: Map<string, TraitImplBlock> = new Map();
86
88
  private freeFunctionsMap: Map<string, ContractFunction> = new Map();
@@ -250,6 +252,10 @@ export class ContractBuilder implements Contract {
250
252
  existingFn.code = [...code];
251
253
  }
252
254
 
255
+ addTopLevelDeclaration(lines: string[]): void {
256
+ this.topLevelDeclarations.push(lines);
257
+ }
258
+
253
259
  addConstructorArgument(arg: Argument): void {
254
260
  for (const existingArg of this.constructorArgs) {
255
261
  if (existingArg.name == arg.name) {
package/src/fungible.ts CHANGED
@@ -17,6 +17,7 @@ export const defaults: Required<FungibleOptions> = {
17
17
  name: 'MyToken',
18
18
  symbol: 'MTK',
19
19
  burnable: false,
20
+ votes: false,
20
21
  pausable: false,
21
22
  upgradeable: false,
22
23
  premint: '0',
@@ -34,6 +35,7 @@ export interface FungibleOptions extends CommonContractOptions {
34
35
  name: string;
35
36
  symbol: string;
36
37
  burnable?: boolean;
38
+ votes?: boolean;
37
39
  pausable?: boolean;
38
40
  upgradeable?: boolean;
39
41
  premint?: string;
@@ -45,6 +47,7 @@ export function withDefaults(opts: FungibleOptions): Required<FungibleOptions> {
45
47
  ...opts,
46
48
  ...withCommonContractDefaults(opts),
47
49
  burnable: opts.burnable ?? defaults.burnable,
50
+ votes: opts.votes ?? defaults.votes,
48
51
  pausable: opts.pausable ?? defaults.pausable,
49
52
  upgradeable: opts.upgradeable ?? defaults.upgradeable,
50
53
  premint: opts.premint || defaults.premint,
@@ -61,10 +64,17 @@ export function buildFungible(opts: FungibleOptions): ContractBuilder {
61
64
 
62
65
  const allOpts = withDefaults(opts);
63
66
 
64
- addBase(c, toByteArray(allOpts.name), toByteArray(allOpts.symbol), allOpts.pausable, allOpts.explicitImplementations);
67
+ addBase(
68
+ c,
69
+ toByteArray(allOpts.name),
70
+ toByteArray(allOpts.symbol),
71
+ allOpts.votes,
72
+ allOpts.pausable,
73
+ allOpts.explicitImplementations,
74
+ );
65
75
 
66
76
  if (allOpts.premint) {
67
- addPremint(c, allOpts.premint);
77
+ addPremint(c, allOpts.premint, allOpts.votes);
68
78
  }
69
79
 
70
80
  if (allOpts.pausable) {
@@ -76,11 +86,11 @@ export function buildFungible(opts: FungibleOptions): ContractBuilder {
76
86
  }
77
87
 
78
88
  if (allOpts.burnable) {
79
- addBurnable(c, allOpts.pausable, allOpts.explicitImplementations);
89
+ addBurnable(c, allOpts.votes, allOpts.pausable, allOpts.explicitImplementations);
80
90
  }
81
91
 
82
92
  if (allOpts.mintable) {
83
- addMintable(c, allOpts.access, allOpts.pausable, allOpts.explicitImplementations);
93
+ addMintable(c, allOpts.access, allOpts.votes, allOpts.pausable, allOpts.explicitImplementations);
84
94
  }
85
95
 
86
96
  setAccessControl(c, allOpts.access, allOpts.explicitImplementations);
@@ -93,6 +103,7 @@ function addBase(
93
103
  c: ContractBuilder,
94
104
  name: string,
95
105
  symbol: string,
106
+ votes: boolean,
96
107
  pausable: boolean,
97
108
  explicitImplementations: boolean,
98
109
  ) {
@@ -102,6 +113,11 @@ function addBase(
102
113
  // Set token functions
103
114
  c.addUseClause('stellar_tokens::fungible', 'Base');
104
115
  c.addUseClause('stellar_tokens::fungible', 'FungibleToken');
116
+ if (votes) {
117
+ c.addUseClause('stellar_tokens::fungible', 'ContractOverrides');
118
+ c.addUseClause('stellar_governance::votes', 'Votes');
119
+ c.addUseClause('stellar_tokens::fungible', 'votes::FungibleVotes');
120
+ }
105
121
  c.addUseClause('soroban_sdk', 'contract');
106
122
  c.addUseClause('soroban_sdk', 'contractimpl');
107
123
  c.addUseClause('soroban_sdk', 'String');
@@ -115,7 +131,7 @@ function addBase(
115
131
  traitName: 'FungibleToken',
116
132
  structName: c.name,
117
133
  tags: explicitImplementations ? ['contractimpl'] : ['contractimpl(contracttrait)'],
118
- assocType: 'type ContractType = Base;',
134
+ assocType: `type ContractType = ${votes ? 'FungibleVotes' : 'Base'};`,
119
135
  };
120
136
 
121
137
  c.addTraitImplBlock(fungibleTokenTrait);
@@ -131,29 +147,47 @@ function addBase(
131
147
  c.addTraitFunction(fungibleTokenTrait, functions.transfer_from);
132
148
  c.addFunctionTag(functions.transfer_from, 'when_not_paused', fungibleTokenTrait);
133
149
  }
150
+
151
+ if (votes) {
152
+ c.addTraitImplBlock({
153
+ traitName: 'Votes',
154
+ structName: c.name,
155
+ tags: explicitImplementations ? ['contractimpl'] : ['contractimpl(contracttrait)'],
156
+ section: 'Extensions',
157
+ });
158
+ }
134
159
  }
135
160
 
136
- function addMintable(c: ContractBuilder, access: Access, pausable: boolean, explicitImplementations: boolean) {
161
+ function addMintable(
162
+ c: ContractBuilder,
163
+ access: Access,
164
+ votes: boolean,
165
+ pausable: boolean,
166
+ explicitImplementations: boolean,
167
+ ) {
168
+ const mintFn = votes ? votesFunctions.mint : functions.mint;
169
+ const mintWithCallerFn = votes ? votesFunctions.mint_with_caller : functions.mint_with_caller;
170
+
137
171
  switch (access) {
138
172
  case false:
139
173
  break;
140
174
  case 'ownable': {
141
- c.addFreeFunction(functions.mint);
175
+ c.addFreeFunction(mintFn);
142
176
 
143
- requireAccessControl(c, undefined, functions.mint, access, undefined, explicitImplementations);
177
+ requireAccessControl(c, undefined, mintFn, access, undefined, explicitImplementations);
144
178
 
145
179
  if (pausable) {
146
- c.addFunctionTag(functions.mint, 'when_not_paused');
180
+ c.addFunctionTag(mintFn, 'when_not_paused');
147
181
  }
148
182
  break;
149
183
  }
150
184
  case 'roles': {
151
- c.addFreeFunction(functions.mint_with_caller);
185
+ c.addFreeFunction(mintWithCallerFn);
152
186
 
153
187
  requireAccessControl(
154
188
  c,
155
189
  undefined,
156
- functions.mint_with_caller,
190
+ mintWithCallerFn,
157
191
  access,
158
192
  {
159
193
  useMacro: true,
@@ -164,7 +198,7 @@ function addMintable(c: ContractBuilder, access: Access, pausable: boolean, expl
164
198
  );
165
199
 
166
200
  if (pausable) {
167
- c.addFunctionTag(functions.mint_with_caller, 'when_not_paused');
201
+ c.addFunctionTag(mintWithCallerFn, 'when_not_paused');
168
202
  }
169
203
  break;
170
204
  }
@@ -175,7 +209,7 @@ function addMintable(c: ContractBuilder, access: Access, pausable: boolean, expl
175
209
  }
176
210
  }
177
211
 
178
- function addBurnable(c: ContractBuilder, pausable: boolean, explicitImplementations: boolean) {
212
+ function addBurnable(c: ContractBuilder, votes: boolean, pausable: boolean, explicitImplementations: boolean) {
179
213
  c.addUseClause('stellar_tokens::fungible', 'burnable::FungibleBurnable');
180
214
 
181
215
  const fungibleBurnableTrait = {
@@ -185,23 +219,29 @@ function addBurnable(c: ContractBuilder, pausable: boolean, explicitImplementati
185
219
  section: 'Extensions',
186
220
  };
187
221
 
188
- if (pausable) {
189
- c.addUseClause('stellar_macros', 'when_not_paused');
222
+ const burnFn = votes ? votesFunctions.burn : functions.burn;
223
+ const burnFromFn = votes ? votesFunctions.burn_from : functions.burn_from;
190
224
 
191
- c.addTraitFunction(fungibleBurnableTrait, functions.burn);
192
- c.addFunctionTag(functions.burn, 'when_not_paused', fungibleBurnableTrait);
225
+ if (pausable || votes || explicitImplementations) {
226
+ if (pausable) {
227
+ c.addUseClause('stellar_macros', 'when_not_paused');
228
+ }
229
+
230
+ c.addTraitFunction(fungibleBurnableTrait, burnFn);
231
+ c.addTraitFunction(fungibleBurnableTrait, burnFromFn);
193
232
 
194
- c.addTraitFunction(fungibleBurnableTrait, functions.burn_from);
195
- c.addFunctionTag(functions.burn_from, 'when_not_paused', fungibleBurnableTrait);
196
- } else if (explicitImplementations) c.addTraitForEachFunctions(fungibleBurnableTrait, fungibleBurnableFunctions);
197
- else {
233
+ if (pausable) {
234
+ c.addFunctionTag(burnFn, 'when_not_paused', fungibleBurnableTrait);
235
+ c.addFunctionTag(burnFromFn, 'when_not_paused', fungibleBurnableTrait);
236
+ }
237
+ } else {
198
238
  c.addTraitImplBlock(fungibleBurnableTrait);
199
239
  }
200
240
  }
201
241
 
202
242
  export const premintPattern = /^(\d*\.?\d*)$/;
203
243
 
204
- function addPremint(c: ContractBuilder, amount: string) {
244
+ function addPremint(c: ContractBuilder, amount: string, votes: boolean) {
205
245
  if (amount !== undefined && amount !== '0') {
206
246
  if (!premintPattern.test(amount)) {
207
247
  throw new OptionsError({
@@ -213,7 +253,7 @@ function addPremint(c: ContractBuilder, amount: string) {
213
253
  const premintAbsolute = toUint(getInitialSupply(amount, 7), 'premint', 'u128');
214
254
 
215
255
  c.addConstructorArgument({ name: 'recipient', type: 'Address' });
216
- c.addConstructorCode(`Base::mint(e, &recipient, ${premintAbsolute});`);
256
+ c.addConstructorCode(`${votes ? 'FungibleVotes' : 'Base'}::mint(e, &recipient, ${premintAbsolute});`);
217
257
  }
218
258
  }
219
259
 
@@ -350,6 +390,36 @@ export const functions = defineFunctions({
350
390
  },
351
391
  });
352
392
 
393
+ const votesFunctions = defineFunctions({
394
+ burn: {
395
+ args: [getSelfArg(), { name: 'from', type: 'Address' }, { name: 'amount', type: 'i128' }],
396
+ code: ['FungibleVotes::burn(e, &from, amount)'],
397
+ },
398
+ burn_from: {
399
+ args: [
400
+ getSelfArg(),
401
+ { name: 'spender', type: 'Address' },
402
+ { name: 'from', type: 'Address' },
403
+ { name: 'amount', type: 'i128' },
404
+ ],
405
+ code: ['FungibleVotes::burn_from(e, &spender, &from, amount)'],
406
+ },
407
+ mint: {
408
+ args: [getSelfArg(), { name: 'account', type: 'Address' }, { name: 'amount', type: 'i128' }],
409
+ code: ['FungibleVotes::mint(e, &account, amount);'],
410
+ },
411
+ mint_with_caller: {
412
+ name: 'mint',
413
+ args: [
414
+ getSelfArg(),
415
+ { name: 'account', type: 'Address' },
416
+ { name: 'amount', type: 'i128' },
417
+ { name: 'caller', type: 'Address' },
418
+ ],
419
+ code: ['FungibleVotes::mint(e, &account, amount);'],
420
+ },
421
+ });
422
+
353
423
  const fungibleTokenTraitFunctions = pickKeys(functions, [
354
424
  'total_supply',
355
425
  'balance',
@@ -361,5 +431,3 @@ const fungibleTokenTraitFunctions = pickKeys(functions, [
361
431
  'name',
362
432
  'symbol',
363
433
  ]);
364
-
365
- const fungibleBurnableFunctions = pickKeys(functions, ['burn', 'burn_from']);
@@ -9,6 +9,7 @@ const blueprint = {
9
9
  name: ['MyToken'],
10
10
  symbol: ['MTK'],
11
11
  burnable: booleans,
12
+ votes: booleans,
12
13
  pausable: booleans,
13
14
  upgradeable: booleans,
14
15
  mintable: booleans,
@@ -0,0 +1,24 @@
1
+ import type { GovernorOptions } from '../governor';
2
+ import { accessOptions } from '../set-access-control';
3
+ import { infoOptions } from '../set-info';
4
+ import { generateAlternatives } from './alternatives';
5
+
6
+ const booleans = [true, false];
7
+
8
+ const blueprint = {
9
+ name: ['MyGovernor'],
10
+ version: ['1.0.0'],
11
+ votingDelay: ['10'],
12
+ votingPeriod: ['100'],
13
+ proposalThreshold: ['100'],
14
+ quorum: ['500'],
15
+ upgradeable: booleans,
16
+ timelock: booleans,
17
+ access: accessOptions,
18
+ info: infoOptions,
19
+ explicitImplementations: booleans,
20
+ };
21
+
22
+ export function* generateGovernorOptions(): Generator<Required<GovernorOptions>> {
23
+ yield* generateAlternatives(blueprint);
24
+ }
@@ -10,6 +10,7 @@ const blueprint = {
10
10
  symbol: ['MTK'],
11
11
  tokenUri: ['https://www.mytoken.com'],
12
12
  burnable: booleans,
13
+ votes: booleans,
13
14
  pausable: booleans,
14
15
  upgradeable: booleans,
15
16
  enumerable: booleans,
@@ -3,6 +3,7 @@ import path from 'path';
3
3
  import crypto from 'crypto';
4
4
 
5
5
  import { generateFungibleOptions } from './fungible';
6
+ import { generateGovernorOptions } from './governor';
6
7
  import { generateNonFungibleOptions } from './non-fungible';
7
8
  import { generateStablecoinOptions } from './stablecoin';
8
9
  import type { GenericOptions, KindedOptions } from '../build-generic';
@@ -20,6 +21,12 @@ export function* generateOptions(kind?: Kind): Generator<GenericOptions> {
20
21
  }
21
22
  }
22
23
 
24
+ if (!kind || kind === 'Governor') {
25
+ for (const kindOpts of generateGovernorOptions()) {
26
+ yield { kind: 'Governor', ...kindOpts };
27
+ }
28
+ }
29
+
23
30
  if (!kind || kind === 'NonFungible') {
24
31
  for (const kindOpts of generateNonFungibleOptions()) {
25
32
  yield { kind: 'NonFungible', ...kindOpts };
@@ -9,6 +9,7 @@ const blueprint = {
9
9
  name: ['MyStablecoin'],
10
10
  symbol: ['MST'],
11
11
  burnable: booleans,
12
+ votes: booleans,
12
13
  pausable: booleans,
13
14
  upgradeable: booleans,
14
15
  mintable: booleans,