npm package: @punkcodeprotocol/sdk
Description: Punkcode Labs. Dynamic NFT protocol.
Latest version: 0.0.1

# 🚀 MetaToken SDK 
[TOC]

## 📌 Overview

## 📥 Installation & Setup

```shell
npm i metatoken_sdk
```

## 📝 How to use MetaTokenSDK? Refer to this example

### 1. Deploy your Avatar and Weapon 
```ts
import { MetaTokenDeployer } from "metatoken_sdk";
const ethProvider = ethers.getDefaultProvider("goerli"); // goerli testnet 
const signer = new ethers.Wallet(key, provider);

// deploy your Avatar
let deployTx = await MetaTokenContract.deployDefault({
    chainId: chainId,
    runner: signer,
    name: "Avatar",
    symbol: "AV",
});
const avatarContract = deployTx.metaTokenContract;

// deploy your Weapon
deployTx = await MetaTokenContract.deployDefault({
    chainId: chainId,
    runner: signer,
    name: "Weapon",
    symbol: "WP",
});
const weaponContract = deployTx.metaTokenContract;
```
|Function| Parameter                               |   Parameter Description   |    type |
|---| --------------------------------------- | --------- |-----|
|**deployDefault**| **signer**  | ethers signer | signer |
|| **chainId**       | chainId of network |number|
|| **name**       | the name of MetaToken |string|
|| **symbol**       | the symbol of MetaToken |String|

### 2. Deploy your PropertyFactory
```ts
deployTx = await PropertyFactory.deployDefault({
    chainId: chainId,
    runner: signer,
    name: "PropertyFactory",
    uri: "<propertyURI>",    
});
const propertyFactoryContract = deploy.propertyFactory;
```
|Function| Parameter                               |   Description    |    type |
|---| --------------------------------------- | --------- |-----|
|**deployDefault**| **signer**  | ethers signer | signer |
|| **chainId**       | chainId of network |number|
|| **name**       | the name of MetaToken |string|
|| **uri**       | the uri of MetaToken |string|

### 3. Mint MetaToken and construct.
```ts
const mintAvatarTx = await avatarContract.mint({to: "<to_address>"});
// first avatar
const avatar00 = new MetaToken({
    tokenAddress: avatarContract.tokenAddress,
    tokenId: mintTx.metaTokenId,
    chainId: chainId,
    signer: signer,
});

const mintWeaponTx = await avatarContract.mint({to: await avatar00.getTokenBoundAccount()});
// first weapon
const weapon00 = new new MetaToken({
    tokenAddress: weaponContract.tokenAddress,
    tokenId: mintWeaponTx.metaTokenId,
    chainId: chainId,
    signer: signer,
});

```
| Function                        | Parameter | Parameter Description  | type   |
| --------------------------------------- | --------- |-----| --------------------------------------- |
| **mint** | **to**    | the address of someone you want to send | String |

|Function| Parameter                               | Parameter Description |    type |
|---| --------------------------------------- | --------- |-----|
|**construct**| **tokenAddress**  | the address of MetaToken | string |
|| **tokenId**  | the id of MetaToken you mint | number |
|| **chainId**  | chainId | number |
|| **signer**  | ethers signer | signer |

### 4. Setup EventUp & EventDown. 

Metatoken can only add tokens from the eventup, and Metatoken can only be added by tokens from the eventdown list

```ts
const setEventsUpTx = await avatar00.getContract().connect(signer).setEventsUp({eventUps:['<weaponTokenAddress>']})
const setEventsDownTx = await weapon00.getContract().connect(signer).setEventsDown({eventDowns:['<avatarTokenAddress>']})
```
|Function| Parameter                               | Parameter Description |    type |
|---| --------------------------------------- | --------- |-----|
|**setEventsUp**| **eventUps**  | list of address you want the MetaToken can be added | list |
|**setEventsDown**| **eventDowns**  | list of address you want the MetaToken can add | list |

### 5. Control your Weapon with your Avatar

You can add weapon, remove weapon, replace them.

**[Note]**  Make sure your Avatar's TokenBoundAccount owns the Weapon

```ts
// you can add child for your token
await avatar00.addChild({
    childToken: {
        tokenAddress: weapon.tokenAddress,
        tokenId: weapon.tokenId,
    },
});
// you can serach your childs
await avatar00.getChilds(); 
// you can search your parent
await weapon00.getParent();
// you can remove child for your token
await avatar00.removeChild({
    waitRemoveChildTokenIndex: 0,
})
// you can replace child for your token
await avatar00.batchReplaceChild({
    waitAddChildTokens: [
        {
            tokenAddress: "<WeaponAddress>",
            tokenId: "<anotherTokenId>",
        },
    ],
    waitRemoveChildTokenIndex: [0],
});
```

|Structure|Parameter| Parameter Description | Type|
|--| --------------------------------------- | --------- |-----|
| **childToken/waitAddChildTokens**  | tokenAddress | Token address | address |
| | tokenId | Token id | int |


|Function| Parameter                               |   Parameter Description   |
|--| --------------------------------------- | --------- |
|**addChild**| **childToken**  | token info you want to add |
|**removeChild**| **waitRemoveChildTokenIndex** | index of token you want to remove from MetaToken |
|**batchReplaceChild**| **waitAddChildTokens** | token info list you want to add  |
|| **waitRemoveChildTokenIndex** | index of token you want to remove from MetaToken |
|**getChilds**|  |  |
|**getParent**|  |  |

### 7. Setup global property

This function is used to configure global properties, as example, we configure "ATTACK" and "Defend" as our default properties.

```ts
// add global property (Attack and Defend)
await propertyFactoryContract.addGlobalProperty({property:["ATK", "DEF"]});
console.log(await propertyFactoryContract.queryGlobalProperty());
// output: [ 'ATK', 'DEF' ]
```

|Function| Parameter                               |   Parameter Description   | Type |
|--| --------------------------------------- | --------- | ---|
|**addGlobalProperty**| **property** | property list | list |

### 8. Register PropertyFactory for your Avatar and Weapon

By register PropertyFactory for your MetaToken, you can manage the properties available for Metatoken with the PropertyFactory.

```ts
// register avatar
await avatarContract.setUpPropertyFactory({
    factoryAddress: propertyFactoryContract.implementationAddress,
});
// register weapon
await weaponContract.setUpPropertyFactory({
    factoryAddress: propertyFactoryContract.implementationAddress,
});
```

|Function| Parameter                               |   Parameter Description   | Type |
|--| --------------------------------------- | --------- | ---|
|**setUpPropertyFactory**| **factoryAddress** | property factory implement address | string |

### 9. Setup Avatar's property and Weapon's property

Configure the properties available for Metatoken.

```ts
// add atk and def for avatar
await propertyFactoryContract.setPropertyFor({
    tokenAddress: avatar.tokenAddress,
    propertyIndex: [0, 1],
});
// add atk for avatar
await propertyFactoryContract.setPropertyFor({
    tokenAddress: weapon.tokenAddress,
    propertyIndex: [0],
});
```
|Function| Parameter                               |   Parameter Description   | Type |
|--| --------------------------------------- | --------- | ---|
|**setPropertyFor**| **tokenAddress** | MetaToken implement address | string |
| | **propertyIndex** | index of property | list |

### 10. Mint property for your Avatar and Weapon
```ts
// add 100 atk to avatar
await propertyFactoryContract.mintProperty({
    to: (await avatar00.getTokenBoundAccount()).address,
    propertyIndex: 0,
    amount: 100,
    data: "0x",
});
// add 50 def to avatar
await propertyFactoryContract.mintProperty({
    to: (await avatar00.getTokenBoundAccount()).address,
    propertyIndex: 1,
    amount: 100,
    data: "0x",
});
// add 45 atk to weapon
await propertyFactoryContract.mintProperty({
    to: (await weapon00.getTokenBoundAccount()).address,
    propertyIndex: 0,
    amount: 100,
    data: "0x",
});
```

|Function| Parameter                               |   Parameter Description   | Type |
|--| --------------------------------------- | --------- | ---|
|**mintProperty**| **to** | to address | string |
| | **propertyIndex** | index of property | number |
| | **amount** | amount | number |
| | **data(optional)** | call data | hex string |

### 11. Now you can search your Avatar's property and Weapon's property
```ts
await propertyFactoryContract.propertiesOf({ tokenAddress: avatar00.tokenAddress, tokenId:0 }),
await propertyFactoryContract.propertiesOf({ tokenAddress: weapon00.tokenAddress }),
```

|Function| Parameter                               |   Parameter Description   | Type |
|--| --------------------------------------- | --------- | ---|
|**propertiesOf**| **tokenAddress** | tokenAddress | string |
| | **tokenId(optional)** | tokenId | number |

### 12. We also support ERC6551

[You can learn how to use TokenBound here.](https://github.com/tokenbound/sdk/blob/main/README.md)