Skip to content

Instantly share code, notes, and snippets.

@anonymoussprocket
Last active November 28, 2020 18:09
Show Gist options
  • Save anonymoussprocket/2df333da147b57510b1f78a9c930caab to your computer and use it in GitHub Desktop.
Save anonymoussprocket/2df333da147b57510b1f78a9c930caab to your computer and use it in GitHub Desktop.
Tezos Token Tantrum

Tezos Token Tantrum

2020, Feb 14

This is a companion code sample to go with the Tezos is now an asset tokenization platform article on Medium from The Cryptonomic Aperiodical. As always, to test this code get infrastructure access from Nautilus Cloud.

Purpose

The code included here demonstrates token deployment and management workflows. It does not have an example for burn(), but that is also available in the API.

Instructions

In addition to providing Tezos node and Conseil configuration on lines 8 and 9, you'll need to get two testnet faucet accounts on lines 45 and 46. Two accounts are used to demontrate the fact that a developer can deploy the token contract and then transfer ownership to the issuer responsible for the financial management of the asset.

import * as fs from 'fs';
import { TezosConseilClient, TezosWalletUtil, setLogLevel, KeyStore, Tzip7ReferenceTokenHelper } from 'conseiljs';
import { ConseilQueryBuilder, ConseilOperator, ConseilDataClient } from 'conseiljs';
setLogLevel('debug');
const tezosNode = '...';
const conseilServer = { url: '...', apiKey: '...', network: 'babylonnet' };
const networkBlockTime = 30 + 1;
async function initAccount(account: string): Promise<KeyStore> {
console.log('~~ initAccount');
console.log(`loading ${account} faucet file`);
const faucetAccount = JSON.parse(fs.readFileSync(`${account}.json`, 'utf8'));
const keystore = await TezosWalletUtil.unlockFundraiserIdentity(faucetAccount['mnemonic'].join(' '), faucetAccount['email'], faucetAccount['password'], faucetAccount['pkh']);
console.log(`public key: ${keystore.publicKey}`);
console.log(`secret key: ${keystore.privateKey}`);
console.log(`account hash: ${keystore.publicKeyHash}`);
return keystore;
}
async function statOperation(groupid: string){
const result = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 7, networkBlockTime);
if (result['status'] === 'failed') {
console.log(`${result['kind']} ${groupid} ${result['status']} at block ${result['block_level']}`);
} else if (result['status'] === 'applied') {
let message = `${result['kind']} ${groupid} included in block ${result['block_level']} for ${result['consumed_gas']}g and ${result['paid_storage_size_diff']}f`
if ('originated_contracts' in result && result['originated_contracts'] != null && result['originated_contracts'].length > 0) {
message += ` new contract at ${result['originated_contracts']}`;
}
console.log(message);
} else {
console.log(JSON.stringify(result));
}
}
async function run() {
const originator = '...';
const issuer = '...';
let groupid ='';
let contractAddress = ''
let mapid = 0;
let keystore = await initAccount(originator);
groupid = await Tzip7ReferenceTokenHelper.deployContract(tezosNode, keystore, 100_000, keystore.publicKeyHash, true, 0);
let conseilResult = await TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 5, networkBlockTime);
contractAddress = conseilResult['originated_contracts'];
console.log(`deployed token at ${contractAddress} (${groupid})`);
console.log(`verify: ${await Tzip7ReferenceTokenHelper.verifyDestination(tezosNode, contractAddress)}`);
const simplestorage = await Tzip7ReferenceTokenHelper.getSimpleStorage(tezosNode, contractAddress);
console.log(`simplestorage: ${JSON.stringify(simplestorage, undefined, 2)}`);
mapid = simplestorage.mapid;
console.log(`token administrator: ${await Tzip7ReferenceTokenHelper.getAdministrator(tezosNode, contractAddress)}`);
groupid = await Tzip7ReferenceTokenHelper.setAdministrator(tezosNode, keystore, contractAddress, issuer, 100_000, 125_000, 1_000);
await statOperation(groupid);
console.log(`token administrator: ${await Tzip7ReferenceTokenHelper.getAdministrator(tezosNode, contractAddress)}`);
let largeAccountQuery = ConseilQueryBuilder.blankQuery();
largeAccountQuery = ConseilQueryBuilder.addFields(largeAccountQuery, 'account_id');
largeAccountQuery = ConseilQueryBuilder.addPredicate(largeAccountQuery, 'balance', ConseilOperator.GT, [9000000000]);
largeAccountQuery = ConseilQueryBuilder.addPredicate(largeAccountQuery, 'account_id', ConseilOperator.STARTSWITH, ['tz']);
largeAccountQuery = ConseilQueryBuilder.addPredicate(largeAccountQuery, 'account_id', ConseilOperator.IN, [originator, issuer], true);
largeAccountQuery = ConseilQueryBuilder.setLimit(largeAccountQuery, 30);
const largeAccountResult = await ConseilDataClient.executeEntityQuery(conseilServer, 'tezos', conseilServer.network, 'accounts', largeAccountQuery);
const largeAccounts = largeAccountResult.map(a => a.account_id);
keystore = await initAccount(issuer);
console.log(`token ${(await Tzip7ReferenceTokenHelper.getPaused(tezosNode, contractAddress) === true) ? 'paused' : 'active' }`);
groupid = await Tzip7ReferenceTokenHelper.activateLedger(tezosNode, keystore, contractAddress, 50_000, 125_000, 100);
await statOperation(groupid);
console.log(`token ${(await Tzip7ReferenceTokenHelper.getPaused(tezosNode, contractAddress)) ? 'paused' : 'active' }`);
console.log(`current supply: ${await Tzip7ReferenceTokenHelper.getTokenSupply(tezosNode, contractAddress)}`);
groupid = await Tzip7ReferenceTokenHelper.mint(tezosNode, keystore, contractAddress, 50_000, issuer, 1_000_000_000, 125_000, 100);
await statOperation(groupid);
console.log(`new supply: ${await Tzip7ReferenceTokenHelper.getTokenSupply(tezosNode, contractAddress)}`);
console.log(`${issuer} balance: ${await Tzip7ReferenceTokenHelper.getAccountBalance(tezosNode, mapid, issuer)}`);
for (let i = 0; i < largeAccounts.length; i++) {
groupid = await Tzip7ReferenceTokenHelper.transferBalance(tezosNode, keystore, contractAddress, 50_000, keystore.publicKeyHash, largeAccounts[i], 1_000, 125_000, 100);
console.log(`balance transfer to "${largeAccounts[i]}"`);
await statOperation(groupid);
}
let smallAccountQuery = ConseilQueryBuilder.blankQuery();
smallAccountQuery = ConseilQueryBuilder.addFields(smallAccountQuery, 'account_id');
smallAccountQuery = ConseilQueryBuilder.addPredicate(smallAccountQuery, 'balance', ConseilOperator.LT, [9000000000]);
smallAccountQuery = ConseilQueryBuilder.addPredicate(smallAccountQuery, 'balance', ConseilOperator.LT, [999000000]);
smallAccountQuery = ConseilQueryBuilder.addPredicate(smallAccountQuery, 'account_id', ConseilOperator.STARTSWITH, ['tz']);
smallAccountQuery = ConseilQueryBuilder.addPredicate(smallAccountQuery, 'account_id', ConseilOperator.IN, [originator, issuer], true);
smallAccountQuery = ConseilQueryBuilder.setLimit(smallAccountQuery, 90);
let smallAccountResult = await ConseilDataClient.executeEntityQuery(conseilServer, 'tezos', conseilServer.network, 'accounts', smallAccountQuery);
const smallAccounts = smallAccountResult.map(a => a.account_id);
console.log(smallAccounts.length);
for (let i = 0; i < largeAccounts.length; i++) {
for (let j = 3 * i, k = 3 * (i + 1); j < k; j++) {
groupid = await Tzip7ReferenceTokenHelper.approveBalance(tezosNode, keystore, contractAddress, 50_000, smallAccounts[j], 100, 125_000, 100);
console.log(`approve allowance for "${smallAccounts[j]}"`);
await statOperation(groupid);
}
}
console.log(`current supply: ${await Tzip7ReferenceTokenHelper.getTokenSupply(tezosNode, contractAddress)}`);
console.log(`${issuer} balance: ${await Tzip7ReferenceTokenHelper.getAccountBalance(tezosNode, mapid, issuer)}`);
}
run();
{
"name": "tezos-token-tantrum",
"version": "0.0.1",
"description": "Tezos Token Tantrum",
"scripts": {
"postinstall": "npm run build",
"build": "tsc *.ts",
"start": "node index.js"
},
"author": "anonymoussprocket",
"license": "UNLICENSED",
"engines": {
"node": ">=12.14.x",
"npm": ">=6.13.x"
},
"homepage": "https://gist.github.com/anonymoussprocket",
"dependencies": {
"conseiljs": "0.4.0-beta"
},
"devDependencies": {
"typescript": "3.7.5"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment