Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/nftopia-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ jobs:

- name: Upload build artifact
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: nftopia-backend-dist
path: nftopia-backend/dist/
2 changes: 1 addition & 1 deletion .github/workflows/nftopia-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:

- name: Upload build artifact
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: nftopia-frontend-build
path: nftopia-frontend/.next/
2 changes: 1 addition & 1 deletion .github/workflows/nftopia-stellar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:

- name: Upload contract artifact
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: nftopia-stellar-contract
path: nftopia-stellar/target/wasm32-unknown-unknown/release/*.wasm
Empty file added .turbo/cookies/1.cookie
Empty file.
Empty file added .turbo/cookies/2.cookie
Empty file.
Empty file added .turbo/cookies/3.cookie
Empty file.
Empty file added .turbo/cookies/4.cookie
Empty file.
Empty file added .turbo/cookies/5.cookie
Empty file.
18 changes: 18 additions & 0 deletions .turbo/daemon/964d605253d87a62-turbo.log.2026-01-29
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
2026-01-29T03:38:10.501310Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf(".turbo/cookies/1.cookie"), AnchoredSystemPathBuf(".turbo/cookies/.turbo-cookie")}
2026-01-29T03:38:10.501332Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Root, path: AnchoredSystemPathBuf("") }}))
2026-01-29T03:38:10.600644Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf(".turbo/cache")}
2026-01-29T03:38:10.600654Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Root, path: AnchoredSystemPathBuf("") }}))
2026-01-29T03:40:36.303858Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf(".turbo/cookies/2.cookie")}
2026-01-29T03:40:36.304546Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Root, path: AnchoredSystemPathBuf("") }}))
2026-01-29T03:40:54.801182Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf(".turbo/cookies/3.cookie")}
2026-01-29T03:40:54.801191Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Root, path: AnchoredSystemPathBuf("") }}))
2026-01-29T03:41:23.000662Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf(".turbo/cookies/4.cookie")}
2026-01-29T03:41:23.000672Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Root, path: AnchoredSystemPathBuf("") }}))
2026-01-29T03:42:21.604995Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf(".turbo/cookies/5.cookie")}
2026-01-29T03:42:21.605006Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Root, path: AnchoredSystemPathBuf("") }}))
2026-01-29T03:45:26.500260Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf(".github/workflows/nftopia-stellar.yml")}
2026-01-29T03:45:26.500293Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Root, path: AnchoredSystemPathBuf("") }}))
2026-01-29T03:45:36.700367Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf(".github/workflows/nftopia-frontend.yml")}
2026-01-29T03:45:36.700380Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Root, path: AnchoredSystemPathBuf("") }}))
2026-01-29T03:45:41.406663Z WARN turborepo_lib::package_changes_watcher: changed_files: {AnchoredSystemPathBuf(".github/workflows/nftopia-backend.yml")}
2026-01-29T03:45:41.406680Z WARN turborepo_lib::package_changes_watcher: changed_packages: Ok(Some({WorkspacePackage { name: Root, path: AnchoredSystemPathBuf("") }}))
8 changes: 8 additions & 0 deletions nftopia-stellar/contracts/nft_contract/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ version = "0.1.0"
edition = "2024"

[dependencies]
soroban-sdk = { workspace = true }

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }

[lib]
crate-type = ["cdylib"]
path = "src/lib.rs"
54 changes: 54 additions & 0 deletions nftopia-stellar/contracts/nft_contract/src/access_control.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use soroban_sdk::{contracttype, Address, Env};

use crate::error::ContractError;
use crate::storage::{get_owner, has_role_entry, set_role_entry};

#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Role {
Owner,
Admin,
Minter,
Burner,
MetadataUpdater,
}

pub fn set_role(env: &Env, role: Role, addr: Address, enabled: bool) {
set_role_entry(env, role, &addr, enabled);
}

pub fn has_role(env: &Env, role: Role, addr: &Address) -> bool {
if role == Role::Owner {
if let Ok(owner) = get_owner(env) {
return &owner == addr;
}
return false;
}

if let Ok(owner) = get_owner(env) {
if &owner == addr {
return true;
}
}

has_role_entry(env, role, addr)
}

pub fn require_role(env: &Env, role: Role) -> Result<(), ContractError> {
let invoker = env.invoker();
invoker.require_auth();
if !has_role(env, role, &invoker) {
return Err(ContractError::Unauthorized);
}
Ok(())
}

pub fn require_owner(env: &Env) -> Result<(), ContractError> {
let invoker = env.invoker();
invoker.require_auth();
let owner = get_owner(env)?;
if invoker != owner {
return Err(ContractError::Unauthorized);
}
Ok(())
}
22 changes: 22 additions & 0 deletions nftopia-stellar/contracts/nft_contract/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use soroban_sdk::contracterror;

#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ContractError {
AlreadyInitialized = 1,
NotInitialized = 2,
Unauthorized = 3,
TokenNotFound = 4,
InvalidBatchLength = 5,
MaxSupplyReached = 6,
MetadataFrozen = 7,
BurnNotConfirmed = 8,
TransfersPaused = 9,
MintingPaused = 10,
ContractPaused = 11,
InvalidRoyaltyPercentage = 12,
RevealNotReady = 13,
InvalidSalePrice = 14,
NotWhitelisted = 15,
ReentrancyDetected = 16,
}
52 changes: 52 additions & 0 deletions nftopia-stellar/contracts/nft_contract/src/events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use soroban_sdk::{Address, Env, String, Symbol};

use crate::access_control::Role;

pub fn emit_transfer(env: &Env, from: Address, to: Address, token_id: u64) {
env.events()
.publish((Symbol::new(env, "transfer"),), (from, to, token_id));
}

pub fn emit_mint(env: &Env, to: Address, token_id: u64) {
env.events()
.publish((Symbol::new(env, "mint"),), (to, token_id));
}

pub fn emit_burn(env: &Env, owner: Address, token_id: u64) {
env.events()
.publish((Symbol::new(env, "burn"),), (owner, token_id));
}

pub fn emit_approval(env: &Env, approved: Address, token_id: u64) {
env.events()
.publish((Symbol::new(env, "approval"),), (approved, token_id));
}

pub fn emit_approval_for_all(env: &Env, owner: Address, operator: Address, approved: bool) {
env.events()
.publish((Symbol::new(env, "approval_for_all"),), (owner, operator, approved));
}

pub fn emit_metadata_update(env: &Env, token_id: u64) {
env.events()
.publish((Symbol::new(env, "metadata_update"),), token_id);
}

pub fn emit_base_uri_update(env: &Env, uri: String) {
env.events()
.publish((Symbol::new(env, "base_uri_update"),), uri);
}

pub fn emit_pause(env: &Env, paused: bool) {
env.events().publish((Symbol::new(env, "pause"),), paused);
}

pub fn emit_role_grant(env: &Env, role: Role, to: Address) {
env.events()
.publish((Symbol::new(env, "role_grant"),), (role, to));
}

pub fn emit_role_revoke(env: &Env, role: Role, from: Address) {
env.events()
.publish((Symbol::new(env, "role_revoke"),), (role, from));
}
10 changes: 10 additions & 0 deletions nftopia-stellar/contracts/nft_contract/src/interface.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use soroban_sdk::{Env, Symbol};

pub fn supports_interface_id(env: &Env, interface_id: Symbol) -> bool {
let nft = Symbol::new(env, "nft");
let metadata = Symbol::new(env, "metadata");
let royalty = Symbol::new(env, "royalty");
let access = Symbol::new(env, "access_control");

interface_id == nft || interface_id == metadata || interface_id == royalty || interface_id == access
}
Loading
Loading