接触了皮毛的michelson之后,一直想写非常皮毛的dapp。但是前端实在没啥基础。这时候发现了这篇好文,很好的给初学者展示了一个dapp的脉络(安装conseiljs里面还有更多的范例)。
文中关于查询block的代码,部分有些老旧。以下是目前可以跑通的版本。
index.js:
const serverInfo = {
url: 'https://conseil-dev.cryptonomic-infra.tech:443',
apiKey: '申请一个自己的cloud账号吧'
};
function refreshTable(blocks = []) {
const tableRef = document.getElementById('query-table').getElementsByTagName('tbody')[0];
tableRef.innerHTML = '';
blocks.map((block, index) => {
const row = tableRef.insertRow(index);
const cell1 = row.insertCell(0);
const cell2 = row.insertCell(1);
const cell3 = row.insertCell(2);
cell1.innerHTML = block.level;
cell2.innerHTML = new Date(block.timestamp).toLocaleString();
cell3.innerHTML = block.hash;
});
}
async function getBlocks(network, query) {
const blocks = await conseiljs.TezosConseilClient.getBlocks(serverInfo, network, query);
refreshTable(blocks);
}
function onClickGo(event) {
event.preventDefault();
const order = document.getElementById('order-select').value;
const limit = parseInt(document.getElementById('limit-input').value);
let query = conseiljs.ConseilQueryBuilder.blankQuery();
query = conseiljs.ConseilQueryBuilder.addFields(query, 'level', 'timestamp', 'hash');
query = conseiljs.ConseilQueryBuilder.addOrdering(query, 'level', order);
query = conseiljs.ConseilQueryBuilder.setLimit(query, limit);
getBlocks('babylonnet', query); //被改成了babylonnet
}
async function fetchMetadata() {
const platformResult = await conseiljs.ConseilMetadataClient.getPlatforms(serverInfo);
const platform = platformResult[0]['name'];
const networksResult = await conseiljs.ConseilMetadataClient.getNetworks(serverInfo, platform);
const network = networksResult[0]['name'];
const entityResult = await conseiljs.ConseilMetadataClient.getEntities(serverInfo, platform, network);
const blocks = Array.from(entityResult).filter(v => v['name'] === 'blocks')[0]['name'];
const attributeResult = await conseiljs.ConseilMetadataClient.getAttributes(serverInfo, platform, network, blocks);
}
document.onreadystatechange = function () {
if(document.readyState === "complete"){
fetchMetadata();
}
}
再者针对智能合约的代码,也有一处修改:
smartPy.html:
<html>
<head>
<script src="https://cdn.jsdelivr.net/gh/cryptonomic/conseiljs/dist-web/conseiljs.min.js"></script>
<script>
const tezosNode = 'https://tezos-dev.cryptonomic-infra.tech:443';
const conseilServer = {
url: 'https://conseil-dev.cryptonomic-infra.tech:443',
apiKey: '申请一个自己的账号吧',
network: 'babylonnet'
}
const networkBlockTime = 30 + 1;
let keyStore = {};
const alphanetFaucetAccount = {
"mnemonic": [ "promote", "grape", "sea", "glide", "still", "suggest", "vehicle", "front", "bulb", "wolf", "cart", "cart", "surround", "creek", "cycle" ],
"secret": "b43d272885698df92e01a9adac18e697e9db42d0",
"amount": "24283188994",
"pkh": "tz1RArF4HTSMHpKywvvU1qtHRg89eWQN1CLL",
"password": "LieZc5k2PT",
"email": "jwydlazq.dhugusjq@tezos.example.org"
};
const secretKey = 'edskS1hYczoFBSmyXZrLJEViq5ksFs1N2L7QKdTF1q3ZJiXvBwmsVtfeBdCXytM1Tzo645JKYjt6iyhqDwUyFMzZTwsq8Y9NHq';
function clearRPCOperationGroupHash(hash) {
return hash.replace(/\"/g, '').replace(/\n/, '');
}
async function initAccount() {
//keyStore = await conseiljs.TezosWalletUtil.unlockFundraiserIdentity(alphanetFaucetAccount.mnemonic.join(' '), alphanetFaucetAccount.email, alphanetFaucetAccount.password, alphanetFaucetAccount.pkh);
keyStore = await conseiljs.TezosWalletUtil.restoreIdentityWithSecretKey(secretKey);
}
async function invokeContract() {
const augend = document.getElementById('augend').value;
const addend = document.getElementById('addend').value;
const contractAddress = 'KT1C8eB3d2VQnuj6ARRT8V4jRUhUuYeNcQK1';
const params = `{"prim": "Pair", "args": [{"int": "${augend}"}, {"int": "${addend}"}]}`;
const paramFormat = conseiljs.TezosParameterFormat.Micheline;
let nodeResult = await conseiljs.TezosNodeWriter.sendContractInvocationOperation(tezosNode, keyStore, contractAddress, 0, 50000, '', 1000, 20000, undefined, params, paramFormat);
const groupid = clearRPCOperationGroupHash(nodeResult.operationGroupID);
console.log(`Injected activation operation with ${groupid}`);
let conseilResult = await conseiljs.TezosConseilClient.awaitOperationConfirmation(conseilServer, conseilServer.network, groupid, 10, networkBlockTime);
if (conseilResult.length == 1 && conseilResult[0]['status'] === 'applied') {
console.log(conseilResult[0]);
conseilResult = await conseiljs.TezosConseilClient.getAccount(conseilServer, conseilServer.network, contractAddress);
console.log(conseilResult[0]);
//document.getElementById('result').innerText = `= ${conseilResult[0]['storage']}`; //现在的conseiljs,getAccount只返回一个元素,而非数组了。
document.getElementById('result').innerText = `= ${conseilResult['storage']}`;
} else if (conseilResult.length == 1 && conseilResult[0]['status'] !== 'applied') {
console.log(`operation ${groupid} failed`);
document.getElementById('result').innerText = '= error';
console.log(conseilResult[0]);
nodeResult = await conseiljs.TezosNodeReader.getBlock(tezosNode, conseilResult[0]['block_hash']);
console.log(nodeResult);
} else {
console.log(`operation ${groupid} appears to have been rejected`);
}
}
async function run() {
await initAccount();
await invokeContract();
}
</script>
</head>
<body>
<form>
<input type="number" id="augend" value="1" /> + <input type="number" id="addend" value="1" /> <span id="result"></span>
<button onclick="run(); return false;">Run</button>
</form>
</body>
</html>