# Announcing ICRC7/ICRC37: A Complete NFT Implementation for the Internet Computer

**URL:** <https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578>\
**Category:** Developers\
**Created:** [May 22, 2025, 1:23pm UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578 "2025-05-22T13:23:58Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ORIGYN](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/origyn/32/24920_2.png) [@ORIGYN](https://forum.dfinity.org/u/ORIGYN)\
**Post date:** [May 22, 2025, 1:23pm UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/1 "2025-05-22T13:23:58Z")

</div>

# Announcing ICRC7/ICRC37: A Complete NFT Implementation for the Internet Computer

## Introduction

Hello Internet Computer Community!

We’re excited to share ORIGYN’s latest contribution to the IC ecosystem: a complete implementation of the ICRC7/ICRC37 NFT standard for the Internet Computer. After months of development and testing, ORIGYN is ready to invite the community to explore, test, and provide feedback on this comprehensive solution.

## Building on Our Previous Work

As some of you may remember from [our ICRC3 announcement](https://forum.dfinity.org/t/introducing-bity-ic-icrc3-a-complete-icrc3-implementation-for-internet-computer-developers/44520), we’ve been working hard to create reusable components for the IC developer community. We structured our codebase to be modular and reusable, allowing developers to leverage specific components for their own projects.

Our ICRC3 transaction standard implementation was just the beginning, and now we’re expanding with this comprehensive NFT solution that leverages the same principles of reusability, standards compliance, and developer-friendly design.

## What We’ve Built

This project provides a production-ready implementation of the ICRC7/ICRC37 NFT standard, consisting of three main components:

### 1. Core NFT Canister

- Full implementation of the ICRC7/ICRC37 standard

- Integrated ICRC3 transaction history

- Certified responses for all queries

- Fine-grained access control for NFT operations

- Flexible storage integration options

### 2. Storage Canister

- High-performance asset storage solution

- Stable memory storage for persistence across upgrades

- Intelligent heap caching system for frequently accessed assets

- Certified HTTP asset serving

- Automatic memory management

- Optimized for minimal latency

### 3. Integration Tests & Example

- Comprehensive test coverage ensuring reliability

- Complete example for deploying an NFT collection

- Step-by-step guide for minting and managing NFTs

- Documentation for all available operations

## Key Features and Benefits

### Standards Compliance

- Full implementation of ICRC7/ICRC37 NFT standard

- Integration with ICRC3 for standardized transaction history

- Forward compatibility with future ICRC standards

### Performance and Reliability

- Optimized storage solution using stable memory

- Intelligent caching mechanisms for frequently accessed assets

- Efficient memory management

- Certified responses for security

### Developer Experience

- Easy-to-use API for NFT operations

- Comprehensive documentation

- Complete example implementation

- Command-line tools for managing collections

### Flexibility

- Modular architecture allowing component reuse

- Customizable metadata structure

- Configurable collection parameters

- Support for various NFT use cases

## Why This Matters for the IC Ecosystem

The Internet Computer needs a robust, standardized approach to NFTs that developers can rely on. Our implementation aims to:

1. **Standardize NFT operations** : Provide a consistent interface for wallets, marketplaces, and applications

2. **Reduce development effort** : Offer a production-ready solution developers can adopt immediately

3. **Improve interoperability** : Enable NFTs to work seamlessly across different applications

4. **Showcase best practices** : Demonstrate efficient patterns for canister development

5. **Build community expertise** : Create a shared understanding of NFT implementation approaches

## Community Involvement

While this implementation is still in beta, we believe strongly in the power of community-driven development. We’ve structured our code to be as reusable as possible, making it easy for anyone to adopt and build upon.

**We need your help to make this truly excellent!** Please:

- **Test the implementation** : Deploy your own collection using our example

- **Provide feedback** : Share your thoughts on the architecture and API design

- **Suggest improvements** : Identify areas where we can enhance functionality

- **Report issues** : Help us identify and fix any bugs or limitations

- **Consider adoption** : Try using this implementation in your own projects

- **Contribute** : Add features or improvements via pull requests

Creating a robust NFT standard implementation for the Internet Computer requires community collaboration, and your input is invaluable. Together, we can build a solution that meets the needs of the entire ecosystem.

## Grant Application

We’re planning to apply for a developer grant to support the ongoing development and maintenance of this project. The grant would help us:

1. **Expand documentation** : Create comprehensive guides, examples, and tutorials

2. **Enhance performance** : Optimize for various usage patterns and scale

3. **Add features** : Implement additional functionality based on community feedback

4. **Ensure compatibility** : Test with various wallets, marketplaces, and applications

5. **Provide long-term support** : Maintain and update the implementation as standards evolve

Your support for our grant application would be greatly appreciated and would help ensure this project continues to serve the community’s needs.

## Getting Started

The project is available on GitHub at [https://github.com/ORIGYN-SA/nft](https://github.com/ORIGYN-SA/nft).

To deploy your own NFT collection, follow these steps:

1. Clone the repository

2. Set up your environment variables

3. Deploy the collection using dfx

4. Upload assets using our command-line tools

5. Mint your first NFTs

Detailed instructions are available in the `example` directory.

## Next Steps & Roadmap

We’re committed to making this the gold standard for NFTs on the Internet Computer. Our roadmap includes:

### Short-term

1. **Finalizing the beta** : Addressing community feedback and fixing any issues

2. **Documentation improvements** : Creating more examples and tutorials

### Medium-term

1. **Continue work on ICRC3** : Expand our ICRC3 implementation and add an indexer to facilitate transaction interactions

2. **Repository separation** : Split the ledger and storage canister repositories to provide more flexibility in how the ledger can be used

3. **ICRC-97 support** : Once validated by DFINITY, implement the ICRC-97 standard to ensure compatibility with Oisy and NFID, which are waiting for this standard to move forward

4. **Intregration with Claimlink** : [See above Origyn bought Claimlink](https://x.com/ORIGYNTech/status/1911741116077998569)

## Conclusion

We’re incredibly excited to share this implementation with the community and look forward to seeing what you build with it. Your feedback and contributions will be essential in making this a truly exceptional solution for the Internet Computer ecosystem.

Thank you for your support, and we can’t wait to hear your thoughts!

* * *

**Resources:**

- [GitHub Repository](https://github.com/ORIGYN-SA/nft)

- [ICRC7 Standard](https://github.com/dfinity/ICRC-7)

- [ICRC3 Implementation](https://github.com/BitySA/dfinity-rust-libraries/tree/master/src/icrc3)

- [Our ICRC3 Announcement](https://forum.dfinity.org/t/introducing-bity-ic-icrc3-a-complete-icrc3-implementation-for-internet-computer-developers/44520)

---

<div class="post-metadata">

**Author:** ![Gwojda](https://avatars.discourse-cdn.com/v4/letter/g/5fc32e/32.png) [@Gwojda](https://forum.dfinity.org/u/Gwojda)\
**Post date:** [May 22, 2025, 1:27pm UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/2 "2025-05-22T13:27:53Z")

</div>

We are thrilled to share ORIGYN’s ICRC7/ICRC37 implementation with the community today! After months of work, it’s fantastic to release this complete NFT solution for the Internet Computer. I can’t wait to see what you’ll build with it and hear your feedback.

---

<div class="post-metadata">

**Author:** ![Gabriel](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/gabriel/32/546_2.png) [@Gabriel](https://forum.dfinity.org/u/Gabriel)\
**Post date:** [May 23, 2025, 1:43pm UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/3 "2025-05-23T13:43:40Z")

</div>

Hey, thank you for this,

I looked over the code,

> pub struct Icrc7Token {  
> pub token\_id: Nat, // ~8-16 bytes (depending on size)  
> pub token\_name: String, // ~20-50 bytes typical  
> pub token\_description: Option, // ~0-200 bytes typical  
> pub token\_logo: Option, // ~50-100 bytes (URL)  
> pub token\_owner: Account, // ~32 bytes (Principal) + 32 bytes (optional subaccount)  
> }

Per NFT: ~150-400 bytes (conservative estimate)

> pub struct Approval {  
> pub spender: Account, // ~64 bytes  
> pub from: Account, // ~64 bytes  
> pub expires\_at: Option, // ~8 bytes  
> pub created\_at: TimestampNanos, // 8 bytes  
> pub memo: Option\<Vec\>, // ~0-64 bytes  
> }

- If 10% of NFTs have 1 approval: ~20 MB
- If each has multiple approvals: could be 100+ MB

Each transaction: ~200-500 bytes

For 1M NFTs with moderate activity:

- Core NFT data: ~300-800 MB
- Approvals: ~20-100 MB
- Transaction history: ~400 MB - 2.5 GB
- Other state: ~50 MB
- Total: ~1-3.5 GB

I made claude analyse the total storage and it looks like once it will reach 1 mil entries, considering candid adds an overhead of 20-30% in size during upgrades it will most likely fail, (4gb heap limit, intruction limit) so why not go all the way with stable storage? (except metadata)

Why did you choose MessagePack vs cbor? I know the NFT structure is overall simple and both perform almost the same (even though CBOR handles binary data natively)

---

<div class="post-metadata">

**Author:** ![Gwojda](https://avatars.discourse-cdn.com/v4/letter/g/5fc32e/32.png) [@Gwojda](https://forum.dfinity.org/u/Gwojda)\
**Post date:** [May 26, 2025, 7:21am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/4 "2025-05-26T07:21:03Z")

</div>

Hey,  
Thanks for this.  
Transaction history are stored with icrc3 in stable memory (ie : archived).  
I just had some reviews issues also here, as icrc3\_add\_transaction is async now, due to archive calls. I’ll goes from this to a icrc3\_add\_transaction no-async method, and use a job thats will automaticly archive transaction after a certain time.  
For nft metadata, that was something i had in mind, and my first implementation was using storage canister also for nft metadata, and stored in stable memory. And then i had some issue with icrc3 standard, as a few calls where async, or needed to have update calls instead of query calls (or composite query, but as composite query only works on same subnet…)  
So i moved to store metadata on heap right now, but yeah i plan to move this part to store nft metadata on stable memory. I think approvals, and others states can stay in heap, and we should be fine that way. What do you think?  
Regarding cbor, it’s on my todo list for improvement also, i already had a comment from dfinity regarding this point. I need to take to time to dig on this part.

Thanks for your review, glad community is helping here !

---

<div class="post-metadata">

**Author:** ![Gwojda](https://avatars.discourse-cdn.com/v4/letter/g/5fc32e/32.png) [@Gwojda](https://forum.dfinity.org/u/Gwojda)\
**Post date:** [June 2, 2025, 9:00am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/5 "2025-06-02T09:00:56Z")

</div>

@dfinity

can you update : [GitHub - dfinity/awesome-internet-computer: A curated list of awesome projects and resources relating to the Internet Computer Protocol](https://github.com/dfinity/awesome-internet-computer?tab=readme-ov-file#implementations) with this implementation link ?  
Thanks !

---

<div class="post-metadata">

**Author:** ![ohsalmeron](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ohsalmeron/32/30099_2.png) [@ohsalmeron](https://forum.dfinity.org/u/ohsalmeron)\
**Post date:** [June 3, 2025, 12:54pm UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/6 "2025-06-03T12:54:39Z")

</div>

I would advise to

1- Cleanup most of the warnings when compiling (I don’t usually mind seeing warnings but there are a lot of them - should take a few hours)

2- Explain what are the tests for on the documentation, while the scripts run without any errors, I’d like to know what is going on.

3- Explain from a developer perspective how can we use this production-ready repo, I’ve went through the code and documentation but couldn’t find clues on what to do or how to use this.

4- Great work+idea to bring this all together, looking forward for more updates!

Thanks

---

<div class="post-metadata">

**Author:** ![Gwojda](https://avatars.discourse-cdn.com/v4/letter/g/5fc32e/32.png) [@Gwojda](https://forum.dfinity.org/u/Gwojda)\
**Post date:** [June 4, 2025, 6:25am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/7 "2025-06-04T06:25:05Z")

</div>

Hey,  
You can check : [nft/example at master · ORIGYN-SA/nft · GitHub](https://github.com/ORIGYN-SA/nft/tree/master/example)

Which is a tutorial how to deploy a collection. You should be able to deploy your own collection. If that’s not the case, ping here and i’ll enhance documentation where you had issues.

Regarding the warnings, yeah i plain to fix them soon 👍

---

<div class="post-metadata">

**Author:** ![Gwojda](https://avatars.discourse-cdn.com/v4/letter/g/5fc32e/32.png) [@Gwojda](https://forum.dfinity.org/u/Gwojda)\
**Post date:** [June 12, 2025, 3:11pm UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/8 "2025-06-12T15:11:38Z")

</div>

Hey,  
I just want to share that we updated the implementation and documentation. We are now compatible with icrc-97 standard, meaning the nft metadata are planed to be stored in a json file (icrc97 format - ie opensea format). In other term, you are free to store your metadata on IPFS, or on dfintiy directly (i personally prefer to store everything on dfinity, thats why we created this storage canister, but you are free to use whatever you want.)  
That also mean i removed the “delete file” method from storage canister, and updating the metadata of an nft is tracked by icrc3 transactions, using urls.

Feel free to test it, and ping here if any comments.  
Thanks !

---

<div class="post-metadata">

**Author:** ![ohsalmeron](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ohsalmeron/32/30099_2.png) [@ohsalmeron](https://forum.dfinity.org/u/ohsalmeron)\
**Post date:** [June 22, 2025, 6:39am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/9 "2025-06-22T06:39:39Z")

</div>

The canister compiles but when running the tests I get this error

> error: linking with `cc` failed: exit status: 1  
> |  
> = note: “cc” “-Wl,–version-script=/tmp/rustcJZzCeW/list” “-Wl,–no-undefined-version” “-m64” “/tmp/rustcJZzCeW/symbols.o” “\<257 object files omitted\>” “-Wl,–as-needed” “-Wl,-Bstatic” “/home/bizkit/GitHub/nft/target/debug/deps/{libbity\_ic\_serializer-d0f59df619aaa963.rlib,librmp\_serde-ba548cfd1a86d85a.rlib,librmp-ba24681c9e7cd79a.rlib,libic\_asset\_certification-a32aaaee3d4c4073.rlib,libglobset-86cd50e229d0cda6.rlib,libbstr-97923d43bf09dfed.rlib,libbity\_ic\_canister\_state\_macros-986aff1ee372338c.rlib,liburl-cf14fd36e8e358cb.rlib,libidna-9b41cc2db4207c20.rlib,libidna\_adapter-f478542b5e0fb5af.rlib,libicu\_normalizer-2e8f0a5ab8310f95.rlib,libicu\_normalizer\_data-5d1a678d344b291c.rlib,libwrite16-4a21213400bb3552.rlib,libutf8\_iter-4dd926676127a369.rlib,libutf16\_iter-c1d656f0774d7f77.rlib,libicu\_properties-286e59fc3e1ccc5e.rlib,libicu\_properties\_data-2325023fb5c18f26.rlib,libicu\_locid\_transform-ab93d3cb705d7a8c.rlib,libicu\_locid\_transform\_data-8ad0c4a60b07d45b.rlib,libicu\_collections-9fe5adeaa49f3ad5.rlib,libicu\_provider-1af6c8b7d1c3af03.rlib,libicu\_locid-63096ef4520721cb.rlib,liblitemap-ecee13c27a5ccbb1.rlib,libtinystr-04b1d7fd4d9f51a5.rlib,libzerovec-a7907cc9d63af3ce.rlib,libwriteable-db6a66dd17f3debd.rlib,libyoke-accc8009c99b0e67.rlib,libzerofrom-30e521ada1df0bdf.rlib,libstable\_deref\_trait-567eccf8a716e5cb.rlib,libform\_urlencoded-023597fd4225ab59.rlib,libpercent\_encoding-3c9d9c63ad89d268.rlib,libbity\_ic\_canister\_logger-37ec85cc7c991a87.rlib,libtracing\_subscriber-dc4875b540d5b866.rlib,libsmallvec-e730f0548166060c.rlib,libtracing\_serde-d7e3c78257b18fa8.rlib,libserde\_json-b2191ce26cd1ce5e.rlib,libryu-2e1ad3a2e1fc761f.rlib,libsharded\_slab-d6c2afa47dbbbf49.rlib,libmatchers-7609a5f40b73546f.rlib,libregex\_automata-c3b93ceea2d9380b.rlib,libregex\_syntax-0602e6492ddb8c9b.rlib,libregex-fdd5fc3061de2d68.rlib,libregex\_automata-88d4294ad1e6b791.rlib,libaho\_corasick-e16ae6995589aa8b.rlib,libregex\_syntax-f039f94e82e64640.rlib,libnu\_ansi\_term-6e21f79c22ab38a6.rlib,liboverload-4adf788bf038356f.rlib,libthread\_local-db9dae63740b7a72.rlib,libtracing\_log-6a4cda1ba47e1d3d.rlib,liblog-a4d7daa48f228739.rlib,libbity\_ic\_icrc3-f858f13bb993d2d2.rlib,libbity\_ic\_icrc3\_archive\_c2c\_client-e2b5013d0b23294d.rlib,libbity\_ic\_canister\_client-4f5e981f6a9abfbd.rlib,libbity\_ic\_subcanister\_manager-a583cc27b70348be.rlib,libcanfund-3391c56acf8ad5b9.rlib,libic\_ledger\_types-afb36ca4eb897733.rlib,libbity\_ic\_utils-e5ac34aa0f6695ce.rlib,libbity\_ic\_stable\_memory-eb66b5bdf340bf05.rlib,libbity\_ic\_icrc3\_archive\_api-041688e9608a545f.rlib,libminicbor-b6e6d6bb7b586cea.rlib,libicrc\_ledger\_types-5afe147e33815c48.rlib,libtime-ab5163fd7c2da1bd.rlib,libtime\_core-aba7fae3346e8591.rlib,libnum\_conv-449ca88c0829d769.rlib,libderanged-ba46076ffb68d683.rlib,libpowerfmt-58451dbb48f8c7ee.rlib,libicrc\_cbor-4fe125e08a5d4493.rlib,libitertools-0a851bd936104108.rlib,libeither-6837b249a36b084d.rlib,libminicbor-04cfd8b694d952f8.rlib,libic\_stable\_structures-06f52fea211fdea1.rlib,libbase32-af2337bc5b2a12c7.rlib,libtracing-9a9a9842b55482e0.rlib,libtracing\_core-75f7edece6f52951.rlib,libonce\_cell-c71ece0e52800bc8.rlib,libbity\_ic\_storage\_canister\_c2c-50cdca17dd70a39d.rlib,libbity\_ic\_canister\_time-f23d87dc402fbc05.rlib,libic\_cdk\_timers-b1b5d37891d1aec6.rlib,libic0-a2af1ae5804017a1.rlib,libfutures-8c843f3e7b16a560.rlib,libfutures\_executor-2c34c238032118b3.rlib,libfutures\_util-982cb6c102b5f518.rlib,libmemchr-df7138072aead54d.rlib,libfutures\_io-689fb191a0ac4ccc.rlib,libslab-dc97005b2fdc1213.rlib,libfutures\_channel-ea61c7e38ce72c4a.rlib,libpin\_project\_lite-12250a02a17ca230.rlib,libfutures\_sink-72c19411dea1817c.rlib,libfutures\_task-59a5705bab797fe3.rlib,libpin\_utils-fcd1b7c1cf393c79.rlib,libfutures\_core-616deeb37b97cb01.rlib,libbity\_ic\_storage\_canister\_api-6e29a29bfdb3d6b8.rlib,libic\_http\_certification-a44055219091dadc.rlib,libserde\_cbor-b542a1c129651568.rlib,libhalf-fe70c3a5b194b715.rlib,liburlencoding-3ef9aa4f002de0ab.rlib,libbase64-b113dbe7721f305b.rlib,libic\_certification-86f2bc04a9778949.rlib,libhttp-fc30868bef377c6c.rlib,libitoa-059a7fbe34ec1e42.rlib,libbytes-23ef84c3ede8db87.rlib,libfnv-e363583e1b6fdae8.rlib,libic\_representation\_independent\_hash-362e0c07994daaf1.rlib,libbity\_ic\_types-b85551da700a06d1.rlib,libic\_cdk-3f63ac30fe34d49f.rlib,libic\_cdk\_executor-b413ba301d181c3b.rlib,libslotmap-fcd432d32b29c261.rlib,libic0-b8436c300da8b4d3.rlib,libic\_management\_canister\_types-378bb1b894480630.rlib,libic\_error\_types-3df184a445875685.rlib,libstrum-d4bedd1463be92c1.rlib,libthiserror-0ffc405ab45d813a.rlib,libcandid-7029357e1a602002.rlib,libstacker-7c8bd302b7e72f46.rlib,libpsm-f2e59667d03f946b.rlib,liblibc-22799f3321850230.rlib,libhex-34b9c439c6a30d87.rlib,libserde\_bytes-76683556fa85a251.rlib,libpretty-707dde4e27a00c96.rlib,libunicode\_width-66440149e2190ed2.rlib,libarrayvec-d7898229bed16c81.rlib,libtyped\_arena-f500e2677ba63b5f.rlib,libleb128-6260f6f9e53a31a4.rlib,libbyteorder-45330488a613b857.rlib,libic\_principal-44c2878f47000e87.rlib,libcrc32fast-364c5844de60373e.rlib,libdata\_encoding-6e55e7f620eeff05.rlib,libsha2-c7718e0a78b132af.rlib,libcpufeatures-abd2f6dd7c87e77f.rlib,libcfg\_if-f52ed1292e79c10c.rlib,libdigest-1b0b65eaf1f1be03.rlib,libsubtle-0482376bbaa3bb74.rlib,libconst\_oid-ad9d3ce34581342d.rlib,libblock\_buffer-29b100166349492a.rlib,libcrypto\_common-60e6b3f2a1954485.rlib,libgeneric\_array-35823659994fc1c8.rlib,libtypenum-218683b74ca28981.rlib,libzeroize-0bf2244456e11d13.rlib,libnum\_bigint-54c3234df037bd2d.rlib,libnum\_integer-bc7914afc1d815cf.rlib,libnum\_traits-932d06b42d1370b4.rlib,libanyhow-82be960f4dd181a1.rlib,libbinread-f2dcfbee5b9f9407.rlib,liblazy\_static-82b154891a502d9d.rlib,libthiserror-f1580a258cca396c.rlib,libserde-4e5dd5ef6b85d165.rlib}.rlib” “/lib/rustlib/x86\_64-unknown-linux-gnu/lib/{libstd-_,libpanic\_unwind-_,libobject-_,libmemchr-_,libaddr2line-_,libgimli-_,librustc\_demangle-_,libstd\_detect-_,libhashbrown-_,librustc\_std\_workspace\_alloc-_,libminiz\_oxide-_,libadler2-_,libunwind-_,libcfg\_if-_,liblibc-_,liballoc-_,librustc\_std\_workspace\_core-_,libcore-_,libcompiler\_builtins-\*}.rlib” “-Wl,-Bdynamic” “-lgcc\_s” “-lutil” “-lrt” “-lpthread” “-lm” “-ldl” “-lc” “-L” “/tmp/rustcJZzCeW/raw-dylibs” “-Wl,–eh-frame-hdr” “-Wl,-z,noexecstack” “-L” “/home/bizkit/GitHub/nft/target/debug/build/psm-06ccb5ea6ee8af6f/out” “-L” “/lib/rustlib/x86\_64-unknown-linux-gnu/lib” “-o” “/home/bizkit/GitHub/nft/target/debug/deps/libcore\_nft.so” “-Wl,–gc-sections” “-shared” “-Wl,-z,relro,-z,now” “-nodefaultlibs”  
> = note: some arguments are omitted. use `--verbose` to show all linker arguments  
> = note: /usr/bin/ld: /home/bizkit/GitHub/nft/target/debug/deps/libbity\_ic\_storage\_canister\_api-6e29a29bfdb3d6b8.rlib(bity\_ic\_storage\_canister\_api-6e29a29bfdb3d6b8.bity\_ic\_storage\_canister\_api.a6ad88f09eff6424-cgu.0.rcgu.o): in function `get_candid_pointer': /home/bizkit/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bity-ic-storage-canister-api-0.2.0/src/lib.rs:13: multiple definition of `get\_candid\_pointer’; /home/bizkit/GitHub/nft/target/debug/deps/core\_nft.69h4gw7vbjqbxn5c4pz8mhnl3.rcgu.o:/home/bizkit/GitHub/nft/src/core\_nft/src/lib.rs:28: first defined here  
> collect2: error: ld returned 1 exit status
> 
> warning: `core_nft` (lib) generated 2 warnings  
> error: could not compile `core_nft` (lib) due to 1 previous error; 2 warnings emitted

Checking this error on an LLM I get the following diagnose

- Both bity-ic-storage-canister-api and your core\_nft crate are calling export\_candid!().

- This macro generates a global symbol called get\_candid\_pointer.

- When you link both crates together (as happens in integration tests), the linker finds two definitions of get\_candid\_pointer, which is not allowed.

Also it would be good idea to have documentation on the storage canister, which I’m really interested.  
The master README displays “Read more about Storage Canister” but there isn’t any.  
[https://github.com/ORIGYN-SA/nft/blob/master/src/storage\_canister/README.md](https://github.com/ORIGYN-SA/nft/blob/master/src/storage_canister/README.md)

I’ll try to deploy a collection next week and show the results.

---

<div class="post-metadata">

**Author:** ![ohsalmeron](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ohsalmeron/32/30099_2.png) [@ohsalmeron](https://forum.dfinity.org/u/ohsalmeron)\
**Post date:** [June 23, 2025, 1:11am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/10 "2025-06-23T01:11:28Z")

</div>

I successfully deployed a collection here:  
[https://dashboard.internetcomputer.org/canister/xea2t-daaaa-aaaaj-qnp2a-cai](https://dashboard.internetcomputer.org/canister/xea2t-daaaa-aaaaj-qnp2a-cai)

You can check the token id’s metadata (icrc7\_token\_metadata) from token 1-159

The CLI tool works great, I was able to automate uploading an entire collection with one script.

Also I added CycleOps to monitor the burn rate and I found that it’s spending a lot of cycles

 ![image](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/3X/6/b/6bd295e0a245bdd25cb0643c7edd8c2ccb89997e.png)

I’m using .webp files to optimize size, along with the .jsons are not even 20Mb but it already burned like $8 USD in cycles. Any idea why?

Another question is why it created another canister for the icrc-97 standard .jsons metadata?  
This one: wanvb-2aaaa-aaaaj-qnp4a-cai  
[https://wanvb-2aaaa-aaaaj-qnp4a-cai.raw.icp0.io/e17e265548a90d803975b95a9d32c158c213dd267b24826d71062f207a57319a.json](https://wanvb-2aaaa-aaaaj-qnp4a-cai.raw.icp0.io/e17e265548a90d803975b95a9d32c158c213dd267b24826d71062f207a57319a.json)

I forked it for testing purposes, what would be the license for this repo?

Great job so far in here, cheers!

---

<div class="post-metadata">

**Author:** ![Gwojda](https://avatars.discourse-cdn.com/v4/letter/g/5fc32e/32.png) [@Gwojda](https://forum.dfinity.org/u/Gwojda)\
**Post date:** [June 23, 2025, 6:00am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/11 "2025-06-23T06:00:03Z")

</div>

Hey, yeah i saw this error in the pipeline last friday. I’ll dig on it today to fix it. For some reason, it’s working correctly on m3 mb pro, but not on linux environnement.  
Thanks for digging here, helpfull ! I’ll ping here once it’s fixed.

About storage canister, i started to discuss that topic with Dfinity which asked me to deploy it on a separate repository. It’s available here : [GitHub - BitySA/ic-storage-canister](https://github.com/BitySA/ic-storage-canister)  
If you have any question feel free to ask here, or i can add you on slack/signal 👍

---

<div class="post-metadata">

**Author:** ![Gwojda](https://avatars.discourse-cdn.com/v4/letter/g/5fc32e/32.png) [@Gwojda](https://forum.dfinity.org/u/Gwojda)\
**Post date:** [June 23, 2025, 6:05am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/12 "2025-06-23T06:05:30Z")

</div>

Can you share the command line you used ? i think it’s related with the “test\_mode” parameter, when available it limit the storage canister stable memory, meaning you’ll create a lot of “subcanister” for storage. I had to create this for integration testing, but also for testing on production environnement directly.  
I’m afraid you’ll have to redeploy the collection without this parameter to false ` test_mode = false;`. I’ll add a comment on it, or just change the documentation to make sure people dont enable this parameter.

Thanks a lot for testing ! ❤

I’ll come back soon with an answer about the licence.

---

<div class="post-metadata">

**Author:** ![Gwojda](https://avatars.discourse-cdn.com/v4/letter/g/5fc32e/32.png) [@Gwojda](https://forum.dfinity.org/u/Gwojda)\
**Post date:** [June 23, 2025, 6:57am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/13 "2025-06-23T06:57:34Z")

</div>

Ah, forgot the reply to your last questions about why another canister is present.  
It’s the storage canister here. How it’s working is :  
Icrc7 ledger manage 2 types of subcanisters, the icrc3 archive canisters and the storage canister.  
Internally, both of this library use this library : [dfinity-rust-libraries/src/subcanister\_manager at master · BitySA/dfinity-rust-libraries · GitHub](https://github.com/BitySA/dfinity-rust-libraries/tree/master/src/subcanister_manager) to scale (create new canisters) and manage subcanisters cycles.  
In fact, icrc3 lib [dfinity-rust-libraries/src/icrc3 at master · BitySA/dfinity-rust-libraries · GitHub](https://github.com/BitySA/dfinity-rust-libraries/tree/master/src/icrc3) is used to manage transaction stuff/security stuff arround transactions. THats also why at start, the collection deployement will burn some cycles as it’ll pop one canister here to archive the transactions to a subcanister via icrc3  
In same veins, you can choose to use IPFS, even s3 (.. 🤢 ) or storage canister. The idea here, is the collection canister act as a proxy (assets are exposed on https endpoint, using last dfinity library for that : [ic\_asset\_certification - Rust](https://docs.rs/ic-asset-certification/latest/ic_asset_certification/)), meaning you can access the assets via [https://xea2t-daaaa-aaaaj-qnp2a-cai.raw.icp0.io/e17e265548a90d803975b95a9d32c158c213dd267b24826d71062f207a57319a.json](https://xea2t-daaaa-aaaaj-qnp2a-cai.raw.icp0.io/e17e265548a90d803975b95a9d32c158c213dd267b24826d71062f207a57319a.json) in your case, which will redirect to the `wanvb-2aaaa-aaaaj-qnp4a-cai` canister, which is a storage canister controlled by your collection canister : [https://dashboard.internetcomputer.org/canister/wanvb-2aaaa-aaaaj-qnp4a-cai](https://dashboard.internetcomputer.org/canister/wanvb-2aaaa-aaaaj-qnp4a-cai)  
If for any reason you want to store more than “stable memory limits”, or you can not store anymore on your storage canister, it will automaticly create a new canister on another subnet to handle infinite scaling.

Advanced info about how storage canister is working :  
Storage canister use stable memory to store assets. BUT, the ic-asset-certification library need assets to be served in heap. (note that currently, asset canister from dfinity store asset in heap.. 😕 )  
So, what i did here, is i use heap as a cache. So if https calls fail, i have to mutate some stuff in state, so i use a update calls : [ic-storage-canister/canister/src/queries/http\_request.rs at master · BitySA/ic-storage-canister · GitHub](https://github.com/BitySA/ic-storage-canister/blob/master/canister/src/queries/http_request.rs#L40)  
If the first RO call fail, that mean the asset is not mapped to heap. So i change to an update call and i start to look for the file, and if not available i return an error. If present, then i map the file to the heap and serve the asset to the client. note that, if no heap left are available, i use a first in first out mecanism to free heap usage. With wasm64 we will have soon ~6gb available in heap.

Does it help you to understand ?

Edit : Note that we will also start to work on encrypted assets, to have “private assets” only visible for nft owner. No timeline yet, will depend on human ressources.

---

<div class="post-metadata">

**Author:** ![ohsalmeron](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ohsalmeron/32/30099_2.png) [@ohsalmeron](https://forum.dfinity.org/u/ohsalmeron)\
**Post date:** [June 23, 2025, 4:42pm UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/14 "2025-06-23T16:42:06Z")

</div>

Thanks for the additional info, it really helps to understand exactly what is going on, I’ll be working on learning more about it.

I think the error on linux is related to my environment and how rust handles multiple projects (canisters, testing, commandline) this is very common issue when testing Github repos.

I like IPFS or even Filecoin for storage but if we can stack it all up together on ICP that’s a better solution, we just gotta figure out how to manage the creation of new canisters on other subnets to handle the infinite scaling(sweet) and cycles management.

Happy to join slack or signal, shoot me the invite!

---

<div class="post-metadata">

**Author:** ![Siriluxfitverse](https://avatars.discourse-cdn.com/v4/letter/s/0ea827/32.png) [@Siriluxfitverse](https://forum.dfinity.org/u/Siriluxfitverse)\
**Post date:** [July 16, 2025, 10:36am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/15 "2025-07-16T10:36:01Z")

</div>

I have some questions. 1. Only deployer can add & remove the minting\_authorities and authorized\_principals ?  
2. What are scope of authorized\_principals ?  
3. Can authorized\_principals update the NFT Metadata?

---

<div class="post-metadata">

**Author:** ![Gwojda](https://avatars.discourse-cdn.com/v4/letter/g/5fc32e/32.png) [@Gwojda](https://forum.dfinity.org/u/Gwojda)\
**Post date:** [July 16, 2025, 12:56pm UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/16 "2025-07-16T12:56:36Z")

</div>

When you deploy the collection, you choose who has access to minting and to “admin” (via authorized\_principals)

authorized\_principals can do admin/management, and update the minting autorities.

Yes, code is here :

> <https://github.com/ORIGYN-SA/nft/blob/master/src/core_nft/src/updates/management.rs#L194>

You can check the method are under 2 types of guards : caller\_is\_governance\_principal and caller\_is\_minting\_authority, which are defined here : [nft/src/core\_nft/src/guards.rs at master · ORIGYN-SA/nft · GitHub](https://github.com/ORIGYN-SA/nft/blob/master/src/core_nft/src/guards.rs#L75)

Thats something i might need to rework/update. This guards/rules mecanism might not be enough precise. I could maybe add some scope, and an admin scope, and check for each method if the principal has the right scope or not, maybe even add “teams” with scope level also.

What do you think?

---

<div class="post-metadata">

**Author:** ![Siriluxfitverse](https://avatars.discourse-cdn.com/v4/letter/s/0ea827/32.png) [@Siriluxfitverse](https://forum.dfinity.org/u/Siriluxfitverse)\
**Post date:** [July 16, 2025, 4:15pm UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/17 "2025-07-16T16:15:22Z")

</div>

I can understand now how it works, A system I want is admin principals who can manage minting authorities and upgrade/update authorities. Minting authorities can mint and update nft metadata. Upgrade update authorities can only update NFT Metadata.

Real world example is like a identity principal who can manage minting canister and upgrade/update canister for NFTs, Minting Canister would let users mint by paying tokens or ICP. Different upgrade/update canister can update metadata of NFTs based on mission, tasks, actions completed by user.

---

<div class="post-metadata">

**Author:** ![RobertoPirrone](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/robertopirrone/32/20879_2.png) [@RobertoPirrone](https://forum.dfinity.org/u/RobertoPirrone)\
**Post date:** [July 27, 2025, 2:28pm UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/18 "2025-07-27T14:28:56Z")

</div>

Awesome!  
a few small quirks (already filed by other people), but I was able to test the functionalities.

I already have an application with a React canister that interacts with a Rust backend used for image and document archiving.  
What is not really clear to me is how to interact with the nft canister from another rust canister. I tried to extract the rust code from the cmdline sources, but it fails in compilation. The problem lays in ic-agent, that uses a version of getrandom that cannot be easily compiled in wasm.  
I’m still a noob in the IC ecosystem, maybe the ic-agent is not intended for inter canister interaction, so I should try to use the inter-canister calls (the example in [https://internetcomputer.org/docs/building-apps/developer-tools/cdks/rust/intercanister](https://internetcomputer.org/docs/building-apps/developer-tools/cdks/rust/intercanister) ), but this is a completely different beast.

Have you ever considered this use case? Or, with a different approach, interacting with the NFT canister from JS?

---

<div class="post-metadata">

**Author:** ![Siriluxfitverse](https://avatars.discourse-cdn.com/v4/letter/s/0ea827/32.png) [@Siriluxfitverse](https://forum.dfinity.org/u/Siriluxfitverse)\
**Post date:** [July 29, 2025, 5:13am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/20 "2025-07-29T05:13:34Z")

</div>

You can use another canister for actions such as minting, burning, update the metadata. For this you need to do inter-canister calls. You will also need to set calling canister principal id as authorized or minting principal according to your application

---

<div class="post-metadata">

**Author:** ![RobertoPirrone](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/robertopirrone/32/20879_2.png) [@RobertoPirrone](https://forum.dfinity.org/u/RobertoPirrone)\
**Post date:** [July 29, 2025, 11:09am UTC](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578/21 "2025-07-29T11:09:54Z")

</div>

Yes, I alrady started to look at it.  
Right now from my backend canister I can query the nft canister to obtain the token metadata (I’m calling the entry point icrc7\_token\_metadata).  
The call is ok, I see the logs of the nft canisters, but it’s not very clear to me how to decode the result.

[Next page](https://forum.dfinity.org/t/announcing-icrc7-icrc37-a-complete-nft-implementation-for-the-internet-computer/48578.md?page=2)
