#007: Smartcoin collateral holder airdrops!
We're getting into advanced territory here, airdropping onto smartcoin collateral holders on the Bitshares blockchain!
Check out the previous 6 custom airdrop spotlight blog posts for more Bitshares airdrop inspriation!
First off, what is a collateral holder?
Collateral holders are accounts which have borrowed into existence a specified smartcoin on the bitshares blockchain. Simply put, they borrowed some USD for example, using their BTS as collateral for their loan.
But why airdrop onto collateral holders?
- Encourage greater participation in the Bitshares DEX smartcoin borrow functionality
- Offer extra incentives to borrowers for your smartcoin of choice (especially private MPA).
- Since these accounts have active debts on the blockchain it's safe to say their account is active, therefore it may be a better airdrop target than a cold storage account.
- Since these users have entered into a blockchain contract with risk associated, it can be speculated that they have a higher risk tolerance than the average Bitshares user.
- Encourage increased collateralization of debt positions, reducing debt risk and improving resiliency of the smartcoin in question.
- To grow blockchain use of your smartcoin of choice
- Enable creation of algorithm based assets with fee redistribution mechanisms
OK Now let's get down to the code!
To run it, run the command node ./getCollateralHolders.js
, this will output the file ./airdrops/collateralHolders.json
for use in the Airdrop Tool's custom airdrop page.
Can you spot the difference? It's using the bitsharesjs-ws package to query directly from the blockchain, this is to fetch the call order data (backing collateral holder data) for each smartcoin.
/* eslint-disable max-len */
const fs = require('fs').promises;
const { Apis } = require('bitsharesjs-ws');
const { humanReadableFloat } = require('./lib/common');
// CONFIGURE THE FOLLOWING:
const inputs = [
"CNY",
"CNY1.0",
"USD",
"USD1.0",
"EUR",
"EUR1.0",
"BTC1.0",
"JPY",
"GBP",
"ARS",
"AUD",
"CAD",
"SILVER",
"GOLD",
"BTC",
"TWENTIX",
"HERTZ",
"HERO",
"HONEST.USD",
"HONEST.GBP",
"HONEST.EUR",
"HONEST.USDSHORT",
"HONEST.BTCSHORT",
"HONEST.EOS",
"HONEST.XRP",
"HONEST.ADA",
"HONEST.XAU",
"HONEST.EOSSHORT",
"HONEST.XMRSHORT",
"HONEST.XRPSHORT",
"HONEST.JPYSHORT",
"HONEST.CNYSHORT",
"HONEST.DOTSHORT",
"HONEST.ETHSHORT",
"URTHR",
"SKULD",
"VERTHANDI",
];
// END CONFIGURATION
const writeToFile = async (fileName, data) => {
console.log(`Writing to ${fileName}`);
await fs.writeFile(fileName, JSON.stringify(data, null, 4));
};
/**
* Get the call orders for each asset
* @param {Array} assetIDs
* @returns {[Promise<Object>]}
*/
const getCallOrders = async (assetIDs) => {
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 333);
});
try {
await Apis.instance("wss://node.xbts.io/ws", true).init_promise;
} catch (error) {
console.log(error);
return [];
}
let assetSymbols;
try {
assetSymbols = await Apis.instance().db_api().exec('lookup_asset_symbols', [assetIDs]);
} catch (error) {
console.log(error);
}
const backingSymbolIDs = assetSymbols.map((x) => x.options.core_exchange_rate.quote.asset_id);
const backingAssetIDs = [...new Set(backingSymbolIDs)];
let backingSymbols;
try {
backingSymbols = await Apis.instance().db_api().exec('lookup_asset_symbols', [backingAssetIDs]);
} catch (error) {
console.log(error);
}
let responses = [];
for (let i = 0; i < assetIDs.length; i++) {
const currentID = assetIDs[i];
let callOrderResponse;
try {
callOrderResponse = await Apis.instance().db_api().exec("get_call_orders", [currentID, 300]);
} catch (error) {
console.log(error);
}
console.log(`${currentID}: ${callOrderResponse.length}`);
if (callOrderResponse && callOrderResponse.length > 0) {
const baseAssetID = callOrderResponse[0].call_price.base.asset_id;
const currentSymbol = backingSymbols.find((symbol) => symbol.id === baseAssetID);
const readableCollateral = callOrderResponse.map((obj) => ({
id: obj.borrower,
qty: 1,
value: humanReadableFloat(obj.collateral, currentSymbol.precision)
}));
responses = [...responses, ...readableCollateral];
}
}
return responses;
};
const getCollateralHolders = async () => {
let callOrders;
try {
callOrders = await getCallOrders(inputs); // Change these values for your own airdrop!
} catch (error) {
console.log(error);
}
if (!callOrders || !callOrders.length) {
console.log("Fetching call orders failed");
process.exit(0);
}
const finalResultValues = [];
callOrders.forEach((callOrder) => {
const existingUserIndex = finalResultValues.findIndex((user) => user.id === callOrder.id);
if (existingUserIndex !== -1) {
const newValue = { ...finalResultValues[existingUserIndex] };
newValue.value += callOrder.value;
newValue.qty += 1;
finalResultValues[existingUserIndex] = newValue;
} else {
finalResultValues.push(callOrder);
}
});
await writeToFile(
'./airdrops/collateralHolders.json',
finalResultValues.sort((a, b) => b.value - a.value)
);
// exit script
process.exit(0);
};
getCollateralHolders();
This outputs JSON to the ./airdrops/collateralHolders.json
file which contains rows like the following:
[
{
"id": "1.2.168607",
"qty": 2,
"value": 22447839.73791
},
{
"id": "1.2.1812553",
"qty": 1,
"value": 1300000
},
{
"id": "1.2.906339",
"qty": 1,
"value": 1184392.19373
},
...
]
These JSON output files can be imported in the custom airdrop section of the Bitshares Airdrop Tool, and broadcast to the Bitshares blockchain via the Bitshares BEET multiwallet:
And finally, the airdrop card prompting you to broadcast the airdrop transaction onto the Bitshares blockchain via the BEET multiwallet:
Once you've broadcast the airdrop via the Beet multiwallet, you'll have an optional receipt like the following for your airdrop:
So, which smartcoins/mpa/pmpa/aba are you interested in performing a collateral holder based airdrop upon?
These developments were brought to you by the NFTEA Gallery.
Consider collecting an NFTEA NFT to support continued Bitshares developments.
Don't have a Bitshares account? Make one today!
Congratulations @nftea.gallery! You have completed the following achievement on the Hive blockchain And have been rewarded with New badge(s)
Your next payout target is 4000 HP.
The unit is Hive Power equivalent because post and comment rewards can be split into HP and HBD
You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word
STOP
Check out our last posts:
The rewards earned on this comment will go directly to the people sharing the post on Reddit as long as they are registered with @poshtoken. Sign up at https://hiveposh.com. Otherwise, rewards go to the author of the blog post.