Skip to content

Working with NFTs

This section provides a complete guide to working with NFT collections using the tonutils library. It covers Standard, Soulbound, Editable, and Editable Onchain collections, including deployment, minting, batch operations, editing, and administrative tasks.


Standard Collection

Deploy Collection

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionStandard
from tonutils.nft.content import CollectionOffchainContent
from tonutils.nft.royalty_params import RoyaltyParams
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner of the NFT collection
OWNER_ADDRESS = "UQ..."

# URI of the collection's metadata
# https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#nft-collection-metadata-example-offchain
URI = "https://example.com/nft/collection.json"
PREFIX_URI = "https://example.com/nft/"

# Royalty parameters: base and factor for calculating the royalty
ROYALTY_BASE = 1000
ROYALTY_FACTOR = 55  # 5.5% royalty


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    collection = CollectionStandard(
        owner_address=Address(OWNER_ADDRESS),
        next_item_index=0,
        content=CollectionOffchainContent(uri=URI, prefix_uri=PREFIX_URI),
        royalty_params=RoyaltyParams(
            base=ROYALTY_BASE,
            factor=ROYALTY_FACTOR,
            address=Address(OWNER_ADDRESS),
        ),
    )

    """ If you want the option to withdraw extra balance in the future and store collection and NFT data on-chain,
        you can use `CollectionStandardModified`. It removes the need for `prefix_uri` because NFTs minted in this
        format include a direct link to the metadata for each item, rather than using a shared prefix for all items.

    Example:

    collection = CollectionStandardModified(
        owner_address=Address(OWNER_ADDRESS),
        next_item_index=0,
        content=CollectionModifiedOffchainContent(uri=URI),  # URI example: `https://example.com/nft/collection.json`.
        royalty_params=RoyaltyParams(
            base=ROYALTY_BASE,
            factor=ROYALTY_FACTOR,
            address=Address(OWNER_ADDRESS),
        ),
    )
    """

    tx_hash = await wallet.transfer(
        destination=collection.address,
        amount=0.05,
        state_init=collection.state_init,
    )

    print(f"Successfully deployed NFT Collection at address: {collection.address.to_str()}")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Mint NFT

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft.content import NFTOffchainContent
from tonutils.nft.contract.standard.collection import CollectionStandard
from tonutils.nft.contract.standard.nft import NFTStandard
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner of the NFT and the NFT collection contract
OWNER_ADDRESS = "UQ..."
COLLECTION_ADDRESS = "EQ..."

# Index of the NFT to be minted
NFT_INDEX = 0

# Suffix URI of the NFT metadata
SUFFIX_URI = f"{NFT_INDEX}.json"


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    nft = NFTStandard(
        index=NFT_INDEX,
        collection_address=Address(COLLECTION_ADDRESS),
    )
    body = CollectionStandard.build_mint_body(
        index=NFT_INDEX,
        owner_address=Address(OWNER_ADDRESS),
        content=NFTOffchainContent(suffix_uri=SUFFIX_URI),
    )

    """ If you deployed the collection using the Modified variant, replace the above code with:
        Replace `CollectionStandard` and `NFTStandard` with their modified versions,
        and use `NFTModifiedOffchainContent` to specify the full `URI` for the NFT metadata.

    Example:

    nft = NFTStandardModified(
        index=NFT_INDEX,
        collection_address=Address(COLLECTION_ADDRESS),
    )
    body = CollectionStandardModified.build_mint_body(
        index=NFT_INDEX,
        owner_address=Address(OWNER_ADDRESS),
        content=NFTModifiedOffchainContent(uri=URI),  # URI example: `https://example.com/nft/0.json`.
    )
    """

    tx_hash = await wallet.transfer(
        destination=COLLECTION_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully minted NFT with index {NFT_INDEX}: {nft.address.to_str()}")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Batch Mint NFT

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionStandard
from tonutils.nft.content import NFTOffchainContent
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner of the NFT and the NFT collection contract
OWNER_ADDRESS = "UQ..."
COLLECTION_ADDRESS = "EQ..."

# Starting index for minting items
FROM_INDEX = 0

# Number of items to mint
ITEMS_COUNT = 100


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = CollectionStandard.build_batch_mint_body(
        data=[
            (
                NFTOffchainContent(suffix_uri=f"{index}.json"),
                Address(OWNER_ADDRESS),
            )
            for index in range(FROM_INDEX, FROM_INDEX + ITEMS_COUNT)
        ],
        from_index=FROM_INDEX,
    )

    """ If you deployed the collection using the Modified variant, replace the above code with:
        Replace `CollectionStandard` with `CollectionStandardModified`, 
        and use `NFTModifiedOffchainContent` to specify the full `URI` for each NFT metadata.

    Example:

    body = CollectionStandardModified.build_batch_mint_body(
        data=[
            (
                NFTModifiedOffchainContent(uri=URI),  # URI example: `https://example.com/nft/{index}.json`.
                Address(OWNER_ADDRESS),
            )
            for index in range(FROM_INDEX, FROM_INDEX + ITEMS_COUNT)
        ],
        from_index=FROM_INDEX,
    )
    """

    tx_hash = await wallet.transfer(
        destination=COLLECTION_ADDRESS,
        amount=ITEMS_COUNT * 0.05,
        body=body,
    )

    print(f"Successfully minted {ITEMS_COUNT} items in the collection at address: {COLLECTION_ADDRESS}.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Soulbound Collection

Deploy Collection

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionSoulbound
from tonutils.nft.content import CollectionOffchainContent
from tonutils.nft.royalty_params import RoyaltyParams
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner of the NFT and the NFT collection contract
OWNER_ADDRESS = "UQ..."

# URI of the collection's metadata
# https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#nft-collection-metadata-example-offchain
URI = "https://example.com/nft/collection.json"
PREFIX_URI = "https://example.com/nft/"

# Royalty parameters: base and factor for calculating the royalty
ROYALTY_BASE = 1000
ROYALTY_FACTOR = 55  # 5.5% royalty


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    collection = CollectionSoulbound(
        owner_address=Address(OWNER_ADDRESS),
        next_item_index=0,
        content=CollectionOffchainContent(uri=URI, prefix_uri=PREFIX_URI),
        royalty_params=RoyaltyParams(
            base=ROYALTY_BASE,
            factor=ROYALTY_FACTOR,
            address=Address(OWNER_ADDRESS),
        ),
    )

    """ If you want the option to withdraw extra balance in the future and store collection and NFT data on-chain,
        you can use `CollectionSoulboundModified`. It removes the need for `prefix_uri` because NFTs minted in this
        format include a direct link to the metadata for each item, rather than using a shared prefix for all items.

    Example:

    collection = CollectionSoulboundModified(
        owner_address=Address(OWNER_ADDRESS),
        next_item_index=0,
        content=CollectionModifiedOffchainContent(uri=URI),  # URI example: `https://example.com/nft/collection.json`.
        royalty_params=RoyaltyParams(
            base=ROYALTY_BASE,
            factor=ROYALTY_FACTOR,
            address=Address(OWNER_ADDRESS),
        ),
    )
    """

    tx_hash = await wallet.transfer(
        destination=collection.address,
        amount=0.05,
        state_init=collection.state_init,
    )

    print(f"Successfully deployed NFT Collection at address: {collection.address.to_str()}")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Mint NFT

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionSoulbound, NFTSoulbound
from tonutils.nft.content import NFTOffchainContent
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner of the NFT and the NFT collection contract
OWNER_ADDRESS = "UQ..."
COLLECTION_ADDRESS = "EQ..."

# Index of the NFT to be minted
NFT_INDEX = 0

# Suffix URI of the NFT metadata
SUFFIX_URI = f"{NFT_INDEX}.json"


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    nft = NFTSoulbound(
        index=NFT_INDEX,
        collection_address=Address(COLLECTION_ADDRESS),
    )
    body = CollectionSoulbound.build_mint_body(
        index=NFT_INDEX,
        owner_address=Address(OWNER_ADDRESS),
        content=NFTOffchainContent(suffix_uri=SUFFIX_URI),
    )

    """ If you deployed the collection using the Modified variant, replace the above code with:
        Replace `CollectionSoulbound` and `NFTSoulbound` with their modified versions, 
        and use `NFTModifiedOffchainContent` to specify the full `URI` for the NFT metadata.

    Example:

    nft = NFTSoulboundModified(
        index=NFT_INDEX,
        collection_address=Address(COLLECTION_ADDRESS),
    )
    body = CollectionSoulboundModified.build_mint_body(
        index=NFT_INDEX,
        owner_address=Address(OWNER_ADDRESS),
        content=NFTModifiedOffchainContent(uri=URI),  # URI example: `https://example.com/nft/0.json`.
    )
    """

    tx_hash = await wallet.transfer(
        destination=COLLECTION_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully minted NFT with index {NFT_INDEX}: {nft.address.to_str()}")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Batch Mint NFT

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionSoulbound
from tonutils.nft.content import NFTOffchainContent
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner and editor of the NFT and the NFT collection contract
OWNER_ADDRESS = "UQ..."
EDITOR_ADDRESS = "UQ..."
COLLECTION_ADDRESS = "EQ..."

# Starting index for minting items
FROM_INDEX = 0

# Number of items to mint
ITEMS_COUNT = 100


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = CollectionSoulbound.build_batch_mint_body(
        data=[
            (
                NFTOffchainContent(suffix_uri=f"{index}.json"),
                Address(OWNER_ADDRESS),
                Address(EDITOR_ADDRESS),
                None,  # revoked at
            )
            for index in range(FROM_INDEX, FROM_INDEX + ITEMS_COUNT)
        ],
        from_index=FROM_INDEX,
    )

    """ If you deployed the collection using the Modified variant, replace the above code with:
        Replace `CollectionSoulbound` with `CollectionSoulboundModified`, 
        and use `NFTModifiedOffchainContent` to specify the full `URI` for each NFT metadata.

    Example:

    body = CollectionSoulboundModified.build_batch_mint_body(
        data=[
            (
                NFTModifiedOffchainContent(uri=URI),  # URI example: `https://example.com/nft/{index}.json`.
                Address(OWNER_ADDRESS),
                Address(EDITOR_ADDRESS),
                None,  # revoked at
            )
            for index in range(FROM_INDEX, FROM_INDEX + ITEMS_COUNT)
        ],
        from_index=FROM_INDEX,
    )
    """

    tx_hash = await wallet.transfer(
        destination=COLLECTION_ADDRESS,
        amount=ITEMS_COUNT * 0.05,
        body=body,
    )

    print(f"Minted {ITEMS_COUNT} items in collection {COLLECTION_ADDRESS}")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Revoke NFT

from tonutils.client import ToncenterV3Client
from tonutils.nft import NFTSoulbound
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the NFT to be revoked
NFT_ADDRESS = "EQ..."


async def main() -> None:
    # Initialize TonapiClient and Wallet
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = NFTSoulbound.build_revoke_body()

    tx_hash = await wallet.transfer(
        destination=NFT_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully revoked NFT at address: {NFT_ADDRESS}.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Destroy NFT

from tonutils.client import ToncenterV3Client
from tonutils.nft import NFTSoulbound
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the NFT to be destroyed
NFT_ADDRESS = "EQ..."


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = NFTSoulbound.build_destroy_body()

    tx_hash = await wallet.transfer(
        destination=NFT_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully destroyed NFT at address: {NFT_ADDRESS}.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Editable Collection

Deploy Collection

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionEditable
from tonutils.nft.content import CollectionOffchainContent
from tonutils.nft.royalty_params import RoyaltyParams
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner of the NFT collection
OWNER_ADDRESS = "UQ..."

# URI of the collection's metadata
# https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#nft-collection-metadata-example-offchain
URI = "https://example.com/nft/collection.json"
PREFIX_URI = "https://example.com/nft/"

# Royalty parameters: base and factor for calculating the royalty
ROYALTY_BASE = 1000
ROYALTY_FACTOR = 55  # 5.5% royalty


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    collection = CollectionEditable(
        owner_address=Address(OWNER_ADDRESS),
        next_item_index=0,
        content=CollectionOffchainContent(uri=URI, prefix_uri=PREFIX_URI),
        royalty_params=RoyaltyParams(
            base=ROYALTY_BASE,
            factor=ROYALTY_FACTOR,
            address=Address(OWNER_ADDRESS),
        ),
    )

    """ If you want the option to withdraw extra balance in the future and store collection and NFT data on-chain,
        you can use `CollectionEditableModified`. It removes the need for `prefix_uri` because NFTs minted in this
        format include a direct link to the metadata for each item, rather than using a shared prefix for all items.

    Example:

    collection = CollectionEditableModified(
        owner_address=Address(OWNER_ADDRESS),
        next_item_index=0,
        content=CollectionModifiedOffchainContent(uri=URI),  # URI example: `https://example.com/nft/collection.json`.
        royalty_params=RoyaltyParams(
            base=ROYALTY_BASE,
            factor=ROYALTY_FACTOR,
            address=Address(OWNER_ADDRESS),
        ),
    )
    """

    tx_hash = await wallet.transfer(
        destination=collection.address,
        amount=0.05,
        state_init=collection.state_init,
    )

    print(f"Successfully deployed NFT Collection at address: {collection.address.to_str()}")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Mint NFT

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionEditable, NFTEditable
from tonutils.nft.content import NFTOffchainContent
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner of the NFT and the NFT collection contract
OWNER_ADDRESS = "UQ..."
COLLECTION_ADDRESS = "EQ..."

# Index of the NFT to be minted
NFT_INDEX = 0

# Suffix URI of the NFT metadata
SUFFIX_URI = f"{NFT_INDEX}.json"


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    nft = NFTEditable(
        index=NFT_INDEX,
        collection_address=Address(COLLECTION_ADDRESS),
    )
    body = CollectionEditable.build_mint_body(
        index=NFT_INDEX,
        owner_address=Address(OWNER_ADDRESS),
        content=NFTOffchainContent(suffix_uri=SUFFIX_URI),
    )

    """ If you deployed the collection using the Modified variant, replace the above code with:
        Replace `CollectionEditable` and `NFTEditable` with their modified versions,
        and use `NFTModifiedOffchainContent` to specify the full `URI` for the NFT metadata.

    Example:

    nft = NFTEditableModified(
        index=NFT_INDEX,
        collection_address=Address(COLLECTION_ADDRESS),
    )
    body = CollectionEditableModified.build_mint_body(
        index=NFT_INDEX,
        owner_address=Address(OWNER_ADDRESS),
        content=NFTModifiedOffchainContent(uri=URI),  # URI example: `https://example.com/nft/0.json`.
    )
    """

    tx_hash = await wallet.transfer(
        destination=COLLECTION_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully minted NFT with index {NFT_INDEX}: {nft.address.to_str()}")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Batch Mint NFT

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionEditable
from tonutils.nft.content import NFTOffchainContent
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner and editor of the NFT and the NFT collection contract
OWNER_ADDRESS = "UQ..."
EDITOR_ADDRESS = "UQ..."
COLLECTION_ADDRESS = "EQ..."

# Starting index for minting items
FROM_INDEX = 0

# Number of items to mint
ITEMS_COUNT = 100


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = CollectionEditable.build_batch_mint_body(
        data=[
            (
                NFTOffchainContent(suffix_uri=f"{index}.json"),
                Address(OWNER_ADDRESS),
                Address(EDITOR_ADDRESS),
            )
            for index in range(FROM_INDEX, FROM_INDEX + ITEMS_COUNT)
        ],
        from_index=FROM_INDEX,
    )

    """ If you deployed the collection using the Modified variant, replace the above code with:
        Replace `CollectionEditable` with `CollectionEditableModified`, 
        and use `NFTModifiedOffchainContent` to specify the full `URI` for each NFT metadata.

    Example:

    body = CollectionEditableModified.build_batch_mint_body(
        data=[
            (
                NFTModifiedOffchainContent(uri=URI),  # URI example: `https://example.com/nft/{index}.json`.
                Address(OWNER_ADDRESS),
                Address(EDITOR_ADDRESS),
            )
            for index in range(FROM_INDEX, FROM_INDEX + ITEMS_COUNT)
        ],
        from_index=FROM_INDEX,
    )
    """

    tx_hash = await wallet.transfer(
        destination=COLLECTION_ADDRESS,
        amount=ITEMS_COUNT * 0.05,
        body=body,
    )

    print(f"Minted {ITEMS_COUNT} items in collection {COLLECTION_ADDRESS}")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Edit NFT Content

from tonutils.client import ToncenterV3Client
from tonutils.nft import NFTEditable
from tonutils.nft.content import NFTOffchainContent
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the NFT to be edited
NFT_ADDRESS = "EQ..."

# Suffix URI of the NFT metadata
SUFFIX_URI = f"new-content.json"


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = NFTEditable.build_edit_content_body(
        content=NFTOffchainContent(suffix_uri=SUFFIX_URI),
    )

    tx_hash = await wallet.transfer(
        destination=NFT_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully edited the content of NFT at address: {NFT_ADDRESS}.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Change NFT Editorship

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import NFTEditable
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the NFT whose editorship will be changed
NFT_ADDRESS = "EQ..."

# Address of the new editor to whom the editorship will be transferred
NEW_EDITOR_ADDRESS = "UQ..."


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = NFTEditable.build_change_editorship_body(
        editor_address=Address(NEW_EDITOR_ADDRESS),
    )

    tx_hash = await wallet.transfer(
        destination=NFT_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully changed the editorship of NFT {NFT_ADDRESS} to {NEW_EDITOR_ADDRESS}.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Edit Collection Content

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionEditable
from tonutils.nft.content import CollectionOffchainContent
from tonutils.nft.royalty_params import RoyaltyParams
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the royalty receiver and the NFT collection contract
ROYALTY_ADDRESS = "UQ..."
COLLECTION_ADDRESS = "EQ..."

# URI of the collection's metadata
# https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#nft-collection-metadata-example-offchain
URI = "https://example.com/nft/collection.json"
PREFIX_URI = "https://example.com/nft/"

# Royalty parameters: base and factor for calculating the royalty
ROYALTY_BASE = 1000
ROYALTY_FACTOR = 60  # 6% royalty


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = CollectionEditable.build_edit_content_body(
        content=CollectionOffchainContent(uri=URI, prefix_uri=PREFIX_URI),
        royalty_params=RoyaltyParams(
            base=ROYALTY_BASE,
            factor=ROYALTY_FACTOR,
            address=Address(ROYALTY_ADDRESS),
        ),
    )

    tx_hash = await wallet.transfer(
        destination=COLLECTION_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully edited the collection at address: {COLLECTION_ADDRESS}.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Change Collection Owner

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionEditable
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the new owner to whom the collection ownership will be transferred
NEW_OWNER_ADDRESS = "UQ..."

# Address of the NFT collection whose ownership will be changed
COLLECTION_ADDRESS = "EQ..."


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = CollectionEditable.build_change_owner_body(
        owner_address=Address(NEW_OWNER_ADDRESS),
    )

    tx_hash = await wallet.transfer(
        destination=COLLECTION_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully changed the owner of collection {COLLECTION_ADDRESS} to {NEW_OWNER_ADDRESS}.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Editable Onchain Collection

Deploy Collection

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionEditableModified
from tonutils.nft.content import CollectionModifiedOnchainContent
from tonutils.nft.royalty_params import RoyaltyParams
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner of the NFT collection
OWNER_ADDRESS = "UQ..."

# Royalty parameters: base and factor for calculating the royalty
ROYALTY_BASE = 1000
ROYALTY_FACTOR = 55  # 5.5% royalty


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    collection = CollectionEditableModified(
        owner_address=Address(OWNER_ADDRESS),
        next_item_index=0,
        content=CollectionModifiedOnchainContent(
            name="Welcome to TON",
            description="Each digital artwork represents a memorable token",
            image_data=b'image data',
        ),
        royalty_params=RoyaltyParams(
            base=ROYALTY_BASE,
            factor=ROYALTY_FACTOR,
            address=Address(OWNER_ADDRESS),
        ),
    )

    tx_hash = await wallet.transfer(
        destination=collection.address,
        amount=0.05,
        state_init=collection.state_init,
    )

    print(f"Successfully deployed NFT Collection at address: {collection.address.to_str()}")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Mint NFT

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionEditableModified, NFTEditableModified
from tonutils.nft.content import NFTModifiedOnchainContent
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the owner of the NFT and the NFT collection contract
OWNER_ADDRESS = "UQ..."
COLLECTION_ADDRESS = "EQ..."

# Index of the NFT to be minted
NFT_INDEX = 0


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    nft = NFTEditableModified(
        index=NFT_INDEX,
        collection_address=Address(COLLECTION_ADDRESS),
    )
    body = CollectionEditableModified.build_mint_body(
        index=NFT_INDEX,
        owner_address=Address(OWNER_ADDRESS),
        content=NFTModifiedOnchainContent(
            name="TON Collectible #0",
            description="Memorable token for completing an onboarding quest about the TON ecosystem",
            image_data=b'image data',
        ),
    )

    tx_hash = await wallet.transfer(
        destination=COLLECTION_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully minted NFT with index {NFT_INDEX}: {nft.address.to_str()}")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Return Collection Balance

from tonutils.client import ToncenterV3Client
from tonutils.nft import CollectionEditableModified
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the NFT collection contract
COLLECTION_ADDRESS = "EQ..."


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = CollectionEditableModified.build_return_balance()

    tx_hash = await wallet.transfer(
        destination=COLLECTION_ADDRESS,
        amount=0.02,
        body=body,
    )

    print(f"Successfully returned the balance of collection {COLLECTION_ADDRESS}.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Listing on Getgems.io

List NFT for Sale

from pytoniq_core import Address

from tonutils.client import ToncenterV3Client
from tonutils.nft import Collection, NFT
from tonutils.nft.marketplace.getgems.addresses import *
from tonutils.nft.marketplace.getgems.contract.salev3r3 import SaleV3R3
from tonutils.utils import to_nano
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the NFT to be listed for sale
NFT_ADDRESS = "EQ.."

# Sale price for the NFT in TON
PRICE = 1


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    nft_data = await NFT.get_nft_data(client, NFT_ADDRESS)
    royalty_params = await Collection.get_royalty_params(client, nft_data.collection_address)

    price = to_nano(PRICE)
    royalty_fee = int(price * (royalty_params.base / royalty_params.factor))
    marketplace_fee = int(price * 0.05)

    sale = SaleV3R3(
        nft_address=NFT_ADDRESS,
        owner_address=wallet.address,
        marketplace_address=TESTNET_GETGEMS_ADDRESS if IS_TESTNET else GETGEMS_ADDRESS,
        marketplace_fee_address=TESTNET_GETGEMS_FEE_ADDRESS if IS_TESTNET else GETGEMS_FEE_ADDRESS,
        royalty_address=royalty_params.address,
        marketplace_fee=marketplace_fee,
        royalty_fee=royalty_fee,
        price=price,
    )
    body = sale.build_transfer_nft_body(
        destination=Address(TESTNET_GETGEMS_DEPLOYER_ADDRESS if IS_TESTNET else GETGEMS_DEPLOYER_ADDRESS),
        owner_address=wallet.address,
        state_init=sale.state_init,
    )

    tx_hash = await wallet.transfer(
        destination=NFT_ADDRESS,
        amount=0.25,
        body=body,
    )

    # Print the result of the operation
    print(f"NFT {NFT_ADDRESS} successfully put on sale at price {PRICE} TON.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Change NFT Price

from tonutils.client import ToncenterV3Client
from tonutils.nft import Collection, NFT
from tonutils.nft.marketplace.getgems.contract.salev3r3 import SaleV3R3
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the NFT and sale contract
NFT_ADDRESS = "EQ..."
SALE_ADDRESS = "EQ..."

# New sale price for the NFT in TON
PRICE = 1


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    nft_data = await NFT.get_nft_data(client, NFT_ADDRESS)
    royalty_params = await Collection.get_royalty_params(client, nft_data.collection_address)

    price = int(PRICE * 1e9)
    royalty_fee = int(price * (royalty_params.base / royalty_params.factor))
    marketplace_fee = int(price * 0.05)

    body = SaleV3R3.build_change_price_body(
        marketplace_fee=marketplace_fee,
        royalty_fee=royalty_fee,
        price=price,
    )

    tx_hash = await wallet.transfer(
        destination=SALE_ADDRESS,
        amount=0.005,
        body=body,
    )

    print(f"Successfully updated the price for NFT sale.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Cancel NFT Sale

from tonutils.client import ToncenterV3Client
from tonutils.nft.marketplace.getgems.contract.salev3r3 import SaleV3R3
from tonutils.wallet import WalletV4R2

# Set to True for test network, False for main network
IS_TESTNET = True

# Mnemonic phrase
MNEMONIC = "word1 word2 word3 ..."

# Address of the sale contract
SALE_ADDRESS = "EQ..."


async def main() -> None:
    client = ToncenterV3Client(is_testnet=IS_TESTNET, rps=1, max_retries=1)
    wallet, _, _, _ = WalletV4R2.from_mnemonic(client, MNEMONIC)

    body = SaleV3R3.build_cancel_sale_body()

    tx_hash = await wallet.transfer(
        destination=SALE_ADDRESS,
        amount=0.2,
        body=body,
    )

    print("Sale has been successfully canceled.")
    print(f"Transaction hash: {tx_hash}")


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())