@ocap/client 1.25.3 → 1.25.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -80
- package/dist/report.html +1 -1
- package/docs/_sidebar.md +22 -0
- package/docs/api-reference-client-methods.md +229 -0
- package/docs/api-reference-client-methods.zh.md +229 -0
- package/docs/api-reference-data-types.md +482 -0
- package/docs/api-reference-data-types.zh.md +482 -0
- package/docs/api-reference-low-level-api.md +228 -0
- package/docs/api-reference-low-level-api.zh.md +228 -0
- package/docs/api-reference-query-mutation-methods.md +814 -0
- package/docs/api-reference-query-mutation-methods.zh.md +814 -0
- package/docs/api-reference-transaction-helpers.md +649 -0
- package/docs/api-reference-transaction-helpers.zh.md +649 -0
- package/docs/api-reference.md +23 -0
- package/docs/api-reference.zh.md +23 -0
- package/docs/core-concepts-client-architecture.md +102 -0
- package/docs/core-concepts-client-architecture.zh.md +102 -0
- package/docs/core-concepts-event-subscriptions.md +123 -0
- package/docs/core-concepts-event-subscriptions.zh.md +123 -0
- package/docs/core-concepts-gas-payment.md +111 -0
- package/docs/core-concepts-gas-payment.zh.md +111 -0
- package/docs/core-concepts-transaction-lifecycle.md +183 -0
- package/docs/core-concepts-transaction-lifecycle.zh.md +183 -0
- package/docs/core-concepts.md +22 -0
- package/docs/core-concepts.zh.md +22 -0
- package/docs/getting-started-basic-usage.md +87 -0
- package/docs/getting-started-basic-usage.zh.md +87 -0
- package/docs/getting-started-installation.md +60 -0
- package/docs/getting-started-installation.zh.md +60 -0
- package/docs/getting-started.md +16 -0
- package/docs/getting-started.zh.md +16 -0
- package/docs/how-to-guides-delegate-permissions.md +167 -0
- package/docs/how-to-guides-delegate-permissions.zh.md +167 -0
- package/docs/how-to-guides-manage-accounts.md +73 -0
- package/docs/how-to-guides-manage-accounts.zh.md +73 -0
- package/docs/how-to-guides-manage-assets.md +255 -0
- package/docs/how-to-guides-manage-assets.zh.md +255 -0
- package/docs/how-to-guides-manage-tokens.md +179 -0
- package/docs/how-to-guides-manage-tokens.zh.md +179 -0
- package/docs/how-to-guides-stake-tokens-and-assets.md +205 -0
- package/docs/how-to-guides-stake-tokens-and-assets.zh.md +205 -0
- package/docs/how-to-guides-transfer-tokens-and-nfts.md +179 -0
- package/docs/how-to-guides-transfer-tokens-and-nfts.zh.md +179 -0
- package/docs/how-to-guides.md +27 -0
- package/docs/how-to-guides.zh.md +27 -0
- package/docs/overview.md +70 -0
- package/docs/overview.zh.md +70 -0
- package/package.json +14 -14
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Gas 费支付
|
|
2
|
+
|
|
3
|
+
在大多数区块链系统中,每笔交易都需要发起人支付一笔费用,通常称为“Gas”。对于可能没有原生货币来支付这些费用的新用户来说,这可能是一个巨大的障碍。OCAP Client 引入了 Gas 费支付功能,允许应用程序开发者代付这些费用,从而为用户创造无缝的“免 Gas”体验。
|
|
4
|
+
|
|
5
|
+
这一强大功能使 dApp 能够将 Gas 的复杂性抽象出来,从而改善用户入门体验和应用的整体可用性。
|
|
6
|
+
|
|
7
|
+
## 工作原理
|
|
8
|
+
|
|
9
|
+
Gas 费支付机制通过标准的 HTTP 标头实现。当您在客户端实例上配置 Gas 支付方钱包时,客户端会自动将两个特殊的标头附加到它发送给区块链节点的每个 `sendTx` 变更中:
|
|
10
|
+
|
|
11
|
+
- `x-gas-payer-pk`:将支付 Gas 费的钱包的公钥。
|
|
12
|
+
- `x-gas-payer-sig`:由 Gas 支付方私钥签名的 JSON Web Token (JWT)。此令牌包含交易的哈希值,作为代付方为该特定交易支付费用的可验证授权。
|
|
13
|
+
|
|
14
|
+
当区块链节点收到交易时,它会执行两个关键的验证:
|
|
15
|
+
|
|
16
|
+
1. 验证用户在交易本身的签名。
|
|
17
|
+
2. 根据交易哈希验证标头中 Gas 支付方的签名。
|
|
18
|
+
|
|
19
|
+
如果两个签名都有效,交易将在用户的授权下执行,但相应的 Gas 费将从 Gas 支付方的账户余额中扣除。
|
|
20
|
+
|
|
21
|
+
### 工作流图
|
|
22
|
+
|
|
23
|
+
下图说明了从交易发起 Gas 费支付到执行的整个流程:
|
|
24
|
+
|
|
25
|
+
```d2 Gas 费支付工作流 icon=mdi:gas-station
|
|
26
|
+
direction: down
|
|
27
|
+
|
|
28
|
+
User-App: {
|
|
29
|
+
label: "用户应用"
|
|
30
|
+
shape: rectangle
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Gas-Payer-Wallet: {
|
|
34
|
+
label: "Gas 支付方钱包\n(应用后端钱包)"
|
|
35
|
+
shape: cylinder
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
OCAP-Client: {
|
|
39
|
+
label: "OCAP Client 实例"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
Blockchain-Node: {
|
|
43
|
+
label: "区块链节点"
|
|
44
|
+
shape: rectangle
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
User-App -> OCAP-Client: "1. 用户发起交易"
|
|
48
|
+
OCAP-Client -> OCAP-Client: "2. 使用用户钱包准备\n并签署交易"
|
|
49
|
+
Gas-Payer-Wallet -> OCAP-Client: "3. 为 Gas 签署交易哈希"
|
|
50
|
+
OCAP-Client -> Blockchain-Node: "4. 发送交易 + Gas 支付方标头"
|
|
51
|
+
Blockchain-Node -> Blockchain-Node: "5. 验证双方签名"
|
|
52
|
+
Blockchain-Node: "6. 执行交易"
|
|
53
|
+
Blockchain-Node -> Gas-Payer-Wallet: "7. 扣除 Gas 费"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 使用示例
|
|
57
|
+
|
|
58
|
+
要启用免 Gas 交易,您只需为代付账户创建一个钱包实例,并使用 `setGasPayer` 方法在客户端上进行设置。
|
|
59
|
+
|
|
60
|
+
```javascript Gas 支付方设置和使用 icon=logos:javascript
|
|
61
|
+
import Client from '@ocap/client';
|
|
62
|
+
import Wallet, { fromRandom } from '@ocap/wallet';
|
|
63
|
+
|
|
64
|
+
// 1. 初始化客户端以连接到 Beta 链
|
|
65
|
+
const client = new Client('https://beta.abtnetwork.io/api');
|
|
66
|
+
|
|
67
|
+
// 2. 为 Gas 支付方(您的应用钱包)创建一个钱包
|
|
68
|
+
// 此钱包必须有足够数量的原生代币(TBA)来支付交易费用。
|
|
69
|
+
// 您可以从水龙头获取测试代币:https://faucet.abtnetwork.io/
|
|
70
|
+
const gasPayerWallet = Wallet.fromJSON({
|
|
71
|
+
sk: '...your_sponsor_secret_key...',
|
|
72
|
+
pk: '...your_sponsor_public_key...',
|
|
73
|
+
address: '...your_sponsor_address...',
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// 3. 在客户端实例上设置 Gas 支付方
|
|
77
|
+
client.setGasPayer(gasPayerWallet);
|
|
78
|
+
|
|
79
|
+
// 4. 为最终用户创建一个钱包。
|
|
80
|
+
const userWallet = fromRandom();
|
|
81
|
+
|
|
82
|
+
// 5. 使用用户的钱包发送一笔交易。
|
|
83
|
+
// 该交易由用户签名,但 Gas 费由 gasPayerWallet 支付。
|
|
84
|
+
async function performGaslessTransaction() {
|
|
85
|
+
try {
|
|
86
|
+
// 注意:虽然新账户在收到第一笔入账交易时会在链上创建,
|
|
87
|
+
// 但它必须在链上存在才能 *发送* 交易。
|
|
88
|
+
// 您可以通过从水龙头向其发送少量代币来初始化它。
|
|
89
|
+
|
|
90
|
+
const receiverAddress = 'z1...'; // 一个有效的接收地址
|
|
91
|
+
const hash = await client.transfer({
|
|
92
|
+
to: receiverAddress,
|
|
93
|
+
tokens: [{ value: '0.1' }], // 发送 0.1 TBA
|
|
94
|
+
wallet: userWallet,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
console.log('免 Gas 交易成功。哈希:', hash);
|
|
98
|
+
console.log(`在浏览器中查看: https://beta.abtnetwork.io/explorer/txs/${hash}`);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error('交易失败:', error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
performGaslessTransaction();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
在此示例中,即使 `userWallet` 的原生代币余额为零,它也可以成功发送交易,因为 `gasPayerWallet` 支付了费用。这创造了一种无摩擦的体验,特别是对于加入您应用的新用户。
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
要了解交易从创建到最终确认的完整过程,请参阅 [交易生命周期](./core-concepts-transaction-lifecycle.md) 文档。
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Transaction Lifecycle
|
|
2
|
+
|
|
3
|
+
Every action that modifies the state of the blockchain, such as transferring tokens or creating an asset, is executed through a transaction. Understanding the lifecycle of a transaction is fundamental to building applications with the OCAP Client. This process involves four main stages: Preparation, Encoding, Signing, and Sending.
|
|
4
|
+
|
|
5
|
+
The OCAP Client provides a flexible set of methods that allow you to either perform these steps individually for maximum control or use high-level helpers that combine them for convenience.
|
|
6
|
+
|
|
7
|
+
This guide breaks down each stage and illustrates both single-signature and multi-signature workflows.
|
|
8
|
+
|
|
9
|
+
## Lifecycle Overview
|
|
10
|
+
|
|
11
|
+
The following diagram illustrates the complete journey of a transaction from preparation to its final submission to the blockchain.
|
|
12
|
+
|
|
13
|
+
```d2 Transaction Lifecycle Diagram
|
|
14
|
+
direction: down
|
|
15
|
+
|
|
16
|
+
Start: {
|
|
17
|
+
label: "1. Prepare Itx"
|
|
18
|
+
shape: oval
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
Encode-Tx: {
|
|
22
|
+
label: "2. Encode Transaction\n(encode<Type>Tx)"
|
|
23
|
+
shape: rectangle
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
Sign-Tx: {
|
|
27
|
+
label: "3. Sign Transaction"
|
|
28
|
+
shape: diamond
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Single-Sign: {
|
|
32
|
+
label: "Single Signature\n(sign<Type>Tx)"
|
|
33
|
+
shape: rectangle
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
Multi-Sign-Flow: {
|
|
37
|
+
label: "Multi-Signature"
|
|
38
|
+
shape: rectangle
|
|
39
|
+
|
|
40
|
+
Multi-Sign-1: {
|
|
41
|
+
label: "Signer 1\n(multiSign<Type>Tx)"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Multi-Sign-2: {
|
|
45
|
+
label: "Signer 2\n(multiSign<Type>Tx)"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Multi-Sign-N: {
|
|
49
|
+
label: "..."
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Multi-Sign-1 -> Multi-Sign-2: "Pass signed TX"
|
|
53
|
+
Multi-Sign-2 -> Multi-Sign-N: "Pass signed TX"
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Send-Tx: {
|
|
57
|
+
label: "4. Send Transaction\n(send<Type>Tx)"
|
|
58
|
+
shape: rectangle
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
End: {
|
|
62
|
+
label: "Transaction Hash"
|
|
63
|
+
shape: oval
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
Start -> Encode-Tx
|
|
67
|
+
Encode-Tx -> Sign-Tx
|
|
68
|
+
Sign-Tx -> Single-Sign: "Single Signer"
|
|
69
|
+
Sign-Tx -> Multi-Sign-Flow: "Multiple Signers"
|
|
70
|
+
Single-Sign -> Send-Tx
|
|
71
|
+
Multi-Sign-Flow -> Send-Tx
|
|
72
|
+
Send-Tx -> End
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Stage 1: Preparation (Creating the `itx`)
|
|
76
|
+
|
|
77
|
+
Every transaction begins with an `itx` (inner transaction). This is a plain JavaScript object that contains the specific data for the action you want to perform. For example, a transfer `itx` would include the recipient's address and the amount.
|
|
78
|
+
|
|
79
|
+
```javascript Preparing the itx icon=logos:javascript
|
|
80
|
+
// The core data for our transfer transaction
|
|
81
|
+
const itx = {
|
|
82
|
+
to: 'z2C8j81aL2oXpA5t42s2h4g9o8p1k6m3n7b', // Recipient's address
|
|
83
|
+
value: await client.fromTokenToUnit(10), // Amount to send, converted to the chain's base unit
|
|
84
|
+
};
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Stage 2: Encoding
|
|
88
|
+
|
|
89
|
+
Encoding transforms the `itx` and other metadata into a standardized, binary format that can be cryptographically signed. The client provides an `encode{TxType}Tx` method for each transaction type (e.g., `encodeTransferV2Tx`).
|
|
90
|
+
|
|
91
|
+
During this stage, the client automatically adds essential metadata:
|
|
92
|
+
|
|
93
|
+
* **`from`**: The sender's address, derived from the provided wallet.
|
|
94
|
+
* **`chainId`**: The identifier of the target blockchain, fetched automatically.
|
|
95
|
+
* **`nonce`**: A unique number to prevent replay attacks, which defaults to the current timestamp (`Date.now()`).
|
|
96
|
+
* **`pk`**: The public key of the sender's wallet.
|
|
97
|
+
|
|
98
|
+
The encoding function returns both the full transaction object and a `Buffer` of the serialized data, which is used for signing.
|
|
99
|
+
|
|
100
|
+
```javascript Encoding the Transaction icon=logos:javascript
|
|
101
|
+
const { object: encodedTx, buffer: txBuffer } = await client.encodeTransferV2Tx({
|
|
102
|
+
tx: { itx },
|
|
103
|
+
wallet: senderWallet,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
console.log('Encoded TX Object:', encodedTx);
|
|
107
|
+
console.log('Buffer to be signed:', txBuffer);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Stage 3: Signing
|
|
111
|
+
|
|
112
|
+
Signing proves ownership of the account and authorizes the transaction. The process differs for single-signature and multi-signature workflows.
|
|
113
|
+
|
|
114
|
+
### Single-Signature Workflow
|
|
115
|
+
|
|
116
|
+
This is the most common scenario, where a single user signs a transaction. The `sign{TxType}Tx` methods take the encoded transaction, sign the binary buffer with the user's private key, and populate the `signature` field.
|
|
117
|
+
|
|
118
|
+
```javascript Signing with a Single Signature icon=logos:javascript
|
|
119
|
+
const signedTx = await client.signTransferV2Tx({
|
|
120
|
+
tx: encodedTx, // The object from the encoding step
|
|
121
|
+
wallet: senderWallet,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
console.log('Signature:', signedTx.signature);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Multi-Signature Workflow
|
|
128
|
+
|
|
129
|
+
Multi-signature (multisig) transactions require approval from multiple parties. This is commonly used for atomic swaps or shared accounts. The process is sequential:
|
|
130
|
+
|
|
131
|
+
1. **Preparation**: The initial transaction is created with a `signaturesList` that defines all required signers.
|
|
132
|
+
2. **Sequential Signing**: The transaction is passed from one signer to the next. Each signer uses the corresponding `multiSign{TxType}Tx` method to add their signature.
|
|
133
|
+
|
|
134
|
+
Internally, the `multiSign` method ensures that each party signs the exact same transaction digest by temporarily stripping all existing signatures before encoding the transaction for signing.
|
|
135
|
+
|
|
136
|
+
Here’s an example for an `ExchangeTx`, where two parties swap assets.
|
|
137
|
+
|
|
138
|
+
```javascript Multi-Signature Signing Example icon=logos:javascript
|
|
139
|
+
// Step 1: Alice (the offerer) prepares and signs the exchange transaction.
|
|
140
|
+
const txFromAlice = await client.prepareExchange({
|
|
141
|
+
offerToken: 10,
|
|
142
|
+
demandToken: 20,
|
|
143
|
+
receiver: bobWallet.address,
|
|
144
|
+
wallet: aliceWallet,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Step 2: The transaction is sent to Bob.
|
|
148
|
+
// Bob (the demander) adds his signature to finalize it.
|
|
149
|
+
const txFromBob = await client.finalizeExchange({
|
|
150
|
+
tx: txFromAlice, // Transaction signed by Alice
|
|
151
|
+
wallet: bobWallet,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
console.log('Alice\'s Signature:', txFromBob.signaturesList[0].signature);
|
|
155
|
+
console.log('Bob\'s Signature:', txFromBob.signaturesList[1].signature);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Stage 4: Sending
|
|
159
|
+
|
|
160
|
+
Once a transaction is fully signed, it can be sent to the blockchain node for processing. The `send{TxType}Tx` methods handle this final step.
|
|
161
|
+
|
|
162
|
+
For convenience, these methods can also perform the signing step implicitly if you provide a wallet and an unsigned transaction. The method returns a promise that resolves with the transaction hash upon successful submission.
|
|
163
|
+
|
|
164
|
+
```javascript Sending the Signed Transaction icon=logos:javascript
|
|
165
|
+
// Using a pre-signed transaction
|
|
166
|
+
const hash = await client.sendTransferV2Tx({ tx: signedTx, wallet: senderWallet });
|
|
167
|
+
|
|
168
|
+
// Or, letting the send method handle the signing automatically
|
|
169
|
+
const hash2 = await client.sendTransferV2Tx({
|
|
170
|
+
tx: { itx }, // Just the inner transaction
|
|
171
|
+
wallet: senderWallet,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
console.log('Transaction sent! Hash:', hash);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
You can also include a `commit: true` option to make the client wait until the transaction is fully confirmed and included in a block before resolving the promise.
|
|
178
|
+
|
|
179
|
+
## Summary
|
|
180
|
+
|
|
181
|
+
The transaction lifecycle provides a robust and flexible framework for interacting with the blockchain. By breaking the process into distinct stages—Preparation, Encoding, Signing, and Sending—the OCAP Client offers developers granular control over transaction creation while also providing simple, high-level helpers for common use cases.
|
|
182
|
+
|
|
183
|
+
For more details on how transaction fees are handled, see the [Gas Payment](./core-concepts-gas-payment.md) guide. To understand the different client types available, refer to the [Client Architecture](./core-concepts-client-architecture.md) documentation.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# 交易生命周期
|
|
2
|
+
|
|
3
|
+
每一个修改区块链状态的操作,例如转移通证或创建资产,都是通过交易来执行的。理解交易的生命周期是使用 OCAP Client 构建应用程序的基础。该过程涉及四个主要阶段:准备、编码、签名和发送。
|
|
4
|
+
|
|
5
|
+
OCAP Client 提供了一套灵活的方法,允许您单独执行这些步骤以实现最大程度的控制,或者使用高级辅助函数将它们组合起来以方便使用。
|
|
6
|
+
|
|
7
|
+
本指南将分解每个阶段,并说明单签名和多重签名工作流。
|
|
8
|
+
|
|
9
|
+
## 生命周期概述
|
|
10
|
+
|
|
11
|
+
下图说明了交易从准备到最终提交至区块链的完整过程。
|
|
12
|
+
|
|
13
|
+
```d2 交易生命周期图
|
|
14
|
+
direction: down
|
|
15
|
+
|
|
16
|
+
Start: {
|
|
17
|
+
label: "1. 准备 Itx"
|
|
18
|
+
shape: oval
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
Encode-Tx: {
|
|
22
|
+
label: "2. 编码交易\n(encode<Type>Tx)"
|
|
23
|
+
shape: rectangle
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
Sign-Tx: {
|
|
27
|
+
label: "3. 签署交易"
|
|
28
|
+
shape: diamond
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Single-Sign: {
|
|
32
|
+
label: "单一签名\n(sign<Type>Tx)"
|
|
33
|
+
shape: rectangle
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
Multi-Sign-Flow: {
|
|
37
|
+
label: "多重签名"
|
|
38
|
+
shape: rectangle
|
|
39
|
+
|
|
40
|
+
Multi-Sign-1: {
|
|
41
|
+
label: "签名者 1\n(multiSign<Type>Tx)"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Multi-Sign-2: {
|
|
45
|
+
label: "签名者 2\n(multiSign<Type>Tx)"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Multi-Sign-N: {
|
|
49
|
+
label: "..."
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Multi-Sign-1 -> Multi-Sign-2: "传递已签名的交易"
|
|
53
|
+
Multi-Sign-2 -> Multi-Sign-N: "传递已签名的交易"
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Send-Tx: {
|
|
57
|
+
label: "4. 发送交易\n(send<Type>Tx)"
|
|
58
|
+
shape: rectangle
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
End: {
|
|
62
|
+
label: "交易哈希"
|
|
63
|
+
shape: oval
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
Start -> Encode-Tx
|
|
67
|
+
Encode-Tx -> Sign-Tx
|
|
68
|
+
Sign-Tx -> Single-Sign: "单一签名者"
|
|
69
|
+
Sign-Tx -> Multi-Sign-Flow: "多个签名者"
|
|
70
|
+
Single-Sign -> Send-Tx
|
|
71
|
+
Multi-Sign-Flow -> Send-Tx
|
|
72
|
+
Send-Tx -> End
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 阶段 1:准备(创建 `itx`)
|
|
76
|
+
|
|
77
|
+
每笔交易都始于一个 `itx`(内部交易)。这是一个纯粹的 JavaScript 对象,包含了您想要执行的操作的具体数据。例如,一笔转账 `itx` 会包含接收者的地址和金额。
|
|
78
|
+
|
|
79
|
+
```javascript 准备 itx icon=logos:javascript
|
|
80
|
+
// 我们转账交易的核心数据
|
|
81
|
+
const itx = {
|
|
82
|
+
to: 'z2C8j81aL2oXpA5t42s2h4g9o8p1k6m3n7b', // 接收者地址
|
|
83
|
+
value: await client.fromTokenToUnit(10), // 发送的金额,已转换为链的基本单位
|
|
84
|
+
};
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 阶段 2:编码
|
|
88
|
+
|
|
89
|
+
编码将 `itx` 和其他元数据转换为一个标准化的二进制格式,以便进行加密签名。客户端为每种交易类型提供了一个 `encode{TxType}Tx` 方法(例如,`encodeTransferV2Tx`)。
|
|
90
|
+
|
|
91
|
+
在此阶段,客户端会自动添加必要的元数据:
|
|
92
|
+
|
|
93
|
+
* **`from`**:发送者的地址,从提供的钱包中派生。
|
|
94
|
+
* **`chainId`**:目标区块链的标识符,自动获取。
|
|
95
|
+
* **`nonce`**:一个唯一的数字,用于防止重放攻击,默认为当前时间戳(`Date.now()`)。
|
|
96
|
+
* **`pk`**:发送者钱包的公钥。
|
|
97
|
+
|
|
98
|
+
编码函数会返回完整的交易对象和一个序列化数据的 `Buffer`,后者用于签名。
|
|
99
|
+
|
|
100
|
+
```javascript 编码交易 icon=logos:javascript
|
|
101
|
+
const { object: encodedTx, buffer: txBuffer } = await client.encodeTransferV2Tx({
|
|
102
|
+
tx: { itx },
|
|
103
|
+
wallet: senderWallet,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
console.log('编码后的交易对象:', encodedTx);
|
|
107
|
+
console.log('待签名的 Buffer:', txBuffer);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 阶段 3:签名
|
|
111
|
+
|
|
112
|
+
签名证明了账户的所有权并授权了该交易。对于单签名和多重签名工作流,此过程有所不同。
|
|
113
|
+
|
|
114
|
+
### 单签名工作流
|
|
115
|
+
|
|
116
|
+
这是最常见的场景,即单个用户签署一笔交易。`sign{TxType}Tx` 方法接收编码后的交易,使用用户的私钥对二进制缓冲区进行签名,并填充 `signature` 字段。
|
|
117
|
+
|
|
118
|
+
```javascript 使用单一签名进行签名 icon=logos:javascript
|
|
119
|
+
const signedTx = await client.signTransferV2Tx({
|
|
120
|
+
tx: encodedTx, // 编码步骤中生成的对象
|
|
121
|
+
wallet: senderWallet,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
console.log('签名:', signedTx.signature);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 多重签名工作流
|
|
128
|
+
|
|
129
|
+
多重签名(multisig)交易需要多方批准。这通常用于原子交换或共享账户。该过程是顺序的:
|
|
130
|
+
|
|
131
|
+
1. **准备**:创建初始交易时,带有一个 `signaturesList`,其中定义了所有必需的签名者。
|
|
132
|
+
2. **顺序签名**:交易从一个签名者传递到下一个。每个签名者使用相应的 `multiSign{TxType}Tx` 方法添加自己的签名。
|
|
133
|
+
|
|
134
|
+
在内部,`multiSign` 方法通过在编码交易以供签名之前临时剥离所有现有签名,来确保各方签署完全相同的交易摘要。
|
|
135
|
+
|
|
136
|
+
以下是一个 `ExchangeTx` 的示例,其中两方交换资产。
|
|
137
|
+
|
|
138
|
+
```javascript 多重签名示例 icon=logos:javascript
|
|
139
|
+
// 步骤 1:Alice(要约方)准备并签署交换交易。
|
|
140
|
+
const txFromAlice = await client.prepareExchange({
|
|
141
|
+
offerToken: 10,
|
|
142
|
+
demandToken: 20,
|
|
143
|
+
receiver: bobWallet.address,
|
|
144
|
+
wallet: aliceWallet,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// 步骤 2:将交易发送给 Bob。
|
|
148
|
+
// Bob(请求方)添加他的签名以最终完成交易。
|
|
149
|
+
const txFromBob = await client.finalizeExchange({
|
|
150
|
+
tx: txFromAlice, // 由 Alice 签署的交易
|
|
151
|
+
wallet: bobWallet,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
console.log('Alice 的签名:', txFromBob.signaturesList[0].signature);
|
|
155
|
+
console.log('Bob 的签名:', txFromBob.signaturesList[1].signature);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## 阶段 4:发送
|
|
159
|
+
|
|
160
|
+
一旦交易完全签名,就可以将其发送到区块链节点进行处理。`send{TxType}Tx` 方法处理这最后一步。
|
|
161
|
+
|
|
162
|
+
为方便起见,如果您提供一个钱包和一个未签名的交易,这些方法也可以隐式执行签名步骤。该方法返回一个 promise,在成功提交后,该 promise 会解析为交易哈希。
|
|
163
|
+
|
|
164
|
+
```javascript 发送已签名的交易 icon=logos:javascript
|
|
165
|
+
// 使用预先签署的交易
|
|
166
|
+
const hash = await client.sendTransferV2Tx({ tx: signedTx, wallet: senderWallet });
|
|
167
|
+
|
|
168
|
+
// 或者,让发送方法自动处理签名
|
|
169
|
+
const hash2 = await client.sendTransferV2Tx({
|
|
170
|
+
tx: { itx }, // 仅内部交易
|
|
171
|
+
wallet: senderWallet,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
console.log('交易已发送!哈希:', hash);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
您还可以包含一个 `commit: true` 选项,使客户端等待交易完全确认并被包含在一个区块中后,再解析该 promise。
|
|
178
|
+
|
|
179
|
+
## 总结
|
|
180
|
+
|
|
181
|
+
交易生命周期为与区块链交互提供了一个健壮而灵活的框架。通过将过程分解为不同的阶段——准备、编码、签名和发送——OCAP Client 为开发者提供了对交易创建的精细控制,同时也为常见用例提供了简单的高级辅助函数。
|
|
182
|
+
|
|
183
|
+
有关交易费用处理的更多详细信息,请参阅 [Gas 支付](./core-concepts-gas-payment.md)指南。要了解可用的不同客户端类型,请参阅 [客户端架构](./core-concepts-client-architecture.md) 文档。
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Core Concepts
|
|
2
|
+
|
|
3
|
+
This section dives into the fundamental principles and architectural decisions that shape the OCAP Client library. Understanding these core concepts will help you leverage the library's full potential, write more efficient code, and troubleshoot issues more effectively.
|
|
4
|
+
|
|
5
|
+
While the [How-to Guides](./how-to-guides.md) provide step-by-step instructions for specific tasks, this section explains the "why" behind the "how." We'll explore the client's structure, how transactions are processed from start to finish, how to listen for real-time events, and how to create gasless user experiences.
|
|
6
|
+
|
|
7
|
+
<x-cards data-columns="2">
|
|
8
|
+
<x-card data-title="Client Architecture" data-icon="lucide:architecture" data-href="/core-concepts/client-architecture">
|
|
9
|
+
Learn about the different client implementations (Node, Browser, Lite) and how to choose the right one for your environment to optimize performance and bundle size.
|
|
10
|
+
</x-card>
|
|
11
|
+
<x-card data-title="Transaction Lifecycle" data-icon="lucide:refresh-cw" data-href="/core-concepts/transaction-lifecycle">
|
|
12
|
+
Follow a transaction's journey from a simple JavaScript object to a confirmed block on the chain, covering creation, encoding, signing, and broadcasting.
|
|
13
|
+
</x-card>
|
|
14
|
+
<x-card data-title="Event Subscriptions" data-icon="lucide:radio-tower" data-href="/core-concepts/event-subscriptions">
|
|
15
|
+
Discover how to use the WebSocket-based subscription feature to listen for real-time on-chain events, enabling dynamic and responsive applications.
|
|
16
|
+
</x-card>
|
|
17
|
+
<x-card data-title="Gas Payment" data-icon="lucide:gas-pump" data-href="/core-concepts/gas-payment">
|
|
18
|
+
Explore the powerful gas payment feature, which allows a designated wallet to sponsor transaction fees for users, creating seamless, gasless experiences.
|
|
19
|
+
</x-card>
|
|
20
|
+
</x-cards>
|
|
21
|
+
|
|
22
|
+
By grasping these foundational topics, you'll be well-equipped to build robust, scalable, and user-friendly applications using the OCAP Client.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# 核心概念
|
|
2
|
+
|
|
3
|
+
本节深入探讨了构成 OCAP Client 库的基本原则和架构决策。理解这些核心概念将帮助您充分利用该库的全部潜力,编写更高效的代码,并更有效地解决问题。
|
|
4
|
+
|
|
5
|
+
[操作指南](./how-to-guides.md) 提供了特定任务的分步说明,而本节则解释了“如何做”背后的“为什么”。我们将探讨客户端的结构、交易从开始到结束的处理过程、如何监听实时事件以及如何创建无 Gas 费用的用户体验。
|
|
6
|
+
|
|
7
|
+
<x-cards data-columns="2">
|
|
8
|
+
<x-card data-title="客户端架构" data-icon="lucide:architecture" data-href="/core-concepts/client-architecture">
|
|
9
|
+
了解不同的客户端实现(Node、Browser、Lite),以及如何为您的环境选择合适的实现以优化性能和包大小。
|
|
10
|
+
</x-card>
|
|
11
|
+
<x-card data-title="交易生命周期" data-icon="lucide:refresh-cw" data-href="/core-concepts/transaction-lifecycle">
|
|
12
|
+
追踪一笔交易从一个简单的 JavaScript 对象到链上确认区块的全过程,涵盖创建、编码、签名和广播。
|
|
13
|
+
</x-card>
|
|
14
|
+
<x-card data-title="事件订阅" data-icon="lucide:radio-tower" data-href="/core-concepts/event-subscriptions">
|
|
15
|
+
了解如何使用基于 WebSocket 的订阅功能来监听实时链上事件,从而实现动态和响应迅速的应用程序。
|
|
16
|
+
</x-card>
|
|
17
|
+
<x-card data-title="Gas 费支付" data-icon="lucide:gas-pump" data-href="/core-concepts/gas-payment">
|
|
18
|
+
探索强大的 Gas 费支付功能,该功能允许指定钱包为用户代付交易费用,从而创造无缝、无 Gas 费用的体验。
|
|
19
|
+
</x-card>
|
|
20
|
+
</x-cards>
|
|
21
|
+
|
|
22
|
+
通过掌握这些基础主题,您将能够使用 OCAP Client 构建强大、可扩展且用户友好的应用程序。
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Basic Usage
|
|
2
|
+
|
|
3
|
+
This guide will walk you through the essential steps to get started with the OCAP Client. You'll learn how to initialize the client, connect to the ArcBlock Beta Chain, and perform a basic query to ensure everything is set up correctly.
|
|
4
|
+
|
|
5
|
+
Following this guide, you should have a working client instance ready to interact with the blockchain in just a few minutes.
|
|
6
|
+
|
|
7
|
+
## 1. Initialize the Client
|
|
8
|
+
|
|
9
|
+
First, you need to import the `@ocap/client` package and create an instance of `GraphQLClient`. The constructor takes the GraphQL endpoint of the blockchain node you want to connect to. For this guide, we will use the public endpoint for the ArcBlock Beta Chain.
|
|
10
|
+
|
|
11
|
+
```javascript Initialize Client icon=logos:javascript
|
|
12
|
+
const GraphQLClient = require('@ocap/client');
|
|
13
|
+
|
|
14
|
+
// Connect to the Beta Chain
|
|
15
|
+
const client = new GraphQLClient('https://beta.abtnetwork.io/api');
|
|
16
|
+
|
|
17
|
+
console.log('OCAP Client initialized!');
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
This creates a client instance that is pre-configured with methods for querying the chain, sending transactions, and more.
|
|
21
|
+
|
|
22
|
+
## 2. Query the Blockchain
|
|
23
|
+
|
|
24
|
+
Now that the client is initialized, you can perform a simple read-only operation to verify the connection. The `getChainInfo` method is perfect for this, as it fetches basic information about the connected blockchain and doesn't require any authentication.
|
|
25
|
+
|
|
26
|
+
```javascript Query Chain Info icon=logos:javascript
|
|
27
|
+
(async () => {
|
|
28
|
+
try {
|
|
29
|
+
const { info } = await client.getChainInfo();
|
|
30
|
+
console.log('Chain Info:', info);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('Failed to get chain info:', error);
|
|
33
|
+
}
|
|
34
|
+
})();
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
If the request is successful, the `info` object will be logged to the console, containing details about the chain such as its ID, network, and supported transaction types. This confirms your client is successfully communicating with the blockchain node.
|
|
38
|
+
|
|
39
|
+
## 3. Prepare an Account
|
|
40
|
+
|
|
41
|
+
To send transactions (write operations), you need a wallet. You can generate a new wallet locally. This wallet represents your on-chain account identity.
|
|
42
|
+
|
|
43
|
+
```javascript Create a Wallet icon=logos:javascript
|
|
44
|
+
const { fromRandom } = require('@ocap/wallet');
|
|
45
|
+
|
|
46
|
+
// Create a new random wallet
|
|
47
|
+
const wallet = fromRandom();
|
|
48
|
+
|
|
49
|
+
console.log('New wallet created:');
|
|
50
|
+
console.log('Address:', wallet.address);
|
|
51
|
+
console.log('PublicKey:', wallet.publicKey);
|
|
52
|
+
console.log('SecretKey:', wallet.secretKey);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Important:** A newly generated wallet is just a key pair. It does not exist on the blockchain yet. An account is automatically created on-chain when its address receives its first incoming transaction.
|
|
56
|
+
|
|
57
|
+
To make your new account active, you need to fund it with some test tokens. You can get free test tokens (`TBA`) for the Beta Chain from the official faucet:
|
|
58
|
+
|
|
59
|
+
<x-card data-title="ArcBlock Faucet" data-icon="lucide:droplet" data-href="https://faucet.abtnetwork.io/" data-cta="Get Test Tokens">
|
|
60
|
+
Visit the faucet and send some TBA to your newly generated address to activate it.
|
|
61
|
+
</x-card>
|
|
62
|
+
|
|
63
|
+
## 4. Query Account State
|
|
64
|
+
|
|
65
|
+
Once you have funded your new account using the faucet, you can query its state to verify the balance.
|
|
66
|
+
|
|
67
|
+
```javascript Query Account State icon=logos:javascript
|
|
68
|
+
(async () => {
|
|
69
|
+
try {
|
|
70
|
+
// Replace with the address you funded from the faucet
|
|
71
|
+
const address = wallet.address;
|
|
72
|
+
|
|
73
|
+
const { state } = await client.getAccountState({ address });
|
|
74
|
+
console.log('Account State:', state);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error('Failed to get account state:', error);
|
|
77
|
+
}
|
|
78
|
+
})();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The `state` object in the response will contain your account's address, balance, nonce (number of transactions sent), and other details. Seeing a non-zero balance confirms that your account has received the tokens from the faucet and is now active on the blockchain.
|
|
82
|
+
|
|
83
|
+
## Next Steps
|
|
84
|
+
|
|
85
|
+
You have successfully set up the OCAP Client, connected to the blockchain, and verified your account. You are now ready to explore more advanced operations.
|
|
86
|
+
|
|
87
|
+
Check out the [How-to Guides](./how-to-guides.md) to learn how to perform common tasks like transferring tokens, managing assets, and more.
|