Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
27ebf04
Before running with prettier
CoveMB Feb 21, 2025
7c7828e
After running with prettier
CoveMB Feb 21, 2025
ce5fcd3
Add consistent-type-imports rule
CoveMB Feb 21, 2025
3cd0b59
Add lint step in ci action
CoveMB Feb 21, 2025
31f0c78
resolve prettier conflict
CoveMB Feb 21, 2025
365421b
After running with prettier
CoveMB Feb 21, 2025
cedaeaa
resolve prettier conflict
CoveMB Feb 21, 2025
98bd8af
Add lint step in ci action
CoveMB Feb 21, 2025
a9098d0
resolve prettier conflict
CoveMB Feb 21, 2025
6e9df26
resolve prettier conflict
CoveMB Feb 21, 2025
574a739
Remove .vscode directory from Git tracking
CoveMB Feb 21, 2025
c0e9002
move linter action in it's own job
CoveMB Feb 21, 2025
86c65dc
add lint note in readme
CoveMB Feb 21, 2025
a1111d3
Update .github/workflows/test.yml
CoveMB Feb 21, 2025
abbd5a4
Merge remote-tracking branch 'upstream/master'
CoveMB Feb 21, 2025
beffa34
Merge branch 'master' into master
ericglau Feb 21, 2025
d6bec2a
lint script files
CoveMB Feb 21, 2025
315b775
Merge branch 'master' of github.com:CoveMB/contracts-wizard
CoveMB Feb 21, 2025
6ed6e4f
Merge remote-tracking branch 'upstream/master'
CoveMB Feb 24, 2025
ea90cd1
Merge remote-tracking branch 'upstream/master'
CoveMB Feb 28, 2025
abf687a
Merge remote-tracking branch 'upstream/master'
CoveMB Mar 4, 2025
426b62d
Merge remote-tracking branch 'upstream/master'
CoveMB Mar 20, 2025
ea25cc1
Merge remote-tracking branch 'upstream/master'
CoveMB Mar 20, 2025
0911f87
Merge remote-tracking branch 'upstream/master'
CoveMB Mar 25, 2025
4914083
Merge remote-tracking branch 'upstream/master'
CoveMB Mar 27, 2025
5ce527f
Merge remote-tracking branch 'upstream/master'
CoveMB Apr 4, 2025
03a32fc
Merge remote-tracking branch 'upstream/master'
CoveMB Apr 7, 2025
b3c0347
Merge remote-tracking branch 'upstream/master'
CoveMB Apr 12, 2025
0a52a65
Merge remote-tracking branch 'upstream/master'
CoveMB May 13, 2025
9e74342
Merge remote-tracking branch 'upstream/master'
CoveMB May 19, 2025
d727f51
Merge remote-tracking branch 'upstream/master'
CoveMB May 21, 2025
60fb18f
Merge remote-tracking branch 'upstream/master'
CoveMB May 26, 2025
cbb7631
Merge remote-tracking branch 'upstream/master'
CoveMB May 27, 2025
0f1267f
Merge remote-tracking branch 'upstream/master'
CoveMB Jun 5, 2025
acc5e6e
Merge remote-tracking branch 'upstream/master'
CoveMB Jun 16, 2025
e3b74c8
Merge remote-tracking branch 'upstream/master'
CoveMB Jun 17, 2025
16ba867
Merge remote-tracking branch 'upstream/master'
CoveMB Jun 26, 2025
10442ac
Merge remote-tracking branch 'upstream/master'
CoveMB Jun 27, 2025
f3d5bea
Merge remote-tracking branch 'upstream/master'
CoveMB Jul 7, 2025
4427128
Merge remote-tracking branch 'upstream/master'
CoveMB Jul 10, 2025
e4734df
Merge remote-tracking branch 'upstream/master'
CoveMB Jul 24, 2025
52bd1e0
Merge remote-tracking branch 'upstream/master'
CoveMB Jul 28, 2025
0de594f
Merge branch 'master' of github.com:CoveMB/contracts-wizard
CoveMB Jul 28, 2025
5bac310
Merge remote-tracking branch 'upstream/master'
CoveMB Jul 30, 2025
63a50d5
Merge remote-tracking branch 'upstream/master'
CoveMB Aug 5, 2025
a10f142
Merge remote-tracking branch 'upstream/master'
CoveMB Aug 20, 2025
8a4840e
Merge remote-tracking branch 'upstream/master'
CoveMB Sep 12, 2025
c8bc5cf
Merge remote-tracking branch 'upstream/master'
CoveMB Sep 24, 2025
46ed7c0
Merge remote-tracking branch 'upstream/master'
CoveMB Sep 25, 2025
f721825
Merge remote-tracking branch 'upstream/master'
CoveMB Oct 20, 2025
d4003bf
Merge remote-tracking branch 'upstream/master'
CoveMB Nov 10, 2025
8c9b79f
Add toggle to switch from default to explicit trait implementation
CoveMB Nov 11, 2025
3d07859
More detailed toggle explain
CoveMB Nov 11, 2025
129e626
Less detailed toggle explain
CoveMB Nov 11, 2025
c91d773
Merge branch 'master' into stellar-default_impl_attribute
CoveMB Nov 11, 2025
4e7869f
Add changeset
CoveMB Nov 11, 2025
c75b5f8
Merge branch 'stellar-default_impl_attribute' of github.com:CoveMB/co…
CoveMB Nov 11, 2025
ac518e1
Add test for explicit trait on each compilation tests
CoveMB Nov 11, 2025
37ca5e8
Add test for explicit trait on each compilation tests
CoveMB Nov 11, 2025
820c1b0
Merge branch 'master' into stellar-default_impl_attribute
CoveMB Nov 12, 2025
0b29d74
remove import unused
CoveMB Nov 12, 2025
7ee110b
Update AI agent
CoveMB Nov 12, 2025
b51c45f
Merge branch 'master' into stellar-default_impl_attribute
CoveMB Nov 12, 2025
8edaf27
Fix mcp tests
CoveMB Nov 12, 2025
c1732af
Fix compilation issues
CoveMB Nov 12, 2025
2088d21
Merge branch 'master' into stellar-default_impl_attribute
CoveMB Nov 12, 2025
876303e
Merge branch 'master' into stellar-default_impl_attribute
CoveMB Nov 13, 2025
720d899
Resolve conflicts
CoveMB Nov 13, 2025
41febb6
Include common in UI build
CoveMB Nov 13, 2025
bcc86e4
Update packages/ui/src/stellar/TraitImplementationSection.svelte
CoveMB Nov 19, 2025
6f295f2
Update .changeset/plain-turkeys-film.md
CoveMB Nov 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/plain-turkeys-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@openzeppelin/wizard-stellar': patch
'@openzeppelin/wizard-common': patch
'@openzeppelin/contracts-mcp': patch
---

Stellar: add an explicitImplementations flag that switches from using default_impl macro to explicit definitions
2 changes: 2 additions & 0 deletions packages/common/src/ai/descriptions/stellar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const stellarCommonDescriptions = {
upgradeable: 'Whether the contract can be upgraded.',
access:
'The type of access control to provision. Ownable is a simple mechanism with a single account authorized for all privileged actions. Roles is a flexible mechanism with a separate role for each privileged action. A role can have many authorized accounts.',
explicitImplementations:
'Whether the contract should use explicit trait implementations instead of using the #[default_impl] macro to auto-generate trait method bodies.',
};

export const stellarFungibleDescriptions = {
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './ai/descriptions/cairo';
export * from './ai/descriptions/solidity';
export * from './ai/descriptions/stellar';
export * from './ai/descriptions/stylus';
export * from './utils/object';
2 changes: 2 additions & 0 deletions packages/common/src/utils/object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const pickKeys = <T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> =>
Object.fromEntries(keys.map(k => [k, obj[k]])) as Pick<T, K>;
45 changes: 30 additions & 15 deletions packages/core/stellar/src/add-pausable.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { getSelfArg } from './common-options';
import type { BaseFunction, ContractBuilder } from './contract';
import type { Access } from './set-access-control';
import { requireAccessControl } from './set-access-control';
import { DEFAULT_ACCESS_CONTROL, requireAccessControl } from './set-access-control';
import { defineFunctions } from './utils/define-functions';

export function addPausable(c: ContractBuilder, access: Access) {
export function addPausable(c: ContractBuilder, access: Access, explicitImplementations: boolean) {
c.addUseClause('stellar_contract_utils::pausable', 'self', { alias: 'pausable' });
c.addUseClause('stellar_contract_utils::pausable', 'Pausable');
c.addUseClause('stellar_macros', 'default_impl');
if (!explicitImplementations) c.addUseClause('stellar_macros', 'default_impl');

const pausableTrait = {
traitName: 'Pausable',
Expand All @@ -16,23 +16,38 @@ export function addPausable(c: ContractBuilder, access: Access) {
section: 'Utils',
};

const pauseFn: BaseFunction = access === 'ownable' ? functions.pause_unused_caller : functions.pause;
const unpauseFn: BaseFunction = access === 'ownable' ? functions.unpause_unused_caller : functions.unpause;
const effectiveAccess = access === false ? DEFAULT_ACCESS_CONTROL : access;
const pauseFn: BaseFunction = effectiveAccess === 'ownable' ? functions.pause_unused_caller : functions.pause;
const unpauseFn: BaseFunction = effectiveAccess === 'ownable' ? functions.unpause_unused_caller : functions.unpause;

c.addTraitFunction(pausableTrait, functions.paused);
c.addTraitFunction(pausableTrait, pauseFn);
c.addTraitFunction(pausableTrait, unpauseFn);
requireAccessControl(c, pausableTrait, pauseFn, access, {
useMacro: true,
role: 'pauser',
caller: 'caller',
});
requireAccessControl(
c,
pausableTrait,
pauseFn,
effectiveAccess,
{
useMacro: true,
role: 'pauser',
caller: 'caller',
},
explicitImplementations,
);

requireAccessControl(c, pausableTrait, unpauseFn, access, {
useMacro: true,
role: 'pauser',
caller: 'caller',
});
requireAccessControl(
c,
pausableTrait,
unpauseFn,
effectiveAccess,
{
useMacro: true,
role: 'pauser',
caller: 'caller',
},
explicitImplementations,
);
}

const functions = defineFunctions({
Expand Down
19 changes: 13 additions & 6 deletions packages/core/stellar/src/add-upgradeable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { requireAccessControl } from './set-access-control';
import type { BaseFunction, ContractBuilder } from './contract';
import { defineFunctions } from './utils/define-functions';

export function addUpgradeable(c: ContractBuilder, access: Access) {
export function addUpgradeable(c: ContractBuilder, access: Access, explicitImplementations: boolean) {
const functions = defineFunctions({
_require_auth: {
args: [getSelfArg(), { name: 'operator', type: '&Address' }],
Expand Down Expand Up @@ -34,9 +34,16 @@ export function addUpgradeable(c: ContractBuilder, access: Access) {

c.addTraitFunction(upgradeableTrait, upgradeFn);

requireAccessControl(c, upgradeableTrait, upgradeFn, access, {
useMacro: false,
role: 'upgrader',
caller: 'operator',
});
requireAccessControl(
c,
upgradeableTrait,
upgradeFn,
access,
{
useMacro: false,
role: 'upgrader',
caller: 'operator',
},
explicitImplementations,
);
}
3 changes: 3 additions & 0 deletions packages/core/stellar/src/common-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const defaults: Required<CommonOptions> = {
export const contractDefaults: Required<CommonContractOptions> = {
...defaults,
access: false,
explicitImplementations: false,
} as const;

export interface CommonOptions {
Expand All @@ -18,6 +19,7 @@ export interface CommonOptions {

export interface CommonContractOptions extends CommonOptions {
access?: Access;
explicitImplementations?: boolean;
}

export function withCommonDefaults(opts: CommonOptions): Required<CommonOptions> {
Expand All @@ -30,6 +32,7 @@ export function withCommonContractDefaults(opts: CommonContractOptions): Require
return {
...withCommonDefaults(opts),
access: opts.access ?? contractDefaults.access,
explicitImplementations: opts.explicitImplementations ?? contractDefaults.explicitImplementations,
};
}

Expand Down
9 changes: 9 additions & 0 deletions packages/core/stellar/src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ export class ContractBuilder implements Contract {
}
}

addTraitForEachFunctions(baseTrait: BaseTraitImplBlock, functions: Record<string, BaseFunction>) {
Object.values(functions).forEach(fn => this.addTraitFunction(baseTrait, fn));
}

// used for adding a function to a trait implementation block
addTraitFunction(baseTrait: BaseTraitImplBlock, fn: BaseFunction): ContractFunction {
const t = this.addTraitImplBlock(baseTrait);
Expand Down Expand Up @@ -241,6 +245,11 @@ export class ContractBuilder implements Contract {
existingFn.tags = [...(existingFn.tags ?? []), tag];
}

setFunctionCode(fn: BaseFunction, code: string[], baseTrait?: BaseTraitImplBlock): void {
const existingFn = this.getOrCreateFunction(fn, baseTrait);
existingFn.code = [...code];
}

addConstructorArgument(arg: Argument): void {
for (const existingArg of this.constructorArgs) {
if (existingArg.name == arg.name) {
Expand Down
4 changes: 4 additions & 0 deletions packages/core/stellar/src/fungible.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ testFungible('fungible full - complex name', {
upgradeable: true,
});

testFungible('fungible explicit trait implementations', {
explicitImplementations: true,
});

testAPIEquivalence('fungible API default');

testAPIEquivalence('fungible API basic', { name: 'CustomToken', symbol: 'CTK' });
Expand Down
73 changes: 68 additions & 5 deletions packages/core/stellar/src/fungible.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,12 @@ Generated by [AVA](https://avajs.dev).
}␊
#[only_owner]␊
fn pause(e: &Env, caller: Address) {␊
fn pause(e: &Env, _caller: Address) {␊
pausable::pause(e);␊
}␊
#[only_owner]␊
fn unpause(e: &Env, caller: Address) {␊
fn unpause(e: &Env, _caller: Address) {␊
pausable::unpause(e);␊
}␊
}␊
Expand Down Expand Up @@ -208,12 +208,12 @@ Generated by [AVA](https://avajs.dev).
}␊
#[only_owner]␊
fn pause(e: &Env, caller: Address) {␊
fn pause(e: &Env, _caller: Address) {␊
pausable::pause(e);␊
}␊
#[only_owner]␊
fn unpause(e: &Env, caller: Address) {␊
fn unpause(e: &Env, _caller: Address) {␊
pausable::unpause(e);␊
}␊
}␊
Expand Down Expand Up @@ -362,7 +362,7 @@ Generated by [AVA](https://avajs.dev).
// Compatible with OpenZeppelin Stellar Soroban Contracts ^0.4.1␊
#![no_std]␊
use soroban_sdk::{Address, contract, contractimpl, Env, String};␊
use soroban_sdk::{Address, contract, contractimpl, Env, String, Symbol};␊
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, this Symbol import is unnecessary here, and it should be removed according to my comment in packages/core/stellar/src/set-access-control.ts.

use stellar_access::access_control::{self as access_control, AccessControl};␊
use stellar_macros::default_impl;␊
use stellar_tokens::fungible::{Base, FungibleToken};␊
Expand Down Expand Up @@ -693,3 +693,66 @@ Generated by [AVA](https://avajs.dev).
#[contractimpl]␊
impl Ownable for CustomToken {}␊
`

## fungible explicit trait implementations

> Snapshot 1

`// SPDX-License-Identifier: MIT␊
// Compatible with OpenZeppelin Stellar Soroban Contracts ^0.4.1␊
#![no_std]␊
use soroban_sdk::{Address, contract, contractimpl, Env, String};␊
use stellar_tokens::fungible::{Base, FungibleToken};␊
#[contract]␊
pub struct MyToken;␊
#[contractimpl]␊
impl MyToken {␊
pub fn __constructor(e: &Env) {␊
Base::set_metadata(e, 18, String::from_str(e, "MyToken"), String::from_str(e, "MTK"));␊
}␊
}␊
#[contractimpl]␊
impl FungibleToken for MyToken {␊
type ContractType = Base;␊
fn total_supply(e: &Env) -> i128 {␊
Self::ContractType::total_supply(e)␊
}␊
fn balance(e: &Env, account: Address) -> i128 {␊
Self::ContractType::balance(e, &account)␊
}␊
fn allowance(e: &Env, owner: Address, spender: Address) -> i128 {␊
Self::ContractType::allowance(e, &owner, &spender)␊
}␊
fn transfer(e: &Env, from: Address, to: Address, amount: i128) {␊
Self::ContractType::transfer(e, &from, &to, amount);␊
}␊
fn transfer_from(e: &Env, spender: Address, from: Address, to: Address, amount: i128) {␊
Self::ContractType::transfer_from(e, &spender, &from, &to, amount);␊
}␊
fn approve(e: &Env, owner: Address, spender: Address, amount: i128, live_until_ledger: u32) {␊
Self::ContractType::approve(e, &owner, &spender, amount, live_until_ledger);␊
}␊
fn decimals(e: &Env) -> u32 {␊
Self::ContractType::decimals(e)␊
}␊
fn name(e: &Env) -> String {␊
Self::ContractType::name(e)␊
}␊
fn symbol(e: &Env) -> String {␊
Self::ContractType::symbol(e)␊
}␊
}␊
`
Binary file modified packages/core/stellar/src/fungible.test.ts.snap
Binary file not shown.
Loading
Loading