@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,179 @@
|
|
|
1
|
+
# Manage Tokens
|
|
2
|
+
|
|
3
|
+
This guide provides step-by-step instructions for managing fungible tokens using the OCAP Client. You will learn how to set up a token factory, which acts as a blueprint for your token, and then use it to mint (create new tokens) and burn (destroy existing tokens). These operations are fundamental to creating and managing custom economies within your application.
|
|
4
|
+
|
|
5
|
+
Once you have minted tokens, you can transfer them between accounts. For more details on that process, please see the [Transfer Tokens and NFTs](./how-to-guides-transfer-tokens-and-nfts.md) guide.
|
|
6
|
+
|
|
7
|
+
## Create a Token Factory
|
|
8
|
+
|
|
9
|
+
A token factory is a smart contract that defines the properties and rules of a fungible token, such as its name, symbol, and supply mechanics. It also governs the process of minting and burning. Creating a factory is the first step before any new tokens can be brought into circulation.
|
|
10
|
+
|
|
11
|
+
The `createTokenFactory` method deploys a new token factory to the blockchain.
|
|
12
|
+
|
|
13
|
+
### Parameters
|
|
14
|
+
<x-field-group>
|
|
15
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet object of the factory owner, used to sign the transaction."></x-field>
|
|
16
|
+
<x-field data-name="token" data-type="object" data-required="true" data-desc="An object defining the properties of the token to be created.">
|
|
17
|
+
<x-field data-name="name" data-type="string" data-required="true" data-desc="The full name of the token (e.g., 'My Awesome Token')."></x-field>
|
|
18
|
+
<x-field data-name="symbol" data-type="string" data-required="true" data-desc="The token's ticker symbol (e.g., 'MAT')."></x-field>
|
|
19
|
+
<x-field data-name="decimal" data-type="number" data-required="true" data-desc="The number of decimal places the token supports."></x-field>
|
|
20
|
+
<x-field data-name="description" data-type="string" data-required="false" data-desc="A brief description of the token."></x-field>
|
|
21
|
+
<x-field data-name="icon" data-type="string" data-required="false" data-desc="URL to an icon for the token."></x-field>
|
|
22
|
+
<x-field data-name="maxTotalSupply" data-type="number" data-required="false" data-desc="The maximum total supply that can ever be minted."></x-field>
|
|
23
|
+
</x-field>
|
|
24
|
+
<x-field data-name="curve" data-type="object" data-required="false" data-desc="Configuration for a bonding curve, which programmatically controls the token's price. If omitted, minting/burning is not tied to a reserve token.">
|
|
25
|
+
<x-field data-name="basePrice" data-type="number" data-required="false" data-desc="The base price for the token in the reserve currency."></x-field>
|
|
26
|
+
<x-field data-name="fixedPrice" data-type="number" data-required="false" data-desc="A fixed price for the token, if not using a dynamic curve."></x-field>
|
|
27
|
+
<x-field data-name="slope" data-type="number" data-required="false" data-desc="The slope of the bonding curve, determining its steepness."></x-field>
|
|
28
|
+
</x-field>
|
|
29
|
+
<x-field data-name="feeRate" data-type="number" data-default="0" data-required="false" data-desc="The fee rate (in basis points) for minting and burning operations."></x-field>
|
|
30
|
+
<x-field data-name="data" data-type="object" data-required="false" data-desc="Optional custom data to attach to the token factory."></x-field>
|
|
31
|
+
</x-field-group>
|
|
32
|
+
|
|
33
|
+
### Returns
|
|
34
|
+
|
|
35
|
+
Returns a promise that resolves to an array containing the transaction hash and the address of the newly created token factory.
|
|
36
|
+
|
|
37
|
+
<x-field-group>
|
|
38
|
+
<x-field data-name="[0]" data-type="string" data-desc="The transaction hash for the factory creation."></x-field>
|
|
39
|
+
<x-field data-name="[1]" data-type="string" data-desc="The address of the new token factory."></x-field>
|
|
40
|
+
</x-field-group>
|
|
41
|
+
|
|
42
|
+
### Example
|
|
43
|
+
|
|
44
|
+
```javascript Create a Token Factory icon=logos:javascript
|
|
45
|
+
import Client from '@ocap/client';
|
|
46
|
+
import Wallet from '@ocap/wallet';
|
|
47
|
+
|
|
48
|
+
const endpoint = 'https://beta.abtnetwork.io/api';
|
|
49
|
+
const client = new Client(endpoint);
|
|
50
|
+
const wallet = Wallet.fromRandom();
|
|
51
|
+
|
|
52
|
+
// First, ensure the wallet has funds. You can get test tokens from a faucet:
|
|
53
|
+
// https://faucet.abtnetwork.io/
|
|
54
|
+
|
|
55
|
+
async function createFactory() {
|
|
56
|
+
try {
|
|
57
|
+
const [hash, factoryAddress] = await client.createTokenFactory({
|
|
58
|
+
wallet,
|
|
59
|
+
token: {
|
|
60
|
+
name: 'My Game Coin',
|
|
61
|
+
symbol: 'MGC',
|
|
62
|
+
decimal: 18,
|
|
63
|
+
description: 'The official currency for My Awesome Game.',
|
|
64
|
+
maxTotalSupply: 1000000,
|
|
65
|
+
},
|
|
66
|
+
feeRate: 100, // 1% fee
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
console.log('Token factory created successfully!');
|
|
70
|
+
console.log('Transaction Hash:', hash);
|
|
71
|
+
console.log('Factory Address:', factoryAddress);
|
|
72
|
+
return factoryAddress;
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error('Error creating token factory:', error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
createFactory();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Mint Tokens
|
|
82
|
+
|
|
83
|
+
Minting is the process of creating new tokens and adding them to the total supply. This is done through a token factory. If the factory was configured with a bonding curve, minting will require a payment in the reserve token.
|
|
84
|
+
|
|
85
|
+
The `mintToken` method initiates a transaction to mint a specified amount of tokens from a factory.
|
|
86
|
+
|
|
87
|
+
### Parameters
|
|
88
|
+
<x-field-group>
|
|
89
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet funding the mint operation and signing the transaction."></x-field>
|
|
90
|
+
<x-field data-name="tokenFactory" data-type="string" data-required="true" data-desc="The address of the token factory to mint from."></x-field>
|
|
91
|
+
<x-field data-name="amount" data-type="number" data-required="true" data-desc="The quantity of tokens to mint."></x-field>
|
|
92
|
+
<x-field data-name="receiver" data-type="string" data-required="true" data-desc="The address that will receive the newly minted tokens."></x-field>
|
|
93
|
+
<x-field data-name="maxReserve" data-type="number" data-required="true" data-desc="The maximum amount of the reserve token the wallet is willing to spend. This acts as a slippage protection mechanism."></x-field>
|
|
94
|
+
<x-field data-name="data" data-type="object" data-required="false" data-desc="Optional custom data to attach to the mint transaction."></x-field>
|
|
95
|
+
</x-field-group>
|
|
96
|
+
|
|
97
|
+
### Returns
|
|
98
|
+
|
|
99
|
+
Returns a promise that resolves to the transaction hash.
|
|
100
|
+
|
|
101
|
+
<x-field data-name="hash" data-type="string" data-desc="The transaction hash for the mint operation."></x-field>
|
|
102
|
+
|
|
103
|
+
### Example
|
|
104
|
+
|
|
105
|
+
```javascript Mint Tokens from a Factory icon=logos:javascript
|
|
106
|
+
async function mintNewTokens(factoryAddress) {
|
|
107
|
+
try {
|
|
108
|
+
const hash = await client.mintToken({
|
|
109
|
+
wallet,
|
|
110
|
+
tokenFactory: factoryAddress,
|
|
111
|
+
amount: 5000,
|
|
112
|
+
receiver: wallet.address, // Mint tokens to our own wallet
|
|
113
|
+
maxReserve: 10, // Max reserve token to pay. Adjust based on bonding curve price.
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
console.log('Tokens minted successfully!');
|
|
117
|
+
console.log('Transaction Hash:', hash);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error('Error minting tokens:', error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Assuming `factoryAddress` is available from the createFactory example
|
|
124
|
+
// const factoryAddress = '...';
|
|
125
|
+
// mintNewTokens(factoryAddress);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Burn Tokens
|
|
129
|
+
|
|
130
|
+
Burning is the opposite of minting; it permanently removes tokens from circulation. If the token factory uses a bonding curve, burning tokens will return a proportional amount of the reserve currency to the user.
|
|
131
|
+
|
|
132
|
+
The `burnToken` method initiates this process.
|
|
133
|
+
|
|
134
|
+
### Parameters
|
|
135
|
+
<x-field-group>
|
|
136
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet that holds the tokens to be burned and will sign the transaction."></x-field>
|
|
137
|
+
<x-field data-name="tokenFactory" data-type="string" data-required="true" data-desc="The address of the token factory."></x-field>
|
|
138
|
+
<x-field data-name="amount" data-type="number" data-required="true" data-desc="The quantity of tokens to burn."></x-field>
|
|
139
|
+
<x-field data-name="receiver" data-type="string" data-required="true" data-desc="The address that will receive the reserve tokens in return."></x-field>
|
|
140
|
+
<x-field data-name="minReserve" data-type="number" data-required="true" data-desc="The minimum amount of the reserve token the wallet expects to receive. This protects against price slippage."></x-field>
|
|
141
|
+
<x-field data-name="data" data-type="object" data-required="false" data-desc="Optional custom data to attach to the burn transaction."></x-field>
|
|
142
|
+
</x-field-group>
|
|
143
|
+
|
|
144
|
+
### Returns
|
|
145
|
+
|
|
146
|
+
Returns a promise that resolves to the transaction hash.
|
|
147
|
+
|
|
148
|
+
<x-field data-name="hash" data-type="string" data-desc="The transaction hash for the burn operation."></x-field>
|
|
149
|
+
|
|
150
|
+
### Example
|
|
151
|
+
|
|
152
|
+
```javascript Burn Tokens icon=logos:javascript
|
|
153
|
+
async function burnExistingTokens(factoryAddress) {
|
|
154
|
+
try {
|
|
155
|
+
const hash = await client.burnToken({
|
|
156
|
+
wallet,
|
|
157
|
+
tokenFactory: factoryAddress,
|
|
158
|
+
amount: 1000,
|
|
159
|
+
receiver: wallet.address, // Receive reserve tokens back to our own wallet
|
|
160
|
+
minReserve: 1, // Min reserve token to receive. Adjust based on bonding curve price.
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
console.log('Tokens burned successfully!');
|
|
164
|
+
console.log('Transaction Hash:', hash);
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error('Error burning tokens:', error);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Assuming `factoryAddress` is available from the createFactory example
|
|
171
|
+
// const factoryAddress = '...';
|
|
172
|
+
// burnExistingTokens(factoryAddress);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Summary
|
|
176
|
+
|
|
177
|
+
In this guide, you've learned the complete lifecycle for managing fungible tokens: creating a factory, minting new tokens into existence, and burning them to reduce the supply. These powerful primitives allow you to build sophisticated economic systems on the OCAP platform.
|
|
178
|
+
|
|
179
|
+
Now that you know how to create tokens, the next logical step is to learn how to move them around. Head over to the [Transfer Tokens and NFTs](./how-to-guides-transfer-tokens-and-nfts.md) guide to see how it's done.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# 管理代币
|
|
2
|
+
|
|
3
|
+
本指南提供了使用 OCAP Client 管理同质化代幣的详细步骤。你将学习如何设置代币工厂(作为代币的蓝图),并使用它来铸造(创建新代币)和销毁(销毁现有代币)。这些操作是在你的应用程序中创建和管理自定义经济体系的基础。
|
|
4
|
+
|
|
5
|
+
铸造代币后,你可以在账户之间进行转移。有关该过程的更多详细信息,请参阅[转移代币和 NFT](./how-to-guides-transfer-tokens-and-nfts.md)指南。
|
|
6
|
+
|
|
7
|
+
## 创建代币工厂
|
|
8
|
+
|
|
9
|
+
代币工厂是一种智能合约,用于定义同质化代幣的属性和规则,例如其名称、符号和供应机制。它还管理铸造和销毁的过程。创建工厂是将任何新代币投入流通的第一步。
|
|
10
|
+
|
|
11
|
+
`createTokenFactory` 方法将一个新的代币工厂部署到区块链上。
|
|
12
|
+
|
|
13
|
+
### 参数
|
|
14
|
+
<x-field-group>
|
|
15
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="工厂所有者的钱包对象,用于签署交易。"></x-field>
|
|
16
|
+
<x-field data-name="token" data-type="object" data-required="true" data-desc="一个定义待创建代币属性的对象。">
|
|
17
|
+
<x-field data-name="name" data-type="string" data-required="true" data-desc="代币的全名(例如,'My Awesome Token')。"></x-field>
|
|
18
|
+
<x-field data-name="symbol" data-type="string" data-required="true" data-desc="代币的股票代码符号(例如,'MAT')。"></x-field>
|
|
19
|
+
<x-field data-name="decimal" data-type="number" data-required="true" data-desc="代币支持的小数位数。"></x-field>
|
|
20
|
+
<x-field data-name="description" data-type="string" data-required="false" data-desc="代币的简要描述。"></x-field>
|
|
21
|
+
<x-field data-name="icon" data-type="string" data-required="false" data-desc="代币图标的 URL。"></x-field>
|
|
22
|
+
<x-field data-name="maxTotalSupply" data-type="number" data-required="false" data-desc="可铸造的最大总供应量。"></x-field>
|
|
23
|
+
</x-field>
|
|
24
|
+
<x-field data-name="curve" data-type="object" data-required="false" data-desc="联合曲线的配置,以编程方式控制代币价格。如果省略,铸造/销毁将不与储备代币挂钩。">
|
|
25
|
+
<x-field data-name="basePrice" data-type="number" data-required="false" data-desc="以储备货币计价的代币基础价格。"></x-field>
|
|
26
|
+
<x-field data-name="fixedPrice" data-type="number" data-required="false" data-desc="代币的固定价格,如果不使用动态曲线。"></x-field>
|
|
27
|
+
<x-field data-name="slope" data-type="number" data-required="false" data-desc="联合曲线的斜率,决定其陡峭程度。"></x-field>
|
|
28
|
+
</x-field>
|
|
29
|
+
<x-field data-name="feeRate" data-type="number" data-default="0" data-required="false" data-desc="铸造和销毁操作的费率(以基点为单位)。"></x-field>
|
|
30
|
+
<x-field data-name="data" data-type="object" data-required="false" data-desc="附加到代币工厂的可选自定义数据。"></x-field>
|
|
31
|
+
</x-field-group>
|
|
32
|
+
|
|
33
|
+
### 返回值
|
|
34
|
+
|
|
35
|
+
返回一个 promise,该 promise 解析为一个数组,其中包含交易哈希和新创建的代币工厂的地址。
|
|
36
|
+
|
|
37
|
+
<x-field-group>
|
|
38
|
+
<x-field data-name="[0]" data-type="string" data-desc="创建工厂的交易哈希。"></x-field>
|
|
39
|
+
<x-field data-name="[1]" data-type="string" data-desc="新代币工厂的地址。"></x-field>
|
|
40
|
+
</x-field-group>
|
|
41
|
+
|
|
42
|
+
### 示例
|
|
43
|
+
|
|
44
|
+
```javascript Create a Token Factory icon=logos:javascript
|
|
45
|
+
import Client from '@ocap/client';
|
|
46
|
+
import Wallet from '@ocap/wallet';
|
|
47
|
+
|
|
48
|
+
const endpoint = 'https://beta.abtnetwork.io/api';
|
|
49
|
+
const client = new Client(endpoint);
|
|
50
|
+
const wallet = Wallet.fromRandom();
|
|
51
|
+
|
|
52
|
+
// 首先,确保钱包中有资金。你可以从水龙头获取测试代币:
|
|
53
|
+
// https://faucet.abtnetwork.io/
|
|
54
|
+
|
|
55
|
+
async function createFactory() {
|
|
56
|
+
try {
|
|
57
|
+
const [hash, factoryAddress] = await client.createTokenFactory({
|
|
58
|
+
wallet,
|
|
59
|
+
token: {
|
|
60
|
+
name: 'My Game Coin',
|
|
61
|
+
symbol: 'MGC',
|
|
62
|
+
decimal: 18,
|
|
63
|
+
description: 'The official currency for My Awesome Game.',
|
|
64
|
+
maxTotalSupply: 1000000,
|
|
65
|
+
},
|
|
66
|
+
feeRate: 100, // 1% 的费用
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
console.log('代币工厂创建成功!');
|
|
70
|
+
console.log('交易哈希:', hash);
|
|
71
|
+
console.log('工厂地址:', factoryAddress);
|
|
72
|
+
return factoryAddress;
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error('创建代币工厂时出错:', error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
createFactory();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 铸造代币
|
|
82
|
+
|
|
83
|
+
铸造是创建新代币并将其添加到总供应量中的过程。这是通过代币工厂完成的。如果工厂配置了联合曲线,铸造将需要使用储备代币进行支付。
|
|
84
|
+
|
|
85
|
+
`mintToken` 方法会启动一个交易,从工厂铸造指定数量的代币。
|
|
86
|
+
|
|
87
|
+
### 参数
|
|
88
|
+
<x-field-group>
|
|
89
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="为铸造操作提供资金并签署交易的钱包。"></x-field>
|
|
90
|
+
<x-field data-name="tokenFactory" data-type="string" data-required="true" data-desc="要从中铸造代币的代币工厂的地址。"></x-field>
|
|
91
|
+
<x-field data-name="amount" data-type="number" data-required="true" data-desc="要铸造的代币数量。"></x-field>
|
|
92
|
+
<x-field data-name="receiver" data-type="string" data-required="true" data-desc="将接收新铸造代币的地址。"></x-field>
|
|
93
|
+
<x-field data-name="maxReserve" data-type="number" data-required="true" data-desc="钱包愿意花费的储备代币的最大数量。这可以作为一种滑点保护机制。"></x-field>
|
|
94
|
+
<x-field data-name="data" data-type="object" data-required="false" data-desc="附加到铸造交易的可选自定义数据。"></x-field>
|
|
95
|
+
</x-field-group>
|
|
96
|
+
|
|
97
|
+
### 返回值
|
|
98
|
+
|
|
99
|
+
返回一个 promise,该 promise 解析为交易哈希。
|
|
100
|
+
|
|
101
|
+
<x-field data-name="hash" data-type="string" data-desc="铸造操作的交易哈希。"></x-field>
|
|
102
|
+
|
|
103
|
+
### 示例
|
|
104
|
+
|
|
105
|
+
```javascript Mint Tokens from a Factory icon=logos:javascript
|
|
106
|
+
async function mintNewTokens(factoryAddress) {
|
|
107
|
+
try {
|
|
108
|
+
const hash = await client.mintToken({
|
|
109
|
+
wallet,
|
|
110
|
+
tokenFactory: factoryAddress,
|
|
111
|
+
amount: 5000,
|
|
112
|
+
receiver: wallet.address, // 将代币铸造到我们自己的钱包
|
|
113
|
+
maxReserve: 10, // 支付的最大储备代币。根据联合曲线价格进行调整。
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
console.log('代币铸造成功!');
|
|
117
|
+
console.log('交易哈希:', hash);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error('铸造代币时出错:', error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 假设 `factoryAddress` 可从 createFactory 示例中获得
|
|
124
|
+
// const factoryAddress = '...';
|
|
125
|
+
// mintNewTokens(factoryAddress);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 销毁代币
|
|
129
|
+
|
|
130
|
+
销毁与铸造相反;它会永久地将代币从流通中移除。如果代币工厂使用联合曲线,销毁代币将向用户返回相应比例的储备货币。
|
|
131
|
+
|
|
132
|
+
`burnToken` 方法会启动此过程。
|
|
133
|
+
|
|
134
|
+
### 参数
|
|
135
|
+
<x-field-group>
|
|
136
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="持有待销毁代币并将签署交易的钱包。"></x-field>
|
|
137
|
+
<x-field data-name="tokenFactory" data-type="string" data-required="true" data-desc="代币工厂的地址。"></x-field>
|
|
138
|
+
<x-field data-name="amount" data-type="number" data-required="true" data-desc="要销毁的代币数量。"></x-field>
|
|
139
|
+
<x-field data-name="receiver" data-type="string" data-required="true" data-desc="将接收返还的储备代币的地址。"></x-field>
|
|
140
|
+
<x-field data-name="minReserve" data-type="number" data-required="true" data-desc="钱包期望收到的储备代币的最低数量。这可以防止价格滑点。"></x-field>
|
|
141
|
+
<x-field data-name="data" data-type="object" data-required="false" data-desc="附加到销毁交易的可选自定义数据。"></x-field>
|
|
142
|
+
</x-field-group>
|
|
143
|
+
|
|
144
|
+
### 返回值
|
|
145
|
+
|
|
146
|
+
返回一个 promise,该 promise 解析为交易哈希。
|
|
147
|
+
|
|
148
|
+
<x-field data-name="hash" data-type="string" data-desc="销毁操作的交易哈希。"></x-field>
|
|
149
|
+
|
|
150
|
+
### 示例
|
|
151
|
+
|
|
152
|
+
```javascript Burn Tokens icon=logos:javascript
|
|
153
|
+
async function burnExistingTokens(factoryAddress) {
|
|
154
|
+
try {
|
|
155
|
+
const hash = await client.burnToken({
|
|
156
|
+
wallet,
|
|
157
|
+
tokenFactory: factoryAddress,
|
|
158
|
+
amount: 1000,
|
|
159
|
+
receiver: wallet.address, // 将储备代币接收回我们自己的钱包
|
|
160
|
+
minReserve: 1, // 接收的最低储备代币。根据联合曲线价格进行调整。
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
console.log('代币销毁成功!');
|
|
164
|
+
console.log('交易哈希:', hash);
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error('销毁代币时出错:', error);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 假设 `factoryAddress` 可从 createFactory 示例中获得
|
|
171
|
+
// const factoryAddress = '...';
|
|
172
|
+
// burnExistingTokens(factoryAddress);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 总结
|
|
176
|
+
|
|
177
|
+
在本指南中,你学习了管理同质化代幣的完整生命周期:创建工厂、铸造新代币以及销毁代币以减少供应。这些强大的原语使你能够在 OCAP 平台上构建复杂的经济系统。
|
|
178
|
+
|
|
179
|
+
现在你已经知道如何创建代币,下一个合乎逻辑的步骤是学习如何转移它们。请前往[转移代币和 NFT](./how-to-guides-transfer-tokens-and-nfts.md)指南查看具体操作方法。
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Stake Tokens and Assets
|
|
2
|
+
|
|
3
|
+
Staking is the process of locking up tokens or assets (NFTs) to a specific receiver, often to secure a network, participate in governance, or earn rewards. This guide provides a step-by-step walkthrough of the entire staking lifecycle using the OCAP Client, including creating a stake, revoking it, claiming the assets back, and slashing a stake for punitive reasons.
|
|
4
|
+
|
|
5
|
+
This process involves a few key methods:
|
|
6
|
+
- `stake()`: To create a new stake.
|
|
7
|
+
- `revokeStake()`: To initiate the process of withdrawing your staked items.
|
|
8
|
+
- `claimStake()`: To finalize the withdrawal and return the items to your account.
|
|
9
|
+
- `slashStake()`: To allow authorized parties to penalize a staker.
|
|
10
|
+
|
|
11
|
+
## How to Stake
|
|
12
|
+
|
|
13
|
+
To begin, you use the `stake` method to lock your tokens or assets. This action creates a new, unique stake address on the chain that holds your staked items and the rules governing them.
|
|
14
|
+
|
|
15
|
+
### Parameters
|
|
16
|
+
|
|
17
|
+
<x-field-group>
|
|
18
|
+
<x-field data-name="to" data-type="string" data-required="true" data-desc="The DID address of the account that will receive the stake."></x-field>
|
|
19
|
+
<x-field data-name="assets" data-type="string[]" data-required="false" data-desc="An array of asset addresses (NFTs) to be staked."></x-field>
|
|
20
|
+
<x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="An array of token objects to be staked.">
|
|
21
|
+
<x-field data-name="address" data-type="string" data-required="true" data-desc="The address of the token contract."></x-field>
|
|
22
|
+
<x-field data-name="value" data-type="number" data-required="true" data-desc="The amount of tokens to stake."></x-field>
|
|
23
|
+
</x-field>
|
|
24
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet object of the staker."></x-field>
|
|
25
|
+
<x-field data-name="locked" data-type="boolean" data-default="false" data-required="false" data-desc="A boolean indicating if the stake is locked upon creation."></x-field>
|
|
26
|
+
<x-field data-name="slashers" data-type="string[]" data-required="false" data-desc="An array of DID addresses permitted to slash this stake. Defaults to the receiver's address if not provided."></x-field>
|
|
27
|
+
<x-field data-name="message" data-type="string" data-required="false" data-desc="An optional note or message for the stake."></x-field>
|
|
28
|
+
<x-field data-name="nonce" data-type="string" data-required="false" data-desc="An optional nonce to ensure the stake address is unique."></x-field>
|
|
29
|
+
</x-field-group>
|
|
30
|
+
|
|
31
|
+
### Example
|
|
32
|
+
|
|
33
|
+
```javascript Staking Tokens and an Asset icon=logos:javascript
|
|
34
|
+
// Assume 'client' is an initialized GraphQLClient instance
|
|
35
|
+
// and 'stakerWallet' is a valid wallet object.
|
|
36
|
+
const receiverAddress = 'z29d5852576b8a8b6f3a8b4b74a3f4a3e2e1d'; // The address of the stake receiver
|
|
37
|
+
|
|
38
|
+
async function createStake() {
|
|
39
|
+
try {
|
|
40
|
+
const [txHash, stakeAddress] = await client.stake({
|
|
41
|
+
to: receiverAddress,
|
|
42
|
+
tokens: [{
|
|
43
|
+
address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E', // Address of the token to stake
|
|
44
|
+
value: 100, // Amount of tokens to stake
|
|
45
|
+
}],
|
|
46
|
+
assets: ['zNKtA1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6'], // Address of the asset/NFT to stake
|
|
47
|
+
message: 'Staking for validator rewards',
|
|
48
|
+
wallet: stakerWallet,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log('Stake transaction sent:', txHash);
|
|
52
|
+
console.log('New stake address created:', stakeAddress);
|
|
53
|
+
return stakeAddress;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error('Error creating stake:', error);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Return Value
|
|
61
|
+
|
|
62
|
+
The `stake` method returns a tuple containing the transaction hash and the newly created `stakeAddress`. This address is crucial for all future interactions with this specific stake, such as revoking or slashing.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## How to Revoke a Stake
|
|
67
|
+
|
|
68
|
+
Revoking a stake is the process initiated by the staker to retrieve their locked tokens and assets. This transaction does not immediately return the funds; instead, it marks them as available for claiming, subject to any on-chain lock-up periods.
|
|
69
|
+
|
|
70
|
+
### Parameters
|
|
71
|
+
|
|
72
|
+
<x-field-group>
|
|
73
|
+
<x-field data-name="from" data-type="string" data-required="true" data-desc="The address of the stake to be revoked (obtained from the 'stake' call)."></x-field>
|
|
74
|
+
<x-field data-name="assets" data-type="string[]" data-required="false" data-desc="An array of asset addresses to revoke from the stake."></x-field>
|
|
75
|
+
<x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="An array of token objects to revoke.">
|
|
76
|
+
<x-field data-name="address" data-type="string" data-required="true" data-desc="The address of the token contract."></x-field>
|
|
77
|
+
<x-field data-name="value" data-type="number" data-required="true" data-desc="The amount of tokens to revoke."></x-field>
|
|
78
|
+
</x-field>
|
|
79
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The staker's wallet object, which must be the original creator of the stake."></x-field>
|
|
80
|
+
</x-field-group>
|
|
81
|
+
|
|
82
|
+
### Example
|
|
83
|
+
|
|
84
|
+
```javascript Revoking a Stake icon=logos:javascript
|
|
85
|
+
// Assume 'stakeAddress' is the address returned from the previous step
|
|
86
|
+
// and 'stakerWallet' is the same wallet used to create the stake.
|
|
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('Revoke stake transaction sent:', revokeTxHash);
|
|
101
|
+
console.log('IMPORTANT: Save this hash to claim your stake later.');
|
|
102
|
+
return revokeTxHash;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error('Error revoking stake:', error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Return Value
|
|
110
|
+
|
|
111
|
+
This function returns the transaction hash of the revoke operation. This hash serves as evidence and is **required** for the final step of claiming the stake.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## How to Claim a Revoked Stake
|
|
116
|
+
|
|
117
|
+
After a stake has been successfully revoked, the staker must send a `claimStake` transaction to move the tokens and assets back into their account. This finalizes the withdrawal process.
|
|
118
|
+
|
|
119
|
+
### Parameters
|
|
120
|
+
|
|
121
|
+
<x-field-group>
|
|
122
|
+
<x-field data-name="from" data-type="string" data-required="true" data-desc="The address of the stake."></x-field>
|
|
123
|
+
<x-field data-name="evidence" data-type="string" data-required="true" data-desc="The transaction hash from the 'revokeStake' call, which serves as proof of revocation."></x-field>
|
|
124
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The staker's wallet object."></x-field>
|
|
125
|
+
</x-field-group>
|
|
126
|
+
|
|
127
|
+
### Example
|
|
128
|
+
|
|
129
|
+
```javascript Claiming Staked Items icon=logos:javascript
|
|
130
|
+
// Assume 'stakeAddress' and 'revokeTxHash' are from the previous steps,
|
|
131
|
+
// and 'stakerWallet' is the staker's wallet.
|
|
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('Claim stake transaction sent:', claimTxHash);
|
|
142
|
+
console.log('Your tokens and assets have been returned to your account.');
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error('Error claiming stake:', error);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Return Value
|
|
150
|
+
|
|
151
|
+
The method returns the final transaction hash. Once this transaction is confirmed on the chain, the staked items are returned to the `wallet`'s address.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## How to Slash a Stake
|
|
156
|
+
|
|
157
|
+
Slashing is a punitive action that can be taken by a designated `slasher` (usually the stake receiver) against a staker. This typically happens if the staker violates certain rules. The slashed tokens or assets are removed from the stake and sent to a designated vault.
|
|
158
|
+
|
|
159
|
+
### Parameters
|
|
160
|
+
|
|
161
|
+
<x-field-group>
|
|
162
|
+
<x-field data-name="from" data-type="string" data-required="true" data-desc="The address of the stake to be slashed."></x-field>
|
|
163
|
+
<x-field data-name="reason" data-type="string" data-required="true" data-desc="A mandatory message explaining why the slash is occurring."></x-field>
|
|
164
|
+
<x-field data-name="assets" data-type="string[]" data-required="false" data-desc="An array of asset addresses to be slashed from the stake."></x-field>
|
|
165
|
+
<x-field data-name="tokens" data-type="object[]" data-required="false" data-desc="An array of token objects to be slashed.">
|
|
166
|
+
<x-field data-name="address" data-type="string" data-required="true" data-desc="The address of the token contract."></x-field>
|
|
167
|
+
<x-field data-name="value" data-type="number" data-required="true" data-desc="The amount of tokens to slash."></x-field>
|
|
168
|
+
</x-field>
|
|
169
|
+
<x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet object of an authorized slasher."></x-field>
|
|
170
|
+
</x-field-group>
|
|
171
|
+
|
|
172
|
+
### Example
|
|
173
|
+
|
|
174
|
+
```javascript Slashing a Stake icon=logos:javascript
|
|
175
|
+
// Assume 'stakeAddress' is the address of the stake to be slashed,
|
|
176
|
+
// and 'slasherWallet' is the wallet of an authorized slasher.
|
|
177
|
+
|
|
178
|
+
async function slashExistingStake(stakeAddress) {
|
|
179
|
+
try {
|
|
180
|
+
const slashTxHash = await client.slashStake({
|
|
181
|
+
from: stakeAddress,
|
|
182
|
+
reason: 'Validator missed signing 10 consecutive blocks.',
|
|
183
|
+
tokens: [{
|
|
184
|
+
address: 'z35n6aTUTK8h5nAF43h21A1g84g3C3D7B5E',
|
|
185
|
+
value: 10, // Slashing 10 tokens as a penalty
|
|
186
|
+
}],
|
|
187
|
+
wallet: slasherWallet,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
console.log('Slash stake transaction sent:', slashTxHash);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error('Error slashing stake:', error);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Return Value
|
|
198
|
+
|
|
199
|
+
This method returns the transaction hash for the slashing operation.
|
|
200
|
+
|
|
201
|
+
## Summary
|
|
202
|
+
|
|
203
|
+
You've now learned the complete lifecycle of staking on the OCAP blockchain: creating a stake with `stake`, retrieving funds with `revokeStake` and `claimStake`, and penalizing bad actors with `slashStake`. This powerful mechanism is fundamental to many decentralized applications.
|
|
204
|
+
|
|
205
|
+
To learn more about the items you can stake, see the [Manage Tokens](./how-to-guides-manage-tokens.md) and [Manage Assets (NFTs)](./how-to-guides-manage-assets.md) guides.
|