SHA256
302 lines
11 KiB
Markdown
302 lines
11 KiB
Markdown
# create-SHiNE-DAO
|
||
|
||
Чистый актуальный комплект для создания SHiNE DAO с переносимым governance mint (`Liquid`) и для работы с NFT, которые:
|
||
|
||
1. можно выпускать через голосование DAO;
|
||
2. можно сжигать через голосование DAO;
|
||
3. в будущем можно будет сжигать через отдельную быструю программу-исполнитель только для одного конкретного `mint`.
|
||
|
||
Этот набор сделан как production-style папка:
|
||
|
||
- без старых `runs/`;
|
||
- без старых `keypairs/`;
|
||
- без legacy-скриптов;
|
||
- без смешивания нескольких исторических подходов.
|
||
|
||
## Что внутри
|
||
|
||
- `dao.config.env.example` - шаблон конфига для создания mint и DAO в три шага.
|
||
- `scripts/01_create_governance_mint.js` - создание governance mint и metadata без депозита в Realm.
|
||
- `scripts/02_create_dao_with_governance_nfts.js` - создание `Realm / TokenOwnerRecord / Governance / Treasury` без deposit и без передачи authority.
|
||
- `scripts/03_transfer_dao_authorities.js` - передача `mint authority`, `freeze authority`, `realm authority` и `metadata update authority` на DAO.
|
||
- `nft-flow.config.env.example` - шаблон конфига для выпуска и burn NFT через уже созданное DAO.
|
||
- `scripts/01_check_dao_config.sh` - проверка конфига перед созданием DAO из существующего mint.
|
||
- `scripts/04_prepare_second_voter.js` - подготовка второго голосующего.
|
||
- `scripts/05_create_empty_nft_template_with_metadata.js` - создание NFT mint-шаблона с metadata и картинкой.
|
||
- `scripts/06_propose_vote_mint_nft.js` - proposal/sign/vote на mint NFT.
|
||
- `scripts/07_execute_mint_nft.js` - execute mint proposal.
|
||
- `scripts/08_propose_vote_burn_nft.js` - proposal/sign/vote на burn NFT.
|
||
- `scripts/09_execute_burn_nft.js` - execute burn proposal.
|
||
- `docs/FUTURE_FAST_BURN_EXECUTOR.md` - описание будущей программы для быстрого burn одного конкретного `mint`.
|
||
|
||
## Подтвержденная база, на которой собран комплект
|
||
|
||
Комплект собран из тех сценариев, которые уже были подтверждены на devnet:
|
||
|
||
- DAO с `Realm / Governance / Native Treasury`;
|
||
- mint NFT через DAO;
|
||
- burn NFT через DAO.
|
||
|
||
## Важное ограничение текущей схемы burn через DAO
|
||
|
||
Текущий стандартный burn через proposal работает так:
|
||
|
||
1. в proposal вшивается конкретная burn-инструкция;
|
||
2. в ней зашит конкретный token account, из которого надо сжигать NFT;
|
||
3. если владелец успеет переложить NFT в другой token account до `execute`, этот `execute` может не пройти.
|
||
|
||
То есть:
|
||
|
||
- burn определяется по `mint`;
|
||
- но исполняется из конкретного текущего token account;
|
||
- если токен двигают между proposal и execute, нужна более быстрая схема.
|
||
|
||
Именно для этого отдельно описан future-подход с одноразовым fast-burn executor.
|
||
|
||
## Что нужно заранее
|
||
|
||
В корне Solana-модуля:
|
||
|
||
```bash
|
||
cd shine-solana/shine
|
||
npm install
|
||
```
|
||
|
||
Нужны зависимости:
|
||
|
||
- `@solana/web3.js`
|
||
- `@solana/spl-token`
|
||
- `@solana/spl-governance`
|
||
- `@metaplex-foundation/mpl-token-metadata`
|
||
- `@metaplex-foundation/umi`
|
||
|
||
Также должны быть установлены CLI:
|
||
|
||
- `solana`
|
||
- `solana-keygen`
|
||
- `node`
|
||
|
||
## Быстрый сценарий: создать mint, раздать токены, создать DAO и затем передать все права на DAO
|
||
|
||
### 1. Создать конфиг
|
||
|
||
```bash
|
||
cp create-SHiNE-DAO/dao.config.env.example create-SHiNE-DAO/dao.config.env
|
||
```
|
||
|
||
Заполнить:
|
||
|
||
- имя DAO;
|
||
- путь к keypair создателя;
|
||
- имя и символ governance mint;
|
||
- при необходимости `DAO_GOV_MINT_KEYPAIR` для красивого или фиксированного mint address;
|
||
- `DAO_GOV_TOKEN_METADATA_URI` и `DAO_GOV_TOKEN_IMAGE_URL`.
|
||
|
||
Обычно используются два keypair-файла:
|
||
|
||
- `DAO_ISSUER_KEYPAIR` - временный кошелёк создателя/оператора;
|
||
- `DAO_GOV_MINT_KEYPAIR` - keypair самого mint, если нужен красивый адрес governance mint.
|
||
|
||
Сгенерировать их можно так:
|
||
|
||
```bash
|
||
solana-keygen new --outfile ./dao-issuer.json
|
||
solana-keygen new --outfile ./dao-gov-mint.json
|
||
```
|
||
|
||
Публичные ключи посмотреть так:
|
||
|
||
```bash
|
||
solana-keygen pubkey ./dao-issuer.json
|
||
solana-keygen pubkey ./dao-gov-mint.json
|
||
```
|
||
|
||
Практическое правило:
|
||
|
||
- первый keypair обычно временный, его красивый адрес не важен;
|
||
- красивым обычно имеет смысл делать именно `DAO_GOV_MINT_KEYPAIR`, потому что это постоянный публичный адрес governance mint.
|
||
|
||
### 2. Создать governance mint
|
||
|
||
```bash
|
||
node create-SHiNE-DAO/scripts/01_create_governance_mint.js ./create-SHiNE-DAO/dao.config.env
|
||
```
|
||
|
||
Этот шаг:
|
||
|
||
1. создаёт mint;
|
||
2. прикрепляет metadata на Arweave;
|
||
3. оставляет у кошелька создателя:
|
||
- `mint authority`
|
||
- `freeze authority`
|
||
- `metadata update authority`
|
||
|
||
Актуальные Arweave-ссылки для governance mint сейчас такие:
|
||
|
||
- image: `https://arweave.net/rPGo-uYIFoLxMBVTGyPr5K6fuF0y9xL-8TlAaZyBJgY`
|
||
- metadata: `https://arweave.net/PdupvtRhj_DTBjTLcjD7Z5GSiEcFUf01GHaYMDs6gGw`
|
||
|
||
### 3. Раздать токены вручную
|
||
|
||
```bash
|
||
spl-token mint <GOVERNANCE_MINT> 1 <WALLET_1>
|
||
spl-token mint <GOVERNANCE_MINT> 1 <WALLET_2>
|
||
```
|
||
|
||
После этого можно руками наминтить управляющие токены на нужные кошельки.
|
||
На этом этапе токен ещё обычный и переносимый.
|
||
|
||
### 4. Проверить конфиг DAO
|
||
|
||
```bash
|
||
./create-SHiNE-DAO/scripts/01_check_dao_config.sh ./create-SHiNE-DAO/dao.config.env
|
||
```
|
||
|
||
Перед проверкой в `dao.config.env` нужно указать:
|
||
|
||
- `DAO_GOV_TOKEN_MINT` - уже созданный mint;
|
||
- `DAO_REALM_NAME` - новое имя DAO;
|
||
- `DAO_ISSUER_KEYPAIR` - кошелёк создателя;
|
||
- `DAO_VOTING_TIME_SEC` - по умолчанию `86400` секунд (1 день);
|
||
- `DAO_APPROVAL_THRESHOLD_PERCENT`.
|
||
|
||
### 5. Создать DAO
|
||
|
||
```bash
|
||
node create-SHiNE-DAO/scripts/02_create_dao_with_governance_nfts.js ./create-SHiNE-DAO/dao.config.env
|
||
```
|
||
|
||
Этот шаг:
|
||
|
||
- создаёт `Realm`;
|
||
- создаёт `TokenOwnerRecord` для кошелька создателя без deposit;
|
||
- создаёт `Governance` и `Native Treasury`;
|
||
- задаёт community token type = `Liquid`;
|
||
- не делает deposit токенов;
|
||
- не передаёт authority.
|
||
|
||
После этого из отчета взять:
|
||
|
||
- `realm`
|
||
- `governance`
|
||
- `communityMint`
|
||
- `tokenOwnerRecord`
|
||
|
||
### 6. Передать все authority на DAO
|
||
|
||
```bash
|
||
node create-SHiNE-DAO/scripts/03_transfer_dao_authorities.js ./create-SHiNE-DAO/dao.config.env
|
||
```
|
||
|
||
Этот шаг передаёт на DAO:
|
||
|
||
- `mint authority`
|
||
- `freeze authority`
|
||
- `realm authority`
|
||
- `metadata update authority`
|
||
|
||
После этого у создателя не должно остаться административных прав на governance mint и Realm.
|
||
|
||
### 7. Создать конфиг NFT-flow
|
||
|
||
```bash
|
||
cp create-SHiNE-DAO/nft-flow.config.env.example create-SHiNE-DAO/nft-flow.config.env
|
||
```
|
||
|
||
Подставить:
|
||
|
||
- `REALM`
|
||
- `GOVERNANCE`
|
||
- `GOVERNING_MINT`
|
||
- `MAIN_KEYPAIR`
|
||
- `VOTER2_KEYPAIR`
|
||
- metadata URI и картинку для целевого NFT.
|
||
|
||
### 8. Подготовить второго голосующего
|
||
|
||
```bash
|
||
node create-SHiNE-DAO/scripts/04_prepare_second_voter.js ./create-SHiNE-DAO/nft-flow.config.env
|
||
```
|
||
|
||
### 9. Создать NFT mint-шаблон с metadata
|
||
|
||
```bash
|
||
node create-SHiNE-DAO/scripts/05_create_empty_nft_template_with_metadata.js ./create-SHiNE-DAO/nft-flow.config.env
|
||
```
|
||
|
||
Скрипт вернет `mint` будущего NFT.
|
||
|
||
### 10. Поднять proposal на mint NFT
|
||
|
||
```bash
|
||
node create-SHiNE-DAO/scripts/06_propose_vote_mint_nft.js \
|
||
./create-SHiNE-DAO/nft-flow.config.env \
|
||
<TARGET_WALLET> \
|
||
<NFT_MINT>
|
||
```
|
||
|
||
### 11. Выполнить mint proposal
|
||
|
||
```bash
|
||
node create-SHiNE-DAO/scripts/07_execute_mint_nft.js \
|
||
./create-SHiNE-DAO/nft-flow.config.env \
|
||
<PROPOSAL> \
|
||
<PROPOSAL_TX> \
|
||
<TARGET_WALLET> \
|
||
<NFT_MINT>
|
||
```
|
||
|
||
### 12. Поднять proposal на burn NFT
|
||
|
||
```bash
|
||
node create-SHiNE-DAO/scripts/08_propose_vote_burn_nft.js \
|
||
./create-SHiNE-DAO/nft-flow.config.env \
|
||
<CURRENT_OWNER_WALLET> \
|
||
<NFT_MINT>
|
||
```
|
||
|
||
### 13. Выполнить burn proposal
|
||
|
||
```bash
|
||
node create-SHiNE-DAO/scripts/09_execute_burn_nft.js \
|
||
./create-SHiNE-DAO/nft-flow.config.env \
|
||
<PROPOSAL> \
|
||
<PROPOSAL_TX> \
|
||
<CURRENT_OWNER_WALLET> \
|
||
<NFT_MINT>
|
||
```
|
||
|
||
## Что важно про картинку NFT
|
||
|
||
У конкретного NFT картинка идет не отдельным on-chain полем, а через metadata JSON по `uri`.
|
||
|
||
То есть нужно:
|
||
|
||
1. загрузить JSON metadata на Arweave/IPFS/HTTPS;
|
||
2. в JSON указать `image`;
|
||
3. в конфиге передать `NFT_METADATA_URI`;
|
||
4. `NFT_IMAGE_URL` хранить для явной проверки и документации.
|
||
|
||
## Что важно про стартовые governance NFT
|
||
|
||
В новом трёхшаговом flow governance mint создается отдельно, токены можно распределить вручную до создания DAO, а затем отдельным шагом DAO получает права на:
|
||
|
||
- `mint authority`
|
||
- `freeze authority`
|
||
- `realm authority`
|
||
- `metadata update authority`
|
||
|
||
Это сделано специально, чтобы:
|
||
|
||
1. сначала спокойно распределить токены;
|
||
2. затем создать Realm без блокировки стартовых токенов;
|
||
3. и только потом окончательно передать контроль DAO.
|
||
|
||
## Future
|
||
|
||
Если нужен сценарий "хитрый владелец постоянно перекладывает NFT", смотреть:
|
||
|
||
- `docs/FUTURE_FAST_BURN_EXECUTOR.md`
|
||
|
||
Там описана целевая отдельная программа, которой DAO может выдать одноразовое право сжечь только один конкретный `mint`.
|