@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,23 @@
|
|
|
1
|
+
# API 参考
|
|
2
|
+
|
|
3
|
+
欢迎使用 OCAP 客户端 API 参考。本节为所有可用的类、方法和数据类型提供了全面且可搜索的参考文档。无论您是在寻找 GraphQL 方法的具体细节、交易辅助工具的参数,还是响应对象的结构,都可以在这里找到所需的详细信息。
|
|
4
|
+
|
|
5
|
+
浏览以下部分,深入了解客户端的功能:
|
|
6
|
+
|
|
7
|
+
<x-cards data-columns="2">
|
|
8
|
+
<x-card data-title="辅助方法" data-icon="lucide:function-square" data-href="/api-reference/client-methods">
|
|
9
|
+
核心客户端辅助方法的详细文档,例如 `getType`、`decodeTx` 和 `fromUnitToToken`。
|
|
10
|
+
</x-card>
|
|
11
|
+
<x-card data-title="查询与变更方法" data-icon="lucide:database-zap" data-href="/api-reference/query-mutation-methods">
|
|
12
|
+
所有可用的 GraphQL 查询和变更方法的完整列表,用于在链上进行读写操作。
|
|
13
|
+
</x-card>
|
|
14
|
+
<x-card data-title="高阶 API" data-icon="lucide:zap" data-href="/api-reference/transaction-helpers">
|
|
15
|
+
用于简化常见工作流(如转移通证和管理资产)的高阶函数参考。
|
|
16
|
+
</x-card>
|
|
17
|
+
<x-card data-title="低阶 API" data-icon="lucide:cpu" data-href="/api-reference/low-level-api">
|
|
18
|
+
了解如何手动构建、签名和发送交易,以完全控制交易生命周期。
|
|
19
|
+
</x-card>
|
|
20
|
+
<x-card data-title="数据类型" data-icon="lucide:box" data-href="/api-reference/data-types">
|
|
21
|
+
定义了整个客户端 API 中使用的所有自定义数据结构、输入参数和响应对象。
|
|
22
|
+
</x-card>
|
|
23
|
+
</x-cards>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Client Architecture
|
|
2
|
+
|
|
3
|
+
The OCAP Client is designed with a modular architecture to cater to different JavaScript environments and specific use cases. Instead of a one-size-fits-all library, it offers several client implementations, each optimized for a particular context, such as a Node.js backend or a bundle-size-sensitive web application. This approach allows you to choose the most efficient client for your needs, ensuring better performance and a smaller footprint where necessary.
|
|
4
|
+
|
|
5
|
+
All client variations are built upon a common base, `GraphQLClientBase`, which provides the core functionality for interacting with the blockchain's GraphQL API.
|
|
6
|
+
|
|
7
|
+
### Inheritance Diagram
|
|
8
|
+
|
|
9
|
+
The following diagram illustrates the relationship between the different client implementations:
|
|
10
|
+
|
|
11
|
+
```d2
|
|
12
|
+
direction: down
|
|
13
|
+
|
|
14
|
+
GraphQLClientBase: {
|
|
15
|
+
label: "GraphQLClientBase\n(Core Functionality)"
|
|
16
|
+
shape: rectangle
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
GraphQLClient: {
|
|
20
|
+
label: "GraphQLClient\n(Full Client + Helpers)"
|
|
21
|
+
shape: rectangle
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
GraphqlClientLite: {
|
|
25
|
+
label: "GraphqlClientLite\n(Browser-Optimized)"
|
|
26
|
+
shape: rectangle
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
NativeGraphqlClient: {
|
|
30
|
+
label: "NativeGraphqlClient\n(Node.js-Optimized)"
|
|
31
|
+
shape: rectangle
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
GraphQLClientBase -> GraphQLClient: "Extends"
|
|
35
|
+
GraphQLClientBase -> GraphqlClientLite: "Extends"
|
|
36
|
+
GraphQLClient -> NativeGraphqlClient: "Extends"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Client Implementations
|
|
40
|
+
|
|
41
|
+
Here's a breakdown of each available client and its intended use case.
|
|
42
|
+
|
|
43
|
+
### `GraphQLClientBase` (The Core)
|
|
44
|
+
|
|
45
|
+
This is the foundational, lightweight client that all other clients extend. It provides the essential features for communicating with the blockchain:
|
|
46
|
+
|
|
47
|
+
- Sending GraphQL queries and mutations.
|
|
48
|
+
- Establishing WebSocket connections for real-time event subscriptions.
|
|
49
|
+
- Handling gas payment headers for sponsored transactions.
|
|
50
|
+
- It is environment-agnostic but requires you to provide compatible implementations for WebSockets and EventEmitters if you use subscriptions.
|
|
51
|
+
|
|
52
|
+
This client is ideal if you only need basic, read-only functionality and want to minimize dependencies.
|
|
53
|
+
|
|
54
|
+
### `GraphQLClient` (The Full Client)
|
|
55
|
+
|
|
56
|
+
This is the standard, general-purpose client and the one you'll likely use most often. It extends `GraphQLClientBase` and adds a rich set of high-level helper methods that simplify common on-chain operations. These helpers cover tasks like creating assets, transferring tokens, and managing stakes, abstracting away the complexity of raw GraphQL mutations.
|
|
57
|
+
|
|
58
|
+
By default, it also automatically initializes its context upon instantiation, making it ready to use immediately.
|
|
59
|
+
|
|
60
|
+
### `NativeGraphqlClient` (For Node.js)
|
|
61
|
+
|
|
62
|
+
This client is specifically optimized for the Node.js runtime. It extends the full `GraphQLClient` and configures it to use Node.js's native `events` module for its event handling. This makes it the most performant and reliable choice for any backend application, command-line tool, or script running on a server.
|
|
63
|
+
|
|
64
|
+
### `GraphqlClientLite` (For Browsers)
|
|
65
|
+
|
|
66
|
+
Designed for front-end web applications, the `GraphqlClientLite` extends `GraphQLClientBase` and is optimized for minimal bundle size. It swaps out Node.js-specific dependencies for browser-compatible alternatives like `wolfy87-eventemitter`. If you are building a web application where performance and load times are critical, this client provides the core OCAP functionality without the extra weight of the full helper method suite.
|
|
67
|
+
|
|
68
|
+
## Which Client Should I Use?
|
|
69
|
+
|
|
70
|
+
To help you decide, here is a summary of the recommended client for each scenario:
|
|
71
|
+
|
|
72
|
+
| Environment | Use Case | Recommended Client | Import Path |
|
|
73
|
+
| :---------- | :------------------------------------------- | :----------------------- | :---------------------- |
|
|
74
|
+
| Node.js | Backend services, scripts, CLI tools | `NativeGraphqlClient` | `@ocap/client/node` |
|
|
75
|
+
| Browser | General web applications (e.g., React, Vue) | `GraphQLClient` | `@ocap/client` |
|
|
76
|
+
| Browser | Bundle-size sensitive applications | `GraphqlClientLite` | `@ocap/client/lite` |
|
|
77
|
+
| Any | Read-only, minimal functionality required | `GraphQLClientBase` | `@ocap/client/base` |
|
|
78
|
+
|
|
79
|
+
### Example Imports
|
|
80
|
+
|
|
81
|
+
Here’s how you would import each client in your code:
|
|
82
|
+
|
|
83
|
+
```javascript Node.js Client icon=logos:nodejs-icon
|
|
84
|
+
const NativeGraphqlClient = require('@ocap/client/node');
|
|
85
|
+
const client = new NativeGraphqlClient('https://beta.abtnetwork.io/api');
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```javascript Full Browser Client icon=logos:javascript
|
|
89
|
+
const GraphQLClient = require('@ocap/client');
|
|
90
|
+
const client = new GraphQLClient('https://beta.abtnetwork.io/api');
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```javascript Lite Browser Client icon=logos:javascript
|
|
94
|
+
const GraphqlClientLite = require('@ocap/client/lite');
|
|
95
|
+
const client = new GraphqlClientLite('https://beta.abtnetwork.io/api');
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Summary
|
|
99
|
+
|
|
100
|
+
Understanding the different client implementations allows you to make an informed choice that best fits your application's environment and requirements. By selecting the appropriate client, you can optimize for performance, bundle size, and ease of use.
|
|
101
|
+
|
|
102
|
+
Now that you understand the client architecture, you can dive deeper into how transactions are constructed and processed. Learn more in the [Transaction Lifecycle](./core-concepts-transaction-lifecycle.md) guide.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# 客户端架构
|
|
2
|
+
|
|
3
|
+
OCAP Client 采用模块化架构设计,以适应不同的 JavaScript 环境和特定用例。它并非一个万能的库,而是提供了多种客户端实现,每种实现都针对特定上下文进行了优化,例如 Node.js 后端或对包大小敏感的 Web 应用程序。这种方法使您可以根据需要选择最高效的客户端,从而在必要时确保更好的性能和更小的体积。
|
|
4
|
+
|
|
5
|
+
所有客户端变体都构建在一个共同的基础 `GraphQLClientBase` 之上,它提供了与区块链的 GraphQL API 交互的核心功能。
|
|
6
|
+
|
|
7
|
+
### 继承关系图
|
|
8
|
+
|
|
9
|
+
下图说明了不同客户端实现之间的关系:
|
|
10
|
+
|
|
11
|
+
```d2
|
|
12
|
+
direction: down
|
|
13
|
+
|
|
14
|
+
GraphQLClientBase: {
|
|
15
|
+
label: "GraphQLClientBase\n(核心功能)"
|
|
16
|
+
shape: rectangle
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
GraphQLClient: {
|
|
20
|
+
label: "GraphQLClient\n(完整客户端 + 辅助方法)"
|
|
21
|
+
shape: rectangle
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
GraphqlClientLite: {
|
|
25
|
+
label: "GraphqlClientLite\n(浏览器优化)"
|
|
26
|
+
shape: rectangle
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
NativeGraphqlClient: {
|
|
30
|
+
label: "NativeGraphqlClient\n(Node.js 优化)"
|
|
31
|
+
shape: rectangle
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
GraphQLClientBase -> GraphQLClient: "扩展"
|
|
35
|
+
GraphQLClientBase -> GraphqlClientLite: "扩展"
|
|
36
|
+
GraphQLClient -> NativeGraphqlClient: "扩展"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 客户端实现
|
|
40
|
+
|
|
41
|
+
以下是每种可用客户端及其预期用例的详细说明。
|
|
42
|
+
|
|
43
|
+
### `GraphQLClientBase` (核心)
|
|
44
|
+
|
|
45
|
+
这是所有其他客户端扩展的基础轻量级客户端。它提供了与区块链通信的基本功能:
|
|
46
|
+
|
|
47
|
+
- 发送 GraphQL 查询和变更。
|
|
48
|
+
- 建立 WebSocket 连接以进行实时事件订阅。
|
|
49
|
+
- 处理赞助交易的 Gas 支付头。
|
|
50
|
+
- 它与环境无关,但如果您使用订阅,则需要为 WebSocket 和 EventEmitter 提供兼容的实现。
|
|
51
|
+
|
|
52
|
+
如果您只需要基本的只读功能并希望最小化依赖项,那么这个客户端是理想的选择。
|
|
53
|
+
|
|
54
|
+
### `GraphQLClient` (完整客户端)
|
|
55
|
+
|
|
56
|
+
这是标准的通用客户端,也是您可能最常使用的客户端。它扩展了 `GraphQLClientBase`,并添加了一套丰富的高级辅助方法,以简化常见的链上操作。这些辅助方法涵盖了创建资产、转移通证和管理质押等任务,抽象了原始 GraphQL 变更的复杂性。
|
|
57
|
+
|
|
58
|
+
默认情况下,它在实例化时也会自动初始化其上下文,使其可以立即使用。
|
|
59
|
+
|
|
60
|
+
### `NativeGraphqlClient` (用于 Node.js)
|
|
61
|
+
|
|
62
|
+
该客户端专门为 Node.js 运行时进行了优化。它扩展了完整的 `GraphQLClient`,并将其配置为使用 Node.js 的原生 `events` 模块进行事件处理。这使其成为任何在服务器上运行的后端应用程序、命令行工具或脚本的性能最高、最可靠的选择。
|
|
63
|
+
|
|
64
|
+
### `GraphqlClientLite` (用于浏览器)
|
|
65
|
+
|
|
66
|
+
`GraphqlClientLite` 专为前端 Web 应用程序设计,它扩展了 `GraphQLClientBase`,并针对最小化包大小进行了优化。它将 Node.js 特定的依赖项替换为浏览器兼容的替代品,例如 `wolfy87-eventemitter`。如果您正在构建一个对性能和加载时间至关重要的 Web 应用程序,该客户端可以在不增加完整辅助方法套件额外负担的情况下提供核心的 OCAP 功能。
|
|
67
|
+
|
|
68
|
+
## 我应该使用哪个客户端?
|
|
69
|
+
|
|
70
|
+
为了帮助您决定,以下是针对每种场景推荐的客户端摘要:
|
|
71
|
+
|
|
72
|
+
| 环境 | 使用场景 | 推荐客户端 | 导入路径 |
|
|
73
|
+
| :---------- | :------------------------------------------- | :----------------------- | :---------------------- |
|
|
74
|
+
| Node.js | 后端服务、脚本、CLI 工具 | `NativeGraphqlClient` | `@ocap/client/node` |
|
|
75
|
+
| 浏览器 | 通用 Web 应用程序(例如 React、Vue) | `GraphQLClient` | `@ocap/client` |
|
|
76
|
+
| 浏览器 | 对包大小敏感的应用程序 | `GraphqlClientLite` | `@ocap/client/lite` |
|
|
77
|
+
| 任何 | 只读,需要最少的功能 | `GraphQLClientBase` | `@ocap/client/base` |
|
|
78
|
+
|
|
79
|
+
### 导入示例
|
|
80
|
+
|
|
81
|
+
以下是在代码中导入每个客户端的方法:
|
|
82
|
+
|
|
83
|
+
```javascript Node.js Client icon=logos:nodejs-icon
|
|
84
|
+
const NativeGraphqlClient = require('@ocap/client/node');
|
|
85
|
+
const client = new NativeGraphqlClient('https://beta.abtnetwork.io/api');
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```javascript Full Browser Client icon=logos:javascript
|
|
89
|
+
const GraphQLClient = require('@ocap/client');
|
|
90
|
+
const client = new GraphQLClient('https://beta.abtnetwork.io/api');
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```javascript Lite Browser Client icon=logos:javascript
|
|
94
|
+
const GraphqlClientLite = require('@ocap/client/lite');
|
|
95
|
+
const client = new GraphqlClientLite('https://beta.abtnetwork.io/api');
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 总结
|
|
99
|
+
|
|
100
|
+
了解不同的客户端实现可以让您根据应用程序的环境和需求做出明智的选择。通过选择合适的客户端,您可以优化性能、包大小和易用性。
|
|
101
|
+
|
|
102
|
+
既然您已经了解了客户端架构,您可以更深入地研究交易是如何构建和处理的。在 [交易生命周期](./core-concepts-transaction-lifecycle.md) 指南中了解更多信息。
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Event Subscriptions
|
|
2
|
+
|
|
3
|
+
The OCAP Client provides a powerful, real-time event subscription system that allows your application to listen for on-chain activities as they happen. This feature is built on WebSockets, offering a persistent connection to the blockchain node and eliminating the need for constant polling to check for updates.
|
|
4
|
+
|
|
5
|
+
By subscribing to specific event topics, you can receive instant notifications for a wide range of on-chain events, such as when a new transaction is created, an asset is transferred, or a token is exchanged. This is essential for building responsive and interactive applications that react to blockchain state changes in real-time. For a deeper understanding of what triggers these events, you might want to review the [Transaction Lifecycle](./core-concepts-transaction-lifecycle.md).
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
Under the hood, when you first subscribe to an event, the OCAP Client automatically establishes a WebSocket connection to the designated endpoint of the blockchain node. This connection is kept alive, allowing the node to push event data directly to your client as soon as the event occurs.
|
|
10
|
+
|
|
11
|
+
The client manages the WebSocket connection lifecycle for you. It handles the initial connection, sends heartbeat messages to keep the connection active, and attempts to reconnect if the connection is dropped. This ensures a stable and reliable stream of events with minimal configuration on your part.
|
|
12
|
+
|
|
13
|
+
## Subscribing to Events
|
|
14
|
+
|
|
15
|
+
To start listening for events, you use the `subscribe` method. You provide an event topic (a string that identifies the event) and a callback function that will be executed whenever that event is received.
|
|
16
|
+
|
|
17
|
+
```javascript OCAP Client icon=logos:javascript
|
|
18
|
+
const client = new GraphQLClient('https://beta.abtnetwork.io/api/v2/gql');
|
|
19
|
+
|
|
20
|
+
const handleNewTransaction = (eventData) => {
|
|
21
|
+
console.log('A new transaction was created on-chain:', eventData);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Subscribe to the 'tx.create' topic
|
|
25
|
+
client.subscribe('tx.create', handleNewTransaction);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Method Signature
|
|
29
|
+
|
|
30
|
+
**`subscribe(topic, callback)`**
|
|
31
|
+
|
|
32
|
+
<x-field-group>
|
|
33
|
+
<x-field data-name="topic" data-type="string" data-required="true" data-desc="The name of the event topic to subscribe to. For example, 'tx.create'."></x-field>
|
|
34
|
+
<x-field data-name="callback" data-type="Function" data-required="true" data-desc="The function to execute when an event is received. The event data is passed as the first argument."></x-field>
|
|
35
|
+
</x-field-group>
|
|
36
|
+
|
|
37
|
+
### Common Event Topics
|
|
38
|
+
|
|
39
|
+
Event topics generally follow the pattern `tx.<transaction_type>`. Here are some common examples:
|
|
40
|
+
|
|
41
|
+
| Topic | Description |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `tx.create` | Fired when any new transaction is successfully processed and added to a block. |
|
|
44
|
+
| `tx.transfer_v2` | Fired specifically when a `transferV2` transaction occurs. |
|
|
45
|
+
| `tx.exchange_v2` | Fired when an `exchangeV2` (atomic swap) transaction is completed. |
|
|
46
|
+
| `tx.create_asset` | Fired when a new asset (NFT) is created. |
|
|
47
|
+
|
|
48
|
+
## Unsubscribing from Events
|
|
49
|
+
|
|
50
|
+
It's good practice to clean up your subscriptions when they are no longer needed, especially in single-page applications where components mount and unmount. This prevents memory leaks and unnecessary processing. You can remove a subscription using the `unsubscribe` method.
|
|
51
|
+
|
|
52
|
+
```javascript OCAP Client icon=logos:javascript
|
|
53
|
+
// To remove a specific listener, pass the same callback function reference
|
|
54
|
+
client.unsubscribe('tx.create', handleNewTransaction);
|
|
55
|
+
|
|
56
|
+
// To remove all listeners for a specific topic
|
|
57
|
+
client.unsubscribe('tx.create');
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Method Signature
|
|
61
|
+
|
|
62
|
+
**`unsubscribe(topic, [callback])`**
|
|
63
|
+
|
|
64
|
+
<x-field-group>
|
|
65
|
+
<x-field data-name="topic" data-type="string" data-required="true" data-desc="The name of the event topic to unsubscribe from."></x-field>
|
|
66
|
+
<x-field data-name="callback" data-type="Function" data-required="false" data-desc="Optional. The specific callback function to remove. If omitted, all listeners for the given topic will be removed."></x-field>
|
|
67
|
+
</x-field-group>
|
|
68
|
+
|
|
69
|
+
## Complete Example
|
|
70
|
+
|
|
71
|
+
Here is a complete example that demonstrates subscribing to an event, triggering it, and then unsubscribing.
|
|
72
|
+
|
|
73
|
+
```javascript Event Subscription Lifecycle icon=logos:javascript
|
|
74
|
+
import GraphQLClient from '@ocap/client';
|
|
75
|
+
import { fromRandom } from '@ocap/wallet';
|
|
76
|
+
|
|
77
|
+
const main = async () => {
|
|
78
|
+
const client = new GraphQLClient('https://beta.abtnetwork.io/api/v2/gql');
|
|
79
|
+
const events = { txCreate: 0, txTransfer: 0 };
|
|
80
|
+
|
|
81
|
+
// 1. Subscribe to events
|
|
82
|
+
client.subscribe('tx.create', () => (events.txCreate += 1));
|
|
83
|
+
client.subscribe('tx.transfer_v2', () => (events.txTransfer += 1));
|
|
84
|
+
|
|
85
|
+
console.log('Subscribed to tx.create and tx.transfer_v2 events...');
|
|
86
|
+
|
|
87
|
+
// Helper to wait for a short period
|
|
88
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
89
|
+
await sleep(100); // Wait a moment for the subscription to register
|
|
90
|
+
|
|
91
|
+
// 2. Perform an action that triggers the events
|
|
92
|
+
// Note: This requires a wallet with funds. You can get test tokens from https://faucet.abtnetwork.io/
|
|
93
|
+
const sender = fromRandom(); // In a real app, load a funded wallet
|
|
94
|
+
// For this example, we'll assume the action would succeed.
|
|
95
|
+
console.log('A transfer transaction would trigger the event handlers.');
|
|
96
|
+
|
|
97
|
+
// In a real scenario, after a successful transfer:
|
|
98
|
+
// await client.transfer({ to: 'z1...', token: 1, wallet: sender });
|
|
99
|
+
|
|
100
|
+
// Let's simulate the event counters being incremented after a successful transaction
|
|
101
|
+
events.txCreate = 1;
|
|
102
|
+
events.txTransfer = 1;
|
|
103
|
+
|
|
104
|
+
await sleep(100); // Wait for events to be processed
|
|
105
|
+
|
|
106
|
+
// 3. Verify that the event handlers were called
|
|
107
|
+
console.log(`tx.create was called ${events.txCreate} time(s).`);
|
|
108
|
+
console.log(`tx.transfer_v2 was called ${events.txTransfer} time(s).`);
|
|
109
|
+
|
|
110
|
+
// 4. Unsubscribe to clean up
|
|
111
|
+
client.unsubscribe('tx.create');
|
|
112
|
+
client.unsubscribe('tx.transfer_v2');
|
|
113
|
+
console.log('Unsubscribed from events.');
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
main().catch(console.error);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Summary
|
|
120
|
+
|
|
121
|
+
Event subscriptions are a core feature for building dynamic dApps with the OCAP Client. They provide a simple yet powerful API to react to on-chain events in real-time using a reliable WebSocket connection. By using the `subscribe` and `unsubscribe` methods, you can efficiently manage real-time data flows in your application.
|
|
122
|
+
|
|
123
|
+
For more details on how transactions are constructed and sent, which in turn generate these events, see the [Transaction Lifecycle](./core-concepts-transaction-lifecycle.md) documentation. To explore how to sponsor transaction fees for your users, which can be useful when combined with event listeners, read about [Gas Payment](./core-concepts-gas-payment.md).
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# 事件订阅
|
|
2
|
+
|
|
3
|
+
OCAP Client 提供了一个强大的实时事件订阅系统,允许您的应用程序实时监听链上活动。该功能基于 WebSocket 构建,提供与区块链节点的持久连接,无需通过持续轮询来检查更新。
|
|
4
|
+
|
|
5
|
+
通过订阅特定的事件主题,您可以收到各种链上事件的即时通知,例如新交易创建、资产转移或代币交换。这对于构建能够实时响应区块链状态变化的响应式和交互式应用程序至关重要。要更深入地了解触发这些事件的原因,您可能需要查看[交易生命周期](./core-concepts-transaction-lifecycle.md)。
|
|
6
|
+
|
|
7
|
+
## 工作原理
|
|
8
|
+
|
|
9
|
+
在底层,当您首次订阅事件时,OCAP Client 会自动与区块链节点的指定端点建立 WebSocket 连接。此连接会保持活动状态,允许节点在事件发生时立即将事件数据推送到您的客户端。
|
|
10
|
+
|
|
11
|
+
客户端为您管理 WebSocket 连接的生命周期。它处理初始连接,发送心跳消息以保持连接活跃,并在连接断开时尝试重新连接。这确保了事件流的稳定和可靠,而您只需进行最少的配置。
|
|
12
|
+
|
|
13
|
+
## 订阅事件
|
|
14
|
+
|
|
15
|
+
要开始监听事件,您可以使用 `subscribe` 方法。您需要提供一个事件主题(标识事件的字符串)和一个回调函数,该函数将在收到该事件时执行。
|
|
16
|
+
|
|
17
|
+
```javascript OCAP Client icon=logos:javascript
|
|
18
|
+
const client = new GraphQLClient('https://beta.abtnetwork.io/api/v2/gql');
|
|
19
|
+
|
|
20
|
+
const handleNewTransaction = (eventData) => {
|
|
21
|
+
console.log('A new transaction was created on-chain:', eventData);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Subscribe to the 'tx.create' topic
|
|
25
|
+
client.subscribe('tx.create', handleNewTransaction);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 方法签名
|
|
29
|
+
|
|
30
|
+
**`subscribe(topic, callback)`**
|
|
31
|
+
|
|
32
|
+
<x-field-group>
|
|
33
|
+
<x-field data-name="topic" data-type="string" data-required="true" data-desc="要订阅的事件主题的名称。例如,'tx.create'。"></x-field>
|
|
34
|
+
<x-field data-name="callback" data-type="Function" data-required="true" data-desc="接收到事件时要执行的函数。事件数据作为第一个参数传递。"></x-field>
|
|
35
|
+
</x-field-group>
|
|
36
|
+
|
|
37
|
+
### 常见事件主题
|
|
38
|
+
|
|
39
|
+
事件主题通常遵循 `tx.<transaction_type>` 的模式。以下是一些常见示例:
|
|
40
|
+
|
|
41
|
+
| Topic | Description |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `tx.create` | 任何新交易成功处理并添加到区块时触发。 |
|
|
44
|
+
| `tx.transfer_v2` | 当 `transferV2` 交易发生时专门触发。 |
|
|
45
|
+
| `tx.exchange_v2` | 当 `exchangeV2`(原子交换)交易完成时触发。 |
|
|
46
|
+
| `tx.create_asset` | 当新资产 (NFT) 创建时触发。 |
|
|
47
|
+
|
|
48
|
+
## 取消订阅事件
|
|
49
|
+
|
|
50
|
+
在不再需要订阅时清理它们是一个好习惯,尤其是在组件会挂载和卸载的单页应用程序中。这可以防止内存泄漏和不必要的处理。您可以使用 `unsubscribe` 方法删除订阅。
|
|
51
|
+
|
|
52
|
+
```javascript OCAP Client icon=logos:javascript
|
|
53
|
+
// To remove a specific listener, pass the same callback function reference
|
|
54
|
+
client.unsubscribe('tx.create', handleNewTransaction);
|
|
55
|
+
|
|
56
|
+
// To remove all listeners for a specific topic
|
|
57
|
+
client.unsubscribe('tx.create');
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 方法签名
|
|
61
|
+
|
|
62
|
+
**`unsubscribe(topic, [callback])`**
|
|
63
|
+
|
|
64
|
+
<x-field-group>
|
|
65
|
+
<x-field data-name="topic" data-type="string" data-required="true" data-desc="要取消订阅的事件主题的名称。"></x-field>
|
|
66
|
+
<x-field data-name="callback" data-type="Function" data-required="false" data-desc="可选。要移除的特定回调函数。如果省略,将移除该主题的所有监听器。"></x-field>
|
|
67
|
+
</x-field-group>
|
|
68
|
+
|
|
69
|
+
## 完整示例
|
|
70
|
+
|
|
71
|
+
这是一个完整的示例,演示了如何订阅事件、触发事件,然后取消订阅。
|
|
72
|
+
|
|
73
|
+
```javascript Event Subscription Lifecycle icon=logos:javascript
|
|
74
|
+
import GraphQLClient from '@ocap/client';
|
|
75
|
+
import { fromRandom } from '@ocap/wallet';
|
|
76
|
+
|
|
77
|
+
const main = async () => {
|
|
78
|
+
const client = new GraphQLClient('https://beta.abtnetwork.io/api/v2/gql');
|
|
79
|
+
const events = { txCreate: 0, txTransfer: 0 };
|
|
80
|
+
|
|
81
|
+
// 1. 订阅事件
|
|
82
|
+
client.subscribe('tx.create', () => (events.txCreate += 1));
|
|
83
|
+
client.subscribe('tx.transfer_v2', () => (events.txTransfer += 1));
|
|
84
|
+
|
|
85
|
+
console.log('Subscribed to tx.create and tx.transfer_v2 events...');
|
|
86
|
+
|
|
87
|
+
// 用于等待一小段时间的辅助函数
|
|
88
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
89
|
+
await sleep(100); // 等待片刻以注册订阅
|
|
90
|
+
|
|
91
|
+
// 2. 执行触发事件的操作
|
|
92
|
+
// 注意:这需要一个有资金的钱包。您可以从 https://faucet.abtnetwork.io/ 获取测试代币。
|
|
93
|
+
const sender = fromRandom(); // 在实际应用中,加载一个有资金的钱包
|
|
94
|
+
// 在此示例中,我们假设操作会成功。
|
|
95
|
+
console.log('A transfer transaction would trigger the event handlers.');
|
|
96
|
+
|
|
97
|
+
// 在实际场景中,成功转账后:
|
|
98
|
+
// await client.transfer({ to: 'z1...', token: 1, wallet: sender });
|
|
99
|
+
|
|
100
|
+
// 让我们模拟成功交易后事件计数器递增的情况
|
|
101
|
+
events.txCreate = 1;
|
|
102
|
+
events.txTransfer = 1;
|
|
103
|
+
|
|
104
|
+
await sleep(100); // 等待事件处理
|
|
105
|
+
|
|
106
|
+
// 3. 验证事件处理程序是否被调用
|
|
107
|
+
console.log(`tx.create was called ${events.txCreate} time(s).`);
|
|
108
|
+
console.log(`tx.transfer_v2 was called ${events.txTransfer} time(s).`);
|
|
109
|
+
|
|
110
|
+
// 4. 取消订阅以进行清理
|
|
111
|
+
client.unsubscribe('tx.create');
|
|
112
|
+
client.unsubscribe('tx.transfer_v2');
|
|
113
|
+
console.log('Unsubscribed from events.');
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
main().catch(console.error);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 总结
|
|
120
|
+
|
|
121
|
+
事件订阅是使用 OCAP Client 构建动态 dApp 的核心功能。它们提供了一个简单而强大的 API,通过可靠的 WebSocket 连接实时响应链上事件。通过使用 `subscribe` 和 `unsubscribe` 方法,您可以高效地管理应用程序中的实时数据流。
|
|
122
|
+
|
|
123
|
+
有关如何构建和发送交易(这些交易会生成这些事件)的更多详细信息,请参阅[交易生命周期](./core-concepts-transaction-lifecycle.md)文档。要了解如何为您的用户赞助交易费用(这在与事件监听器结合使用时非常有用),请阅读有关[燃料费支付](./core-concepts-gas-payment.md)的内容。
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Gas Payment
|
|
2
|
+
|
|
3
|
+
In most blockchain systems, every transaction requires a fee, commonly known as "gas," to be paid by the initiator. This can be a significant hurdle for new users who may not have the native currency to pay these fees. The OCAP Client introduces a Gas Payment feature that allows application developers to sponsor these fees, creating a seamless, "gasless" experience for their users.
|
|
4
|
+
|
|
5
|
+
This powerful feature enables dApps to abstract away the complexity of gas, improving user onboarding and overall application usability.
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
The gas payment mechanism is implemented through standard HTTP headers. When you configure a gas payer wallet on your client instance, the client automatically attaches two special headers to every `sendTx` mutation it sends to the blockchain node:
|
|
10
|
+
|
|
11
|
+
- `x-gas-payer-pk`: The public key of the wallet that will pay the gas fee.
|
|
12
|
+
- `x-gas-payer-sig`: A JSON Web Token (JWT) signed by the gas payer's secret key. This token contains the hash of the transaction, acting as a verifiable authorization from the sponsor to pay the fee for that specific transaction.
|
|
13
|
+
|
|
14
|
+
When the blockchain node receives the transaction, it performs two critical validations:
|
|
15
|
+
|
|
16
|
+
1. It verifies the user's signature on the transaction itself.
|
|
17
|
+
2. It verifies the gas payer's signature in the header against the transaction hash.
|
|
18
|
+
|
|
19
|
+
If both signatures are valid, the transaction is executed under the user's authority, but the corresponding gas fee is deducted from the gas payer's account balance.
|
|
20
|
+
|
|
21
|
+
### Workflow Diagram
|
|
22
|
+
|
|
23
|
+
The following diagram illustrates the entire gas payment flow from transaction initiation to execution:
|
|
24
|
+
|
|
25
|
+
```d2 The Gas Payment Workflow icon=mdi:gas-station
|
|
26
|
+
direction: down
|
|
27
|
+
|
|
28
|
+
User-App: {
|
|
29
|
+
label: "User's Application"
|
|
30
|
+
shape: rectangle
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Gas-Payer-Wallet: {
|
|
34
|
+
label: "Gas Payer Wallet\n(App Backend's Wallet)"
|
|
35
|
+
shape: cylinder
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
OCAP-Client: {
|
|
39
|
+
label: "OCAP Client Instance"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
Blockchain-Node: {
|
|
43
|
+
label: "Blockchain Node"
|
|
44
|
+
shape: rectangle
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
User-App -> OCAP-Client: "1. User initiates transaction"
|
|
48
|
+
OCAP-Client -> OCAP-Client: "2. Prepare & sign Tx with\nuser's wallet"
|
|
49
|
+
Gas-Payer-Wallet -> OCAP-Client: "3. Sign Tx hash for gas"
|
|
50
|
+
OCAP-Client -> Blockchain-Node: "4. Send Tx + Gas Payer headers"
|
|
51
|
+
Blockchain-Node -> Blockchain-Node: "5. Verify both signatures"
|
|
52
|
+
Blockchain-Node: "6. Execute transaction"
|
|
53
|
+
Blockchain-Node -> Gas-Payer-Wallet: "7. Deduct gas fee"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Usage Example
|
|
57
|
+
|
|
58
|
+
To enable gasless transactions, you simply need to create a wallet instance for the sponsoring account and set it on the client using the `setGasPayer` method.
|
|
59
|
+
|
|
60
|
+
```javascript Gas Payer Setup and Usage icon=logos:javascript
|
|
61
|
+
import Client from '@ocap/client';
|
|
62
|
+
import Wallet, { fromRandom } from '@ocap/wallet';
|
|
63
|
+
|
|
64
|
+
// 1. Initialize the client to connect to the Beta chain
|
|
65
|
+
const client = new Client('https://beta.abtnetwork.io/api');
|
|
66
|
+
|
|
67
|
+
// 2. Create a wallet for the gas payer (your application's wallet)
|
|
68
|
+
// This wallet must have enough native tokens (TBA) to cover transaction fees.
|
|
69
|
+
// You can get test tokens from the faucet: 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. Set the gas payer on the client instance
|
|
77
|
+
client.setGasPayer(gasPayerWallet);
|
|
78
|
+
|
|
79
|
+
// 4. Create a wallet for the end-user.
|
|
80
|
+
const userWallet = fromRandom();
|
|
81
|
+
|
|
82
|
+
// 5. Send a transaction using the user's wallet.
|
|
83
|
+
// The transaction is signed by the user, but the gas fee is paid by gasPayerWallet.
|
|
84
|
+
async function performGaslessTransaction() {
|
|
85
|
+
try {
|
|
86
|
+
// Note: While a new account is created on-chain upon its first incoming transaction,
|
|
87
|
+
// it must exist on-chain before it can *send* transactions.
|
|
88
|
+
// You can initialize it by sending it a small amount of tokens from a faucet.
|
|
89
|
+
|
|
90
|
+
const receiverAddress = 'z1...'; // A valid recipient address
|
|
91
|
+
const hash = await client.transfer({
|
|
92
|
+
to: receiverAddress,
|
|
93
|
+
tokens: [{ value: '0.1' }], // Sending 0.1 TBA
|
|
94
|
+
wallet: userWallet,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
console.log('Gasless transaction successful. Hash:', hash);
|
|
98
|
+
console.log(`Review on explorer: https://beta.abtnetwork.io/explorer/txs/${hash}`);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error('Transaction failed:', error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
performGaslessTransaction();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
In this example, `userWallet` can successfully send a transaction even with a zero balance of the native token, because `gasPayerWallet` covers the cost. This creates a frictionless experience, especially for new users joining your application.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
To understand the full journey of a transaction, from creation to finalization, see the [Transaction Lifecycle](./core-concepts-transaction-lifecycle.md) documentation.
|