logo
back
back
Назад

Используя dApps , смарт-аккаунты и смарт-аcсеты , вы можете реализовать различные приложения с поддержкой блокчейна: игры и азартные игры, DeFi, цифровая идентификация, цепочки поставок и многое другое

Создайте Smart Asset Smart Asset Smart Asset

Функционал учетной записи WAVES позволяет только убедиться, что выпущенная из нее транзакция действительно была отправлена с этой учетной записи

Подробнее
gradient
img
img

Создайте свой первый смарт-ассет за один шаг в WAVES IDE

Смарт-ассет без сжигания

arrow
plus

Создайте свой первый смарт-ассет

Step 1

Директивы

Каждый скрипт Ride должен начинаться с директив Эти директивы сообщают компилятору, что:

< Скрипт использует стандартную библиотеку версии 6 >
< Тип скрипта Smart Account >
< Скрипт будет привязан к учетной записи >
ride
Копировать
1
2
3
{-# STDLIB_VERSION 6 #-}
{-# CONTENT_TYPE EXPRESSION #-}
{-# SCRIPT_TYPE ASSET #-}

Вспомогательные определения и логические выражения

После директив вы можете определить вспомогательные переменные и функции. Выражение проверяет транзакции с активом на соответствие заданным условиям. Если условия не выполняются, транзакция отклоняется

ride
Копировать
1
2
3
4
match tx {
    case t : SetAssetScriptTransaction | BurnTransaction => throw("You can`t set new script or burn token")
    case _ => true
}

Добавьте скрипт в свой проект

Это намного проще, чем вы себе представляете. Скажите «Hello World» в сети WAVES Вставьте этот скрипт в свой проект

Новый проект IDE
ride
Копировать
1
2
3
4
5
6
7
8
{-# STDLIB_VERSION 6 #-}
{-# CONTENT_TYPE EXPRESSION #-}
{-# SCRIPT_TYPE ASSET #-}

match tx {
    case t : SetAssetScriptTransaction | BurnTransaction => throw("You can`t set new script or burn token")
    case _ => true
}
arrow
plus

Развернуть

Step 2

deploy
deploy
deploy

Развертывание скрипта в сети Waves

deploy
deploy
deploy

Во время развертывания вам нужно будет создать свою учетную запись, если у вас ее еще нет

arrow
plus

Запустить тест

Step 3

// Запустить тест с помощью Surfboard

// В предыдущем разделе мы выполняем все действия, которые нам нужны для тестирования смарт-аккаунта, и генерируется определенное количество аккаунтов с указанным балансом

ride
Копировать
1
2
3
4
5
6
7
8
9
10
11
describe('Smart-asset test suite', async function () {
    const wvs = 10 ** 8;
    let curtAssetId;

    this.timeout(100000);

before(async function () {
    await setupAccounts({
        curt: 10 * wvs
    });
});

//Развертывание осуществляется транзакцией установки скрипта на аккаунт

ride
Копировать
1
2
3
4
5
6
7
8
9
10
11
    accontScript = compile(file('account-script.ride'));
const ssTx = setScript({ script: accontScript }, accounts.user);
    await broadcast(ssTx);
    await waitForTx(ssTx.id);

    const ssTx2 = setScript({ script: accontScript }, accounts.secondUser);
    await broadcast(ssTx2);
    await waitForTx(ssTx2.id);

    console.log('Script has been set')
});

//Каждый раздел it() служит для проверки некоторой функциональности
// Трансфер Waves

ride
Копировать
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
it('Should transfer less than 1500', async function () {
    const transferTx = transfer({ amount: 1000, recipient: address(accounts.secondUser), fee: 1000000 }, accounts.user);

    // Get account effective balance
    const userBalanceBefore = await balance(address(accounts.user));
    const secondUserBalanceBefore = await balance(address(accounts.secondUser));

    await broadcast(transferTx);
    await waitForTx(transferTx.id);

    const userBalanceAfter = await balance(address(accounts.user));
    const secondUserBalanceAfter = await balance(address(accounts.secondUser));

    expect(userBalanceBefore).to.be.gt(userBalanceAfter);
    expect(secondUserBalanceBefore).to.be.lt(secondUserBalanceAfter);
})

// Попытка осуществить перевод на сумму, превышающую лимит

ride
Копировать
1
2
3
4
5
6
7
8
9
10
11
it('Should not transfer more than 1000', async function () {
    const transferTx = transfer({ amount: 2000, recipient: address(accounts.secondUser), fee: 1000000 }, accounts.user);

    expect(broadcast(transferTx)).to.be.rejectedWith("");
})

it('Should not set script again', async function () {
    const ssTx = setScript({ script: accontScript, fee: 1500000 }, accounts.user);

    expect(broadcast(ssTx)).to.be.rejectedWith("");
})

// Вносите записи в список как транзакцию данных, чтобы проверить стандартное поведение аккаунта для других типов транзакций

ride
Копировать
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
it('Should store data', async function () {
    const records = [
        { key: 'integerVal', value: 1 },
        { key: 'booleanVal', value: true },
        { key: 'stringVal', value: 'Lorem ipsum dolor sit amet' }
    ]

    const dataTx = data({ data: records, fee: 1000000 }, accounts.user);
    await broadcast(dataTx);
    await waitForTx(dataTx.id);

    const store = await accountData(address(accounts.user));

    expect(store["integerVal"].value).to.be.equal(1);
    expect(store["booleanVal"].value).to.be.equal(true);
    expect(store["stringVal"].value).to.be.equal('Lorem ipsum dolor sit amet');
  })
})

Также вы можете запустить тест, используя транзакцию InvokeScript

//Пример вызова функции из dApp

java
Копировать
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import com.wavesplatform.crypto.Crypto;
import com.wavesplatform.transactions.BurnTransaction;
import com.wavesplatform.transactions.IssueTransaction;
import com.wavesplatform.transactions.SetAssetScriptTransaction;
import com.wavesplatform.transactions.TransferTransaction;
import com.wavesplatform.transactions.account.PrivateKey;
import com.wavesplatform.transactions.common.Amount;
import com.wavesplatform.transactions.common.AssetId;
import com.wavesplatform.transactions.common.Base64String;
import com.wavesplatform.wavesj.Node;
import com.wavesplatform.wavesj.Profile;
import com.wavesplatform.wavesj.ScriptInfo;
import com.wavesplatform.wavesj.exceptions.NodeException;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.web3j.utils.Files;

import java.io.File;
import java.io.IOException;

public class AssetScriptTest {

    static Node node;

    static PrivateKey curt;

    // additional info can be found - https://hub.docker.com/r/wavesplatform/waves-private-node
    static PrivateKey faucet = PrivateKey.fromSeed("waves private node seed with waves tokens");

    static int errorCode = 306;

    // In the before section, we perform all the actions that we need to test scripts
    @BeforeClass
    public static void before() throws NodeException, IOException {
        node = new Node(Profile.LOCAL);

        // A certain number of accounts with the specified balance is generated
        curt = PrivateKey.fromSeed(Crypto.getRandomSeedBytes());
        TransferTransaction transfer1 = TransferTransaction.builder(
            curt.address(), Amount.of(10_00_000_000)
        ).getSignedWith(faucet);
        node.broadcast(transfer1);
        node.waitForTransaction(transfer1.id());
    }

    @Test
    public void test() throws NodeException, IOException {
        //Should issue smart-asset with quantity 100_000_000'

        // Specify the parameters of the smart asset (at this stage, a stub is installed as a script,
        // which is equal "true")
        IssueTransaction issueTx = IssueTransaction.builder(
            "mySmartToken",
            100_000_000,
            8
        )
        .isReissuable(true)
        .description("some desc")
        .script(new Base64String("AQa3b8tH"))
        .getSignedWith(curt);

        AssetId curtAssetId = node.broadcast(issueTx).assetId();
        node.waitForTransaction(issueTx.id());

        // Check the balance of the token on the account - all the tokens of the issuing account
        long total = node.getAssetBalance(curt.address(), curtAssetId);
        Assert.assertEquals(issueTx.quantity(), total);

        // Should set real script and try to change script

        // Compiling the Smart Asset Script
        String source = Files.readString(new File("src/test/resources/smart-asset-script.ride"));
        ScriptInfo assetScript = node.compileScript(source);

        // Install the script on the smart asset (already allowed to do this)
        SetAssetScriptTransaction sasTx = SetAssetScriptTransaction.builder(
            curtAssetId, assetScript.script()
        ).getSignedWith(curt);
        node.broadcast(sasTx);
        node.waitForTransaction(sasTx.id());

        // Try to change the smart asset script again, get an errornode.waitForTransaction(sasTx.id());
        SetAssetScriptTransaction sasTx2 = SetAssetScriptTransaction.builder(
            curtAssetId, assetScript.script()
        ).getSignedWith(curt);
        try {
            node.broadcast(sasTx2);
        } catch (NodeException nodeException) {
            Assert.assertEquals(errorCode, nodeException.getErrorCode());
        }

        //Should try burn some curtAsset

        // Trying to burn a certain number of tokens - get an error, because the script forbids from such actions with the asset
        BurnTransaction bTx = BurnTransaction.builder(Amount.of(100, curtAssetId))
            .extraFee(400000)
            .getSignedWith(curt);
        try {
            node.broadcast(bTx);
        } catch (NodeException nodeException) {
            Assert.assertEquals(errorCode, nodeException.getErrorCode());
        }
    }
}

Поздравляем!

Вы успешно создали свой первый dApp. Он был опубликован в сети Waves.

Остались вопросы?

Давайте

Оставаться на связиОставаться на связиОставаться на связи

Узнайте о новых инфраструктурных продуктах, библиотеках и новых решениях для упрощения работы с блокчейном