Transaksi Offline

Sign Transaksi

Untuk membuat suatu transaksi offline, kamu harus sign transaksi tersebut, kemudian siapapun dapat mem-broadcast-nya di network.

Press </> button to view full source
// there are two ways you can recover the tx
// 3.a Recover Tranasction (use populate then addSignauture)
{
  let recoverTx = Transaction.populate(Message.from(realDataNeedToSign));
  recoverTx.addSignature(feePayer.publicKey, Buffer.from(feePayerSignature));
  recoverTx.addSignature(alice.publicKey, Buffer.from(aliceSignature));

  // 4. Send transaction
  console.log(
    `txhash: ${await connection.sendRawTransaction(recoverTx.serialize())}`
  );
}

// or

// 3.b. Recover Tranasction (use populate with signature)
{
  let recoverTx = Transaction.populate(Message.from(realDataNeedToSign), [
    bs58.encode(feePayerSignature),
    bs58.encode(aliceSignature),
  ]);

  // 4. Send transaction
  console.log(
    `txhash: ${await connection.sendRawTransaction(recoverTx.serialize())}`
  );
}

Sign Transaksi Sebagian

Ketika suatu transaksi membutuhkan banyak signature, kamu bisa sign sebagian. Kemudian signer yang lain dapat sign dan mem-broadcast-nya ke network.

Beberapa contoh situasi dimana hal ini berguna:

  • Mengirim sebuah SPL token untuk menerima pembayaran
  • Sign suatu transaksi sehingga kamu bisa memverifikasi keasliannya
  • Call custom program dalam suatu transaksi yang membutuhkan signature-mu

Dalam contoh ini Bob mengirimkan Alice sebuah SPL token untuk menerima pembayaran:

Press </> button to view full source
// 1. Add an instruction to send the token from Bob to Alice
transaction.add(
  createTransferCheckedInstruction(
    bobTokenAddress, // source
    tokenAddress, // mint
    aliceTokenAccount.address, // destination
    bobKeypair.publicKey, // owner of source account
    1 * 10 ** tokenMint.decimals, // amount to transfer
    tokenMint.decimals // decimals of token
  )
);

// 2. Bob partially signs the transaction
transaction.partialSign(bobKeypair);

// 3. Serialize the transaction without requiring all signatures
const serializedTransaction = transaction.serialize({
  requireAllSignatures: false,
});

// 4. Alice can deserialize the transaction
const recoveredTransaction = Transaction.from(
  Buffer.from(transactionBase64, "base64")
);

Durable Nonce

RecentBlockhash adalah sebuah nilai penting dalam suatu transaksi. Transaksi-mu akan gagal jika menggunakan recent blockhash yang sudah expired (melebihi 150 blocks). Kamu bisa menggunakan durable nonce untuk mendapatkan recent blockhash yang tidak akan expired. Untuk memicu mekanisme ini, transaksi-mu harus

  1. Menggunakan suatu nonce yang tersimpan dalam nonce account sebagai sebuah recent blockhash
  2. Memasukkan nonce advance operation di instruksi pertama

Membuat Akun Nonce

Press </> button to view full source
let tx = new Transaction().add(
  // create nonce account
  SystemProgram.createAccount({
    fromPubkey: feePayer.publicKey,
    newAccountPubkey: nonceAccount.publicKey,
    lamports: await connection.getMinimumBalanceForRentExemption(
      NONCE_ACCOUNT_LENGTH
    ),
    space: NONCE_ACCOUNT_LENGTH,
    programId: SystemProgram.programId,
  }),
  // init nonce account
  SystemProgram.nonceInitialize({
    noncePubkey: nonceAccount.publicKey, // nonce account pubkey
    authorizedPubkey: nonceAccountAuth.publicKey, // nonce account authority (for advance and close)
  })
);

console.log(
  `txhash: ${await connection.sendTransaction(tx, [feePayer, nonceAccount])}`
);

Mendapatkan Akun Nonce

Press </> button to view full source
let accountInfo = await connection.getAccountInfo(nonceAccountPubkey);
let nonceAccount = NonceAccount.fromAccountData(accountInfo.data);

Menggunakan Akun Nonce

Press </> button to view full source
let tx = new Transaction().add(
  // nonce advance must be the first instruction
  SystemProgram.nonceAdvance({
    noncePubkey: nonceAccountPubkey,
    authorizedPubkey: nonceAccountAuth.publicKey,
  }),
  // after that, you do what you really want to do, here we append a transfer instruction as an example.
  SystemProgram.transfer({
    fromPubkey: feePayer.publicKey,
    toPubkey: nonceAccountAuth.publicKey,
    lamports: 1,
  })
);
// assign `nonce` as recentBlockhash
tx.recentBlockhash = nonceAccount.nonce;
tx.feePayer = feePayer.publicKey;
tx.sign(
  feePayer,
  nonceAccountAuth
); /* fee payer + nonce account authority + ... */

console.log(`txhash: ${await connection.sendRawTransaction(tx.serialize())}`);
Last Updated: 9/20/2022, 1:22:28 AM
Contributors: akangaziz