Liberland blockchain is based on Substrate
Recommended way to interact with the chain programmatically is through PolkadotjsApi
- Testnet chain explorer
- Testnet endpoint
- Mainnet chain explorer
- Mainnet endpoints
- Government-operated
- Dwellir-operated
LLM is an on chain asset of the Assets pallet with id of 1
const { ApiPromise, WsProvider } = require('@polkadot/api');
const provider = new WsProvider('<WS_ENDPOINT>');
const api = await ApiPromise.create({ provider });
// <ASSET_ID> of LLM is 1
const LLMInfo = await api.query.assets.account('<ASSET_ID>', '<WALLET_ADDRESS>');
console.log(LLMInfo.toJSON().data?.balance ?? '0x0')
To create a new address, a minimum of 1 LLD needs to be deposited as an existential deposit
const { ApiPromise, WsProvider } = require('@polkadot/api');
const { Keyring } = require("@polkadot/api");
const provider = new WsProvider('<WS_ENDPOINT>');
const api = await ApiPromise.create({ provider });
const keyring = new Keyring({ type: 'sr25519' });
const sender = keyring.addFromUri('<SENDER-ACCOUNT-PRIVATE-KEY>');
// minimum <AMOUNT> is new BN('1000000000000');
const transferExtrinsic = api.tx.balances.transfer('<WALLET_ADDRESS_TO_CREATE>', '<AMOUNT>');
const txHash = await transferExtrinsic.signAndSend(sender) ;
const { ApiPromise, WsProvider } = require('@polkadot/api');
const provider = new WsProvider('<WS_ENDPOINT>');
const api = await ApiPromise.create({ provider });
const hash = await api.rpc.chain.getBlockHash('<BLOCKNUMBER>');
const block = await api.rpc.chain.getBlock(hash);
console.log(block.block.extrinsics.toHuman());
const { ApiPromise, WsProvider } = require('@polkadot/api');
const provider = new WsProvider('<WS_ENDPOINT>');
const api = await ApiPromise.create({ provider });
const bestNumber = await api.derive.chain.bestNumber();
console.log(bestNumber.toNumber());
Transactions (a.k.a. extrinsics) are uniquely identified by block hash + their index. See also https://wiki.polkadot.network/docs/build-protocol-info#unique-identifiers-for-extrinsics
const txId = {
blockHash: BLOCK_HASH,
index: EXTRINSIC_INDEX,
};
const { ApiPromise, WsProvider } = require('@polkadot/api');
const provider = new WsProvider('<WS_ENDPOINT>');
const api = await ApiPromise.create({ provider });
const apiAt = await api.at(txId.blockHash);
const allEvents = await apiAt.query.system.events();
const txEvents = allEvents.filter(({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.eq(txId.index));
const successEvent = txEvents.find(({ event }) => api.events.system.ExtrinsicSuccess.is(event));
const failureEvent = txEvents.find(({ event }) => api.events.system.ExtrinsicFailed.is(event));
if (successEvent) {
const transferEvents = txEvents.filter(({ event }) => api.events.assets.Transferred.is(event));
transferEvents.forEach(({ event }) => {
const [assetId, fromAccount, toAccount, amount] = event.data;
if (assetId == 1) {
console.log(`Transfer of ${amount} grains of LLM from ${fromAccount} to ${toAccount}`);
}
});
} else {
const [dispatchError, dispatchInfo] = failureEvent.event.data;
let errorInfo;
// decode the error
if (dispatchError.isModule) {
// for module errors, we have the section indexed, lookup
// (For specific known errors, we can also do a check against the
// api.errors.<module>.<ErrorName>.is(dispatchError.asModule) guard)
const decoded = api.registry.findMetaError(dispatchError.asModule);
errorInfo = `${decoded.section}.${decoded.name}`;
} else {
// Other, CannotLookup, BadOrigin, no extra info
errorInfo = dispatchError.toString();
}
console.log(`ExtrinsicFailed:: ${errorInfo}`);
}
const { ApiPromise, WsProvider } = require('@polkadot/api');
const { Keyring } = require("@polkadot/api");
const provider = new WsProvider('<WS_ENDPOINT>');
const api = await ApiPromise.create({ provider });
const keyring = new Keyring({ type: 'sr25519' });
const sender = keyring.addFromUri('<SENDER-ACCOUNT-PRIVATE-KEY>');
const transferExtrinsic = api.tx.llm.sendLlm('<ACCOUNT_TO>', '<AMOUNT>');
const txHash = await transferExtrinsic.signAndSend(sender);
Optionally, for token transfers, you can use the "assets.transfer" method and then provide the id of the asset you want to transfer. An example transfer for LLM (LLM=1).
const { ApiPromise, WsProvider } = require('@polkadot/api');
const { Keyring } = require("@polkadot/api");
const provider = new WsProvider('<WS_ENDPOINT>');
const api = await ApiPromise.create({ provider });
const keyring = new Keyring({ type: 'sr25519' });
const sender = keyring.addFromUri('<SENDER-ACCOUNT-PRIVATE-KEY>');
// The following value 1 is the ID token of LLM.
const transferExtrinsic = api.tx.assets.transfer(1, '<ACCOUNT_TO>', '<AMOUNT>');
const txHash = await transferExtrinsic.signAndSend(sender);
See also https://polkadot.js.org/docs/api/cookbook/tx/#how-do-i-get-the-decoded-enum-for-an-extrinsicfailed-event for example on how to see if tx succeeded.