主页 > imtokendapp授权 > java和android如何使用web3j开发以太坊智能合约并进行交易教程

java和android如何使用web3j开发以太坊智能合约并进行交易教程

imtokendapp授权 2023-01-17 10:27:27

从广义上讲,web3j 支持三种类型的以太坊交易:

为了进行这些交易,以太币(以太坊区块链的代币)必须存在于以太坊账户中进行交易的地方。这是为了支付gas成本,也就是支付参与交易的以太坊客户端的交易执行成本,支付这个成本将结果提交给以太坊区块链。获取以太币的说明如下。

此外,我们还可以查询智能合约的状态。

11831773-de56977d1832091c.png

图片

如何获得以太币

有两种方式获取以太币你可以选择:

在私有链或公共测试链(testnet)中挖掘自己非常简单明了。但是,在主公链(主网)中,它需要大量的专用 GPU 时间,这基本上是不可行的,除非您已经有多个专用 GPU 的矿工。如果你想使用私有链,这里有一些指导。

要购买以太币,您需要通过交易所。由于不同地区有不同的交易所,你也需要研究去哪里。包含多个交流,是一个很好的参考。

以太坊测试网(testnets)

以太坊有很多专用的测试网或测试网,得到各种客户端的支持。

对于开发,建议您使用 Rinkeby 或 KoVan 测试链。这是因为他们使用的工作量证明 POA 共识机制,可确保交易和区块的创建始终如一且及时。 Ropsten 测试链虽然是最接近公链(主网)的,但由于采用了 PoW 工作量证明共识机制,在过去也曾遭受过攻击,这往往会给以太坊开发者带来更多问题。

您可以通过 Rinkeby 测试链上的 Rinkeby Crypto Fauce 请求以太坊。详情请看这里。

可以在此处找到有关如何请求 Kovan 测试链的详细信息。

如果您需要在 Ropsten 上获得一些以太币,请将您的钱包地址发布到 web3j gitter 频道,其中一些会发送给您。

在testnet测试链或私链上挖矿

怎么通过合约地址买币_狗狗币以太坊合约地址_狗狗币的合约地址dogecoin

在以太坊测试链测试网中,挖矿难度低于公链主网。这意味着您可以使用普通 CPU(例如笔记本电脑)挖掘新的以太币。你需要做的就是运行一个以太坊客户端,比如 geth 或 Parity,然后开始做一些储备。更多信息可以在他们的官方网站上找到。

一旦你开采了一些以太币,你就可以开始使用以太坊区块链了。

不过,如上所述,使用 Kovan 或 Rinkeby 来测试网络更简单。

气体

当在以太坊上发生交易时,执行交易的客户端必须支付交易成本并将交易的输出提交到以太坊区块链。

此成本以 gas 为单位,其中 gas 是用于在以太坊虚拟机中执行交易指令的金额。请参阅以获取更多信息。

当您使用以太坊客户端时,这意味着有两个参数指示您要花费多少以太币来完成转账:

这两个参数共同决定了您愿意在交易成本上花费的最大以太币数量。也就是说,您不会花费超过 gas price * gas limit 的 gas。 Gas 价格也会影响交易发生的速度,这取决于其他交易是否为矿工提供了更优惠的 Gas 价格。

您可能需要调整这些参数以确保及时交易。

交易机制

当您使用一些 Ether 创建有效帐户时,您可以使用两种机制与 Ethereum 进行交易。

Web3j 支持这两种机制。

通过以太坊客户端验证签名交易

为了通过以太坊客户端进行交易,首先确保您使用的客户端知道您的钱包地址。最好运行自己的以太坊客户端,比如 geth/Parity,这样可以更方便地完成。运行客户端后,您可以通过以下方式创建以太坊钱包:

通过创建你的钱包文件,你可以通过web3j开户,首先创建一个支持geth/Parity管理命令的web3j实例:

Admin web3j = Admin.build(new HttpService());

怎么通过合约地址买币_狗狗币的合约地址dogecoin_狗狗币以太坊合约地址

然后您可以解锁帐户,如果成功,则发送交易:

PersonalUnlockAccount personalUnlockAccount = web3j.personalUnlockAccount("0x000...", "a password").send();
if (personalUnlockAccount.accountUnlocked()) {
    // send a transaction
}
@ >

以这种方式发送的事务应该通过 EthSendTransaction 创建,使用 Transaction 类型:

Transaction transaction = Transaction.createContractTransaction(
              ,
              ,
              BigInteger.valueOf(),  // we use default gas limit
              "0x..."
      );
      org.web3j.protocol.core.methods.response.EthSendTransaction
              transactionResponse = parity.ethSendTransaction(ethSendTransaction)
              .send();
      String transactionHash = transactionResponse.getTransactionHash();
      // poll for transaction response via org.web3j.protocol.Web3j.ethGetTransactionReceipt()

获取nonce值的地方,下面会提到。

有关此事务工作流程的更多信息,请参阅 DeployContractIT 和场景。

有关 web3j 支持的各种管理命令的更多详细信息,请参见管理 API。

离线交易签名

如果您不想管理自己的以太坊客户端,或者不想向您的以太坊客户端提供密码等钱包详细信息,那么只需通过离线交易验证签名即可。

离线交易签名认证允许您使用您的以太坊钱包在 web3j 中签署交易,让您可以完全控制您的私人凭证。然后可以将离线创建的交易发送到网络上的任何以太坊客户端,只要它是有效的交易,它将将该交易传播到其他节点。

如果需要,还可以执行进程外交易签名认证。这可以通过重写sign方法来实现。

创建和使用钱包文件以太坊钱包文件

为了进行离线交易,您需要将您的钱包文件或公钥和私钥与私人钱包/账户相关联。

web3j 可以为您生成一个新的安全以太坊钱包文件,或者它可以通过私钥与现有的钱包文件一起使用。

创建新的钱包文件:

String fileName = WalletUtils.generateNewWalletFile(
        "your password",
        new File("/path/to/destination"));

怎么通过合约地址买币_狗狗币以太坊合约地址_狗狗币的合约地址dogecoin

从钱包文件加载凭据:

Credentials credentials = WalletUtils.loadCredentials(
        "your password",
        "/path/to/walletfile");

这些凭证随后用于签署交易,请参阅 Web3 秘密存储定义 Web3 秘密存储定义

签署以太坊交易

要使用离线签名交易进行签名,需要设置一个RawTransaction类型。 RawTransaction 与前面提到的 Transaction 类型类似,但不需要通过特定的账户地址请求,因为可以从签名中推断出来。

为了创建和签署原生交易,交易的顺序如下:

nonce 是一个不断增加的数字,用于唯一标识交易。在交易被挖掘之前,随机数只能使用一次。可以使用相同的 nonce 发送多个版本的交易,但一旦其中一个被挖掘,所有后续提交都将被拒绝。

一旦获得下一个可用的nonce,这个值就可以用来创建一个交易对象:

RawTransaction rawTransaction  = RawTransaction.createEtherTransaction(
             nonce, , , , );

然后可以对交易进行签名和编码:

byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, );
String hexValue = Numeric.toHexString(signedMessage);

凭据的加载位置。

然后使用以下命令发送交易:

EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
String transactionHash = ethSendTransaction.getTransactionHash();
// poll for transaction response via org.web3j.protocol.Web3j.ethGetTransactionReceipt()

有关创建和发送原始交易的完整示例怎么通过合约地址买币,请参阅 CreateRawTransactionIT。

事务随机数随机数

狗狗币的合约地址dogecoin_狗狗币以太坊合约地址_怎么通过合约地址买币

nonce 是用于唯一标识交易的递增值。在交易被挖掘之前,随机数只能使用一次。可以使用相同的 nonce 发送多个版本的交易,但一旦其中一个被挖掘,所有后续提交都将被拒绝。

下一个可用的nonce可以通过eth_getTransactionCount方法获得:

EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
             address, DefaultBlockParameterName.LATEST).sendAsync().get();
     BigInteger nonce = ethGetTransactionCount.getTransactionCount();

然后你可以使用 nonce 来创建你的交易对象:

RawTransaction rawTransaction  = RawTransaction.createEtherTransaction(
             nonce, , , , );

交易类型

web3j 中不同类型的事务使用 Transaction 和 RawTransaction 对象。关键区别在于交易对象必须始终有一个地址,以便处理 eth_sendTransaction 请求的以太坊客户端知道使用哪个钱包来表示消息发送者并发送该交易。如上所述,离线签名认证对原始交易进行签名不是必需的。

以下部分概述了不同交易类型所需的关键交易属性。以下属性对所有人都是不变的:

Transaction 和 RawTransaction 对象在所有后续示例中可互换使用。

从一方到另一方的以太币交易

在两方之间发送以太币需要关于交易对象的最少信息:

BigInteger value = Convert.toWei("1.0", Convert.Unit.ETHER).toBigInteger();
RawTransaction rawTransaction  = RawTransaction.createEtherTransaction(
             , , , , value);
// send...
@ >

但是,建议您使用 TransferClass 发送 Ether,它负责 nonce 管理并通过不断的轮询为您提供响应:

Web3j web3 = Web3j.build(new HttpService());  // defaults to http://localhost:8545/
Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
TransactionReceipt transactionReceipt = Transfer.sendFunds(
        web3, credentials, "0x
|", BigDecimal.valueOf(1.0), Convert.Unit.ETHER).send();

p>

使用智能合约包装器

怎么通过合约地址买币_狗狗币的合约地址dogecoin_狗狗币以太坊合约地址

使用下面列出的智能合约包装器时,从 Solidity 到本地 Java 类型的所有转换都必须手动执行。使用非常高效,它负责所有代码生成和转换。

创建智能合约

要部署新的智能合约,需要提供以下属性:

// using a raw transaction
RawTransaction rawTransaction = RawTransaction.createContractTransaction(
        ,
        ,
        ,
        ,
        "0x ");
// send...
// get contract address
EthGetTransactionReceipt transactionReceipt =
             web3j.ethGetTransactionReceipt(transactionHash).send();
if (transactionReceipt.getTransactionReceipt.isPresent()) {
    String contractAddress = transactionReceipt.get().getContractAddress();
} else {
    // try again
}

如果智能合约包含构造函数,则必须对关联的构造函数字段值进行编码并附加到编译后的智能合约代码中:

String encodedConstructor =
             FunctionEncoder.encodeConstructor(Arrays.asList(new Type(value), ...));
// using a regular transaction
Transaction transaction = Transaction.createContractTransaction(
        ,
        ,
        ,
        ,
        ,
        "0x " + encodedConstructor);
// send...

智能合约交易

要与现有的智能合约进行交易,需要提供以下属性:

web3j负责函数编码怎么通过合约地址买币,具体实现请参考应用程序二进制接口部分Application Binary Interface。

Function function = new Function<>(
             "functionName",  // function we're calling
             Arrays.asList(new Type(value), ...),  // Parameters to pass as Solidity Types
             Arrays.asList(new TypeReference() {}, ...));
String encodedFunction = FunctionEncoder.encode(function)
Transaction transaction = Transaction.createFunctionCallTransaction(
             , , , contractAddress, , encodedFunction);
org.web3j.protocol.core.methods.response.EthSendTransaction transactionResponse =
             web3j.ethSendTransaction(transaction).sendAsync().get();
String transactionHash = transactionResponse.getTransactionHash();
// wait for response using EthGetTransactionReceipt...

无论消息签名的返回类型如何,都无法从事务性函数调用返回值。但是,可以使用过滤器捕获函数返回的值。有关详细信息,请参阅过滤器和事件部分。

查询智能合约状态

这个功能是通过调用JSON-RPC来实现的。

eth_call 允许您调用智能合约上的方法来查询值。这个函数没有交易成本,因为它不会改变任何智能合约方法的状态,它只是返回它们的值:

Function function = new Function<>(
             "functionName",
             Arrays.asList(new Type(value)),  // Solidity Types in smart contract functions
             Arrays.asList(new TypeReference() {}, ...));
String encodedFunction = FunctionEncoder.encode(function)
org.web3j.protocol.core.methods.response.EthCall response = web3j.ethCall(
             Transaction.createEthCallTransaction(, contractAddress, encodedFunction),
             DefaultBlockParameterName.LATEST)
             .sendAsync().get();
List someTypes = FunctionReturnDecoder.decode(
             response.getValue(), function.getOutputParameters());

注意:如果 a 执行了无效的函数调用,返回值将是一个实例,或者得到一个空的null返回结果。

汇智网原文翻译,原文请看这里