@ocap/client 1.25.2 → 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,205 @@
|
|
|
1
|
+
# 质押通证和资产
|
|
2
|
+
|
|
3
|
+
质押是将通证或资产 (NFT) 锁定到特定接收者的过程,通常是为了保护网络、参与治理或赚取奖励。本指南使用 OCAP Client 提供了整个质押生命周期的分步演练,包括创建质押、撤销质押、领回资产以及因惩罚性原因罚没质押。
|
|
4
|
+
|
|
5
|
+
此过程涉及几个关键方法:
|
|
6
|
+
- `stake()`:创建一个新的质押。
|
|
7
|
+
- `revokeStake()`:启动撤回已质押物品的过程。
|
|
8
|
+
- `claimStake()`:完成撤回并将物品返还到您的账户。
|
|
9
|
+
- `slashStake()`:允许授权方惩罚质押者。
|
|
10
|
+
|
|
11
|
+
## 如何质押
|
|
12
|
+
|
|
13
|
+
首先,您使用 `stake` 方法来锁定您的通证或资产。此操作会在链上创建一个新的、唯一的质押地址,该地址持有您质押的物品及管理它们的规则。
|
|
14
|
+
|
|
15
|
+
### 参数
|
|
16
|
+
|
|
17
|
+
<x-field-group>
|
|
18
|
+
<x-field data-name="to" data-type="string" data-required="true" data-desc="将接收质押的账户的 DID 地址。"></x-field>
|
|
19
|
+
<x-field data-name="assets" data-type="string[]" data-required="false" data-desc="要质押的资产地址 (NFT) 数组。"></x-field>
|
|
20
|
+
<x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="要质押的通证对象数组。">
|
|
21
|
+
<x-field data-name="address" data-type="string" data-required="true" data-desc="通证合约的地址。"></x-field>
|
|
22
|
+
<x-field data-name="value" data-type="number" data-required="true" data-desc="要质押的通证数量。"></x-field>
|
|
23
|
+
</x-field>
|
|
24
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="质押者的钱包对象。"></x-field>
|
|
25
|
+
<x-field data-name="locked" data-type="boolean" data-default="false" data-required="false" data-desc="一个布尔值,指示质押在创建时是否被锁定。"></x-field>
|
|
26
|
+
<x-field data-name="slashers" data-type="string[]" data-required="false" data-desc="允许罚没此质押的 DID 地址数组。如果未提供,则默认为接收者地址。"></x-field>
|
|
27
|
+
<x-field data-name="message" data-type="string" data-required="false" data-desc="质押的可选备注或消息。"></x-field>
|
|
28
|
+
<x-field data-name="nonce" data-type="string" data-required="false" data-desc="一个可选的 nonce,以确保质押地址是唯一的。"></x-field>
|
|
29
|
+
</x-field-group>
|
|
30
|
+
|
|
31
|
+
### 示例
|
|
32
|
+
|
|
33
|
+
```javascript 质押通证和资产 icon=logos:javascript
|
|
34
|
+
// 假设 'client' 是一个已初始化的 GraphQLClient 实例
|
|
35
|
+
// 并且 'stakerWallet' 是一个有效的钱包对象。
|
|
36
|
+
const receiverAddress = 'z29d5852576b8a8b6f3a8b4b74a3f4a3e2e1d'; // 质押接收者的地址
|
|
37
|
+
|
|
38
|
+
async function createStake() {
|
|
39
|
+
try {
|
|
40
|
+
const [txHash, stakeAddress] = await client.stake({
|
|
41
|
+
to: receiverAddress,
|
|
42
|
+
tokens: [{
|
|
43
|
+
address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E', // 要质押的通证地址
|
|
44
|
+
value: 100, // 要质押的通证数量
|
|
45
|
+
}],
|
|
46
|
+
assets: ['zNKtA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6'], // 要质押的资产/NFT 地址
|
|
47
|
+
message: '为验证者奖励而质押',
|
|
48
|
+
wallet: stakerWallet,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log('质押交易已发送:', txHash);
|
|
52
|
+
console.log('新的质押地址已创建:', stakeAddress);
|
|
53
|
+
return stakeAddress;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error('创建质押时出错:', error);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 返回值
|
|
61
|
+
|
|
62
|
+
`stake` 方法返回一个包含交易哈希和新创建的 `stakeAddress` 的元组。此地址对于未来与此特定质押的所有交互(例如撤销或罚没)都至关重要。
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 如何撤销质押
|
|
67
|
+
|
|
68
|
+
撤销质押是质押者为取回其锁定的通证和资产而发起的过程。此交易不会立即返还资金;相反,它会将资金标记为可领取,但需遵守任何链上锁定期。
|
|
69
|
+
|
|
70
|
+
### 参数
|
|
71
|
+
|
|
72
|
+
<x-field-group>
|
|
73
|
+
<x-field data-name="from" data-type="string" data-required="true" data-desc="要撤销的质押地址(从 'stake' 调用中获取)。"></x-field>
|
|
74
|
+
<x-field data-name="assets" data-type="string[]" data-required="false" data-desc="要从质押中撤销的资产地址数组。"></x-field>
|
|
75
|
+
<x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="要撤销的通证对象数组。">
|
|
76
|
+
<x-field data-name="address" data-type="string" data-required="true" data-desc="通证合约的地址。"></x-field>
|
|
77
|
+
<x-field data-name="value" data-type="number" data-required="true" data-desc="要撤销的通证数量。"></x-field>
|
|
78
|
+
</x-field>
|
|
79
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="质押者的钱包对象,必须是质押的原始创建者。"></x-field>
|
|
80
|
+
</x-field-group>
|
|
81
|
+
|
|
82
|
+
### 示例
|
|
83
|
+
|
|
84
|
+
```javascript 撤销质押 icon=logos:javascript
|
|
85
|
+
// 假设 'stakeAddress' 是上一步返回的地址
|
|
86
|
+
// 并且 'stakerWallet' 是用于创建质押的同一个钱包。
|
|
87
|
+
|
|
88
|
+
async function revokeExistingStake(stakeAddress) {
|
|
89
|
+
try {
|
|
90
|
+
const revokeTxHash = await client.revokeStake({
|
|
91
|
+
from: stakeAddress,
|
|
92
|
+
tokens: [{
|
|
93
|
+
address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E',
|
|
94
|
+
value: 100,
|
|
95
|
+
}],
|
|
96
|
+
assets: ['zNKtA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6'],
|
|
97
|
+
wallet: stakerWallet,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
console.log('撤销质押交易已发送:', revokeTxHash);
|
|
101
|
+
console.log('重要提示:请保存此哈希值,以便稍后领取您的质押。');
|
|
102
|
+
return revokeTxHash;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error('撤销质押时出错:', error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 返回值
|
|
110
|
+
|
|
111
|
+
此函数返回撤销操作的交易哈希。此哈希作为证据,并且是领取质押的最后一步所**必需**的。
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 如何领取已撤销的质押
|
|
116
|
+
|
|
117
|
+
在质押成功撤销后,质押者必须发送一个 `claimStake` 交易,才能将通证和资产移回其账户。这标志着撤回过程的最终完成。
|
|
118
|
+
|
|
119
|
+
### 参数
|
|
120
|
+
|
|
121
|
+
<x-field-group>
|
|
122
|
+
<x-field data-name="from" data-type="string" data-required="true" data-desc="质押的地址。"></x-field>
|
|
123
|
+
<x-field data-name="evidence" data-type="string" data-required="true" data-desc="来自 'revokeStake' 调用的交易哈希,用作撤销证明。"></x-field>
|
|
124
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="质押者的钱包对象。"></x-field>
|
|
125
|
+
</x-field-group>
|
|
126
|
+
|
|
127
|
+
### 示例
|
|
128
|
+
|
|
129
|
+
```javascript 领取已质押的物品 icon=logos:javascript
|
|
130
|
+
// 假设 'stakeAddress' 和 'revokeTxHash' 来自之前的步骤,
|
|
131
|
+
// 并且 'stakerWallet' 是质押者的钱包。
|
|
132
|
+
|
|
133
|
+
async function claimRevokedStake(stakeAddress, revokeTxHash) {
|
|
134
|
+
try {
|
|
135
|
+
const claimTxHash = await client.claimStake({
|
|
136
|
+
from: stakeAddress,
|
|
137
|
+
evidence: revokeTxHash,
|
|
138
|
+
wallet: stakerWallet,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
console.log('领取质押交易已发送:', claimTxHash);
|
|
142
|
+
console.log('您的通证和资产已返回到您的账户。');
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error('领取质押时出错:', error);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 返回值
|
|
150
|
+
|
|
151
|
+
该方法返回最终的交易哈希。一旦该交易在链上得到确认,质押的物品将返还到 `wallet` 的地址。
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 如何罚没质押
|
|
156
|
+
|
|
157
|
+
罚没是一种惩罚性操作,可由指定的 `slasher`(通常是质押接收者)对质押者采取。这通常发生在质押者违反某些规则的情况下。被罚没的通证或资产将从质押中移除,并发送到指定的保险库。
|
|
158
|
+
|
|
159
|
+
### 参数
|
|
160
|
+
|
|
161
|
+
<x-field-group>
|
|
162
|
+
<x-field data-name="from" data-type="string" data-required="true" data-desc="要被罚没的质押地址。"></x-field>
|
|
163
|
+
<x-field data-name="reason" data-type="string" data-required="true" data-desc="一条强制性消息,解释罚没发生的原因。"></x-field>
|
|
164
|
+
<x-field data-name="assets" data-type="string[]" data-required="false" data-desc="要从质押中罚没的资产地址数组。"></x-field>
|
|
165
|
+
<x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="要罚没的通证对象数组。">
|
|
166
|
+
<x-field data-name="address" data-type="string" data-required="true" data-desc="通证合约的地址。"></x-field>
|
|
167
|
+
<x-field data-name="value" data-type="number" data-required="true" data-desc="要罚没的通证数量。"></x-field>
|
|
168
|
+
</x-field>
|
|
169
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="授权罚没者的钱包对象。"></x-field>
|
|
170
|
+
</x-field-group>
|
|
171
|
+
|
|
172
|
+
### 示例
|
|
173
|
+
|
|
174
|
+
```javascript 罚没质押 icon=logos:javascript
|
|
175
|
+
// 假设 'stakeAddress' 是要被罚没的质押地址,
|
|
176
|
+
// 并且 'slasherWallet' 是授权罚没者的钱包。
|
|
177
|
+
|
|
178
|
+
async function slashExistingStake(stakeAddress) {
|
|
179
|
+
try {
|
|
180
|
+
const slashTxHash = await client.slashStake({
|
|
181
|
+
from: stakeAddress,
|
|
182
|
+
reason: '验证者连续错过 10 个区块的签名。',
|
|
183
|
+
tokens: [{
|
|
184
|
+
address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E',
|
|
185
|
+
value: 10, // 罚没 10 个通证作为惩罚
|
|
186
|
+
}],
|
|
187
|
+
wallet: slasherWallet,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
console.log('罚没质押交易已发送:', slashTxHash);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error('罚没质押时出错:', error);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 返回值
|
|
198
|
+
|
|
199
|
+
此方法返回罚没操作的交易哈希。
|
|
200
|
+
|
|
201
|
+
## 总结
|
|
202
|
+
|
|
203
|
+
现在您已经学习了在 OCAP 区块链上质押的完整生命周期:使用 `stake` 创建质押,使用 `revokeStake` 和 `claimStake` 取回资金,以及使用 `slashStake` 惩罚不良行为者。这个强大的机制是许多去中心化应用的基础。
|
|
204
|
+
|
|
205
|
+
要了解更多关于您可以质押的物品的信息,请参阅[管理通证](./how-to-guides-manage-tokens.md)和[管理资产 (NFT)](./how-to-guides-manage-assets.md)指南。
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Transfer Tokens and NFTs
|
|
2
|
+
|
|
3
|
+
This guide provides a step-by-step walkthrough for transferring fungible tokens (both native and custom) and non-fungible tokens (NFTs or assets) between accounts using the OCAP Client. The primary method for all transfers is `client.transfer()`.
|
|
4
|
+
|
|
5
|
+
One key feature to remember is that a new account is automatically created on-chain when it receives its first incoming transaction. This means you can transfer tokens or assets to a brand new address without any prior setup for the recipient.
|
|
6
|
+
|
|
7
|
+
## The `transfer` Method
|
|
8
|
+
|
|
9
|
+
The `client.transfer()` method is a versatile helper function that simplifies the process of sending assets and tokens. It constructs, signs, and sends the appropriate transaction (`transferV2Tx`) to the blockchain in a single call.
|
|
10
|
+
|
|
11
|
+
### Parameters
|
|
12
|
+
|
|
13
|
+
<x-field-group>
|
|
14
|
+
<x-field data-name="to" data-type="string" data-required="true">
|
|
15
|
+
<x-field-desc markdown>The recipient's account address. This must be a valid DID address.</x-field-desc>
|
|
16
|
+
</x-field>
|
|
17
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The sender's wallet object used to sign the transaction."></x-field>
|
|
18
|
+
<x-field data-name="token" data-type="number" data-default="0">
|
|
19
|
+
<x-field-desc markdown>The amount of the chain's native token to transfer. The client handles the conversion to the correct decimal units automatically.</x-field-desc>
|
|
20
|
+
</x-field>
|
|
21
|
+
<x-field data-name="assets" data-type="string[]" data-default="[]" data-desc="An array of asset addresses (NFTs) to transfer."></x-field>
|
|
22
|
+
<x-field data-name="tokens" data-type="object[]" data-default="[]">
|
|
23
|
+
<x-field-desc markdown>An array of custom fungible token objects to transfer.</x-field-desc>
|
|
24
|
+
<x-field data-name="address" data-type="string" data-required="true" data-desc="The address of the custom token contract."></x-field>
|
|
25
|
+
<x-field data-name="value" data-type="number" data-required="true" data-desc="The amount of the custom token to transfer."></x-field>
|
|
26
|
+
</x-field>
|
|
27
|
+
<x-field data-name="memo" data-type="string" data-required="false" data-desc="An optional message or note to include with the transaction."></x-field>
|
|
28
|
+
<x-field data-name="delegator" data-type="string" data-required="false">
|
|
29
|
+
<x-field-desc markdown>If the `wallet` is acting on behalf of another account, this should be the address of the delegating account. See the [Delegate Permissions](./how-to-guides-delegate-permissions.md) guide for more details.</x-field-desc>
|
|
30
|
+
</x-field>
|
|
31
|
+
</x-field-group>
|
|
32
|
+
|
|
33
|
+
### Returns
|
|
34
|
+
|
|
35
|
+
<x-field data-name="Promise<string>" data-type="Promise">
|
|
36
|
+
<x-field-desc markdown>A Promise that resolves to the transaction hash upon successful submission to the blockchain.</x-field-desc>
|
|
37
|
+
</x-field>
|
|
38
|
+
|
|
39
|
+
## Step-by-Step Examples
|
|
40
|
+
|
|
41
|
+
### Prerequisites
|
|
42
|
+
|
|
43
|
+
Before you start, make sure you have:
|
|
44
|
+
|
|
45
|
+
1. An initialized `GraphQLClient` connected to a chain host like `https://beta.abtnetwork.io`.
|
|
46
|
+
2. A sender's wallet object (`senderWallet`) that is funded with enough tokens to cover the transfer and transaction fees.
|
|
47
|
+
3. A recipient's wallet object (`recipientWallet`) to get their address. The recipient's account does not need to exist on-chain yet.
|
|
48
|
+
|
|
49
|
+
```javascript Basic Setup icon=logos:javascript
|
|
50
|
+
import GraphQLClient from '@ocap/client';
|
|
51
|
+
import { fromRandom } from '@ocap/wallet';
|
|
52
|
+
|
|
53
|
+
// 1. Initialize the client
|
|
54
|
+
const client = new GraphQLClient({ endpoint: 'https://beta.abtnetwork.io/api' });
|
|
55
|
+
|
|
56
|
+
// 2. Create wallets for sender and recipient
|
|
57
|
+
// In a real application, the sender's wallet would be loaded, not created randomly.
|
|
58
|
+
const senderWallet = fromRandom(); // Assume this wallet is funded
|
|
59
|
+
const recipientWallet = fromRandom();
|
|
60
|
+
|
|
61
|
+
console.log(`Sender Address: ${senderWallet.address}`);
|
|
62
|
+
console.log(`Recipient Address: ${recipientWallet.address}`);
|
|
63
|
+
|
|
64
|
+
// To fund the sender's wallet for this example, use the faucet:
|
|
65
|
+
// https://faucet.abtnetwork.io/
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Example 1: Transferring Native Tokens
|
|
69
|
+
|
|
70
|
+
This example shows how to send 10 native tokens from the sender to the recipient.
|
|
71
|
+
|
|
72
|
+
```javascript Transfer Native Tokens icon=logos:javascript
|
|
73
|
+
async function transferNativeTokens() {
|
|
74
|
+
try {
|
|
75
|
+
const hash = await client.transfer({
|
|
76
|
+
to: recipientWallet.address,
|
|
77
|
+
token: 10, // The amount of native tokens to send
|
|
78
|
+
wallet: senderWallet,
|
|
79
|
+
memo: 'Sending you 10 native tokens!'
|
|
80
|
+
});
|
|
81
|
+
console.log('Native token transfer successful. Tx Hash:', hash);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
console.error('Error transferring tokens:', err);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
transferNativeTokens();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Example 2: Transferring an NFT (Asset)
|
|
91
|
+
|
|
92
|
+
To transfer an NFT, you need its unique asset address. First, you would create or acquire an asset (see [Manage Assets (NFTs)](./how-to-guides-manage-assets.md)). For this example, let's assume `senderWallet` already owns an NFT with the address `zNKj...`.
|
|
93
|
+
|
|
94
|
+
```javascript Transfer an NFT icon=logos:javascript
|
|
95
|
+
async function transferNFT() {
|
|
96
|
+
// Assume this is the address of an NFT owned by senderWallet
|
|
97
|
+
const nftAddress = 'zNKjL4wTmxQPk5nN2ADDPCd58286b2de3f3e';
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const hash = await client.transfer({
|
|
101
|
+
to: recipientWallet.address,
|
|
102
|
+
assets: [nftAddress], // An array of asset addresses
|
|
103
|
+
wallet: senderWallet,
|
|
104
|
+
memo: 'Here is the NFT you wanted.'
|
|
105
|
+
});
|
|
106
|
+
console.log('NFT transfer successful. Tx Hash:', hash);
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error('Error transferring NFT:', err);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
transferNFT();
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Example 3: Transferring Custom Tokens
|
|
116
|
+
|
|
117
|
+
This example demonstrates how to transfer a custom fungible token. You need the token's contract address. See the [Manage Tokens](./how-to-guides-manage-tokens.md) guide for information on creating custom tokens.
|
|
118
|
+
|
|
119
|
+
```javascript Transfer Custom Tokens icon=logos:javascript
|
|
120
|
+
async function transferCustomToken() {
|
|
121
|
+
// Assume this is the address of a custom token owned by senderWallet
|
|
122
|
+
const customTokenAddress = 'z37bA4x...';
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
const hash = await client.transfer({
|
|
126
|
+
to: recipientWallet.address,
|
|
127
|
+
wallet: senderWallet,
|
|
128
|
+
tokens: [
|
|
129
|
+
{ address: customTokenAddress, value: 50 } // 50 units of a custom token
|
|
130
|
+
],
|
|
131
|
+
memo: 'Sending 50 custom tokens.'
|
|
132
|
+
});
|
|
133
|
+
console.log('Custom token transfer successful. Tx Hash:', hash);
|
|
134
|
+
} catch (err) {
|
|
135
|
+
console.error('Error transferring custom token:', err);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
transferCustomToken();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Example 4: A Combined Transfer
|
|
143
|
+
|
|
144
|
+
You can send native tokens, custom tokens, and multiple NFTs all in a single, atomic transaction. This is highly efficient.
|
|
145
|
+
|
|
146
|
+
```javascript Combined Transfer icon=logos:javascript
|
|
147
|
+
async function combinedTransfer() {
|
|
148
|
+
// Assume these are addresses of assets and tokens owned by senderWallet
|
|
149
|
+
const nftAddress1 = 'zNKjL4wTmxQPk5nN2ADDPCd58286b2de3f3e';
|
|
150
|
+
const nftAddress2 = 'zNKiabcdeQPk5nN2ADDPCd58286b2defghj';
|
|
151
|
+
const customTokenAddress = 'z37bA4x...'; // Address of a custom fungible token
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
const hash = await client.transfer({
|
|
155
|
+
to: recipientWallet.address,
|
|
156
|
+
wallet: senderWallet,
|
|
157
|
+
token: 5, // 5 native tokens
|
|
158
|
+
assets: [nftAddress1, nftAddress2], // An array of two NFTs
|
|
159
|
+
tokens: [
|
|
160
|
+
{ address: customTokenAddress, value: 50 } // 50 units of a custom token
|
|
161
|
+
],
|
|
162
|
+
memo: 'Sending a mix of tokens and NFTs.'
|
|
163
|
+
});
|
|
164
|
+
console.log('Combined transfer successful. Tx Hash:', hash);
|
|
165
|
+
} catch (err) {
|
|
166
|
+
console.error('Error with combined transfer:', err);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
combinedTransfer();
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
By following these examples, you can easily implement token and NFT transfers in your application. For more details on creating the items you wish to transfer, please see the related guides.
|
|
174
|
+
|
|
175
|
+
### Further Reading
|
|
176
|
+
|
|
177
|
+
- [How to Manage Assets (NFTs)](./how-to-guides-manage-assets.md)
|
|
178
|
+
- [How to Manage Tokens](./how-to-guides-manage-tokens.md)
|
|
179
|
+
- [High-level API](./api-reference-transaction-helpers.md)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# 转移代币和 NFT
|
|
2
|
+
|
|
3
|
+
本指南提供了使用 OCAP Client 在账户之间转移可替代代币(原生和自定义)和非替代代幣(NFT 或资产)的详细步骤。所有转移操作的主要方法是 `client.transfer()`。
|
|
4
|
+
|
|
5
|
+
需要记住的一个关键特性是,当新账户收到第一笔入账交易时,它会自动在链上创建。这意味着您可以将代币或资产转移到一个全新的地址,而无需为接收方进行任何预先设置。
|
|
6
|
+
|
|
7
|
+
## `transfer` 方法
|
|
8
|
+
|
|
9
|
+
`client.transfer()` 方法是一个多功能的辅助函数,可简化发送资产和代币的过程。它通过一次调用即可构建、签名并将相应的交易(`transferV2Tx`)发送到区块链。
|
|
10
|
+
|
|
11
|
+
### 参数
|
|
12
|
+
|
|
13
|
+
<x-field-group>
|
|
14
|
+
<x-field data-name="to" data-type="string" data-required="true">
|
|
15
|
+
<x-field-desc markdown>接收方的账户地址。必须是有效的 DID 地址。</x-field-desc>
|
|
16
|
+
</x-field>
|
|
17
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="用于签署交易的发送方钱包对象。"></x-field>
|
|
18
|
+
<x-field data-name="token" data-type="number" data-default="0">
|
|
19
|
+
<x-field-desc markdown>要转移的链上原生代币数量。客户端会自动处理到正确小数单位的转换。</x-field-desc>
|
|
20
|
+
</x-field>
|
|
21
|
+
<x-field data-name="assets" data-type="string[]" data-default="[]" data-desc="要转移的资产地址(NFT)数组。"></x-field>
|
|
22
|
+
<x-field data-name="tokens" data-type="object[]" data-default="[]">
|
|
23
|
+
<x-field-desc markdown>要转移的自定义可替代代币对象数组。</x-field-desc>
|
|
24
|
+
<x-field data-name="address" data-type="string" data-required="true" data-desc="自定义代币合约的地址。"></x-field>
|
|
25
|
+
<x-field data-name="value" data-type="number" data-required="true" data-desc="要转移的自定义代币数量。"></x-field>
|
|
26
|
+
</x-field>
|
|
27
|
+
<x-field data-name="memo" data-type="string" data-required="false" data-desc="交易中可包含的可选消息或备注。"></x-field>
|
|
28
|
+
<x-field data-name="delegator" data-type="string" data-required="false">
|
|
29
|
+
<x-field-desc markdown>如果 `wallet` 代表另一个账户行事,此处应为委托账户的地址。更多详情请参见 [委托权限](./how-to-guides-delegate-permissions.md) 指南。</x-field-desc>
|
|
30
|
+
</x-field>
|
|
31
|
+
</x-field-group>
|
|
32
|
+
|
|
33
|
+
### 返回值
|
|
34
|
+
|
|
35
|
+
<x-field data-name="Promise<string>" data-type="Promise">
|
|
36
|
+
<x-field-desc markdown>一个 Promise,在成功提交到区块链后,会解析为交易哈希值。</x-field-desc>
|
|
37
|
+
</x-field>
|
|
38
|
+
|
|
39
|
+
## 分步示例
|
|
40
|
+
|
|
41
|
+
### 前提条件
|
|
42
|
+
|
|
43
|
+
在开始之前,请确保您已具备:
|
|
44
|
+
|
|
45
|
+
1. 一个已初始化并连接到链主机(如 `https://beta.abtnetwork.io`)的 `GraphQLClient`。
|
|
46
|
+
2. 一个发送方的钱包对象(`senderWallet`),其中有足够的代币以支付转账和交易费用。
|
|
47
|
+
3. 一个接收方的钱包对象(`recipientWallet`)以获取其地址。接收方的账户尚无需在链上存在。
|
|
48
|
+
|
|
49
|
+
```javascript Basic Setup icon=logos:javascript
|
|
50
|
+
import GraphQLClient from '@ocap/client';
|
|
51
|
+
import { fromRandom } from '@ocap/wallet';
|
|
52
|
+
|
|
53
|
+
// 1. 初始化客户端
|
|
54
|
+
const client = new GraphQLClient({ endpoint: 'https://beta.abtnetwork.io/api' });
|
|
55
|
+
|
|
56
|
+
// 2. 为发送方和接收方创建钱包
|
|
57
|
+
// 在实际应用中,发送方的钱包应该是加载的,而不是随机创建的。
|
|
58
|
+
const senderWallet = fromRandom(); // 假设此钱包已有资金
|
|
59
|
+
const recipientWallet = fromRandom();
|
|
60
|
+
|
|
61
|
+
console.log(`发送方地址: ${senderWallet.address}`);
|
|
62
|
+
console.log(`接收方地址: ${recipientWallet.address}`);
|
|
63
|
+
|
|
64
|
+
// 要为本示例中的发送方钱包充值,请使用水龙头:
|
|
65
|
+
// https://faucet.abtnetwork.io/
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 示例 1:转移原生代币
|
|
69
|
+
|
|
70
|
+
此示例展示了如何从发送方发送 10 个原生代币给接收方。
|
|
71
|
+
|
|
72
|
+
```javascript Transfer Native Tokens icon=logos:javascript
|
|
73
|
+
async function transferNativeTokens() {
|
|
74
|
+
try {
|
|
75
|
+
const hash = await client.transfer({
|
|
76
|
+
to: recipientWallet.address,
|
|
77
|
+
token: 10, // 要发送的原生代币数量
|
|
78
|
+
wallet: senderWallet,
|
|
79
|
+
memo: '正在向您发送 10 个原生代币!'
|
|
80
|
+
});
|
|
81
|
+
console.log('原生代币转移成功。交易哈希:', hash);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
console.error('转移代币时出错:', err);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
transferNativeTokens();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 示例 2:转移 NFT(资产)
|
|
91
|
+
|
|
92
|
+
要转移 NFT,您需要其唯一的资产地址。首先,您需要创建或获取一个资产(参见 [管理资产 (NFTs)](./how-to-guides-manage-assets.md))。在本示例中,我们假设 `senderWallet` 已经拥有一个地址为 `zNKj...` 的 NFT。
|
|
93
|
+
|
|
94
|
+
```javascript Transfer an NFT icon=logos:javascript
|
|
95
|
+
async function transferNFT() {
|
|
96
|
+
// 假设这是 senderWallet 拥有的一个 NFT 的地址
|
|
97
|
+
const nftAddress = 'zNKjL4wTmxQPk5nN2ADDPCd58286b2de3f3e';
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const hash = await client.transfer({
|
|
101
|
+
to: recipientWallet.address,
|
|
102
|
+
assets: [nftAddress], // 资产地址数组
|
|
103
|
+
wallet: senderWallet,
|
|
104
|
+
memo: '这是您想要的 NFT。'
|
|
105
|
+
});
|
|
106
|
+
console.log('NFT 转移成功。交易哈希:', hash);
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error('转移 NFT 时出错:', err);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
transferNFT();
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 示例 3:转移自定义代币
|
|
116
|
+
|
|
117
|
+
此示例演示了如何转移自定义可替代代币。您需要代币的合约地址。有关创建自定义代币的信息,请参见 [管理代币](./how-to-guides-manage-tokens.md) 指南。
|
|
118
|
+
|
|
119
|
+
```javascript Transfer Custom Tokens icon=logos:javascript
|
|
120
|
+
async function transferCustomToken() {
|
|
121
|
+
// 假设这是 senderWallet 拥有的一个自定义代币的地址
|
|
122
|
+
const customTokenAddress = 'z37bA4x...';
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
const hash = await client.transfer({
|
|
126
|
+
to: recipientWallet.address,
|
|
127
|
+
wallet: senderWallet,
|
|
128
|
+
tokens: [
|
|
129
|
+
{ address: customTokenAddress, value: 50 } // 50 单位的自定义代币
|
|
130
|
+
],
|
|
131
|
+
memo: '正在发送 50 个自定义代币。'
|
|
132
|
+
});
|
|
133
|
+
console.log('自定义代币转移成功。交易哈希:', hash);
|
|
134
|
+
} catch (err) {
|
|
135
|
+
console.error('转移自定义代币时出错:', err);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
transferCustomToken();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 示例 4:组合转移
|
|
143
|
+
|
|
144
|
+
您可以在单笔原子交易中同时发送原生代币、自定义代币和多个 NFT。这种方式非常高效。
|
|
145
|
+
|
|
146
|
+
```javascript Combined Transfer icon=logos:javascript
|
|
147
|
+
async function combinedTransfer() {
|
|
148
|
+
// 假设这些是 senderWallet 拥有的资产和代币的地址
|
|
149
|
+
const nftAddress1 = 'zNKjL4wTmxQPk5nN2ADDPCd58286b2de3f3e';
|
|
150
|
+
const nftAddress2 = 'zNKiabcdeQPk5nN2ADDPCd58286b2defghj';
|
|
151
|
+
const customTokenAddress = 'z37bA4x...'; // 自定义可替代代币的地址
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
const hash = await client.transfer({
|
|
155
|
+
to: recipientWallet.address,
|
|
156
|
+
wallet: senderWallet,
|
|
157
|
+
token: 5, // 5 个原生代币
|
|
158
|
+
assets: [nftAddress1, nftAddress2], // 包含两个 NFT 的数组
|
|
159
|
+
tokens: [
|
|
160
|
+
{ address: customTokenAddress, value: 50 } // 50 单位的自定义代币
|
|
161
|
+
],
|
|
162
|
+
memo: '正在发送混合的代币和 NFT。'
|
|
163
|
+
});
|
|
164
|
+
console.log('组合转移成功。交易哈希:', hash);
|
|
165
|
+
} catch (err) {
|
|
166
|
+
console.error('组合转移时出错:', err);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
combinedTransfer();
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
通过遵循这些示例,您可以轻松地在您的应用程序中实现代币和 NFT 的转移。有关创建您希望转移的项目的更多详细信息,请参阅相关指南。
|
|
174
|
+
|
|
175
|
+
### 延伸阅读
|
|
176
|
+
|
|
177
|
+
- [如何管理资产 (NFTs)](./how-to-guides-manage-assets.md)
|
|
178
|
+
- [如何管理代币](./how-to-guides-manage-tokens.md)
|
|
179
|
+
- [高级 API](./api-reference-transaction-helpers.md)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# How-to Guides
|
|
2
|
+
|
|
3
|
+
This section provides practical, step-by-step instructions for completing common tasks with the OCAP Client. Each guide is designed as a self-contained recipe to help you accomplish a specific goal, from managing accounts to performing complex atomic swaps.
|
|
4
|
+
|
|
5
|
+
<x-cards data-columns="2">
|
|
6
|
+
<x-card data-title="Manage Accounts" data-href="/how-to-guides/manage-accounts" data-icon="lucide:user-cog">
|
|
7
|
+
Covers account-related operations such as migrating an account to new keys.
|
|
8
|
+
</x-card>
|
|
9
|
+
<x-card data-title="Delegate Permissions" data-href="/how-to-guides/delegate-permissions" data-icon="lucide:key-round">
|
|
10
|
+
Shows how to authorize another account to send transactions on your behalf, specifying which actions are permitted.
|
|
11
|
+
</x-card>
|
|
12
|
+
<x-card data-title="Transfer Tokens and NFTs" data-href="/how-to-guides/transfer-tokens-and-nfts" data-icon="lucide:arrow-right-left">
|
|
13
|
+
Provides a step-by-step guide on transferring fungible tokens and non-fungible tokens (assets) between accounts.
|
|
14
|
+
</x-card>
|
|
15
|
+
<x-card data-title="Manage Assets (NFTs)" data-href="/how-to-guides/manage-assets" data-icon="lucide:gem">
|
|
16
|
+
Walks through the complete lifecycle of Non-Fungible Tokens, including creation, updating, and acquiring assets from a factory.
|
|
17
|
+
</x-card>
|
|
18
|
+
<x-card data-title="Manage Tokens" data-href="/how-to-guides/manage-tokens" data-icon="lucide:coins">
|
|
19
|
+
Explains how to perform fungible token operations like minting and burning tokens from a token factory.
|
|
20
|
+
</x-card>
|
|
21
|
+
<x-card data-title="Stake Tokens and Assets" data-href="/how-to-guides/stake-tokens-and-assets" data-icon="lucide:piggy-bank">
|
|
22
|
+
A step-by-step guide on how to stake tokens or assets to a receiver, including revoking and claiming stakes.
|
|
23
|
+
</x-card>
|
|
24
|
+
<x-card data-title="Perform Atomic Swaps" data-href="/how-to-guides/perform-atomic-swaps" data-icon="lucide:repeat">
|
|
25
|
+
A guide on how to securely exchange tokens and assets between two parties using a multi-signature transaction.
|
|
26
|
+
</x-card>
|
|
27
|
+
</x-cards>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# 操作指南
|
|
2
|
+
|
|
3
|
+
本部分提供了使用 OCAP Client 完成常见任务的实用分步说明。每个指南都设计为独立的指南,旨在帮助您实现从管理账户到执行复杂原子交换等特定目标。
|
|
4
|
+
|
|
5
|
+
<x-cards data-columns="2">
|
|
6
|
+
<x-card data-title="管理账户" data-href="/how-to-guides/manage-accounts" data-icon="lucide:user-cog">
|
|
7
|
+
涵盖与账户相关的操作,例如将账户迁移到新的密钥。
|
|
8
|
+
</x-card>
|
|
9
|
+
<x-card data-title="委托权限" data-href="/how-to-guides/delegate-permissions" data-icon="lucide:key-round">
|
|
10
|
+
展示了如何授权另一个账户代表您发送交易,并指定允许的操作。
|
|
11
|
+
</x-card>
|
|
12
|
+
<x-card data-title="转移代币和 NFT" data-href="/how-to-guides/transfer-tokens-and-nfts" data-icon="lucide:arrow-right-left">
|
|
13
|
+
提供了在账户之间转移同质化代币和非同质化代币(资产)的分步指南。
|
|
14
|
+
</x-card>
|
|
15
|
+
<x-card data-title="管理资产 (NFTs)" data-href="/how-to-guides/manage-assets" data-icon="lucide:gem">
|
|
16
|
+
详细介绍了非同质化代币的完整生命周期,包括创建、更新以及从工厂获取资产。
|
|
17
|
+
</x-card>
|
|
18
|
+
<x-card data-title="管理代币" data-href="/how-to-guides/manage-tokens" data-icon="lucide:coins">
|
|
19
|
+
解释了如何执行同质化代币操作,例如从代币工厂铸造和销毁代币。
|
|
20
|
+
</x-card>
|
|
21
|
+
<x-card data-title="质押代币和资产" data-href="/how-to-guides/stake-tokens-and-assets" data-icon="lucide:piggy-bank">
|
|
22
|
+
一个关于如何将代币或资产质押给接收方的分步指南,包括撤销和领取质押。
|
|
23
|
+
</x-card>
|
|
24
|
+
<x-card data-title="执行原子交换" data-href="/how-to-guides/perform-atomic-swaps" data-icon="lucide:repeat">
|
|
25
|
+
一个关于如何使用多重签名交易在两方之间安全地交换代币和资产的指南。
|
|
26
|
+
</x-card>
|
|
27
|
+
</x-cards>
|