Arxium

Issue a regulated asset

Set an asset’s rules, then watch the chain refuse every transfer that breaks them.

This walkthrough covers what Arxium is for. You register an asset that only KYC'd holders may hold. Transfers to a holder are refused until a registered attestor has attested it. The chain enforces the rules on every transfer, so no app can skip them.

Two roles are involved. The issuer registers the asset and sets its rules. An attestor, normally a KYC provider, vouches for accounts. You play the issuer, using the Console key from the quickstart. On devnet, the Arxium devnet attestor attests your accounts from the Console.

0. Get attested in the Console

The rules apply to both ends of every transfer, so the issuer needs an attestation too. In the Console, open Faucet, complete the security check under Verify yourself on the chain and click Get attested. The devnet attestor attests your Console key's address with the KYC and AML claims. The card says Attested, with the attestor's name, once the grant is in a block. No email is needed.

ISSUER=arx1...      # your Console key (ARX_KEY)

curl -s -H "Authorization: Bearer $ARX_TOKEN" $ARX_RPC/accounts/$ISSUER
# {…, "identity_hash":"…", "attested_by":"arx1…", "claims":["Kyc","Aml"], "jurisdiction":null, …}

1. Register the asset

# <asset-id> <symbol> <name> <decimals> [required claims] [allowed jurisdictions]
arx send register-asset fund-a FUNDA "Fund A" 0 kyc

ASSET=$(curl -s -H "Authorization: Bearer $ARX_TOKEN" \
  $ARX_RPC/assets/alias/$ISSUER/fund-a | jq -r .ref)
echo $ASSET         # arxasset1...

The asset's chain-wide reference, arxasset1…, is derived from your address and the id you chose. Two issuers can both use fund-a without colliding. Claim topics are kyc, aml, accredited and jurisdiction. Jurisdictions are ISO 3166-1 alpha-2 codes.

2. Issue supply

arx send issue-asset $ASSET 1000

The 1,000 units land on the issuer, which is already attested from step 0.

3. Try an unattested holder

Sign in to the Console with a second account, generate its signing key under Settings, and copy its address. Don't click Get attested on it yet. (The holder.json key from the quickstart works for this step too, but only a Console account can be attested from the Console.)

HOLDER=arx1...      # the second Console account's key

arx send transfer-asset $ASSET $HOLDER 100
action dropped: compliance check failed: arx1w86p… is not KYC'd/allowlisted

The holder has no attestation, so the chain drops the transfer. The reason above is the exact text the node returns. It's also in GET /actions/{signature} and in the block's effects.

4. Attest the holder, and the transfer goes through

In the second account, click Get attested and wait for Attested. Then send again:

arx send transfer-asset $ASSET $HOLDER 100      # "status": "confirmed"

curl -s -H "Authorization: Bearer $ARX_TOKEN" $ARX_RPC/accounts/$HOLDER/assets
# [{"symbol":"FUNDA", "balance":100, "transfer_eligible":true, "eligibility_reason":"eligible", …}]

Wallets can check eligibility_reason before sending. It reports the sender-side gate that would fail, such as missing_attestation, jurisdiction_not_allowed or holder_frozen.

5. Restrict by country

An attestation can also record the holder's country, and an asset can list the countries allowed to hold it. The devnet attestor doesn't record a country, because it checks no documents. So an asset restricted to, say, Switzerland and Liechtenstein refuses even attested devnet accounts:

arx send register-asset fund-ch FUNDCH "Fund CH" 0 kyc CH,LI
# …issue, then transfer from an attested issuer:
action dropped: arx1…'s jurisdiction (None) is not among those arxasset1… permits

A new grant replaces the old one completely, so an attestor can also take a claim or a country away by re-attesting. Attestors are added and removed by a validator vote, and the Explorer names the attestor next to every attestation.

Beyond these, issuers can cap holders, balance per holder and attestation age, freeze an asset or a single holder, lock amounts, and recover a lost holder's position. Each refusal comes with a specific message. The Console issuer pages cover the same flow with a UI, and the SDK has an encoder for each action (encodeRegisterAsset, encodeTransferAsset, encodeSetAssetLimits and the rest) to use with ArxiumRpc.sendAction.