blockchainstellar

Blockchain: Stellar, Cara Kirim dan Terima Uang

Setelah kita punya account, maka kita bisa kirim dan terima uang melalui Stellar network. Jika belum punya, buat dulu sekarang, lihat di step sebelumnya.

Nantinya, kita akan mengirim uang ke orang lain yang sudah punya account. Namun untuk tutorial ini, kita hanya akan membuat account kedua untuk mencoba langkah-langkah mengirim dan menerima uang di Stellar. Cara membuat account kedua sama seperti langkah membuat account yang pertama.

Mengirim Uang

Kegiatan yang mengubah sesuati di Stellar, seperti mengirim uang, mengupdate account, membuat offer untuk pertukaran currency, disebut dengan operations.

Untuk menjalankan sebuat operation, kita membuat transaction, yang merupakan sekelompok operations disertai dengan  informasi tambahan, seperti account mana yang membuat transaksi ini dan sebuah cryptographic signature untuk mem-verify bahwa transaksi ini adalah authentic.

Jika ada satu operation yang gagal dalam transaction ini maka transaction itu dianggap gagal juga. Misalnya kita punya 100 lumens dan kita membuat payment operations masing-masing 60 lumens. Jika kita membuat 2 transactions (masing-masing dengan 1 operation), yang pertama akan berhasil dan yang kedua akan gagal karena kurang saldo. Akan tersisa 40 lumens setelah transaksi pertama. Namun jika kita buat group dengan 2 payments dalam 1 transaction, maka keduanya akan gagal dan sisa saldo account tetap 100 lumens .

Setiap transaction membutuhkan biaya. Seperti halnya saldo minimum accounts, biaya ini menghindarkan orang yang ingin melakukan overloading ke system dengan banyak sekali transactions. Disebut dengan base fee, nilainya sangat kecil —100 stroops per operation (sama dengan 0.00001 XLM; stroops lebih mudah diingat daripada pecahan yang sangat kecil dari satu lumen). Transaction yang berisi 2 operations membutuhkan biaya 200 stroops.

Building a Transaction

Stellar menyimpan dan mengkomunukasikan data transaction dalam format biner yang disebut XDR. Untungnya, Stellar SDK sudah menyediakan tools yang mengatur detail semua hal tersebut. Ini perintah untuk mengirim 10 lumens ke account lain:

var StellarSdk = require('stellar-sdk');
StellarSdk.Network.useTestNetwork();
var server = new StellarSdk.Server('https://horizon-testnet.stellar.org');
var sourceKeys = StellarSdk.Keypair
  .fromSecret('SCZANGBA5YHTNYVVV4C3U252E2B6P6F5T3U6MM63WBSBZATAQI3EBTQ4');
var destinationId = 'GA2C5RFPE6GCKMY3US5PAB6UZLKIGSPIUKSLRB6Q723BM2OARMDUYEJ5';
// Transaction will hold a built transaction we can resubmit if the result is unknown.
var transaction;

// First, check to make sure that the destination account exists.
// You could skip this, but if the account does not exist, you will be charged
// the transaction fee when the transaction fails.
server.loadAccount(destinationId)
  // If the account is not found, surface a nicer error message for logging.
  .catch(StellarSdk.NotFoundError, function (error) {
    throw new Error('The destination account does not exist!');
  })
  // If there was no error, load up-to-date information on your account.
  .then(function() {
    return server.loadAccount(sourceKeys.publicKey());
  })
  .then(function(sourceAccount) {
    // Start building the transaction.
    transaction = new StellarSdk.TransactionBuilder(sourceAccount)
      .addOperation(StellarSdk.Operation.payment({
        destination: destinationId,
        // Because Stellar allows transaction in many currencies, you must
        // specify the asset type. The special "native" asset represents Lumens.
        asset: StellarSdk.Asset.native(),
        amount: "10"
      }))
      // A memo allows you to add your own metadata to a transaction. It's
      // optional and does not affect how Stellar treats the transaction.
      .addMemo(StellarSdk.Memo.text('Test Transaction'))
      .build();
    // Sign the transaction to prove you are actually the person sending it.
    transaction.sign(sourceKeys);
    // And finally, send it off to Stellar!
    return server.submitTransaction(transaction);
  })
  .then(function(result) {
    console.log('Success! Results:', result);
  })
  .catch(function(error) {
    console.error('Something went wrong!', error);
    // If the result is unknown (no response body, timeout etc.) we simply resubmit
    // already built transaction:
    // server.submitTransaction(transaction);
  });

Apa-apaan tu? Mari kita bongkar satu per satu..

  1. Pastikan bahwa account ID yang kita kirimu uang benar-benar ada dengan cara loading data account tersebut dari Stellar network. Mestinya semua OK jika kita tidak melakukan langkah ini, tapi dengan ini kita bisa pastikan tidak akan ada transaksi gagal karena tidak adanya account tujuan. Kita bisa lakukan langkah yang sama untuk mem-verifikasi account tujuan untuk hal lainnya. Jika nantinya ini adalah untuk aplikasi perbankan, disini saatnya kita melakukan regulatory compliance checks dan verifikasi KYC.
    server.loadAccount(destinationId)
      .then(function(account) { /* validate the account */ })
  2. Load data account yang mengirim uang. Suatu account hanya dapat melakukan satu transaksi pada suatu waktu dan memiliki sesuatu yang disebut  sequence number, yang membantu Stellar untuk mem-verifikasi urutan dari transactions. Sequence number transaksi harus cocok dengan sequence number account, sehingga kita perlu mengambil angka sequence number account yang terakhir dari network..then(function() {
       return server.loadAccount(sourceKeys.publicKey());
    })
    SDK akan secara otomatis meng-increment sequence number account ketika kita membuat suatu transaction, sehingga kita tidak perlu mengambil informasi ini lagi jika kita ingin menjalankan transaksi kedua.
  3. Mulai membuat transaction. Ini memerlukan objetc account, bukan cuma account ID, karena kita perlu meng-increment sequence number account.
    var transaction = new StellarSdk.TransactionBuilder(sourceAccount)
    
  4. Tambah operasi payment pada account. Perhatikan, kita perlu menentukan type asset yang kita kirimkan saat ini, dimana “native” currency Stellar adalah lumen, tapi intinya kita bisa kirim type asset apapun atau currency apapun yang kita mau, misal dari dollars ke bitcoin ke semua jenis asset yang kita bisa kasi trust ke yang mengeluarkannya atau redeem. Untuk sekarang kita fokus ke  lumens dulu, yang disebut juga sebagai “native” assets dalam SDK:
    .addOperation(StellarSdk.Operation.payment({
      destination: destinationId,
      asset: StellarSdk.Asset.native(),
      amount: "10"
    }))
    

    Perhatikan juga angka amount adalah string dan bukan number. Ketika bertransaksi dengan jumlah pecahan yang sangat kecil atau angka yang sangat besar, perhitungan pada angka floating point bisa mncul ketidak akuratan. Karena tidak semua systems punya cara sendiri untuk menyimpan angka pecahan yang sangat kecil atau sangat besar dengan akurat, Stellar menggunakan strings sebagai cara yang handal untuk menyimpan amount antar system dengan tepat dan akurat.

  5. Sebagai tambahan, kita bisa juga masukkan metadata kita sendiri, disebut dengan memo, pada suatu transaction. Stellar tidak melakukan apapu terhadap data ini, dan kita bisa gunakan untuk kebutuhan apapun yang kita perlu. Jika untuk bank penerima atau pengirim atas nama orang lain, misalnya, kita mungkin perlu isikan nama orang yang mengirim dan menerimanya.

    .addMemo(StellarSdk.Memo.text('Test Transaction'))
  6. Setelah transaction punya data yang diperlukan, kita perlu melakukan sign secara cryptographically menggunakan secret seed. Ini untuk membuktikan bahwa data tersebut benar-benar berasal dari kita dan bukan orang lain yang pura-pura menjadi kita.transaction.sign(sourceKeys);
  7. Akhirnya, kirimkan transaksi ke Stellar network!

PENTING Ada kemungkinan kita tidak menerima response dari Horizon server karena bug, network conditions, dan lainnya. Pada situasi ini, tidak mungkin untuk menentukan status transaction kita. Itu sebabnya kita perlu menyimpan transaction yang sudah terbentuk (atau transaction encoded dalam XDR format) pada sebuah variable atau tabel database dan melakukan resubmit jika kita tidak tau statusnya. Jika transaction itu sudah dengan sukses tersimpan pada ledger, maka Horizon akan mengeluarkan result yang sudah tersimpan dan bukan mencoba untuk men-submit transaction itu lagi. Hanya pada kasus status suatu transaction adalah unknown, kita perlu melakukan resubmission ke network.

Receive Payments

Kita tidak perlu melakukan apapun pada Stellar account ketika menerima uang. Jika pengirim berhasil membuat transaksi pengiriman asset kepada kita, maka asset itu otomatis masuk ke account kita.

Namun begitu, kita perlu mengetahui bahwa seseorang sudah benar-benar mengirimkan sesuatu kepada kita. Jika kita adalah bank yang menerima pembayaran atas nama orang lain, maka kita perlu mencari apa yang dikirimkan ke kita, supaya kita bisa keluarkan dananya ke tujuan akhir. Jika kita menjalankan bisnis ritel, kita perlu yakin bahwa customer benar-benar sudah membayar sebelum kita berikan barang yang dibelinya. Dan jika kita adalah rental mobil otomatis menggunakan Stellar, kita perlu mem-verifikasi bahwa customer sudah benar-benar membayar sebelum dia bisa menyalakan mesin mobil sewaannya.

Contoh program sederhana yang memonitor network atas pembayaran dan mencetaknya ketika ada penerimaan transfer:

var StellarSdk = require('stellar-sdk');
var server = new StellarSdk.Server('https://horizon-testnet.stellar.org');
var accountId = 'GC2BKLYOOYPDEFJKLKY6FNNRQMGFLVHJKQRGNSSRRGSMPGF32LHCQVGF';

// Create an API call to query payments involving the account.
var payments = server.payments().forAccount(accountId);

// If some payments have already been handled, start the results from the
// last seen payment. (See below in `handlePayment` where it gets saved.)
var lastToken = loadLastPagingToken();
if (lastToken) {
  payments.cursor(lastToken);
}

// `stream` will send each recorded payment, one by one, then keep the
// connection open and continue to send you new payments as they occur.
payments.stream({
  onmessage: function(payment) {
    // Record the paging token so we can start from here next time.
    savePagingToken(payment.paging_token);

    // The payments stream includes both sent and received payments. We only
    // want to process received payments here.
    if (payment.to !== accountId) {
      return;
    }

    // In Stellar’s API, Lumens are referred to as the “native” type. Other
    // asset types have more detailed information.
    var asset;
    if (payment.asset_type === 'native') {
      asset = 'lumens';
    }
    else {
      asset = payment.asset_code + ':' + payment.asset_issuer;
    }

    console.log(payment.amount + ' ' + asset + ' from ' + payment.from);
  },

  onerror: function(error) {
    console.error('Error in payment stream');
  }
});

function savePagingToken(token) {
  // In most cases, you should save this to a local database or file so that
  // you can load it next time you stream new payments.
}

function loadLastPagingToken() {
  // Get the last paging token from a local database or file
}

Ada dua bagian penting pada program ini.

Pertama, kita buat query atas payments terkait suatu account. Seperti query lainnya pada Stellar, hal ini bisa menghasilkan jumlah items yang banyak, jadi API mengeluarkan paging tokens, yang bisa kita gunakan kemudian untuk memulai query lagi dari titik sebelumnya. Pada contoh ini, functions untuk menyimpan dan me-load paging tokens dibiarkan kosong dulu, tapi pada aplikasi nyata nantinya, kita harus menyimpan paging tokens ke file atau database supaya kita bisa ambil lagi data dari titik terakhir, terutama jika program ada crash atau user sengaja menutupnya.

var payments = server.payments().forAccount(accountId);
var lastToken = loadLastPagingToken();
if (lastToken) {
  payments.cursor(lastToken);
}

Kedua, hasil dari query adalah berupa streaming. Ini cara paling mudah untuk memonitor payments atau transactions lainnya. Setiap payment akan dikirim pada stream, satu per satu. Setelah semua payments terkirim, stream tetap dalam kondisi open dan jika ada payments lagi maka akan dikirim lagi ke stream.

Cara mencobanya: Jalankan program ini, lalu pada window lainnya buatlah payment. Maka akan terlihat payment tersebut muncul pada program monitor ini.

payments.stream({
  onmessage: function(payment) {
    // handle a payment
  }
});

 

Kita bisa juga me-request payments dalam group atau pages transaksi. Setelah kita memproses setiap page of payments, kita perlu melakukan request ke page berikutnya sampai tidak ada yang tersisa.

payments.call().then(function handlePage(paymentsPage) {
  paymentsPage.records.forEach(function(payment) {
    // handle a payment
  });
  return paymentsPage.next().then(handlePage);
});

Transaksi Beda Currency

Salah satu hal amazing pada Stellar network adalah bahwa kita bisa kirim dan terima macam-macam asset, seperti US dollar, Nigerian naira, digital currencies seperti bitcoin, atau bahkan asset bikinan kita sendiri.

Asset Stellar yang native, lumen, sangatlah sederhana, tapi asset lainnya dapat dianggap sebagai credit yang dikeluarkan oleh suatu account. Faktanya, ketika kita menjualbelikan US dollars pada Stellar network, kita tidak benar-benar menjual US dollars—kita menjual US dollars milik suatu account. Itu sebabnya mengapa assets pada contoh ini punya code dan sebuah issuer.

issuer adalah ID dari account yang membuat asset tersebut. Memahami account mana yang mengeluarkan asset tersebut adalah hal yang penting—kita perlu berikan trust padanya, jika kita ingin menarik dollar kita pada Stellar network menjadi uang dollar fisik, issuer akan bisa memberikannya kepada kita. Karena ini, kita biasanya hanya memberi trust kepada institusi financial besar untuk asset yang mewakili currency suatu negara.

Stellar juga mendukung payments yang dikirim dengan suatu type asset, dan menerimanya dalam type asset lain. Kita bisa kirim Nigerian naira ke teman di Germany dan mereka terima dalam euro. Transaksi multi-currency ini dimungkinkan dengan adanya mekanisme market yang built-in dimana orang bisa membuat offers untuk membeli dan menjual macam-macam type asset. Stellar akan otomatis mencarikan offer orang yang terbaik untuk menukarkan currencies agar bisa menkonversi dari naira ke euros. System ini disebut distributed exchange.

Kita bisa pelajari lebih dalam tentang assets di sini.

What Next?

Setelah menguasai cara kirim dan terima payments menggunakan Stellar’s API, kita sudah siap untuk membuat macam-macam financial software yang amazing. Lihat lagi bagian lain dari API, lalu lanjut ke bagian ini lebih detail:

 

Source Code

Source code script di atas bisa ambil dari sini ya..

https://github.com/akhdaniel/stellar

 

Akhmad D. Sembiring
Blockchain Expert Indonesia