@d9-network/ink 0.1.0 → 0.2.0
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 +82 -0
- package/dist/index.cjs +78 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -9
- package/dist/index.d.mts +21 -9
- package/dist/index.mjs +79 -40
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# @d9-network/ink
|
|
2
|
+
|
|
3
|
+
Type-safe SDK for interacting with ink! smart contracts on the D9 blockchain network.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @d9-network/ink
|
|
9
|
+
# or
|
|
10
|
+
bun add @d9-network/ink
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @d9-network/ink
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { createD9InkSdk } from "@d9-network/ink";
|
|
19
|
+
import { usdt } from "@d9-network/spec"; // Contract descriptor
|
|
20
|
+
|
|
21
|
+
// Create SDK instance
|
|
22
|
+
const sdk = await createD9InkSdk({
|
|
23
|
+
endpoint: "wss://mainnet.d9network.xyz:40300",
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Create contract instance
|
|
27
|
+
const contract = sdk.createContract(usdt, "cXYZ...contractAddress");
|
|
28
|
+
|
|
29
|
+
// Query contract state
|
|
30
|
+
const result = await contract.query("PSP22::balance_of", {
|
|
31
|
+
origin: "cXYZ...yourAddress",
|
|
32
|
+
args: { owner: "cXYZ...targetAddress" },
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (result.success) {
|
|
36
|
+
console.log("Balance:", result.value);
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
- **Type-safe contract interactions**: Full TypeScript inference for message parameters and return types
|
|
43
|
+
- **Automatic gas estimation**: Dry-run execution before submitting transactions
|
|
44
|
+
- **AccountId with D9 prefix**: All addresses automatically use D9 SS58 prefix (9)
|
|
45
|
+
- **Event parsing**: Type-safe decoding of contract events
|
|
46
|
+
- **Comprehensive error handling**: Detailed error types for debugging
|
|
47
|
+
|
|
48
|
+
## API Overview
|
|
49
|
+
|
|
50
|
+
### SDK Creation
|
|
51
|
+
|
|
52
|
+
| Export | Description |
|
|
53
|
+
| --------------------- | -------------------------- |
|
|
54
|
+
| `createD9InkSdk` | Create ink SDK instance |
|
|
55
|
+
| `createD9InkContract` | Create individual contract |
|
|
56
|
+
|
|
57
|
+
### Encoding/Decoding
|
|
58
|
+
|
|
59
|
+
| Export | Description |
|
|
60
|
+
| -------------------------- | --------------------------- |
|
|
61
|
+
| `encodeCall` | Encode contract call |
|
|
62
|
+
| `decodeContractCallResult` | Decode contract call result |
|
|
63
|
+
| `InkCodecs` | Pre-defined SCALE codecs |
|
|
64
|
+
|
|
65
|
+
### Error Types
|
|
66
|
+
|
|
67
|
+
| Export | Description |
|
|
68
|
+
| --------------- | --------------------- |
|
|
69
|
+
| `ContractError` | Base contract error |
|
|
70
|
+
| `DecodeError` | Result decoding error |
|
|
71
|
+
| `LangError` | ink! language error |
|
|
72
|
+
| `NetworkError` | RPC/WebSocket error |
|
|
73
|
+
|
|
74
|
+
## Documentation
|
|
75
|
+
|
|
76
|
+
For complete documentation, examples, and API reference, visit:
|
|
77
|
+
|
|
78
|
+
- [D9 SDK Documentation](https://docs.d9network.xyz/docs/sdk/ink/overview)
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -11,10 +11,25 @@ let rxjs = require("rxjs");
|
|
|
11
11
|
/**
|
|
12
12
|
* D9 Network constants
|
|
13
13
|
*/
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* D9 SS58 address prefix.
|
|
16
|
+
*
|
|
17
|
+
* SS58 is the address format used by Substrate-based chains. Each chain has a unique
|
|
18
|
+
* prefix that determines the address format and ensures addresses are network-specific.
|
|
19
|
+
*
|
|
20
|
+
* D9 uses prefix 9, which produces addresses starting with 'c' or 'd'.
|
|
21
|
+
*
|
|
22
|
+
* This prefix is automatically applied to all AccountId encoding/decoding operations
|
|
23
|
+
* in the SDK, including:
|
|
24
|
+
* - Contract call parameter encoding
|
|
25
|
+
* - Result decoding
|
|
26
|
+
* - Event parsing
|
|
27
|
+
*
|
|
28
|
+
* @see https://github.com/paritytech/ss58-registry for the full SS58 registry
|
|
29
|
+
*/
|
|
15
30
|
const D9_SS58_PREFIX = 9;
|
|
16
31
|
/** D9 token decimals */
|
|
17
|
-
const D9_DECIMALS =
|
|
32
|
+
const D9_DECIMALS = 12;
|
|
18
33
|
/** D9 token symbol */
|
|
19
34
|
const D9_SYMBOL = "D9";
|
|
20
35
|
/** USDT token decimals */
|
|
@@ -152,13 +167,6 @@ function decodeContractCallResult(result) {
|
|
|
152
167
|
};
|
|
153
168
|
}
|
|
154
169
|
/**
|
|
155
|
-
* Legacy function - decode and return just the exec result data.
|
|
156
|
-
* @deprecated Use decodeContractCallResult for full information
|
|
157
|
-
*/
|
|
158
|
-
function decodeResult(result) {
|
|
159
|
-
return decodeContractCallResult(result).data;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
170
|
* Unwrap the inner value from Result<T, LangError> by checking the variant byte.
|
|
163
171
|
*
|
|
164
172
|
* Ink contracts wrap their return values in Result<T, LangError>.
|
|
@@ -1094,6 +1102,43 @@ function isErrorType(error, type) {
|
|
|
1094
1102
|
//#endregion
|
|
1095
1103
|
//#region src/contract.ts
|
|
1096
1104
|
/**
|
|
1105
|
+
* Decode response data using papi's value codec with proper result unwrapping.
|
|
1106
|
+
* This helper handles the common pattern of wrapping inner data in an Ok variant
|
|
1107
|
+
* and extracting the actual value from papi's decoded result.
|
|
1108
|
+
*
|
|
1109
|
+
* @param innerData - The raw response bytes to decode
|
|
1110
|
+
* @param codec - The papi codec with value.dec method
|
|
1111
|
+
* @param method - Method name for error context
|
|
1112
|
+
* @returns Decoded value or error
|
|
1113
|
+
*/
|
|
1114
|
+
function decodeWithPapiFallback(innerData, codec, method) {
|
|
1115
|
+
try {
|
|
1116
|
+
const fullResult = new Uint8Array(1 + innerData.length);
|
|
1117
|
+
fullResult[0] = 0;
|
|
1118
|
+
fullResult.set(innerData, 1);
|
|
1119
|
+
const papiResult = codec.value.dec(fullResult);
|
|
1120
|
+
if (papiResult !== null && typeof papiResult === "object" && "success" in papiResult && "value" in papiResult) {
|
|
1121
|
+
if (papiResult.success) return {
|
|
1122
|
+
success: true,
|
|
1123
|
+
value: papiResult.value
|
|
1124
|
+
};
|
|
1125
|
+
return {
|
|
1126
|
+
success: false,
|
|
1127
|
+
error: new DecodeError(method, `Contract returned error: ${JSON.stringify(papiResult.value)}`, papiResult.value)
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
return {
|
|
1131
|
+
success: true,
|
|
1132
|
+
value: papiResult
|
|
1133
|
+
};
|
|
1134
|
+
} catch (error) {
|
|
1135
|
+
return {
|
|
1136
|
+
success: false,
|
|
1137
|
+
error: new DecodeError(method, `Failed to decode response: ${error instanceof Error ? error.message : String(error)}`, { error })
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1097
1142
|
* Patch LangError type in ink metadata to fix the missing index 0 variant issue.
|
|
1098
1143
|
* Uses structuredClone for efficient deep cloning.
|
|
1099
1144
|
*/
|
|
@@ -1225,35 +1270,20 @@ function createD9InkContract(descriptor, address, options) {
|
|
|
1225
1270
|
decodedResponse = decoder.dec(innerData);
|
|
1226
1271
|
} catch (decodeError) {
|
|
1227
1272
|
console.warn("D9InkContract: Failed to decode response:", decodeError);
|
|
1228
|
-
const
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
else return {
|
|
1235
|
-
success: false,
|
|
1236
|
-
error: new DecodeError(method, `Contract returned error: ${JSON.stringify(papiResult.value)}`, papiResult.value)
|
|
1237
|
-
};
|
|
1238
|
-
else decodedResponse = papiResult;
|
|
1239
|
-
} catch (error) {
|
|
1240
|
-
return {
|
|
1241
|
-
success: false,
|
|
1242
|
-
error: new DecodeError(method, `Failed to decode response: ${error instanceof Error ? error.message : String(error)}`, { error })
|
|
1243
|
-
};
|
|
1244
|
-
}
|
|
1273
|
+
const fallbackResult = decodeWithPapiFallback(innerData, codec, method);
|
|
1274
|
+
if (!fallbackResult.success) return {
|
|
1275
|
+
success: false,
|
|
1276
|
+
error: fallbackResult.error
|
|
1277
|
+
};
|
|
1278
|
+
decodedResponse = fallbackResult.value;
|
|
1245
1279
|
}
|
|
1246
1280
|
else {
|
|
1247
|
-
const
|
|
1248
|
-
|
|
1249
|
-
fullResult.set(innerData, 1);
|
|
1250
|
-
const papiResult = codec.value.dec(fullResult);
|
|
1251
|
-
if (papiResult !== null && typeof papiResult === "object" && "success" in papiResult && "value" in papiResult) if (papiResult.success) decodedResponse = papiResult.value;
|
|
1252
|
-
else return {
|
|
1281
|
+
const fallbackResult = decodeWithPapiFallback(innerData, codec, method);
|
|
1282
|
+
if (!fallbackResult.success) return {
|
|
1253
1283
|
success: false,
|
|
1254
|
-
error:
|
|
1284
|
+
error: fallbackResult.error
|
|
1255
1285
|
};
|
|
1256
|
-
|
|
1286
|
+
decodedResponse = fallbackResult.value;
|
|
1257
1287
|
}
|
|
1258
1288
|
return {
|
|
1259
1289
|
success: true,
|
|
@@ -1346,22 +1376,31 @@ function createD9InkContract(descriptor, address, options) {
|
|
|
1346
1376
|
return createSendableTransaction(method, sendOptions);
|
|
1347
1377
|
}
|
|
1348
1378
|
/**
|
|
1349
|
-
* Create storage query interface
|
|
1379
|
+
* Create storage query interface.
|
|
1380
|
+
*
|
|
1381
|
+
* @deprecated Storage queries are not yet implemented. This API is exposed for
|
|
1382
|
+
* future compatibility but will throw errors if used. Use contract messages
|
|
1383
|
+
* (query/send) to read contract state instead.
|
|
1384
|
+
*
|
|
1385
|
+
* @returns ContractStorage interface with unimplemented methods
|
|
1350
1386
|
*/
|
|
1351
1387
|
function getStorage() {
|
|
1388
|
+
const notImplementedWarning = (method) => {
|
|
1389
|
+
console.warn(`[D9InkContract] ${method}() is not implemented. Storage queries are planned for a future release. Use contract messages to read state instead.`);
|
|
1390
|
+
};
|
|
1352
1391
|
return {
|
|
1353
1392
|
async getRoot() {
|
|
1354
|
-
|
|
1393
|
+
notImplementedWarning("getRoot");
|
|
1355
1394
|
return {
|
|
1356
1395
|
success: false,
|
|
1357
|
-
value: new ContractError("Storage queries not yet implemented", "METADATA_ERROR")
|
|
1396
|
+
value: new ContractError("Storage queries not yet implemented. Use contract messages to read state.", "METADATA_ERROR")
|
|
1358
1397
|
};
|
|
1359
1398
|
},
|
|
1360
1399
|
async getNested(path, ..._keys) {
|
|
1361
|
-
|
|
1400
|
+
notImplementedWarning("getNested");
|
|
1362
1401
|
return {
|
|
1363
1402
|
success: false,
|
|
1364
|
-
value: new ContractError(`Storage query for "${path}" not yet implemented
|
|
1403
|
+
value: new ContractError(`Storage query for "${path}" not yet implemented. Use contract messages to read state.`, "METADATA_ERROR")
|
|
1365
1404
|
};
|
|
1366
1405
|
}
|
|
1367
1406
|
};
|
|
@@ -2016,7 +2055,6 @@ exports.createPSP22TransferStream = createPSP22TransferStream;
|
|
|
2016
2055
|
exports.createTypedRpc = createTypedRpc;
|
|
2017
2056
|
exports.decodeContractCallResult = decodeContractCallResult;
|
|
2018
2057
|
exports.decodeInkValue = decodeInkValue;
|
|
2019
|
-
exports.decodeResult = decodeResult;
|
|
2020
2058
|
exports.encodeCall = encodeCall;
|
|
2021
2059
|
exports.encodeContractCall = encodeContractCall;
|
|
2022
2060
|
exports.encodeContractCallWithLimits = encodeContractCallWithLimits;
|