diff --git a/packages/core-cairo/CHANGELOG.md b/packages/core-cairo/CHANGELOG.md index 2f891031..d313b129 100644 --- a/packages/core-cairo/CHANGELOG.md +++ b/packages/core-cairo/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.10.0 (2024-03-12) + +- **Breaking changes**: + - Use OpenZeppelin Contracts for Cairo v0.10.0. ([#344](https://github.com/OpenZeppelin/contracts-wizard/pull/344)) + - ERC721: Remove token URI parameter from safe mint functions. + - ERC721: Add optional base URI parameter. If not set, this defaults to empty string. + - Use string literals for ByteArray initialization instead of short strings. + ## 0.9.2 (2024-02-26) - Remove code comment for Cairo lang version. ([#337](https://github.com/OpenZeppelin/contracts-wizard/pull/337)) diff --git a/packages/core-cairo/package.json b/packages/core-cairo/package.json index 315e5cf8..e1253a8a 100644 --- a/packages/core-cairo/package.json +++ b/packages/core-cairo/package.json @@ -1,6 +1,6 @@ { "name": "@openzeppelin/wizard-cairo", - "version": "0.9.2", + "version": "0.10.0", "description": "A boilerplate generator to get started with OpenZeppelin Contracts for Cairo", "license": "MIT", "repository": "github:OpenZeppelin/contracts-wizard", diff --git a/packages/core-cairo/src/contract.test.ts.md b/packages/core-cairo/src/contract.test.ts.md index ec16ea3c..18eec541 100644 --- a/packages/core-cairo/src/contract.test.ts.md +++ b/packages/core-cairo/src/contract.test.ts.md @@ -9,7 +9,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -24,7 +24,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -44,7 +44,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -64,7 +64,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -89,7 +89,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -114,7 +114,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ @@ -142,7 +142,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState) {␊ - self.foo.initializer('param1');␊ + self.foo.initializer("param1");␊ }␊ }␊ ` @@ -152,7 +152,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod Foo {␊ diff --git a/packages/core-cairo/src/contract.test.ts.snap b/packages/core-cairo/src/contract.test.ts.snap index df21cd12..4631a748 100644 Binary files a/packages/core-cairo/src/contract.test.ts.snap and b/packages/core-cairo/src/contract.test.ts.snap differ diff --git a/packages/core-cairo/src/custom.test.ts.md b/packages/core-cairo/src/custom.test.ts.md index f124755d..68b1a8e6 100644 --- a/packages/core-cairo/src/custom.test.ts.md +++ b/packages/core-cairo/src/custom.test.ts.md @@ -9,7 +9,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -24,7 +24,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -90,7 +90,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -148,7 +148,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -163,7 +163,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -204,7 +204,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ @@ -256,7 +256,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyContract {␊ diff --git a/packages/core-cairo/src/custom.test.ts.snap b/packages/core-cairo/src/custom.test.ts.snap index 99e95ea1..48e84d6a 100644 Binary files a/packages/core-cairo/src/custom.test.ts.snap and b/packages/core-cairo/src/custom.test.ts.snap differ diff --git a/packages/core-cairo/src/erc20.test.ts.md b/packages/core-cairo/src/erc20.test.ts.md index 497095ce..bee9f2b3 100644 --- a/packages/core-cairo/src/erc20.test.ts.md +++ b/packages/core-cairo/src/erc20.test.ts.md @@ -9,7 +9,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -41,7 +41,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ }␊ }␊ ` @@ -51,7 +51,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -84,7 +84,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ }␊ ␊ #[generate_trait]␊ @@ -104,7 +104,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -154,7 +154,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ @@ -237,7 +237,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ ␊ @@ -299,7 +299,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, default_admin: ContractAddress, pauser: ContractAddress) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ self.accesscontrol.initializer();␊ ␊ self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ @@ -385,7 +385,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -436,7 +436,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ @@ -526,7 +526,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -559,7 +559,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, recipient: ContractAddress) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ ␊ self.erc20._mint(recipient, 1000000000000000000000);␊ }␊ @@ -571,7 +571,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -603,7 +603,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ }␊ }␊ ` @@ -613,7 +613,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -657,7 +657,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ }␊ ␊ @@ -678,7 +678,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ ␊ @@ -734,7 +734,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, default_admin: ContractAddress, minter: ContractAddress) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ self.accesscontrol.initializer();␊ ␊ self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ @@ -758,7 +758,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -818,7 +818,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, recipient: ContractAddress, owner: ContractAddress) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ self.ownable.initializer(owner);␊ ␊ self.erc20._mint(recipient, 2000000000000000000000);␊ @@ -925,7 +925,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ const PAUSER_ROLE: felt252 = selector!("PAUSER_ROLE");␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ @@ -1006,7 +1006,7 @@ Generated by [AVA](https://avajs.dev). minter: ContractAddress,␊ upgrader: ContractAddress,␊ ) {␊ - self.erc20.initializer('MyToken', 'MTK');␊ + self.erc20.initializer("MyToken", "MTK");␊ self.accesscontrol.initializer();␊ ␊ self.erc20._mint(recipient, 2000000000000000000000);␊ diff --git a/packages/core-cairo/src/erc20.test.ts.snap b/packages/core-cairo/src/erc20.test.ts.snap index aebafc48..63b18875 100644 Binary files a/packages/core-cairo/src/erc20.test.ts.snap and b/packages/core-cairo/src/erc20.test.ts.snap differ diff --git a/packages/core-cairo/src/erc20.ts b/packages/core-cairo/src/erc20.ts index a1665d91..b538f1df 100644 --- a/packages/core-cairo/src/erc20.ts +++ b/packages/core-cairo/src/erc20.ts @@ -10,7 +10,7 @@ import { defineComponents } from './utils/define-components'; import { defaults as commonDefaults } from './common-options'; import { printContract } from './print'; import { externalTrait } from './external-trait'; -import { toShortString } from './utils/convert-strings'; +import { toStringLiteral } from './utils/convert-strings'; export const defaults: Required = { name: 'MyToken', @@ -57,7 +57,7 @@ export function buildERC20(opts: ERC20Options): Contract { const allOpts = withDefaults(opts); - addBase(c, toShortString(allOpts.name, 'name'), toShortString(allOpts.symbol, 'symbol')); + addBase(c, toStringLiteral(allOpts.name), toStringLiteral(allOpts.symbol)); addERC20ImplAndCamelOnlyImpl(c, allOpts.pausable); if (allOpts.premint) { diff --git a/packages/core-cairo/src/erc721.test.ts b/packages/core-cairo/src/erc721.test.ts index 248d5bf0..b9cf264b 100644 --- a/packages/core-cairo/src/erc721.test.ts +++ b/packages/core-cairo/src/erc721.test.ts @@ -31,6 +31,10 @@ function testERC721(title: string, opts: Partial) { testERC721('basic', {}); +testERC721('base uri', { + baseUri: 'https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/', +}); + testERC721('burnable', { burnable: true, }); diff --git a/packages/core-cairo/src/erc721.test.ts.md b/packages/core-cairo/src/erc721.test.ts.md index 7c1f4e35..89a738d9 100644 --- a/packages/core-cairo/src/erc721.test.ts.md +++ b/packages/core-cairo/src/erc721.test.ts.md @@ -9,7 +9,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -51,7 +51,59 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState) {␊ - self.erc721.initializer('MyToken', 'MTK');␊ + self.erc721.initializer("MyToken", "MTK", "");␊ + }␊ + }␊ + ` + +## base uri + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ + ␊ + #[starknet::contract]␊ + mod MyToken {␊ + use openzeppelin::token::erc721::ERC721Component;␊ + use openzeppelin::introspection::src5::SRC5Component;␊ + ␊ + component!(path: ERC721Component, storage: erc721, event: ERC721Event);␊ + component!(path: SRC5Component, storage: src5, event: SRC5Event);␊ + ␊ + #[abi(embed_v0)]␊ + impl ERC721MetadataImpl = ERC721Component::ERC721MetadataImpl;␊ + #[abi(embed_v0)]␊ + impl ERC721MetadataCamelOnly = ERC721Component::ERC721MetadataCamelOnlyImpl;␊ + #[abi(embed_v0)]␊ + impl ERC721Impl = ERC721Component::ERC721Impl;␊ + #[abi(embed_v0)]␊ + impl ERC721CamelOnly = ERC721Component::ERC721CamelOnlyImpl;␊ + #[abi(embed_v0)]␊ + impl SRC5Impl = SRC5Component::SRC5Impl;␊ + ␊ + impl ERC721InternalImpl = ERC721Component::InternalImpl;␊ + ␊ + #[storage]␊ + struct Storage {␊ + #[substorage(v0)]␊ + erc721: ERC721Component::Storage,␊ + #[substorage(v0)]␊ + src5: SRC5Component::Storage,␊ + }␊ + ␊ + #[event]␊ + #[derive(Drop, starknet::Event)]␊ + enum Event {␊ + #[flat]␊ + ERC721Event: ERC721Component::Event,␊ + #[flat]␊ + SRC5Event: SRC5Component::Event,␊ + }␊ + ␊ + #[constructor]␊ + fn constructor(ref self: ContractState) {␊ + self.erc721.initializer("MyToken", "MTK", "https://gateway.pinata.cloud/ipfs/QmcP9hxrnC1T5ATPmq2saFeAM1ypFX9BnAswCdHB9JCjLA/");␊ }␊ }␊ ` @@ -61,7 +113,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -104,7 +156,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState) {␊ - self.erc721.initializer('MyToken', 'MTK');␊ + self.erc721.initializer("MyToken", "MTK", "");␊ }␊ ␊ #[generate_trait]␊ @@ -125,7 +177,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -185,7 +237,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ - self.erc721.initializer('MyToken', 'MTK');␊ + self.erc721.initializer("MyToken", "MTK", "");␊ self.ownable.initializer(owner);␊ }␊ ␊ @@ -307,7 +359,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -361,7 +413,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ - self.erc721.initializer('MyToken', 'MTK');␊ + self.erc721.initializer("MyToken", "MTK", "");␊ self.ownable.initializer(owner);␊ }␊ ␊ @@ -374,11 +426,9 @@ Generated by [AVA](https://avajs.dev). recipient: ContractAddress,␊ token_id: u256,␊ data: Span,␊ - token_uri: felt252,␊ ) {␊ self.ownable.assert_only_owner();␊ self.erc721._safe_mint(recipient, token_id, data);␊ - self.erc721._set_token_uri(token_id, token_uri);␊ }␊ ␊ #[external(v0)]␊ @@ -387,9 +437,8 @@ Generated by [AVA](https://avajs.dev). recipient: ContractAddress,␊ tokenId: u256,␊ data: Span,␊ - tokenURI: felt252,␊ ) {␊ - self.safe_mint(recipient, tokenId, data, tokenURI);␊ + self.safe_mint(recipient, tokenId, data);␊ }␊ }␊ }␊ @@ -400,7 +449,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ const MINTER_ROLE: felt252 = selector!("MINTER_ROLE");␊ ␊ @@ -458,7 +507,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, default_admin: ContractAddress, minter: ContractAddress) {␊ - self.erc721.initializer('MyToken', 'MTK');␊ + self.erc721.initializer("MyToken", "MTK", "");␊ self.accesscontrol.initializer();␊ ␊ self.accesscontrol._grant_role(DEFAULT_ADMIN_ROLE, default_admin);␊ @@ -474,11 +523,9 @@ Generated by [AVA](https://avajs.dev). recipient: ContractAddress,␊ token_id: u256,␊ data: Span,␊ - token_uri: felt252,␊ ) {␊ self.accesscontrol.assert_only_role(MINTER_ROLE);␊ self.erc721._safe_mint(recipient, token_id, data);␊ - self.erc721._set_token_uri(token_id, token_uri);␊ }␊ ␊ #[external(v0)]␊ @@ -487,9 +534,8 @@ Generated by [AVA](https://avajs.dev). recipient: ContractAddress,␊ tokenId: u256,␊ data: Span,␊ - tokenURI: felt252,␊ ) {␊ - self.safe_mint(recipient, tokenId, data, tokenURI);␊ + self.safe_mint(recipient, tokenId, data);␊ }␊ }␊ }␊ @@ -500,7 +546,7 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 `// SPDX-License-Identifier: MIT␊ - // Compatible with OpenZeppelin Contracts for Cairo ^0.9.0␊ + // Compatible with OpenZeppelin Contracts for Cairo ^0.10.0␊ ␊ #[starknet::contract]␊ mod MyToken {␊ @@ -570,7 +616,7 @@ Generated by [AVA](https://avajs.dev). ␊ #[constructor]␊ fn constructor(ref self: ContractState, owner: ContractAddress) {␊ - self.erc721.initializer('MyToken', 'MTK');␊ + self.erc721.initializer("MyToken", "MTK", "");␊ self.ownable.initializer(owner);␊ }␊ ␊ @@ -698,12 +744,10 @@ Generated by [AVA](https://avajs.dev). recipient: ContractAddress,␊ token_id: u256,␊ data: Span,␊ - token_uri: felt252,␊ ) {␊ self.ownable.assert_only_owner();␊ self.pausable.assert_not_paused();␊ self.erc721._safe_mint(recipient, token_id, data);␊ - self.erc721._set_token_uri(token_id, token_uri);␊ }␊ ␊ #[external(v0)]␊ @@ -712,9 +756,8 @@ Generated by [AVA](https://avajs.dev). recipient: ContractAddress,␊ tokenId: u256,␊ data: Span,␊ - tokenURI: felt252,␊ ) {␊ - self.safe_mint(recipient, tokenId, data, tokenURI);␊ + self.safe_mint(recipient, tokenId, data);␊ }␊ }␊ ␊ diff --git a/packages/core-cairo/src/erc721.test.ts.snap b/packages/core-cairo/src/erc721.test.ts.snap index d25dbde5..dd8e7136 100644 Binary files a/packages/core-cairo/src/erc721.test.ts.snap and b/packages/core-cairo/src/erc721.test.ts.snap differ diff --git a/packages/core-cairo/src/erc721.ts b/packages/core-cairo/src/erc721.ts index e5c538cf..fb5bd6d5 100644 --- a/packages/core-cairo/src/erc721.ts +++ b/packages/core-cairo/src/erc721.ts @@ -10,11 +10,12 @@ import { defaults as commonDefaults } from './common-options'; import { printContract } from './print'; import { addSRC5Component } from './common-components'; import { externalTrait } from './external-trait'; -import { toShortString } from './utils/convert-strings'; +import { toStringLiteral } from './utils/convert-strings'; export const defaults: Required = { name: 'MyToken', symbol: 'MTK', + baseUri: '', burnable: false, pausable: false, mintable: false, @@ -30,6 +31,7 @@ export function printERC721(opts: ERC721Options = defaults): string { export interface ERC721Options extends CommonOptions { name: string; symbol: string; + baseUri?: string; burnable?: boolean; pausable?: boolean; mintable?: boolean; @@ -39,6 +41,7 @@ function withDefaults(opts: ERC721Options): Required { return { ...opts, ...withCommonDefaults(opts), + baseUri: opts.baseUri ?? defaults.baseUri, burnable: opts.burnable ?? defaults.burnable, pausable: opts.pausable ?? defaults.pausable, mintable: opts.mintable ?? defaults.mintable, @@ -54,7 +57,7 @@ export function buildERC721(opts: ERC721Options): Contract { const allOpts = withDefaults(opts); - addBase(c, toShortString(allOpts.name, 'name'), toShortString(allOpts.symbol, 'symbol')); + addBase(c, toStringLiteral(allOpts.name), toStringLiteral(allOpts.symbol), toStringLiteral(allOpts.baseUri)); addERC721ImplAndCamelOnlyImpl(c, allOpts.pausable); if (allOpts.pausable) { @@ -132,11 +135,11 @@ function addERC721ImplAndCamelOnlyImpl(c: ContractBuilder, pausable: boolean) { } } -function addBase(c: ContractBuilder, name: string, symbol: string) { +function addBase(c: ContractBuilder, name: string, symbol: string, baseUri: string) { c.addComponent( components.ERC721Component, [ - name, symbol + name, symbol, baseUri, ], true, ); @@ -202,11 +205,9 @@ const functions = defineFunctions({ { name: 'recipient', type: 'ContractAddress' }, { name: 'token_id', type: 'u256' }, { name: 'data', type: 'Span' }, - { name: 'token_uri', type: 'felt252' }, ], code: [ 'self.erc721._safe_mint(recipient, token_id, data);', - 'self.erc721._set_token_uri(token_id, token_uri);', ] }, safeMint: { @@ -215,10 +216,9 @@ const functions = defineFunctions({ { name: 'recipient', type: 'ContractAddress' }, { name: 'tokenId', type: 'u256' }, { name: 'data', type: 'Span' }, - { name: 'tokenURI', type: 'felt252' }, ], code: [ - 'self.safe_mint(recipient, tokenId, data, tokenURI);', + 'self.safe_mint(recipient, tokenId, data);', ] }, diff --git a/packages/core-cairo/src/generate/erc721.ts b/packages/core-cairo/src/generate/erc721.ts index c420495f..448adcf7 100644 --- a/packages/core-cairo/src/generate/erc721.ts +++ b/packages/core-cairo/src/generate/erc721.ts @@ -9,6 +9,7 @@ const booleans = [true, false]; const blueprint = { name: ['MyToken'], symbol: ['MTK'], + baseUri: ['https://example.com/'], burnable: booleans, pausable: booleans, mintable: booleans, diff --git a/packages/core-cairo/src/print.ts b/packages/core-cairo/src/print.ts index 360c4a1a..e7dc9457 100644 --- a/packages/core-cairo/src/print.ts +++ b/packages/core-cairo/src/print.ts @@ -224,7 +224,7 @@ export function printValue(value: Value): string { throw new Error(`Number not representable (${value})`); } } else { - return `'${value}'`; + return `"${value}"`; } } diff --git a/packages/core-cairo/src/utils/convert-strings.test.ts b/packages/core-cairo/src/utils/convert-strings.test.ts index 1d5b94d0..f0acda8d 100644 --- a/packages/core-cairo/src/utils/convert-strings.test.ts +++ b/packages/core-cairo/src/utils/convert-strings.test.ts @@ -1,6 +1,6 @@ import test from 'ava'; -import { toIdentifier, toShortString } from './convert-strings'; +import { toIdentifier, toStringLiteral } from './convert-strings'; import { OptionsError } from '../error'; test('identifier - unmodified', t => { @@ -42,29 +42,31 @@ test('identifier - no valid chars', t => { t.is(error.messages.name, 'Identifier is empty or does not have valid characters'); }); -test('short string - unmodified', t => { - t.is(toShortString('abc', 'foo'), 'abc'); +test('toStringLiteral - unmodified', t => { + t.is(toStringLiteral('abc'), 'abc'); }); -test('short string - remove accents', t => { - t.is(toShortString('ábc', 'foo'), 'abc'); +test('toStringLiteral - remove accents', t => { + t.is(toStringLiteral('ábc'), 'abc'); }); -test('short string - remove non-ascii-printable characters', t => { - t.is(toShortString('abc😀', 'foo'), 'abc'); +test('toStringLiteral - remove non-ascii-printable characters', t => { + t.is(toStringLiteral('abc😀'), 'abc'); }); -test('short string - escape single quote', t => { - t.is(toShortString("abc'def", 'foo'), "abc\\'def"); +test('toStringLiteral - escape double quote', t => { + t.is(toStringLiteral("abc\"def"), "abc\\\"def"); }); -test('short string - escape backslash', t => { - t.is(toShortString('abc\\def', 'foo'), 'abc\\\\def'); +test('toStringLiteral - does not escape single quote', t => { + t.is(toStringLiteral("abc'def"), "abc'def"); }); -test('short string - max 31 characters', t => { - t.is(toShortString('A234567890123456789012345678901', 'foo'), 'A234567890123456789012345678901'); +test('toStringLiteral - escape backslash', t => { + t.is(toStringLiteral('abc\\def'), 'abc\\\\def'); +}); - let error = t.throws(() => toShortString('A2345678901234567890123456789012', 'foo'), { instanceOf: OptionsError }); - t.is(error.messages.foo, 'String is longer than 31 characters'); +test('more than 31 characters', t => { + t.is(toStringLiteral('A234567890123456789012345678901'), 'A234567890123456789012345678901'); + t.is(toStringLiteral('A2345678901234567890123456789012'), 'A2345678901234567890123456789012'); }); \ No newline at end of file diff --git a/packages/core-cairo/src/utils/convert-strings.ts b/packages/core-cairo/src/utils/convert-strings.ts index e0966e9e..6a5e02e8 100644 --- a/packages/core-cairo/src/utils/convert-strings.ts +++ b/packages/core-cairo/src/utils/convert-strings.ts @@ -20,19 +20,11 @@ export function toIdentifier(str: string, capitalize = false): string { } /** - * Converts to a felt252-compatible short string according to the rules in https://docs.cairo-lang.org/language_constructs/literal-expressions.html#short_string_literals + * Converts to a ByteArray compatible string literal */ -export function toShortString(str: string, field: string): string { - const result = str +export function toStringLiteral(str: string): string { + return str .normalize('NFD').replace(/[\u0300-\u036f]/g, '') // remove accents .replace(/[^\x20-\x7E]+/g, '') // remove non-ascii-printable characters - .replace(/(\\|')/g, (_, c) => '\\' + c); // escape backslash or single quote - - if (result.length > 31) { - throw new OptionsError({ - [field]: 'String is longer than 31 characters', - }); - } else { - return result; - } + .replace(/(\\|")/g, (_, c) => '\\' + c); // escape backslash or double quotes } \ No newline at end of file diff --git a/packages/core-cairo/src/utils/version.ts b/packages/core-cairo/src/utils/version.ts index 6ec406d8..1081f30f 100644 --- a/packages/core-cairo/src/utils/version.ts +++ b/packages/core-cairo/src/utils/version.ts @@ -1,10 +1,10 @@ /** * The actual latest version to use in links. */ -export const contractsVersion = '0.9.0'; +export const contractsVersion = '0.10.0'; export const contractsVersionTag = `v${contractsVersion}`; /** * Semantic version string representing of the minimum compatible version of Contracts to display in output. */ -export const compatibleContractsSemver = '^0.9.0'; +export const compatibleContractsSemver = '^0.10.0'; diff --git a/packages/ui/src/cairo/ERC721Controls.svelte b/packages/ui/src/cairo/ERC721Controls.svelte index f66fa34e..edd04aa6 100644 --- a/packages/ui/src/cairo/ERC721Controls.svelte +++ b/packages/ui/src/cairo/ERC721Controls.svelte @@ -33,6 +33,13 @@ +