@0xobelisk/sui-client 0.5.27 → 0.5.28
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 +89 -196
- package/dist/dubhe.d.ts +1 -1
- package/dist/errors/index.d.ts +7 -0
- package/dist/index.js +26 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +26 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/dubhe.ts +2 -1
- package/src/errors/index.ts +31 -0
package/README.md
CHANGED
|
@@ -1,78 +1,57 @@
|
|
|
1
1
|
# Dubhe Client SDK
|
|
2
2
|
|
|
3
|
-
Dubhe is client
|
|
4
|
-
|
|
5
|
-
Currently we only support browsers, Node and the COCOS game engine.
|
|
3
|
+
Dubhe is a client-agnostic SDK that supports various platforms including browsers, Node.js, and the COCOS game engine. It provides a simple interface to interact with your Sui Move contracts.
|
|
6
4
|
|
|
7
5
|
## Getting Started
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
### Prerequisites
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
Before using the SDK, make sure you have:
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
1. Created and deployed your contract using the Dubhe CLI
|
|
12
|
+
2. Obtained the `packageId` after deployment
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
### Data Model Setup
|
|
16
15
|
|
|
16
|
+
First, define your contract's configuration using `DubheConfig`:
|
|
17
17
|
|
|
18
18
|
```typescript
|
|
19
19
|
import { DubheConfig } from '@0xobelisk/sui-common';
|
|
20
20
|
|
|
21
|
-
export const
|
|
21
|
+
export const dubheConfig = {
|
|
22
22
|
name: 'counter',
|
|
23
23
|
description: 'counter',
|
|
24
|
-
systems: ['
|
|
24
|
+
systems: ['counter'],
|
|
25
25
|
schemas: {
|
|
26
26
|
counter: {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
structure: {
|
|
28
|
+
value: 'StorageValue<u32>',
|
|
29
|
+
},
|
|
29
30
|
},
|
|
30
31
|
},
|
|
31
|
-
sample_schema: 'u64',
|
|
32
32
|
} as DubheConfig;
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Generate the contract code using CLI:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
|
|
38
|
+
dubhe schemagen --configPath dubhe.config.ts
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
```rust
|
|
44
|
-
// contracts/counter/system/counter_system.move
|
|
45
|
-
module counter::counter_system {
|
|
46
|
-
use counter::world::World;
|
|
47
|
-
use counter::counter_schema;
|
|
48
|
-
|
|
49
|
-
public entry fun inc(world: &mut World){
|
|
50
|
-
let value = counter_schema::get(world) + 1;
|
|
51
|
-
counter_schema::set(world,value);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
```
|
|
41
|
+
### Initializing the Client
|
|
55
42
|
|
|
56
|
-
|
|
43
|
+
There are two ways to initialize the Dubhe client:
|
|
57
44
|
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
obelisk publish --network devnet --configPath dubhe.config.ts
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
We'll get the `packageId` and `worldId` on the command line.
|
|
64
|
-
|
|
65
|
-
### Init Dubhe Client
|
|
45
|
+
1. Using dynamic metadata loading:
|
|
66
46
|
|
|
67
47
|
```typescript
|
|
68
|
-
import {
|
|
69
|
-
|
|
70
|
-
const network = "devnet" as NetworkType
|
|
71
|
-
const packageId = "0x804578b9eed47d461bba52c393cf148302819e2ba0a0f558356cc419b3e941ed"
|
|
48
|
+
import { loadMetadata, Dubhe, NetworkType } from "@0xobelisk/sui-client";
|
|
72
49
|
|
|
73
|
-
const
|
|
50
|
+
const network = "devnet" as NetworkType;
|
|
51
|
+
const packageId = "YOUR_PACKAGE_ID";
|
|
74
52
|
|
|
75
|
-
const
|
|
53
|
+
const metadata = await loadMetadata(network, packageId);
|
|
54
|
+
const dubhe = new Dubhe({
|
|
76
55
|
networkType: network,
|
|
77
56
|
packageId: packageId,
|
|
78
57
|
metadata: metadata,
|
|
@@ -80,205 +59,119 @@ const obelisk = new Dubhe({
|
|
|
80
59
|
});
|
|
81
60
|
```
|
|
82
61
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
If you need to call a method in the system, you can do so using the `obelisk.tx.moudleName.funcName()` form.
|
|
62
|
+
2. Using pre-saved metadata (recommended for better performance):
|
|
86
63
|
|
|
87
64
|
```typescript
|
|
88
|
-
import
|
|
89
|
-
|
|
90
|
-
const metadata = await getMetadata(network, packageId);
|
|
65
|
+
import metadata from './metadata.json';
|
|
91
66
|
|
|
92
|
-
const
|
|
67
|
+
const dubhe = new Dubhe({
|
|
93
68
|
networkType: network,
|
|
94
69
|
packageId: packageId,
|
|
95
70
|
metadata: metadata,
|
|
96
71
|
secretKey: privkey
|
|
97
72
|
});
|
|
98
|
-
|
|
99
|
-
// Initiate transactions through the account set up by obelisk
|
|
100
|
-
const tx = new TransactionBlock()
|
|
101
|
-
|
|
102
|
-
const world = tx.pure(WORLD_ID)
|
|
103
|
-
const params = [
|
|
104
|
-
world,
|
|
105
|
-
]
|
|
106
|
-
|
|
107
|
-
const res_tx = await obelisk.tx.counter_system.inc(tx, params)
|
|
108
|
-
|
|
109
|
-
// If you want to encapsulate the TransactionBlock
|
|
110
|
-
const tx = new TransactionBlock()
|
|
111
|
-
const world = tx.pure(WORLD_ID)
|
|
112
|
-
const params = [
|
|
113
|
-
world,
|
|
114
|
-
]
|
|
115
|
-
// By isolating the signature from the transactionBlock construction in this way,
|
|
116
|
-
// the front-end wallet plugin can signAndSend() directly to the transactionBlock,
|
|
117
|
-
// facilitating front-end interaction.
|
|
118
|
-
const new_tx = await obelisk.tx.counter_system.inc(tx, params, undefined, true) as TransactionBlock;
|
|
119
|
-
|
|
120
|
-
const response = await obelisk.signAndSendTxn(
|
|
121
|
-
new_tx
|
|
122
|
-
)
|
|
123
73
|
```
|
|
124
74
|
|
|
125
|
-
###
|
|
75
|
+
### Executing Transactions
|
|
126
76
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
If your system method provides a method with no modification status and a return, then you can query it via `obelisk.query.moudleName.funcName()`.
|
|
77
|
+
To call contract methods:
|
|
130
78
|
|
|
131
79
|
```typescript
|
|
132
|
-
|
|
133
|
-
const obelisk = new Dubhe({
|
|
134
|
-
networkType: NETWORK,
|
|
135
|
-
packageId: PACKAGE_ID,
|
|
136
|
-
metadata: metadata,
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
const tx = new TransactionBlock()
|
|
140
|
-
const world = tx.pure(WORLD_ID)
|
|
141
|
-
const params = [
|
|
142
|
-
world,
|
|
143
|
-
]
|
|
144
|
-
const query_value = await obelisk.query.counter_system.get(tx, params);
|
|
145
|
-
```
|
|
80
|
+
import { Transaction } from "@0xobelisk/sui-client";
|
|
146
81
|
|
|
147
|
-
|
|
82
|
+
// Create transaction
|
|
83
|
+
const tx = new Transaction();
|
|
84
|
+
const params = [/* your parameters */];
|
|
148
85
|
|
|
149
|
-
|
|
86
|
+
// Execute transaction
|
|
87
|
+
const response = await dubhe.tx.counter_system.inc(tx, params);
|
|
150
88
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
networkType: NETWORK,
|
|
155
|
-
packageId: PACKAGE_ID,
|
|
156
|
-
metadata: metadata,
|
|
157
|
-
});
|
|
158
|
-
const world_value = await obelisk.getWorld(WORLD_ID)
|
|
89
|
+
// For wallet integration
|
|
90
|
+
await dubhe.tx.counter_system.inc(tx, params, undefined, true);
|
|
91
|
+
const response = await dubhe.signAndSendTxn(tx);
|
|
159
92
|
```
|
|
160
93
|
|
|
94
|
+
### Querying Data
|
|
161
95
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
List all schema name in the world store.
|
|
96
|
+
To query contract state:
|
|
165
97
|
|
|
166
98
|
```typescript
|
|
167
|
-
const
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
packageId: PACKAGE_ID,
|
|
171
|
-
metadata: metadata,
|
|
172
|
-
});
|
|
173
|
-
const schemaNames = await obelisk.listSchemaNames(
|
|
174
|
-
'0x1541f3a2e7ac48e3e68e60bb97a7cee94e16316cc3f9043a9c0f5e6790ea3af0'
|
|
175
|
-
);
|
|
176
|
-
```
|
|
99
|
+
const tx = new Transaction();
|
|
100
|
+
const params = [/* your parameters */];
|
|
101
|
+
const result = await dubhe.query.counter_system.get(tx, params);
|
|
177
102
|
|
|
103
|
+
// For BCS encoded results
|
|
104
|
+
const decodedData = dubhe.view(result);
|
|
105
|
+
```
|
|
178
106
|
|
|
179
|
-
|
|
107
|
+
### BCS Data Decoding
|
|
180
108
|
|
|
181
|
-
|
|
109
|
+
The SDK provides a `view()` method to decode BCS-encoded return values from contract queries.
|
|
182
110
|
|
|
183
|
-
|
|
184
|
-
const metadata = await getMetadata(NETWORK, PACKAGE_ID);
|
|
185
|
-
const obelisk = new Dubhe({
|
|
186
|
-
networkType: NETWORK,
|
|
187
|
-
packageId: PACKAGE_ID,
|
|
188
|
-
metadata: metadata,
|
|
189
|
-
});
|
|
111
|
+
#### Supported Types
|
|
190
112
|
|
|
191
|
-
|
|
113
|
+
- Basic types (u8, u16, u32, u64, u128, u256)
|
|
114
|
+
- Boolean
|
|
115
|
+
- String
|
|
116
|
+
- Vector
|
|
117
|
+
- Struct
|
|
118
|
+
- Option
|
|
119
|
+
- Custom objects
|
|
192
120
|
|
|
193
|
-
|
|
194
|
-
const schemaName = "simple_schema"
|
|
195
|
-
const entityId = "0x00000000000000000000000000000000000000000000000000000000000003ed"
|
|
196
|
-
const entities = await obelisk.getEntity(
|
|
197
|
-
worldId,
|
|
198
|
-
schemaName,
|
|
199
|
-
entityId
|
|
200
|
-
);
|
|
121
|
+
#### Example with Complex Types
|
|
201
122
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
123
|
+
```typescript
|
|
124
|
+
// Example contract return type
|
|
125
|
+
struct GameState {
|
|
126
|
+
score: u64,
|
|
127
|
+
player_name: String,
|
|
128
|
+
is_active: bool,
|
|
129
|
+
items: vector<Item>
|
|
130
|
+
}
|
|
208
131
|
|
|
132
|
+
// Query and decode
|
|
133
|
+
const tx = new Transaction();
|
|
134
|
+
const result = await dubhe.query.game_system.get_state(tx, params);
|
|
135
|
+
const decodedState = dubhe.view(result);
|
|
209
136
|
```
|
|
210
137
|
|
|
138
|
+
#### Known Limitations
|
|
211
139
|
|
|
212
|
-
|
|
140
|
+
⚠️ **Important Note**:
|
|
213
141
|
|
|
214
|
-
|
|
142
|
+
1. The current implementation cannot automatically decode enum types due to limitations in Sui metadata.
|
|
143
|
+
2. Some complex nested structures might require additional handling.
|
|
215
144
|
|
|
216
|
-
|
|
217
|
-
const metadata = await getMetadata(NETWORK, PACKAGE_ID);
|
|
218
|
-
const obelisk = new Dubhe({
|
|
219
|
-
networkType: NETWORK,
|
|
220
|
-
packageId: PACKAGE_ID,
|
|
221
|
-
metadata: metadata,
|
|
222
|
-
});
|
|
145
|
+
### Entity Key Generation
|
|
223
146
|
|
|
224
|
-
|
|
147
|
+
Dubhe provides three methods for generating entity keys:
|
|
225
148
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
const entities = await obelisk.containEntity(
|
|
230
|
-
worldId,
|
|
231
|
-
schemaName,
|
|
232
|
-
entityId
|
|
233
|
-
);
|
|
149
|
+
```typescript
|
|
150
|
+
// From object ID
|
|
151
|
+
const objectKey = await dubhe.entity_key_from_object(objectId);
|
|
234
152
|
|
|
235
|
-
//
|
|
236
|
-
const
|
|
237
|
-
const entities = await obelisk.containEntity(
|
|
238
|
-
worldId,
|
|
239
|
-
singletonSchemaName
|
|
240
|
-
);
|
|
153
|
+
// From string data
|
|
154
|
+
const bytesKey = await dubhe.entity_key_from_bytes('hello');
|
|
241
155
|
|
|
156
|
+
// From number
|
|
157
|
+
const numberKey = await dubhe.entity_key_from_u256(123);
|
|
242
158
|
```
|
|
243
159
|
|
|
244
|
-
|
|
160
|
+
### Query Owned Objects
|
|
245
161
|
|
|
246
|
-
|
|
162
|
+
To query objects owned by a specific address:
|
|
247
163
|
|
|
248
164
|
```typescript
|
|
249
|
-
const metadata = await getMetadata(NETWORK, PACKAGE_ID);
|
|
250
|
-
const obelisk = new Dubhe({
|
|
251
|
-
networkType: NETWORK,
|
|
252
|
-
packageId: PACKAGE_ID,
|
|
253
|
-
metadata: metadata,
|
|
254
|
-
});
|
|
255
|
-
|
|
256
165
|
const owner = "0xfa99b5b0463fcfb7d0203c701a76da5eda21a96190eb1368ab36a437cc89195e";
|
|
257
|
-
const
|
|
166
|
+
const ownedObjects = await dubhe.getOwnedObjects(owner);
|
|
258
167
|
```
|
|
259
168
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
You can customize how the key is generated in the system, but I recommend that you generate the entity key using the user's address or objectId as the associative data, as this will help you associate the generated entity with address/objectId. This will help you associate the generated entity with the user's address, and then you can quickly determine the creator of the entity by the user's address or objectId.
|
|
263
|
-
|
|
264
|
-
We provide three ways to convert entity keys, and of course you are welcome to contribute more entity key specifications.
|
|
169
|
+
## Best Practices
|
|
265
170
|
|
|
171
|
+
1. Use pre-saved metadata for better performance in production
|
|
172
|
+
2. Implement proper error handling for BCS decoding
|
|
173
|
+
3. Consider the limitations of enum type handling when designing your contract return types
|
|
266
174
|
|
|
267
|
-
|
|
268
|
-
// Create key based on objectId.
|
|
269
|
-
// You can use the user's address as the entity key,
|
|
270
|
-
// or you can use the Id of an object as the entity key.
|
|
271
|
-
//
|
|
272
|
-
// For example: using the objectId of the NFT as the key,
|
|
273
|
-
// you can set the owner of the nft as the owner of the accessed entity.
|
|
274
|
-
let objectAddress = await obelisk.entity_key_from_object(
|
|
275
|
-
'0x1541f3a2e7ac48e3e68e60bb97a7cee94e16316cc3f9043a9c0f5e6790ea3af0'
|
|
276
|
-
);
|
|
277
|
-
|
|
278
|
-
// hexAddress(keccak256(inputStringData))
|
|
279
|
-
let bytesAddress = await obelisk.entity_key_from_bytes('hello');
|
|
280
|
-
|
|
281
|
-
// hexAddress(inputNumberData)
|
|
282
|
-
let numberAddress = await obelisk.entity_key_from_u256(123);
|
|
283
|
-
```
|
|
175
|
+
## Support
|
|
284
176
|
|
|
177
|
+
For more information or support, please visit our GitHub repository or join our community channels.
|
package/dist/dubhe.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export declare class Dubhe {
|
|
|
39
39
|
get query(): MapMoudleFuncQuery;
|
|
40
40
|
get tx(): MapMoudleFuncTx;
|
|
41
41
|
get object(): MapObjectStruct;
|
|
42
|
-
view(dryResult: DevInspectResults): any[]
|
|
42
|
+
view(dryResult: DevInspectResults): any[];
|
|
43
43
|
/**
|
|
44
44
|
* if derivePathParams is not provided or mnemonics is empty, it will return the keypair.
|
|
45
45
|
* else:
|
package/dist/index.js
CHANGED
|
@@ -946,6 +946,31 @@ function numberToAddressHex(num) {
|
|
|
946
946
|
|
|
947
947
|
// src/dubhe.ts
|
|
948
948
|
var import_bcs2 = require("@mysten/bcs");
|
|
949
|
+
|
|
950
|
+
// src/errors/index.ts
|
|
951
|
+
var ContractDataParsingError = class extends Error {
|
|
952
|
+
constructor(dryResult) {
|
|
953
|
+
const error = dryResult?.effects?.status?.error || "";
|
|
954
|
+
const functionMatch = error ? error.match(/function_name: Some\("([^"]+)"\)/) : null;
|
|
955
|
+
const moduleMatch = error ? error.match(/address: ([a-fA-F0-9]+)/) : null;
|
|
956
|
+
const functionName = functionMatch ? functionMatch[1] : "unknown";
|
|
957
|
+
const moduleAddress = moduleMatch ? "0x" + moduleMatch[1] : "unknown";
|
|
958
|
+
const errorMessage = dryResult.error ? dryResult.error : "UNKNOWN_ERROR";
|
|
959
|
+
const message = [
|
|
960
|
+
`
|
|
961
|
+
- Function: ${functionName}`,
|
|
962
|
+
`- Module Address: ${moduleAddress}`,
|
|
963
|
+
`- Error Message: ${errorMessage}`
|
|
964
|
+
].join("\n");
|
|
965
|
+
super(message);
|
|
966
|
+
this.errorType = "ContractDataParsingError";
|
|
967
|
+
this.functionName = functionName;
|
|
968
|
+
this.moduleAddress = moduleAddress;
|
|
969
|
+
this.errorMessage = errorMessage;
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
// src/dubhe.ts
|
|
949
974
|
function isUndefined(value) {
|
|
950
975
|
return value === void 0;
|
|
951
976
|
}
|
|
@@ -1376,7 +1401,7 @@ var Dubhe = class {
|
|
|
1376
1401
|
}
|
|
1377
1402
|
return returnValues;
|
|
1378
1403
|
} else {
|
|
1379
|
-
|
|
1404
|
+
throw new ContractDataParsingError(dryResult);
|
|
1380
1405
|
}
|
|
1381
1406
|
}
|
|
1382
1407
|
/**
|