Bắt đầu (~v1.4.0)

Điều kiện tiên quyết

Phần phụ thuộc

maven

<dependency>
  <groupId>com.klaytn.caver</groupId>
  <artifactId>core</artifactId>
  <version>1.4.0</version>
</dependency>

gradle

implementation 'com.klaytn.caver:core:1.4.0'

Nếu bạn muốn dùng phần phụ thuộc Android, bạn chỉ cần thêm -android vào cuối chuỗi phiên bản. (ví dụ 1.0.1-android)

Nếu bạn muốn xem chi tiết của các yêu cầu và phản hồi JSON-RPC, vui lòng đưa phần phụ thuộc LOGBack vào dự án của mình. Dưới đây là một ví dụ về tập tin xây dựng Gradle. Bạn cũng có thể thêm phần phụ thuộc vào Maven. Vì caver-java sử dụng giao diện đăng nhập SLF4J, bạn có thể chuyển sang trình ghi bản ghi mà bạn thích thay cho LOGBack.

implementation "ch.qos.logback:logback-classic:1.2.3"

Lưu ý: Trong kho dữ liệu trung tâm, các phiên bản RC, Andriod và Java được liệt kê cùng nhau. Nếu bạn sử dụng ký tự đại diện để lấy một phiên bản, bạn có thể dùng phải một phiên bản không phù hợp với nền tảng của mình.

Cài đặt

Nếu bạn muốn tạo các giao dịch liên quan đến một hợp đồng thông minh, bạn cần cài trình biên dịch Solidity và công cụ dòng lệnh caver-java trước.

Trình biên dịch Solidity

Bạn có thể cài đặt trình biên dịch Solidity vào máy tính của mình bằng cách làm theo hướng dẫn trong tài liệu của dự án. Klaytn khuyên bạn nên cài đặt phiên bản Solidity 0.4.24 hoặc 0.5.6. Nếu bạn dùng macOS, bạn có thể cài đặt các phiên bản trên qua Homebrew:

$ brew install klaytn/klaytn/solidity@0.4.24  # version 0.4.24
$ brew install klaytn/klaytn/solidity@0.5.6   # version 0.5.6

Công cụ dòng lệnh

Công cụ dòng lệnh cho phép bạn dùng dòng lệnh để tạo các lớp vỏ bọc chức năng bằng Solidity cho hợp đồng thông minh.

Cài đặt (Homebrew)

Cần có Java 1.8 trở lên để cài đặt công cụ này.

$ brew tap klaytn/klaytn
$ brew install caver-java

Sau khi cài đặt, bạn có thể chạy lệnh "caver-java" như dưới đây:

$ caver-java solidity generate -b <smart-contract>.bin -a <smart-contract>.abi -o <outputPath> -p <packagePath>

Cài đặt (Khác)

Hiện tại, chúng tôi không hỗ trợ các trình quản lý gói khác. Một giải pháp khác mà chúng tôi cung cấp là một phương pháp để xây dựng CLI như bên dưới.

  • Tải xuống hoặc tách luồng caver-java.

  • Dùng Gradle thực hiện tác vụ "shadowDistZip" trong mô-đun bảng điều khiển. Kết quả là console/build/distributions/console-shadow-{version}.zip được tạo ra.

    $ ./gradlew :console:shadowDistZip
  • Giải nén tập tin zip trong thư mục xây dựng

    $ unzip ./console/build/distributions/console-shadow-{version}.zip
  • Thực thi tập tin nhị phân để chạy công cụ dòng lệnh như dưới đây. Bạn có thể tìm thấy tập tin mã lập trình shell dành cho người dùng macOS và tập tin batch dành cho người dùng Window.

    $ ./console/build/distributions/console-shadow-{version}/bin/caver-java

Quản lý tài khoản

Tạo một tài khoản

Để ký các giao dịch, bạn cần có một cặp khóa EC (Elliptic Curve) hoặc một tập tin lưu trữ khóa Klaytn.

Sử dụng một cặp khóa EC

Bạn có thể tạo ra một tài khoản Klaytn bằng cặp khóa EC như dưới đây:

KlayCredentials credentials = KlayCredentials.create(Keys.createEcKeyPair());
String privateKey = Numeric.toHexStringWithPrefix(credentials.getEcKeyPair().getPrivateKey()); 
String address = credentials.getAddress();

Sử dụng một tập tin lưu trữ khóa

Nếu bạn muốn tạo một tài khoản mới bằng tập tin lưu trữ khóa (bạn cũng có thể tạo một tập tin lưu trữ khóa mới trong Ví Klaytn):

KlayWalletUtils.generateNewWalletFile(
        <yourPassword>,
        new File(<walletFilePath>)
);

Để tải một tài khoản bằng tập tin lưu trữ khóa như dưới đây:

KlayCredentials credentials = KlayWalletUtils.loadCredentials(<password>, <walletFilePath>);

Gửi giao dịch

Nhận KLAY qua Vòi Baobab

Sau khi tạo một tài khoản, bạn có thể nhận được một ít đồng KLAY dùng cho mạng thử nghiệm Baobab qua Vòi Baobab, có sẵn tại https://baobab.wallet.klaytn.foundation/. Đồng KLAY dùng cho mạng thử nghiệm mà bạn nhận được sẽ được sử dụng để thanh toán phí giao dịch sau này.

Kết nối với Baobab

Bạn có thể kết nối với mạng Baobab như dưới đây:

Caver caver  = Caver.build(https://your.baobab.en.url:8651);

Gửi một giao dịch chuyển giá trị

Sau khi đã nhận được một đối tượng Caver cụ thể và tạo một tài khoản có KLAY, bạn có thể gửi 1 peb đến địa chỉ nhất định (0xe97f27e9a5765ce36a7b919b1cb6004c7209217e) với hạn mức gas BigInteger.valueOf(100_000) như dưới đây:

TransactionManager được đưa vào để ẩn bớt sự phức tạp của các loại giao dịch. Ví dụ: một đối tượng FeeDelegatedValueTransferTransaction có thể được chuyển đổi từ một đối tượng ValueTransferTransaction. Để biết thêm thông tin, hãy xem [Ủy thác phí][]. Ngoài Ủy thác phí, TransactionManager còn có thể được sử dụng cùng GetNonceProcessor, ErrorHandlerTransactionReceiptProcessor.

TransactionManager transactionManager = new TransactionManager.Builder(caver, credentials)
        .setChaindId(ChainId.BAOBAB_TESTNET).build();

ValueTransferTransaction valueTransferTransaction = ValueTransferTransaction.create(
        credentials.getAddress(),  // fromAddress
        "0xe97f27e9a5765ce36a7b919b1cb6004c7209217e",  // toAddress
        BigInteger.ONE,  // value
        BigInteger.valueOf(100_000)  // gasLimit
);

KlayRawTransaction klayRawTransaction = transactionManager.sign(valueTransferTransaction);
String transactionHash = transactionManager.send(klayRawTransaction);

TransactionReceiptProcessor transactionReceiptProcessor = new PollingTransactionReceiptProcessor(caver, 1000, 15);  // pollingSleepDuration = 1000, pollingAttempts = 15
KlayTransactionReceipt.TransactionReceipt transactionReceipt = transactionReceiptProcessor.waitForTransactionReceipt(transactionHash);

Nếu bạn sử dụng lớp ValueTransfer, bạn có thể biên soạn và gửi một giao dịch đi dễ dàng hơn. Đó và vì lớp ValueTransfer khiến các quy trình trên trở nên đơn giản hơn như dưới đây:

KlayTransactionReceipt.TransactionReceipt transactionReceipt
        = ValueTransfer.create(caver, credentials, ChainId.BAOBAB_TESTNET).sendFunds(
                redentials.getAddress(),  // fromAddress
                "0xe97f27e9a5765ce36a7b919b1cb6004c7209217e",  // toAddress
                BigDecimal.ONE,  // value 
                Convert.Unit.PEB,  // unit 
                BigInteger.valueOf(100_000)  // gasLimit
            ).send();

Kiểm tra biên lai

Nếu bạn gửi một giao dịch qua sendFunds, caver-java sẽ tìm cách lấy biên lai giao dịch theo mặc định. Sau khi nhận được biên lai, bạn có thể thấy bản ghi sau trong bảng điều khiển.

{
   "jsonrpc":"2.0",
   "id":4,
   "result":{
      "blockHash":"0x45542cc3e3bce952f368c5da9d40f972c134fed2b2b6815231b5caf33c79dacd",
      "blockNumber":"0x39a57b",
      "contractAddress":null,
      "from":"0xe97f27e9a5765ce36a7b919b1cb6004c7209217e",
      "gas":"0x186a0",
      "gasPrice":"0x5d21dba00",
      "gasUsed":"0x5208",
      "nhật ký":[],
      "nhật kýBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
      "nonce":"0x114e",
      "senderTxHash":"0x3d50b9fa9fec58443f5618ed7e0f5aec5e9a6f7269d9ff606ff87156ca5b4afd",
      "signatures":[
         {
            ...
         }
      ],
      "trạng thái":"0x1",
      "to":"0xe97f27e9a5765ce36a7b919b1cb6004c7209217e",
      "transactionHash":"0x3d50b9fa9fec58443f5618ed7e0f5aec5e9a6f7269d9ff606ff87156ca5b4afd",
      "transactionIndex":"0x1",
      "type":"TxTypeValueTransfer",
      "typeInt":8,
      "value":"0x1"
   }
}

Trong biên lai này, bạn có thể kiểm tra trạng thái của việc thực thi giao dịch. Nếu trường "trạng thái" trong biên lai là "0x1", điều này có nghĩa là giao dịch đã được xử lý thành công. Nếu không, giao dịch đã thất bại. Thông báo lỗi chi tiết được hiển thị trong trường txError. Để biết thêm chi tiết, hãy xem txError.

Gửi các loại giao dịch khác

Cập nhật tài khoản

Nếu bạn muốn cập nhật khóa của một tài khoản đã cho vào khóa [AccountKeyPublic][] mới:

AccountUpdateTransaction tài khoảnUpdateTransaction = AccountUpdateTransaction.create(
        credentials.getAddress(),  // fromAddress
        AccountKeyPublic.create(
                "0xbf8154a3c1580b5478ceec0aac319055185280ce22406c6dc227f4de85316da1",  // publicKeyX
                "0x0dc8e4b9546adcc6d1f11796e43e478bd7ffbe302917667837179f4da77591d8"  // publicKeyY
        ),  // newAccountKey
        BigInteger.valueOf(100_000)  // gasLimit
);
Account.create(caver, credentials, ChainId.BAOBAB_TESTNET).sendUpdateTransaction(tài khoảnUpdateTransaction).send();

Khóa tài khoản tương ứng với cấu trúc khóa liên kết với một tài khoản. Để biết thêm chi tiết và các loại khóa tài khoản Klaytn, vui lòng đọc [AccountKey][].

Hợp đồng thông minh

caver-java hỗ trợ tạo tự động mã vỏ bọc của hợp đồng thông minh. Với vỏ bọc này, bạn có thể dễ dàng triển khai và thực thi một hợp đồng thông minh. Trước khi tạo một mã vỏ bọc, bạn cần lập trước một hợp đồng thông minh. Lưu ý: Việc này chỉ có tác dụng nếu trình biên dịch Solidity đã được cài trên máy tính của bạn. Hãy xem [Trình biên dịch Solidity][].

$ solc <contract>.sol --bin --abi --optimize -o <output-dir>/

Sau đó, tạo mã vỏ bọc bằng cách dùng [công cụ dòng lệnh][] của caver-java.

$ caver-java solidity generate -b <smart-contract>.bin -a <smart-contract>.abi -o <outputPath> -p <packagePath>

Lệnh trên sẽ cho kết quả đầu ra <smartContract>.java. Sau khi tạo được mã vỏ bọc, bạn có thể triển khai hợp đồng thông minh như dưới đây:

<smartContract> contract = <smartContract>.deploy(
        caver, credentials, <chainId>, <gasProvider>,
        <param1>, ..., <paramN>).send();

Sau khi hợp đồng thông minh đã được triển khai, bạn có thể tạo một phiên bản hợp đồng thông minh cụ thể như dưới đây:

<smartContract> contract = <smartContract>.load(
        <deployedContractAddress>, caver, credentials, <chainId>, <gasProvider>
);

Để giao dịch với một hợp đồng thông minh:

KlayTransactionReceipt.TransactionReceipt transactionReceipt = contract.<someMethod>(
        <param1>,
        ...).send();

Để gọi một hợp đồng thông minh:

<type> result = contract.<someMethod>(<param1>, ...).send();

Ví dụ

Phần này mô tả cách để triển khai và thực thi một hợp đồng thông minh trên mạng thử nghiệm Baobab. Trong ví dụ này, chúng ta dùng hợp đồng thông minh ERC20Mock. Nếu việc triển khai hợp đồng thông minh thất bại và kết quả trả về là một địa chỉ hợp đồng trống, nó sẽ ném ra RuntimeException.

ERC20Mock erc20Mock = ERC20Mock.deploy(
        caver, credentials, 
        ChainId.BAOBAB_TESTNET,  // chainId
        new DefaultGasProvider(),  // gasProvider
        credentials.getAddress(),  // param1(initialAccount)
        BigInteger.valueOf(100)  // param2(initialBalance)
).send();
String deployedContractAddress = erc20Mock.getContractAddress();

Để tạo một đối tượng cụ thể của hợp động ERC20Mock đã triển khai:

ERC20Mock erc20Mock = ERC20Mock.load(
        deployedContractAddress, 
        caver, credentials, 
        ChainId.BAOBAB_TESTNET,  // chainId 
        new DefaultGasProvider()  // gasProvider
);

Nếu bạn chuyển 10 token đến một địa chỉ được chỉ định (e.g., 0x2c8ad0ea2e0781db8b8c9242e07de3a5beabb71a), hãy dùng mã sau:

KlayTransactionReceipt.TransactionReceipt transactionReceipt = erc20Mock.transfer(
        "0x2c8ad0ea2e0781db8b8c9242e07de3a5beabb71a",  // toAddress
        BigInteger.valueOf(10)  // value
).send();

Để kiểm tra số dư của người nhận (e.g., 0x2c8ad0ea2e0781db8b8c9242e07de3a5beabb71a), hãy dùng mã sau:

BigInteger balance = erc20Mock.balanceOf(
        "0x2c8ad0ea2e0781db8b8c9242e07de3a5beabb71a"  // owner
).send();

Ủy thác phí

Klaytn cung cấp tính năng [Ủy thác phí][], cho phép nhà cung cấp dịch vụ trả phí giao dịch thay cho người sử dụng.

Chuyển giá trị

Ở phía máy khách, máy khách là người khởi tạo giao dịch sẽ tạo một giao dịch chuyển giá trị có phí được ủy thác như sau: Người gửi tạo một đối tượng ValueTransferTransaction, sau đó transactionManager.sign() trả vệ một đối tượng FeeDelegatedValueTransferTransaction đã được ký nếu tham số thứ hai được đặt là true.

TransactionManager transactionManager = new TransactionManager.Builder(caver, credentials)
        .setChaindId(ChainId.BAOBAB_TESTNET).build();  // BAOBAB_TESTNET = 1001
ValueTransferTransaction valueTransferTransaction = ValueTransferTransaction.create(
        credentials.getAddress(),  // fromAddress
        "0xe97f27e9a5765ce36a7b919b1cb6004c7209217e",  // toAddress
        BigInteger.ONE,  // value
        BigInteger.valueOf(100_000)  // gasLimit
);
String senderRawTransaction = transactionManager.sign(valueTransferTransaction, true).getValueAsString();  // isFeeDelegated : true

Một giao dịch đã ký, senderRawTransaction, được tạo ra. Bây giờ, người gửi chuyển giao dịch đến người trả phí, người này sẽ thanh toán khoản phí giao dịch. Các giao dịch chuyển nhượng giữa người gửi và người trả phí không được thực hiện trên mạng lưới Klaytn. Giao thức phải được chính họ xác định.

Sau khi người trả phí nhận được giao dịch từ người gửi, người trả phí có thể gửi giao dịch bằng lớp FeePayerManager như sau. FeePayerManager.executeTransaction() sẽ ký giao dịch nhận được bằng khóa riêng tư của người trả phí và gửi giao dịch đến mạng lưới Klaytn.

KlayCredentials feePayer = KlayWalletUtils.loadCredentials(<password>, <walletfilePath>);
FeePayerManager feePayerManager = new FeePayerManager.Builder(caver, feePayer)
        .setChainId(ChainId.BAOBAB_TESTNET)
        .build();
feePayerManager.executeTransaction(senderRawTransaction);

Thực thi hợp đồng thông minh

Sự khác biệt giữa việc thực thi hợp đồng thông minh có phí được ủy thác với việc chuyển giá trị có phí ủy thác như trên nằm ở chỗ: việc này cần có dữ liệu đầu vào để gọi một hàm của hợp đồng thông minh. Người gửi có thể tạo một giao dịch thực thi hợp đồng thông minh có phí được ủy thác như sau. Lưu ý rằng transactionManager.sign() trả về đối tượng TxTypeFeeDelegatedSmartContractExecution nếu bạn đặt true cho tham số thứ hai. Ví dụ dưới đây gọi phương pháp transfer của hợp đồng ERC20Mock được mô tả trong [Smart Contract][].

String recipient = "0x34f773c84fcf4a0a9e2ef07c4615601d60c3442f";
BigInteger transferValue = BigInteger.valueOf(20);
Function function = new Function(
        ERC20Mock.FUNC_TRANSFER,  // FUNC_TRANSFER = "transfer"
        Arrays.asList(new Address(recipient), new Uint256(transferValue)),  // inputParameters
        Collections.emptyList()  // outputParameters
);
String data = FunctionEncoder.encode(function);

TransactionManager transactionManager = new TransactionManager.Builder(caver, credentials)
        .setChaindId(ChainId.BAOBAB_TESTNET).build();  // BAOBAB_TESTNET = 1001
SmartContractExecutionTransaction smartContractExecution = 
        SmartContractExecutionTransaction.create(
                credentials.getAddress(),  // fromAddress
                erc20Mock.getContractAddress(),  // contractAddress
                BigInteger.ZERO,  // value
                Numeric.hexStringToByteArray(data),  // data
                BigInteger.valueOf(100_000)  // gasLimit
        );
String senderRawTransaction = transactionManager.sign(smartContractExecution, true).getValueAsString();

Sau khi bạn nhận được senderRawTransaction, phần còn lại quả quá trình sử dụng FeePayerManager theo cùng một cách như đã thấy tại [fee-delegated value transfer][] ở trên:

KlayCredentials feePayer = KlayWalletUtils.loadCredentials(<password>, <walletfilePath>);
FeePayerManager feePayerManager = new FeePayerManager.Builder(caver, feePayer).build();
feePayerManager.executeTransaction(senderRawTransaction);

Sử dụng nhiều loại AccountKey

caver-java mang đến nhiều lớp mới để hỗ trợ các loại [AccountKey][] khác nhau được nền tảng hỗ trợ. Tính năng này được hỗ trợ từ phiên bản 1.2.0.

AccountKey

Để cập nhật khóa tài khoản trên nền tảng Klaytn, caver-java cung cấp giao diện AccountKey. Nội dung dưới đây mô tả về AccountKey implementations, AccountKeyPublic, AccountKeyWeightedMultiSigAccountKeyRoleBased. Hãy xem [AccountUpdate](#tài khoản-update) để tìm hiểu về cách cập nhật Tài khoản.

AccountKeyPublic

AccountKeyPublic là sự triển khai của AccountKey với một khóa công khai. Bạn có thể tạo như sau:

ECKeyPair newKeyPair = Keys.createEcKeyPair();
AccountKeyPublic newAccountKey = AccountKeyPublic.create(newKeyPair.getPublicKey());

Để sử dụng tài khoản được cập nhật bằng AccountKeyPublic, bạn cần tạo KlayCredentials như dưới đây:

KlayCredentials validCredentails = KlayCredentials.create(newKeyPair, oldCredentials.getAddress());

// Because the tài khoản address is decoupled from the AccountKeyPublic (public key), you can't use the tài khoản if you create the credentials without address as below.
KlayCredentials invalidCredentails = KlayCredentials.create(newKeyPair);

AccountKeyWeightedMultiSig

AccountKeyWeightedMultiSig là một khóa tài khoản có chứa nhiều khóa công khai với trọng số khác nhau. AccountKeyWeightedMultiSig còn xác định ngưỡng, tổng trọng số của các khóa cần phải ký để sử dụng tài khoản. Số lượng khóa tối đa được hỗ trợ là 10. Bạn có thể tạo AccountKeyWeightedMultiSig như dưới đây:

List<AccountKeyWeightedMultiSig.WeightedPublicKey> weightedTransactionPublicKeys = new ArrayList<>();

int weight1 = 10;
int weight2 = 30;

ECKeyPair ecKeyPair1 = Keys.createEcKeyPair();
ECKeyPair ecKeyPair2 = Keys.createEcKeyPair();

AccountKeyWeightedMultiSig.WeightedPublicKey weightedPublicKey1 = AccountKeyWeightedMultiSig.WeightedPublicKey.create(
                BigInteger.valueOf(weight1),
                AccountKeyPublic.create(ecKeyPair1.getPublicKey())
);

AccountKeyWeightedMultiSig.WeightedPublicKey weightedPublicKey2 = AccountKeyWeightedMultiSig.WeightedPublicKey.create(
                BigInteger.valueOf(weight2),
                AccountKeyPublic.create(ecKeyPair2.getPublicKey())
);

weightedTransactionPublicKeys.add(weightedPublicKey1);
weightedTransactionPublicKeys.add(weightedPublicKey2);

AccountKeyWeightedMultiSig newAccountKey = AccountKeyWeightedMultiSig.create(
                BigInteger.valueOf(weight1 + weight2),
                weightedTransactionPublicKeys
);

Để sử dụng tài khoản được cập nhật bằng AccountKeyWeightedMultiSig, bạn có thể tạo KlayCredentials như sau:

List<ECKeyPair> transactionECKeyPairList = new ArrayList<>();

transactionECKeyPairList.add(ecKeyPair1);
transactionECKeyPairList.add(ecKeyPair2);

KlayCredentials newCredentails = KlayCredentials.create(transactionECKeyPairList, address);

AccountKeyRoleBased

AccountKeyRoleBased là một danh sách chứa AccountKey. Từng AccountKey đươc chỉ định một vai trò cụ thể theo vị trí của nó. AccountKey có thể là AccountKeyPublic,AccountKeyWeightedMultiSig hoặc AccountKeyFail. Nếu AccountKeyNil được dùng cho một vai trò cụ thể, khóa này sẽ không được cập nhật cho vai trò đó và AccountKey hiện có sẽ được sử dụng. Nếu AccountKeyFail được sử dụng, việc ký cho vai trò đó sẽ luôn thất bại, vì thế, hãy cẩn thận khi dùng AccountKeyFail.

List<AccountKey> roleBasedAccountKeyList = new ArrayList<>();

ECKeyPair newKeyPair1 = Keys.createEcKeyPair(); // for RoleTransaction
roleBasedAccountKeyList.add(AccountKeyPublic.create(newKeyPair1.getPublicKey()));

ECKeyPair newKeyPair2 = Keys.createEcKeyPair(); // for RoleAccountUpdate
roleBasedAccountKeyList.add(AccountKeyPublic.create(newKeyPair2.getPublicKey()));

ECKeyPair newKeyPair3 = Keys.createEcKeyPair(); // for RoleFeePayer
roleBasedAccountKeyList.add(AccountKeyPublic.create(newKeyPair3.getPublicKey()));

newAccountKey = AccountKeyRoleBased.create(roleBasedAccountKeyList);

Để sử dụng tài khoản được cập nhật bằng AccountKeyRoleBased, bạn có thể tạo KlayCredentials như sau:

List<ECKeyPair> transactionECKeyPairList = Arrays.asList(newKeyPair1);
List<ECKeyPair> updateECKeyPairList = Arrays.asList(newKeyPair2);
List<ECKeyPair> feePayerECKeyPairList = Arrays.asList(newKeyPair3);

KlayCredentials newCredentails = KlayCredentials.create(transactionECKeyPairList, updateECKeyPairList, feePayerECKeyPairList, address);

Nếu tài khoản không có khóa cho một vai trò cụ thể, hãy dùng Danh sách trống làm đối số.

List<ECKeyPair> transactionECKeyPairList = Collections.emptyList();
List<ECKeyPair> updateECKeyPairList = Arrays.asList(newKeyPair2);
List<ECKeyPair> feePayerECKeyPairList = Collections.emptyList();

KlayCredentials newCredentails = KlayCredentials.create(transactionECKeyPairList, updateECKeyPairList, feePayerECKeyPairList, address);

Nếu tài khoản có nhiều khóa cho một vai trò cụ thể, bạn có thể dùng nhiều khóa như dưới đây.

List<ECKeyPair> transactionECKeyPairList = Collections.emptyList();
List<ECKeyPair> updateECKeyPairList = Arrays.asList(newKeyPair2-1, newKeyPair2-2, newKeyPair2-3);
List<ECKeyPair> feePayerECKeyPairList = Collections.emptyList();

KlayCredentials newCredentails = KlayCredentials.create(transactionECKeyPairList, updateECKeyPairList, feePayerECKeyPairList, address);

Gửi một giao dịch có nhiều người ký

Nếu một tài khoản có AccountKeyMultiSig hoặc AccountKeyRoleBased, từng khóa có thể được quản lý bởi nhiều người khác nhau.

Phần này mô tả cách để thu thập nhiều chữ ký và gửi giao dịch nếu có nhiều người ký.

Người ký ký tuần tự

rawTransaction có một giao dịch mã hóa RLP chứa cả txSignatures lẫn feePayerSignatures. feePayerSignature chỉ được đưa vào khi giao dịch là giao dịch có phí ủy thác.

Khi không có người trả phí, quy trình ký và thực thi giao dịch lặp đi lặp lại có thể được chia thành ba phần. 1. RLP mã hóa giao dịch và gửi nó đến người ký dưới hình thức rawTransaction. 2. Người ký ký bằng khóa của riêng mình cho rawTransaction nhận được. 3. Gửi rawTransaction đã ký đến EN. Bước 2 có thể được lặp lại nếu có nhiều người ký.

//// 1. Alice tạo một giao dịch, ký và gửi cho Bob.
//// Alice Side
ValueTransferTransaction transactionTransformer = ValueTransferTransaction.create(from, to, BigInteger.ONE, GAS_LIMIT);

TransactionManager transactionManager_alice = new TransactionManager.Builder(caver, senderCredential_alice)
                    .setTransactionReceiptProcessor(new PollingTransactionReceiptProcessor(caver, 1000, 10))
                    .setChaindId(LOCAL_CHAIN_ID)
                    .build();

String rawTransaction_signed_alice = transactionManager_alice.sign(transactionTransformer).getValueAsString();

//// 2. Bob ký giao dịch nhận được và gửi cho Charlie.
//// Bob Side
            TransactionManager transactionManager_bob = new TransactionManager.Builder(caver, senderCredential_bob)
                    .setTransactionReceiptProcessor(new PollingTransactionReceiptProcessor(caver, 1000, 10))
                    .setChaindId(LOCAL_CHAIN_ID)
                    .build();

String rawTransaction_signed_alice_and_bob = transactionManager_bob.sign(rawTransaction_signed_alice).getValueAsString();

//// 3. Charlie ký giao dịch nhận được và gửi đến Klaytn EN.
//// Charlie Side
TransactionManager transactionManager_charlie = new TransactionManager.Builder(caver, senderCredential_charlie)
                    .setTransactionReceiptProcessor(new PollingTransactionReceiptProcessor(caver, 1000, 10))
                    .setChaindId(LOCAL_CHAIN_ID)
                    .build();

KlayTransactionReceipt.TransactionReceipt transactionReceipt = transactionManager_charlie.executeTransaction(rawTransaction_signed_alice_and_bob);

Người trả phí ký tuần tự

(Các) chữ ký của người trả phí cũng có thể được thêm vào một cách tuần tự. Ký bằng FeePayerManager tích lũy feePayerSignatures trong giao dịch. Thứ tự ký không quan trọng. Nếu bạn ký bằng TransactionManager, txSignature sẽ được thêm vào. Nếu bạn ký bằng FeePayerManager, feePayerSignatures sẽ được thêm vào giao dịch thô.

//// 1. Bob nhận được giao dịch từ Alice và ký giao dịch với tư cách là người trả phí.
//// Bob Side
FeePayerManager feePayerManager_bob = new FeePayerManager.Builder(caver, feePayerCredentials_bob)
                    .setTransactionReceiptProcessor(new PollingTransactionReceiptProcessor(caver, 1000, 10))
                    .setChainId(LOCAL_CHAIN_ID)
                    .build();

String rawTransaction_signed_alice_and_bob = feePayerManager_bob.sign(rawTransaction_signed_alice).getValueAsString();

//// 2. Charlie ký giao dịch nhận được và gửi đến Klaytn EN.
//// Charlie Side
FeePayerManager feePayerManager_charlie = new FeePayerManager.Builder(caver, feePayerCredentials_charlie)
                    .setTransactionReceiptProcessor(new PollingTransactionReceiptProcessor(caver, 1000, 10))
                    .setChainId(LOCAL_CHAIN_ID)
                    .build();

KlayTransactionReceipt.TransactionReceipt transactionReceipt =  feePayerManager_charlie.executeTransaction(rawTransaction_signed_alice_and_bob);

Xin cảm ơn

Dự án web3j vì nguồn cảm hứng này. 🙂

[AccountKeyPublic]: ../../../../klaytn/design/tài khoảns.md#tài khoảnkeypublic [AccountKey]: ../../../../klaytn/design/tài khoảns.md#tài khoản-key [Trình biên dịch Solidity]: #solidity-compiler [công cụ dòng lệnh]: #command-line-tool [Ủy thác phí]: ../../../../klaytn/design/transactions/README.md#fee-delegation [Smart Contract]: #smart-contract [fee-delegated value transfer]: #value-transfer

Last updated