Các SDK chính trong Harmony

Giới thiệu

Trong bài viết lần này mình sẽ giới thiệu một nền tảng blockchain tương đối giống với Ethereum là Harmony. Đây là nền tảng blockchain có hỗ trợ viết các Smart Contract bằng solidity và cũng sử dụng Truffle để deploy contract. Tuy nhiên trong bài viết lần này mình sẽ giới thiệu các SDK của Harmony để tương tác với mạng Blockchain cũng như tương tác với các Smart Contract có trên mạng.

Bài viết sẽ yêu cầu bạn cần một chút kiến thức về Solidity để có thể viết các smart contract, bài này chủ yếu sẽ hướng đến các SDK được Harmony cung cấp để tương tác với mạng Blockchain của họ.

Các SDK chính

Các SDK chính để tương tác với Harmony bao gồm:

  • harmony-js/core : Package chứa các function tương tác với các thành phần trong mạng như Trx, account, những function này đa phần là những function đọc dữ liệu
  • harmony-js/account: Package chứa các function để tương tác với Account như tạo account, tạo ví, export, import privateKey
  • harmony-js/utils : Package chứa các function để chuyển đổi các loại đơn vị trong mạng như convert hex, string hay convert one sang wei
  • harmony-js/transaction : Package chứa các function để tracking dữ liệu của một transaction từ lúc khởi tạo cho đến lúc được lưu vào chain
  • harmony-js/contract: Package chứa các function giúp developer có thể tương tác với những smart contract đã được deploy lên mạng Harmony

Đầu tiên chúng ta cần phải có môi tường để test, cần các package chính là harmony và tslib:

yarn init
yarn add @harmony-js/[email protected]
yarn add tslib

Đã có đủ các package cần thiết, bây giờ khởi tạo 1 file để cùng test nào :

touch testSDK.js

Khởi tạo một instance trong file testSDK.js, instance này sẽ giúp ta tương tác với Harmony: Node này là node của mạng testnet : https://api.s0.b.hmny.io/

const { Harmony } = require('@harmony-js/core');
const {
  ChainID,
  ChainType,
  hexToNumber,
  numberToHex,
  fromWei,
  Units,
  Unit,
} = require('@harmony-js/utils');

const hmy = new Harmony(
    'https://api.s0.b.hmny.io/',
    {
        chainType: ChainType.Harmony,
        chainId: ChainID.HmyTestnet,
    },
);

harmony-js/core

Trên mạng Harmony địa chỉ của các ví có thể được biểu thị dưới 2 dạng là checksumAddressbech32Address . Trong đó checksumAddress là địa chỉ có dạng hex như Ethereum còn bech32 là địa chỉ của Harmony có prefix one

Lấy balance của 1 địa chỉ

hmy.blockchain
  .getBalance({ address: 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7' })
  .then((response) => {
    console.log('balance in ONEs: ' + fromWei(hexToNumber(response.result), Units.one));
  });

Lấy transaction thông qua hash

hmy.blockchain
  .getTransactionByHash({
    txnHash: '0x56c73eb993b18dc04baacec5c2e9d1292a090f6a978a4a1c461db5255fcbc831',
  })
  .then((response) => {
    console.log(response.result);
  });

Lấy latest block number

hmy.blockchain.getBlockNumber().then((response) => {
  console.log('current block number: ' + hexToNumber(response.result));
});

Truy vấn người nhận transaction thông qua hash

hmy.blockchain
  .getTransactionReceipt({
    txnHash: '0x56c73eb993b18dc04baacec5c2e9d1292a090f6a978a4a1c461db5255fcbc831',
  })
  .then((response) => {
    console.log(response.result);
  });

Tạo transaction chuyển One

Cách này sẽ sử dụng privateKey để tự kí transaction, địa chỉ nhận (to) có thể là dạng bech32 hoặc checksum đều thảo mãn

// key corresponds to one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7, only has testnet balance
hmy.wallet.addByPrivateKey('45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e');

async function transfer() {
  const txn = hmy.transactions.newTx({
    to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
    value: new Unit(1).asOne().toWei(),
    // gas limit, you can use string
    gasLimit: '21000',
    // send token from shardID
    shardID: 0,
    // send token to toShardID
    toShardID: 0,
    // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
    gasPrice: new hmy.utils.Unit('1').asGwei().toWei(),
  });

  // sign the transaction use wallet;
  const signedTxn = await hmy.wallet.signTransaction(txn);
  const txnHash = await hmy.blockchain.sendTransaction(signedTxn);
  console.log(txnHash.result);
}

transfer();

harmony-js/account

Đâu là package giúp chúng ta có thể tự tạo các địa chỉ, tạo ví lưu trữ các địa chỉ đó và cũng có thể kí các transaction.

Tạo tài khoản và hiển thị address tương ứng

const account = new Account(); // or const account = Account.new()
console.log(account.checksumAddress);
console.log(account.bech32Address);

Import privateKey để tạo Account

const account = Account.add('45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e');
console.log(account.checksumAddress);

Import keystore để tạo Account

const passphrase = '';
const keystore = '{"version":3,"id":"33363566-3564-4264-a638-363531666335","address":"7c41e0668b551f4f902cfaec05b5bdca68b124ce","crypto":{"ciphertext":"9b09380afb742838b32d9afc0ec1a3df35dbd7a41e3a160d08c07a4d0e79b855","cipherparams":{"iv":"1cd0e0522260eef055b9170f4825f4a0"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"salt":"bf35e36c45cccefcef73a4c900f41c682c94c28630d94d2d1f764760d245f30b","n":8192,"r":8,"p":1,"dklen":32},"mac":"25b4442972356bea02af57eba3b87803086d90b5e7657a57b528b89b1aa25f2f"}}';
const account = new Account();
account.fromFile(keystore, passphrase).then(account => {
    console.log(account.bech32Address);
});

Export account dưới dạng keystore

const passphrase = '';
const keystore = '{"version":3,"id":"33363566-3564-4264-a638-363531666335","address":"7c41e0668b551f4f902cfaec05b5bdca68b124ce","crypto":{"ciphertext":"9b09380afb742838b32d9afc0ec1a3df35dbd7a41e3a160d08c07a4d0e79b855","cipherparams":{"iv":"1cd0e0522260eef055b9170f4825f4a0"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"salt":"bf35e36c45cccefcef73a4c900f41c682c94c28630d94d2d1f764760d245f30b","n":8192,"r":8,"p":1,"dklen":32},"mac":"25b4442972356bea02af57eba3b87803086d90b5e7657a57b528b89b1aa25f2f"}}';
const account = new Account();
account.fromFile(keystore, passphrase).then(account => {
    console.log(account.bech32Address);
});

Lấy balance của account

const account = new Account(
  '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e'
);
account.getBalance().then(response => {
    console.log(response);
});
//{ balance: '9126943763247054940484', nonce: 45, shardID: 0 }

Kí transaction

Tạo tài khoản từ privateKey tương tự như việc add signer trong harmony-js/core

const { TransactionFactory } = require('@harmony-js/transaction');
const { Unit } = require('@harmony-js/utils');
const factory = new TransactionFactory();

//Import privateKey
const account = new Account('45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e');

const txn = factory.newTx({
  to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
  value: new Unit(1).asOne().toWei(),
  // gas limit, you can use string
  gasLimit: '21000',
  // send token from shardID
  shardID: 0,
  // send token to toShardID
  toShardID: 0,
  // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
  gasPrice: new Unit('1').asGwei().toWei(),
});

account.signTransaction(txn).then((signedTxn) => {
  console.log(signedTxn);
});

Tạo wallet

Một wallet có thể chứa một hoặc nhiều các account

const { Wallet } = require('@harmony-js/account')
const wallet = new Wallet();

Add account vào wallet

//Thông qua mnemonic của account 
const mnemonics = 'horse distance dry brother pretty manual chicken mushroom town swim prize clutch';
const account = wallet.addByMnemonic(mnemonics);
//Thông qua privateKey của account
const account = wallet.addByPrivateKey('0x676cd9773dd23a4c1d7f22767c61c7b6723cc6be37b078545f6e0e91433a23dd')
//Thông qua keystore file
const keystore = '{"version":3,"id":"33363566-3564-4264-a638-363531666335","address":"7c41e0668b551f4f902cfaec05b5bdca68b124ce","crypto":{"ciphertext":"9b09380afb742838b32d9afc0ec1a3df35dbd7a41e3a160d08c07a4d0e79b855","cipherparams":{"iv":"1cd0e0522260eef055b9170f4825f4a0"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"salt":"bf35e36c45cccefcef73a4c900f41c682c94c28630d94d2d1f764760d245f30b","n":8192,"r":8,"p":1,"dklen":32},"mac":"25b4442972356bea02af57eba3b87803086d90b5e7657a57b528b89b1aa25f2f"}}';
const passphrase = '';
wallet.addByKeyStore(keystore, passphrase).then(account => {
    console.log(account.bech32Address);
});

Tạo account thông qua passphrase

const passphrase = 'harmony-one';
wallet.createAccount(passphrase).then(account => {
    console.log(account.bech32Address);
});

Lấy toàn bộ các account trong wallet

wallet.accounts.forEach(addr => {
    const account = wallet.getAccount(addr);
    console.log(account.bech32Address);
});

Kí transaction bằng wallet

wallet.setSigner(signerAddr);
const txn = factory.newTx({
  to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
  value: new Unit(1).asOne().toWei(),
  // gas limit, you can use string
  gasLimit: '21000',
  // send token from shardID
  shardID: 0,
  // send token to toShardID
  toShardID: 0,
  // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
  gasPrice: new Unit('1').asGwei().toWei(),
});

wallet.signTransaction(txn).then((signedTxn) => {
  console.log(signedTxn);
});

harmony-js/transaction

Package này cung cấp các api để tương tác với các transaction từ việc tạo, gửi transaction hay subcription receipt

Việc đầu tiên vẫn là tạo instance Harmony testnet và import các hàm cần sử dụng:

const { Harmony } = require('@harmony-js/core');
const {
  ChainID,
  ChainType,
  hexToNumber,
  numberToHex,
  fromWei,
  Units,
  Unit,
} = require('@harmony-js/utils');

const hmy = new Harmony(
    'https://api.s0.b.hmny.io/',
    {
        chainType: ChainType.Harmony,
        chainId: ChainID.HmyTestnet,
    },
);

Lấy thông tin transaction thông qua transaction hash

const raw = '0xf86d21843b9aca00825208808094d6ba69da5b45ec98b53e3258d7de756a567b6763880de0b6b3a76400008028a0da8887719f377401963407fc1d82d2ab52404600cf7bea37c27bd2dfd7c86aaaa03c405b0843394442b303256a804bde835821a8a77bd88a2ced9ffdc8b0a409e9';
const tx = hmy.transactions.recover(raw);

//output
Transaction {
  blockNumbers: [],
  confirmations: 0,
  confirmationCheck: 0,
  cxStatus: 'NONE',
  cxBlockNumbers: [],
  cxConfirmations: 0,
  cxConfirmationCheck: 0,
  messenger: Messenger {
    chainType: 'hmy',
    chainId: 2,
    Network_ID: 'Local',
    send: [Function (anonymous)],
    subscribe: [Function (anonymous)],
    unsubscribe: [Function (anonymous)],
    provider: HttpProvider {
      middlewares: [Object],
      reqMiddleware: Map(0) {},
      resMiddleware: Map(0) {},
      url: 'https://api.s0.b.hmny.io/',
      fetcher: [Object],
      options: [Object]
    },
    config: { Default: [Object], DefaultWS: [Object] },
    JsonRpc: JsonRpc { toPayload: [Function (anonymous)], messageId: 0 },
    shardProviders: Map(0) {}
  },
  txStatus: 'SIGNED',
  emitter: Emitter {
    handlers: {},
    emitter: {
      on: [Function: on],
      off: [Function: off],
      emit: [Function: emit]
    },
    off: [Function: bound off],
    emit: [Function: bound emit],
    resolve: [Function (anonymous)],
    reject: [Function (anonymous)],
    promise: Promise { <pending> },
    then: [Function: bound then]
  },
  id: '0x19c362d9d4e97d6b2dabad67c8271f395ee362c7948bed78f5c3cfc99c9fba97',
  shardID: 0,
  from: '0x7c41E0668B551f4f902cFaec05B5Bdca68b124CE',
  nonce: 33,
  gasPrice: BN { negative: 0, words: [ 60475904, 14 ], length: 2, red: null },
  gasLimit: BN { negative: 0, words: [ 21000 ], length: 1, red: null },
  toShardID: 0,
  to: '0xd6ba69DA5b45eC98b53e3258d7DE756a567B6763',
  value: BN {
    negative: 0,
    words: [ 56885248, 2993385, 222 ],
    length: 3,
    red: null
  },
  data: '0x',
  chainId: 2,
  rawTransaction: '0xf86d21843b9aca00825208808094d6ba69da5b45ec98b53e3258d7de756a567b6763880de0b6b3a76400008028a0da8887719f377401963407fc1d82d2ab52404600cf7bea37c27bd2dfd7c86aaaa03c405b0843394442b303256a804bde835821a8a77bd88a2ced9ffdc8b0a409e9',
  unsignedRawTransaction: '0x',
  signature: {
    r: '0xda8887719f377401963407fc1d82d2ab52404600cf7bea37c27bd2dfd7c86aaa',
    s: '0x3c405b0843394442b303256a804bde835821a8a77bd88a2ced9ffdc8b0a409e9',
    recoveryParam: 0,
    v: 40
  },
  receipt: undefined
}

Kí transaction và đợi khi transaction thành công sẽ log ra receipt

const txn = hmy.transactions.newTx({
  to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
  value: new Unit(1).asOne().toWei(),
  // gas limit, you can use string
  gasLimit: '21000',
  // send token from shardID
  shardID: 0,
  // send token to toShardID
  toShardID: 0,
  // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
  gasPrice: new hmy.utils.Unit('1').asGwei().toWei()
});

hmy.wallet.addByPrivateKey('45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e');

hmy.wallet.signTransaction(txn).then(signedTxn => {
  signedTxn.sendTransaction().then(([tx, hash]) => {
    console.log('tx hash: ' + hash);
    signedTxn.confirm(hash).then(response => {
      console.log(response.receipt);
    });
  });
});

Output:

{
  blockHash: '0x84e485e697721745d28201d00679b7ab1cf250a0c313556cb125015b672d7800',
  blockNumber: '0x19f0d1',
  contractAddress: '0x0000000000000000000000000000000000000000',
  cumulativeGasUsed: '0x5208',
  from: 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7',
  gasUsed: '0x5208',
  logs: [],
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  shardID: 0,
  status: '0x1',
  to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
  transactionHash: '0x4194c6b83d4c7f9b5a4f680ad4d0e4ed9a718becaf30a9a40290daae091d2cbe',
  transactionIndex: '0x0',
  byzantium: true
}

Tổng hợp các trạng thái của một transaction từ khi khới tạo cho đến khi thành công (hoặc bị revert)

Một transaction từ khi được khởi tạo sẽ trải qua các trạng thái cho đến khi thành công hoặc bị revert

async function transfer() {
  hmy.wallet.addByPrivateKey('45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e');
  const txn = hmy.transactions.newTx({
    to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
    value: new Unit(1).asOne().toWei(),
    // gas limit, you can use string
    gasLimit: '21000',
    // send token from shardID
    shardID: 0,
    // send token to toShardID
    toShardID: 0,
    // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
    gasPrice: new hmy.utils.Unit('1').asGwei().toWei()
  });
  const signedTxn = await hmy.wallet.signTransaction(txn);
  signedTxn
    .observed()
    .on('transactionHash', txnHash => {
      console.log('');
      console.log('--- hash ---');
      console.log('');
      console.log(txnHash);
      console.log('');
    })
    .on('receipt', receipt => {
      console.log('');
      console.log('--- receipt ---');
      console.log('');
      console.log(receipt);
      console.log('');
    })
    .on('cxReceipt', receipt => {
      console.log('');
      console.log('--- cxReceipt ---');
      console.log('');
      console.log(receipt);
      console.log('');
    })
    .on('error', error => {
      console.log('');
      console.log('--- error ---');
      console.log('');
      console.log(error);
      console.log('');
    });

  const [sentTxn, txnHash] = await signedTxn.sendTransaction();

  const confiremdTxn = await sentTxn.confirm(txnHash);

  // if the transactino is cross-shard transaction
  if (!confiremdTxn.isCrossShard()) {
    if (confiremdTxn.isConfirmed()) {
      console.log('--- Result ---');
      console.log('');
      console.log('Normal transaction');
      console.log(`${txnHash} is confirmed`);
      console.log('');
      console.log('please see detail in explorer:');
      console.log('');
      console.log('https://explorer.testnet.harmony.one/#/tx/' + txnHash);
      console.log('');
      process.exit();
    }
  }
  if (confiremdTxn.isConfirmed() && confiremdTxn.isCxConfirmed()) {
    console.log('--- Result ---');
    console.log('');
    console.log('Cross-Shard transaction');
    console.log(`${txnHash} is confirmed`);
    console.log('');
    console.log('please see detail in explorer:');
    console.log('');
    console.log('https://explorer.testnet.harmony.one/#/tx/' + txnHash);
    console.log('');
    process.exit();
  }
}
transfer();

harmony-js/utils

Package này tuy ít function nhưng thực ra lại được dùng khá nhiều do nó giúp convert các đơn vị trong Harmony

Đơn vị trong harmony

const { Units } = require('@harmony-js/utils');

[Units.wei, '1'], // 1 wei
[Units.Kwei, '1000'], // 1e3 wei
[Units.Mwei, '1000000'], // 1e6 wei
[Units.Gwei, '1000000000'], // 1e9 wei
[Units.szabo, '1000000000000'], // 1e12 wei
[Units.finney, '1000000000000000'], // 1e15 wei
[Units.ether, '1000000000000000000'], // 1e18 wei
[Units.one, '1000000000000000000'], // 1e18 wei
[Units.Kether, '1000000000000000000000'], // 1e21 wei
[Units.Mether, '1000000000000000000000000'], // 1e24 wei
[Units.Gether, '1000000000000000000000000000'], // 1e27 wei
[Units.Tether, '1000000000000000000000000000000'], // 1e30 wei

Các function thường được sử dụng bao gồm :

const { Units, Unit, numberToString, add0xToString, fromWei, toWei, numToStr} = require('@harmony-js/utils');
const { BN } = require('@harmony-js/crypto');

const one = new Unit('1').asOne();
const oneToGwei = one.toGwei();
console.log(oneToGwei);

// numberToString
const num = 123;
const str = numberToString(num)
console.log(str);

// add0xToString
const str = '12345';
const expected = add0xToString(str)
console.log(expected);

// fromWei
const Wei = new BN('1000000000000000000');
const expected = fromWei(Wei, Units.one);
console.log(expected);

// toWei
const one = new BN('1');
const expected = toWei(one, hmy.utils.Units.one);
const num = numToStr(expected);
console.log(num);

harmony-js/contract

Package cuối cùng này cũng là một trong những package quan trọng nhất, nó cung cấp các API để có thể tương tác với các smart contract

Đầu tiên chúng ta phải deploy 1 contract lên mạng testnet của Harmony. Tuy nhiên mình đã chuẩn bị 1 contract đã deploy để các bạn có thể test trực tiếp.

Đầu tiên tạo một file Counter.json với nội dung trong đường dẫn này: https://raw.githubusercontent.com/harmony-one/sdk/master/packages/harmony-contract/Counter.json

Tạo instance contract Counter và log ra các methods của nó:

const { Harmony } = require("@harmony-js/core");
const { ChainID, ChainType } = require("@harmony-js/utils");
const hmy = new Harmony("https://api.s0.b.hmny.io", {
  chainType: ChainType.Harmony,
  chainId: ChainID.HmyTestnet,
});

const contractJson = require("./Counter.json");
const contractAddr = "0x19f64050e6b2d376e52AC426E366c49EEb0724B1";

const contract = hmy.contracts.createContract(contractJson.abi, contractAddr);
console.log(contract.methods);

Output:

{
  incrementCounter: [Function (anonymous)],
  '0x5b34b966': [Function (anonymous)],
  'incrementCounter()': [Function (anonymous)],
  decrementCounter: [Function (anonymous)],
  '0xf5c5ad83': [Function (anonymous)],
  'decrementCounter()': [Function (anonymous)],
  getCount: [Function (anonymous)],
  '0xa87d942c': [Function (anonymous)],
  'getCount()': [Function (anonymous)],
  contractConstructor: [Function (anonymous)]
}

Estimate lượng gas tiêu thụ cho các transaction

const { Harmony } = require('@harmony-js/core');
const { ChainID, ChainType, hexToNumber } = require('@harmony-js/utils');
const hmy = new Harmony('https://api.s0.b.hmny.io', {
  chainType: ChainType.Harmony,
  chainId: ChainID.HmyTestnet
});

const contractJson = require('./Counter.json');
const contractAddr = '0x19f64050e6b2d376e52AC426E366c49EEb0724B1';

const contract = hmy.contracts.createContract(contractJson.abi, contractAddr);

const options1 = { gasPrice: '0x3B9ACA00' }; // gas price in hex corresponds to 1 Gwei or 1000000000

contract.methods
  .getCount()
  .estimateGas(options1)
  .then(gas => {
    console.log('gas required for getCount is ' + hexToNumber(gas));
  });

Output:

gas required for getCount is 22077

Gọi đến các function read-only trên smart contract

Mặc dù đây là những function không tốn gas nhưng hiện tại những api này vẫn cần truyền gasPrice và gasLimit

Hàm dưới đây sẽ tính lượng gasLimit cần phải dùng và thêm vào methods:

let options2 = { gasPrice: 1000000000, gasLimit: 21000 }; // setting the default gas limit, but changing later based on estimate gas

contract.methods
  .getCount()
  .estimateGas(options1)
  .then(gas => {
    options2 = { ...options2, gasLimit: hexToNumber(gas) };
    contract.methods
      .getCount()
      .call(options2)
      .then(count => {
        console.log('counter value: ' + count);
      });
  });

Output:

ounter value: 15

Gọi đến function thay đổi dữ liệu trên contract

Đây là các function thay đổi dữ liệu trên smart contract do đó sẽ đòi hỏi lượng phí gas và phải kí transaction, do đó sẽ phải addPrivateKey.

const options1 = { gasPrice: '0x3B9ACA00' }; // gas price in hex corresponds to 1 Gwei or 1000000000
let options2 = { gasPrice: 1000000000, gasLimit: 21000 }; // setting the default gas limit, but changing later based on estimate gas

contract.wallet.addByPrivateKey('1f054c21a0f57ebc402c00e14bd1707ddf45542d4ed9989933dbefc4ea96ca68');

contract.methods.incrementCounter().estimateGas(options1).then(gas => {
  options2 = {...options2, gasLimit: hexToNumber(gas)};
  contract.methods.incrementCounter().send(options2).then(response => {
    console.log(response.transaction.receipt);
  });
});

Cuối cùng là có thể subcription các Event trong contract để lắng nghe các Event contract emit từ contract Counter:

const { ContractFactory } = require('@harmony-js/contract');
const { Wallet } = require('@harmony-js/account');
const { Messenger, WSProvider } = require('@harmony-js/network');
const { ChainID, ChainType, hexToNumber } = require('@harmony-js/utils');
const ws = new WSProvider('wss://ws.s0.b.hmny.io');

const wallet = new Wallet(
  new Messenger(
    ws,
    ChainType.Harmony,
    ChainID.HmyTestnet,
  ),
);
const factory = new ContractFactory(wallet);

const contractJson = require("./Counter.json");
const contractAddr = '0x8ada52172abda19b9838eb00498a40952be6a019';

const contract = factory.createContract(contractJson.abi, contractAddr);

contract.events
  .IncrementedBy()
  .on('data', (event) => {
    console.log(event);
  })
  .on('error', console.error);

Kết luận

Về cơ bản những SDK phía trên là những SDK chính cần thiết để xây dựng một DApp trên nền tảng Harmony. Hi vọng bài viết giúp ích được cho các bạn.

Nguồn tham khảo

https://github.com/harmony-one/sdk


All Rights Reserved