Функционал учетной записи WAVES позволяет только убедиться, что выпущенная из нее транзакция действительно была отправлена с этой учетной записи
Смарт-ассет без сжигания
Каждый скрипт Ride должен начинаться с директив Эти директивы сообщают компилятору, что:
{-# 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
}
Это намного проще, чем вы себе представляете. Скажите «Hello World» в сети WAVES Вставьте этот скрипт в свой проект
{-# 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
}
Развертывание скрипта в сети Waves
Во время развертывания вам нужно будет создать свою учетную запись, если у вас ее еще нет
// Запустить тест с помощью Surfboard
// В предыдущем разделе мы выполняем все действия, которые нам нужны для тестирования смарт-аккаунта, и генерируется определенное количество аккаунтов с указанным балансом
describe('Smart-asset test suite', async function () {
const wvs = 10 ** 8;
let curtAssetId;
this.timeout(100000);
before(async function () {
await setupAccounts({
curt: 10 * wvs
});
});
//Развертывание осуществляется транзакцией установки скрипта на аккаунт
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
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);
})
// Попытка осуществить перевод на сумму, превышающую лимит
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("");
})
// Вносите записи в список как транзакцию данных, чтобы проверить стандартное поведение аккаунта для других типов транзакций
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');
})
})
//Пример вызова функции из dApp
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.