Developer Center

Developer Center

  • Getting Started
  • Built-in Features
  • REST API Endpoints
  • Guides
  • Cheat Sheet

›Account Restriction

Getting Started

  • What is Sirius Chain
  • Setting up your workstation
  • Writing your first application

Built-in Features

  • Account
  • Mosaic (SDA)
  • Namespace
  • Transfer Transaction
  • Aggregate Transaction
  • Multisig Account
  • Metadata
  • Account Restriction
  • Cross-Chain Swaps
  • Exchange Market
  • Decentralized Exchange Market
  • Liquidity Provider
  • Storage

Protocol

  • Node
  • Block
  • Cryptography
  • Transaction
  • Validating
  • Consensus Algorithms
  • Receipt
  • Inflation

REST API

  • Overview
  • Tools
  • Serialization
  • Websockets
  • Status Errors

SDKs

  • Overview
  • Architecture
  • Languages
  • Extending Sirius Chain Capabilities
  • SDK Development
  • SDK Documentation

Wallets & Explorers

  • Wallets & Explorers

Cheat Sheet

  • Sirius Chain Cheat Sheet

Guides

  • Overview
  • External Guides
  • Account

    • Creating and opening an account
    • Getting account information
    • Getting the amount of XPX sent to an account
    • Reading transactions from an account

    Account Restriction

    • Preventing spam attacks with account restrictions

    Aggregate Transaction

    • Sending payouts with aggregate-complete transaction
    • Creating an escrow with aggregate bonded transaction
    • Asking for mosaics with aggregate-bonded transaction
    • Signing announced aggregate-bonded transactions

    Block

    • Listening to New Blocks
    • Getting block by height

    Cross Chain Swaps

    • Atomic cross-chain swap between Sirius public and private chains

    Metadata

    • Account Metadata
    • Mosaic Metadata
    • Namespace Metadata
    • Account Metadata (Deprecated since 0.7.0 Sirius Chain release)
    • Mosaic Metadata (Deprecated since 0.7.0 Sirius Chain release)
    • Namespace Metadata (Deprecated since 0.7.0 Sirius Chain release)

    Monitoring

    • Monitor transaction

    Mosaic

    • Creating a mosaic (SDA)
    • Getting the mosaic information
    • Getting the asset identifier behind a namespace with receipts

    Mosaic Levy

    • Modifying Mosaic Supply

    Multisig Account

    • Converting an account to multisig
    • Modifying a multisig account
    • Creating a multi-level multisig-account
    • Sending a multisig transaction

    Namespace

    • Registering a namespace
    • Registering a subnamespace
    • Getting the Namespace information
    • Linking a namespace to a mosaic
    • Linking namespace to account

    Transfer Transaction

    • Transfer transaction
    • Sending an encrypted message

    Storage

    • Data Modification Cancel
    • Data Modification
    • Download Channel
    • Download Payment
    • Drive Closure
    • Finish Download Channel
    • Prepare Bc Drive
    • Replicator Offboarding
    • Replicator Onboarding
    • Storage Payment
    • Verification Payment

Storage

  • Overview
  • Participate
  • External Economy
  • Roles
  • Verification
  • Challenge
  • Rewards
  • Transaction Schemas
  • Built-In Features

    • Drive
    • Replicator
    • Verifier
    • Supercontracts

    Protocols

    • Cross-Block Protocol
    • Fair Streaming

    Storage User Application

    • Overview
    • Getting Started
    • Managing Drives
    • Managing Drive Files
    • Downloading Data

Preventing spam attacks with account restrictions

Learn how to add and remove account restrictions.

Background

Imagine you are a company using the public chain to certify the quality of your products.

When the quality verification process concludes, an operator sends a quality seal to the product account, which the customers can review by scanning a QR code. For the convenience of the customers, you only want to show relevant transactions and prevent spam from cluttering the product account.

The final customers can review the product mosaics scanning a QR code. For that reason, the company only wants to show related transactions, avoiding that others spam their products with non-related information.

Blocking spam attacks

Blocking spam attacks

Thus, you opt to configure the product account restrictions to only receive transactions that follow a set of conditions.

Prerequisites

  • XPX-Chain-SDK.
  • A text editor or IDE.
  • Finish sending a transfer transaction guide.
  • Finish creating a mosaic guide.
  • An account with XPX.

Getting into some code

Before starting solving the use case, you will need to set up two accounts with xpx2-cli.

  1. Create an account to represent the product.
CLI
xpx2-cli account generate

Introduce network type (MIJIN_TEST, MIJIN, MAIN_NET, TEST_NET): TEST_NET
Do you want to save it? [y/n]: y
Introduce Sirius Chain Node URL. (Example: http://bctestnet1.brimstone.xpxsirius.io:3000): http://bctestnet1.brimstone.xpxsirius.io:3000
Insert profile name (blank means default and it could overwrite the previous profile): product

New Account: VDFRDC-F6RXWX-EOOTVI-RLCNUK-KYRSU6-MXW2FC-OR4V
Public Key: 8DC55282AC40307C230F432EE29E52BD93860C167011B11FA1BAEE124B76AB19
Private Key: 123..456
  1. Create another account for the company.
CLI
xpx2-cli account generate

Introduce network type (MIJIN_TEST, MIJIN, MAIN_NET, TEST_NET): TEST_NET
Do you want to save it? [y/n]: y
Introduce Sirius Chain Node URL. (Example: http://bctestnet1.brimstone.xpxsirius.io:3000): http://bctestnet1.brimstone.xpxsirius.io:3000
Insert profile name (blank means default and it could overwrite the previous profile): company

New Account: VBI774-YMFDZI-FPEPC5-4EKRC2-5DKDZJ-H2QVRW-4HBP
Public Key: DBA5A88911D01CE951A5DEAFD86108A029EA359BB211B399FC53B8908D6AE272
Private Key: 654..321

Next, you will configure the product’s account to only accept receiving transfer transactions that contain a specific mosaic.

Blocking transaction by address

An account can decide to receive transactions only from an allowed list of addresses. Similarly, an account can specify a blocked list of addresses to block transactions from.

Note

Allowing and blocking restrictions are mutually exclusive per restriction type. In other words, an account can only be configured to have either an allowed or blocked list per type of restriction.

By default, when there is no restriction set, all the accounts in the network can announce transactions to the stated account.

Returning to our previous example, let us imagine that you want to configure the product account to only accept receiving transactions that come from the company’s account. You might take the following steps to do so:

  1. Define the account restriction modification. Add to the company’s address SBI774-YMFDZI-FPEPC5-4EKRC2-5DKDZJ-H2QVRW-4HBP to the allowed list.
Golang
TypeScript
JavaScript
address, err := sdk.NewAddressFromRaw("VBI774-YMFDZI-FPEPC5-4EKRC2-5DKDZJ-H2QVRW-4HBP")
if err != nil {
panic(err)
}

modification := sdk.AccountPropertiesAddressModification{ sdk.AddProperty, address, }
const companyAddress = Address.createFromRawAddress('VBI774-YMFDZI-FPEPC5-4EKRC2-5DKDZJ-H2QVRW-4HBP');
const addressRestriction = AccountRestrictionModification.createForAddress(RestrictionModificationType.Add, companyAddress);
const companyAddress = Address.createFromRawAddress('VBI774-YMFDZI-FPEPC5-4EKRC2-5DKDZJ-H2QVRW-4HBP');
const addressRestriction = AccountRestrictionModification.createForAddress(RestrictionModificationType.Add, companyAddress);
  1. Create AccountRestrictionTransaction, with restriction type "AllowAddress". Add to the array the modification created in the previous step.
Golang
TypeScript
JavaScript
transaction, err := client.NewAccountPropertiesAddressTransaction(
sdk.NewDeadline(time.Hour),
sdk.BlockAddress,
[]*sdk.AccountPropertiesAddressModification{ &modification },
)
if err != nil {
panic(err)
}
const transaction = AccountRestrictionTransaction
.createAddressRestrictionModificationTransaction(
Deadline.create(),
RestrictionType.AllowAddress,
[addressRestriction],
NetworkType.TEST_NET);
const transaction = AccountRestrictionTransaction
.createAddressRestrictionModificationTransaction(
Deadline.create(),
RestrictionType.AllowAddress,
[addressRestriction],
NetworkType.TEST_NET);
  1. Sign and announce the transaction.
Golang
TypeScript
JavaScript
productAccount, err := client.NewAccountFromPrivateKey(os.Getenv("PRODUCT_PRIVATE_KEY"))
if err != nil {
panic(err)
}

signedTransaction, err := productAccount.Sign(transaction)
if err != nil {
panic(err)
}

_, err = client.Transaction.Announce(context.Background(), signedTransaction)
if err != nil {
panic(err)
}
const productPrivateKey = process.env.PRIVATE_KEY as string;
const networkGenerationHash = process.env.NETWORK_GENERATION_HASH as string;
const productAccount = Account.createFromPrivateKey(productPrivateKey, NetworkType.TEST_NET);
const signedTransaction = productAccount.sign(transaction, networkGenerationHash);

const transactionHttp = new TransactionHttp('http://bctestnet1.brimstone.xpxsirius.io:3000');
transactionHttp
.announce(signedTransaction)
.subscribe(x => console.log(x), err => console.error(err));
const productPrivateKey = process.env.PRIVATE_KEY;
const networkGenerationHash = process.env.NETWORK_GENERATION_HASH;
const productAccount = Account.createFromPrivateKey(productPrivateKey, NetworkType.TEST_NET);
const signedTransaction = productAccount.sign(transaction, networkGenerationHash);

const transactionHttp = new TransactionHttp('http://bctestnet1.brimstone.xpxsirius.io:3000');
transactionHttp
.announce(signedTransaction)
.subscribe(x => console.log(x), err => console.error(err));

Now, if you send a transfer transaction from another account, you will get an error as only VBI774-YMFDZI-FPEPC5-4EKRC2-5DKDZJ-H2QVRW-4HBP is allowed to send the transactions to the product.

On the other hand, if you send a transaction from your company account, you will receive a confirmation message as you would normally.

Blocking transactions by mosaic id

Imagine that the account that represents the company owns the following mosaics:

  • company.share: represents shares of the company.
  • company.quality.seal: represents that the product has passed a quality test.
  • company.safety.seal: represents that the product has passed a safety test.

In this case, it might be useful if the product could only receive seals and not company shares.

Thus, you could narrow the type of transactions that the product can receive from the company’s account through the use of negation. Instead of specifically allowing the seals, the product can be set up to block receiving transactions that contain company.share. This is how it can be done:

  1. Define the account restriction modification. Add the mosaic id you want to block to the blocked list.
Golang
TypeScript
JavaScript
id, err := strconv.ParseInt("2b890153b7a18ff2", 16, 64)
if err != nil {
panic(err)
}

companyShareMosaicId, err := sdk.NewMosaicId(uint64(id))
if err != nil {
panic(err)
}

modification := &sdk.AccountPropertiesMosaicModification{ sdk.AddProperty, companyShareMosaicId, }
const companyShareMosaicId = new MosaicId('2b890153b7a18ff2'); // Replace with the mosaic id representing the company share.
const mosaicRestriction = AccountRestrictionModification.createForMosaic(RestrictionModificationType.Add, companyShareMosaicId);
const companyShareMosaicId = new MosaicId('2b890153b7a18ff2'); // Replace with the mosaic id representing the company share.
const mosaicRestriction = AccountRestrictionModification.createForMosaic(RestrictionModificationType.Add, companyShareMosaicId);
  1. Create an AccountRestrictionTransaction, with restriction type BlockMosaic. Add to the array the modification created in the previous step.
Golang
TypeScript
JavaScript
transaction, err := client.NewAccountPropertiesMosaicTransaction(
sdk.NewDeadline(time.Hour),
sdk.BlockMosaic,
[]*sdk.AccountPropertiesMosaicModification{modification},
)
if err != nil {
panic(err)
}
const transaction = AccountRestrictionTransaction
.createMosaicRestrictionModificationTransaction(
Deadline.create(),
RestrictionType.BlockMosaic,
[mosaicRestriction],
NetworkType.TEST_NET);
const transaction = AccountRestrictionTransaction
.createMosaicRestrictionModificationTransaction(
Deadline.create(),
RestrictionType.BlockMosaic,
[mosaicRestriction],
NetworkType.TEST_NET);
  1. Sign and announce the transaction.
Golang
TypeScript
JavaScript
productAccount, err := client.NewAccountFromPrivateKey(os.Getenv("PRODUCT_PRIVATE_KEY"))
if err != nil {
panic(err)
}

signedTransaction, err := productAccount.Sign(transaction)
if err != nil {
panic(err)
}

_, err = client.Transaction.Announce(context.Background(), signedTransaction)
if err != nil {
panic(err)
}
const productPrivateKey = process.env.PRIVATE_KEY;
const networkGenerationHash = process.env.NETWORK_GENERATION_HASH;
const productAccount = Account.createFromPrivateKey(productPrivateKey, NetworkType.TEST_NET);
const signedTransaction = productAccount.sign(transaction, networkGenerationHash);

const transactionHttp = new TransactionHttp('http://bctestnet1.brimstone.xpxsirius.io:3000');
transactionHttp
.announce(signedTransaction)
.subscribe(x => console.log(x), err => console.error(err));
const productPrivateKey = process.env.PRIVATE_KEY;
const networkGenerationHash = process.env.NETWORK_GENERATION_HASH;
const productAccount = Account.createFromPrivateKey(productPrivateKey, NetworkType.TEST_NET);
const signedTransaction = productAccount.sign(transaction, networkGenerationHash);

const transactionHttp = new TransactionHttp('http://bctestnet1.brimstone.xpxsirius.io:3000');
transactionHttp
.announce(signedTransaction)
.subscribe(x => console.log(x), err => console.error(err));

Removing a restriction

After the company sells the product to the final client, they want to remove the condition that only allowed the company’s account to send transactions to the product. The account restrictions can be removed as easily as they were set up:

  1. Define the account restriction modification. Remove from the allowed list the company’s address.
Golang
TypeScript
JavaScript
address, err := sdk.NewAddressFromRaw("VBI774-YMFDZI-FPEPC5-4EKRC2-5DKDZJ-H2QVRW-4HBP")
if err != nil {
panic(err)
}

modification := &sdk.AccountPropertiesAddressModification{ sdk.RemoveProperty, address, }

const companyAddress = Address.createFromRawAddress('VBI774-YMFDZI-FPEPC5-4EKRC2-5DKDZJ-H2QVRW-4HBP');
const addressRestriction = AccountRestrictionModification.createForAddress(RestrictionModificationType.Remove, companyAddress);
const companyAddress = Address.createFromRawAddress('VBI774-YMFDZI-FPEPC5-4EKRC2-5DKDZJ-H2QVRW-4HBP');
const addressRestriction = AccountRestrictionModification.createForAddress(RestrictionModificationType.Remove, companyAddress);
  1. Create an AccountRestrictionTransaction, setting the type AllowAddress. Add the modification created as well.
Golang
TypeScript
JavaScript
transaction, err := client.NewAccountPropertiesAddressTransaction(
sdk.NewDeadline(time.Hour),
sdk.AllowAddress,
[]*sdk.AccountPropertiesAddressModification{ modification },
)
if err != nil {
panic(err)
}
const transaction = AccountRestrictionTransaction
.createAddressRestrictionModificationTransaction(
Deadline.create(),
RestrictionType.AllowAddress,
[addressRestriction],
NetworkType.TEST_NET);
const transaction = AccountRestrictionTransaction
.createAddressRestrictionModificationTransaction(
Deadline.create(),
RestrictionType.AllowAddress,
[addressRestriction],
NetworkType.TEST_NET);
  1. Sign and announce the transaction.
Golang
TypeScript
JavaScript
productAccount, err := client.NewAccountFromPrivateKey(os.Getenv("PRODUCT_PRIVATE_KEY"))
if err != nil {
panic(err)
}

signedTransaction, err := productAccount.Sign(transaction)
if err != nil {
panic(err)
}

_, err = client.Transaction.Announce(context.Background(), signedTransaction)
if err != nil {
panic(err)
}
const productPrivateKey = process.env.PRIVATE_KEY as string;
const networkGenerationHash = process.env.NETWORK_GENERATION_HASH as string;
const productAccount = Account.createFromPrivateKey(productPrivateKey, NetworkType.TEST_NET);
const signedTransaction = productAccount.sign(transaction,networkGenerationHash);

const transactionHttp = new TransactionHttp('http://bctestnet1.brimstone.xpxsirius.io:3000');
transactionHttp
.announce(signedTransaction)
.subscribe(x => console.log(x), err => console.error(err));
const productPrivateKey = process.env.PRIVATE_KEY;
const networkGenerationHash = process.env.NETWORK_GENERATION_HASH;
const productAccount = Account.createFromPrivateKey(productPrivateKey, NetworkType.TEST_NET);
const signedTransaction = productAccount.sign(transaction,networkGenerationHash);

const transactionHttp = new TransactionHttp('http://bctestnet1.brimstone.xpxsirius.io:3000');
transactionHttp
.announce(signedTransaction)
.subscribe(x => console.log(x), err => console.error(err));
← Reading transactions from an accountSending payouts with aggregate-complete transaction →
  • Background
  • Prerequisites
  • Getting into some code
    • Blocking transaction by address
    • Blocking transactions by mosaic id
    • Removing a restriction
  • Follow our profile
  • Ask development questions
  • Join our Discord channel
  • Explore our Youtube channel
  • Explore Github
Protocol
BlockConsensus AlgorithmsCryptographyInflationNodeReceiptTransactionValidating
Built-in Features
AccountAggregate TransactionCross-Chain SwapsExchange MarketDecentralized Exchange MarketMetadataMosaicMultisig AccountNamespaceTransfer TransactionStorageLiquidity Provider
References
REST APISDKsCheat Sheet
Includes Documentation Forked from NEM
Copyright © 2025 Sirius Chain