# CW721 Tokens

Paloma.py enables developers to create and interact with the Cosmos version of NFTs - [CW721 tokens](https://github.com/CosmWasm/cw-nfts/blob/main/packages/cw721/README.md) without knowing Rust. The SDK allows you to bypass learning CosmWasm and simply staying in Python.

There are 9 functions for CW721 that are implemented in paloma.py.

## instantiate()

Create a new CW721 by instantiating a CW721 smart contract. You'll need the code id of a deployed CW20 compatible wasm code. You can find the deployed CW721 compatible contracts in the [resource section](/content/guide/resources/networks.html#deployed-contracts/index.html). You may also upload your own contract and use that instead. See the [smart contract documentation](/content/guide/develop/quick-start/paloma-py/smart-contracts/index.html) for more details.
As CW721 creator, you'll choose the name, symbol and the total supply amount which is minted to the deployer wallet.

Arguments:

- `wallet` (Paloma address): CW721 deployer wallet address
- `code_id` (int): Code_id of CW721 wasm code
- `name` (str): CW721 token name
- `symbol` (str): CW721 token symbol
- `minter`: CW721 token minter
- `decimals` (int): CW721 token decimals
- `total_supply` (int): CW721 token total supply

Returns:
BlockTxBroadcastResult: Transaction Broadcast Result

## mint()

With this function you will be able to mint the NFTs.

Arguments:

- `wallet` (Paloma address): CW721 sender wallet address
- `token` (str): CW721 token address
- `token_id` (str): CW721 token id
- `owner` (str): owner who will receive the CW721 token
- `token_uri` (str): URI of the minting token used to construct the metadata

Returns:
BlockTxBroadcastResult: Transaction Broadcast Result

## approve()

This allows the `spender` to transfer or send the token from the owner's account. If `expires` is set, then this allowance expires at the time/height limit.

Arguments:

- `wallet` (Paloma address): CW721 owner wallet address
- `token` (str): CW721 token address
- `spender` (str): the address who will get permission to the CW721 token
- `token_id` (str): token id of the CW721 token
- `expires`: (dict, optional) {"at_height": height(u64)} / {"at_time":timestamp(nanosecond, u64)}

Returns:
BlockTxBroadcastResult: Transaction Broadcast Result

## revoke()

Removes previously granted approval from the `spender`.

Arguments:

- `wallet` (Paloma address): CW721 sender wallet address
- `token` (str): token address
- `spender` (str): approved address for which approval should be revoked
- `token_id` (str): CW721 token id

Returns:
BlockTxBroadcastResult: Transaction Broadcast Result

## approve_all()

This function allows an `operator` to transfer or send any available token from the owner's account. If `expires` is set, then this allowance has a time/height limit.

Arguments:

- `wallet` (Paloma address): CW721 sender wallet address
- `token` (str): CW721 token address
- `operator` (str): the address who will get permission to the CW721 tokens
- `expires`: (dict, optional) {"at_height": height(u64)} / {"at_time":timestamp(nanosecond, u64)}

Returns:
BlockTxBroadcastResult: Transaction Broadcast Result

## revoke_all()

Removes previously granted approval from the `operator`.

Arguments:

- `wallet` (Paloma address): CW721 sender wallet address
- `token` (str): CW721 token address
- `operator` (str): approved address for which approval should be revoked

Returns:
BlockTxBroadcastResult: Transaction Broadcast Result

## transfer_nft()

Allows to send a CW721 NFT token to another address.

Arguments:

- `wallet` (Paloma address): CW721 sender wallet address
- `token` (str): CW721 token address
- `recipient` (str): token receiver address
- `token_id` (str): token id

Returns:
BlockTxBroadcastResult: Transaction Broadcast Result

## send_nft()

This function allows you to send a CW721 token to a CW721 compatible contract along with a message.

Arguments:

- `wallet` (Paloma address): CW721 sender wallet address
- `token` (str): CW721 token address
- `contract` (str): token receiver contract address
- `token_id` (str): token id
- `msg` (str): base64 encoded message

Returns:
BlockTxBroadcastResult: Transaction Broadcast Result

## burn()

This removes a specific CW721 token.

Arguments:

- `wallet` (Paloma Address): wallet from which the tokens should be removed
- `token` (str): CW721 token address
- `token_id` (str): token id to be burnt

Returns:
BlockTxBroadcastResult: Transaction Broadcast Result

## Example

See the example below for a sample use of the available functions.

```py
import asyncio
from pathlib import Path

import uvloop
from terra_proto.cosmwasm.wasm.v1 import AccessType
from paloma_sdk.client.lcd import AsyncLCDClient
from paloma_sdk.client.lcd.api.tx import CreateTxOptions
from paloma_sdk.core.wasm import MsgInstantiateContract, MsgStoreCode
from paloma_sdk.key.mnemonic import MnemonicKey
from paloma_sdk.core.wasm.data import AccessConfig
from paloma_sdk.util.contract import get_code_id, get_contract_address, read_file_as_b64

async def main():
    paloma = AsyncLCDClient(url="https://lcd.testnet.palomaswap.com/", chain_id="paloma-testnet-17")
    paloma.gas_prices = "0.01ugrain"
    # test1 = paloma.wallets["test1"]
    acc = MnemonicKey(
        mnemonic="notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius"
    )

acc2 = MnemonicKey(
        mnemonic="index light average senior silent limit usual local involve delay update rack cause inmate wall render magnet common feature laundry exact casual resource hundred"
    )
    test1 = paloma.wallet(acc)
    test2 = paloma.wallet(acc2)

# print(test1.key.acc_address)
    store_code_tx = await test1.create_and_sign_tx(
        CreateTxOptions(
            msgs=[\
                MsgStoreCode(\
                    test1.key.acc_address,\
                    read_file_as_b64(Path(__file__).parent / "./cw721_base.wasm"),\
                    AccessConfig(AccessType.ACCESS_TYPE_EVERYBODY, ""),\
                )\
            ]
        )
    )
    store_code_tx_result = await paloma.tx.broadcast(store_code_tx)
    print(store_code_tx_result)

code_id = get_code_id(store_code_tx_result)

# code_id = 1
    print(f"code_id:{code_id}")

result = await paloma.cw721.instantiate(
        test1, code_id, "CW721 Token", "CWFT", test1.key.acc_address
    )
    print(result)

contract_address = result.logs[0].events_by_type["instantiate"][\
            "_contract_address"\
        ][0]
    print(contract_address)

result = await paloma.cw721.mint(
        test1, contract_address, "1", test1.key.acc_address, "test uri"
    )
    print(result)

result = await paloma.cw721.approve(
        test1, contract_address, test2.key.acc_address, "1"
    )
    print(result)

result = await paloma.cw721.revoke(
        test1, contract_address, test2.key.acc_address, "1"
    )
    print(result)

result = await paloma.cw721.approve_all(
        test1, contract_address, test2.key.acc_address
    )
    print(result)

result = await paloma.cw721.revoke_all(
        test1, contract_address, test2.key.acc_address
    )
    print(result)

result = await paloma.cw721.transfer_nft(
        test1, contract_address, test2.key.acc_address, "1"
    )
    print(result)

result = await paloma.cw721.burn(
        test2, contract_address, "1"
    )
    print(result)

await paloma.session.close()

uvloop.install()
asyncio.run(main())
```
