The shortest honest path to a transaction on the live testnet.
0. Get test DMS
There is no public faucet yet. Ask the team; note your vx… address. Eoonia's in-app faucet claim works for wallet users.
1. Connect
import { ApiPromise, WsProvider } from "@polkadot/api";
const api = await ApiPromise.create({
provider: new WsProvider("wss://rpc.testnet.empooriochain.org"),
});
console.log((await api.rpc.system.chain()).toString()); // EmpoorioChain testnet
console.log(api.runtimeVersion.specVersion.toNumber()); // 220 (at time of writing)
Polkadot.js reads the runtime metadata at connect, including the two EmpoorioChain-specific signed extensions (CheckPqcPolicy, CheckDormantAccount). If you use a different library, you must register them or every transaction will fail with a codec error — this single omission kept the testnet transaction-free for its first 102,912 blocks.
2. A key
import { Keyring } from "@polkadot/keyring";
const keyring = new Keyring({ type: "sr25519", ss58Format: 2026 });
const me = keyring.addFromUri(process.env.SEED!);
console.log(me.address); // vx…
3. Read something
const { data } = await api.query.system.account(me.address);
console.log(data.free.toHuman()); // your DMS, 18 decimals
console.log((await api.query.balances.totalIssuance()).toHuman());
4. Estimate the fee
const tx = api.tx.balances.transferKeepAlive(RECIPIENT, 1n * 10n ** 18n); // 1 DMS
const info = await tx.paymentInfo(me);
console.log(info.partialFee.toHuman()); // ≈ 0.000025 DMS
5. Send, and watch the three states
await new Promise<void>((resolve, reject) => {
tx.signAndSend(me, ({ status, dispatchError, txHash }) => {
if (dispatchError) return reject(new Error(dispatchError.toString()));
if (status.isReady) console.log("submitted", txHash.toHex());
if (status.isInBlock) console.log("included in", status.asInBlock.toHex());
if (status.isFinalized) { console.log("finalized"); resolve(); }
});
});
Expect included in about 3.5 s and finalized in about 17 s. Only the last means done.
6. Look at it
Open https://empooscan.com and search the block hash — bearing in mind the explorer's indexer was being repaired at the time of writing. api.rpc.chain.getBlock(hash) always works.
7. Things that go wrong
| Symptom | Cause |
|---|---|
connection refused | You hit the rate limit (~10 req/s per IP, one-hour ban). Back off or run a node. |
Bad input data provided to validate_transaction | Your library omitted the custom signed extensions. |
1010: Invalid Transaction: Inability to pay some fees | No test DMS. |
| Transaction stuck as future | Nonce gap — you sent in parallel from one account. |
| Everything fails after an upgrade | Stale metadata. Reconnect. |
8. Next
A DEX swap (api.tx.dex.swap), a DID (api.tx.identitySsi.registerDid), an asset (api.tx.assets.create). Each is a pallet, each is in metadata, and each was exercised for the first time on this chain in September 2026 — so if you find a gap, you are early, and the team wants to know.
Based on GETTING_STARTED.md, FORMATO_DE_EXTRINSECOS.md, RED.json and the fee snapshot.


