@d9-network/ink 0.1.1 → 1.0.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/dist/index.mjs CHANGED
@@ -5,24 +5,9 @@ import { ss58Decode } from "@polkadot-labs/hdkd-helpers";
5
5
  import { HexSink, Src } from "@subsquid/scale-codec";
6
6
  import { AccountId, Bytes as Bytes$1, Option, Struct, Tuple, Variant, Vector, _void, bool, i128, i16, i32, i64, i8, str, u128, u16, u32, u64, u8 } from "@polkadot-api/substrate-bindings";
7
7
  import { blake2b } from "@noble/hashes/blake2.js";
8
+ import { AbortedError, AbortedError as AbortedError$1, ContractError, ContractError as ContractError$1, ContractExecutionError, D9_SS58_PREFIX, DecodeError, DecodeError as DecodeError$1, EncodeError, LangError, LangError as LangError$1, MetadataError, MetadataError as MetadataError$1, NetworkError, SignerError, TimeoutError, TimeoutError as TimeoutError$1, TransactionError, TransactionError as TransactionError$1, isContractError, isErrorType } from "@d9-network/spec";
8
9
  import { catchError, filter, from, map, mergeMap, of, share } from "rxjs";
9
10
 
10
- //#region src/constants.ts
11
- /**
12
- * D9 Network constants
13
- */
14
- /** D9 SS58 address prefix */
15
- const D9_SS58_PREFIX = 9;
16
- /** D9 token decimals */
17
- const D9_DECIMALS = 2;
18
- /** D9 token symbol */
19
- const D9_SYMBOL = "D9";
20
- /** USDT token decimals */
21
- const USDT_DECIMALS = 2;
22
- /** USDT token symbol */
23
- const USDT_SYMBOL = "USDT";
24
-
25
- //#endregion
26
11
  //#region src/encode.ts
27
12
  /**
28
13
  * Encode a contract call for ContractsApi_call state_call.
@@ -152,13 +137,6 @@ function decodeContractCallResult(result) {
152
137
  };
153
138
  }
154
139
  /**
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
140
  * Unwrap the inner value from Result<T, LangError> by checking the variant byte.
163
141
  *
164
142
  * Ink contracts wrap their return values in Result<T, LangError>.
@@ -934,166 +912,77 @@ function createMessageBuilder(descriptor) {
934
912
  }
935
913
 
936
914
  //#endregion
937
- //#region src/errors.ts
938
- /**
939
- * Base error class for all contract-related errors
940
- */
941
- var ContractError = class ContractError extends Error {
942
- timestamp;
943
- cause;
944
- constructor(message, type, label, details, cause) {
945
- super(message, { cause });
946
- this.type = type;
947
- this.label = label;
948
- this.details = details;
949
- this.name = "ContractError";
950
- this.timestamp = /* @__PURE__ */ new Date();
951
- if (Error.captureStackTrace) Error.captureStackTrace(this, ContractError);
952
- }
953
- /**
954
- * Create a formatted error message for logging
955
- */
956
- toLogString() {
957
- const parts = [
958
- `[${this.type}]`,
959
- this.label ? `${this.label}:` : "",
960
- this.message
961
- ].filter(Boolean);
962
- if (this.details) parts.push(`Details: ${JSON.stringify(this.details)}`);
963
- return parts.join(" ");
964
- }
965
- /**
966
- * Convert to a plain object for serialization
967
- */
968
- toJSON() {
969
- return {
970
- name: this.name,
971
- type: this.type,
972
- message: this.message,
973
- label: this.label,
974
- details: this.details,
975
- timestamp: this.timestamp.toISOString(),
976
- stack: this.stack
977
- };
978
- }
979
- };
980
- /**
981
- * Error thrown when contract metadata is missing or invalid
982
- */
983
- var MetadataError = class extends ContractError {
984
- constructor(message, details) {
985
- super(message, "METADATA_ERROR", void 0, details);
986
- this.name = "MetadataError";
987
- }
988
- };
989
- /**
990
- * Error thrown when encoding call data fails
991
- */
992
- var EncodeError = class extends ContractError {
993
- constructor(label, message, details) {
994
- super(message, "ENCODE_ERROR", label, details);
995
- this.name = "EncodeError";
996
- }
997
- };
998
- /**
999
- * Error thrown when decoding response fails
1000
- */
1001
- var DecodeError = class extends ContractError {
1002
- constructor(label, message, details) {
1003
- super(message, "DECODE_ERROR", label, details);
1004
- this.name = "DecodeError";
1005
- }
1006
- };
1007
- /**
1008
- * Error thrown for network/RPC errors
1009
- */
1010
- var NetworkError = class extends ContractError {
1011
- constructor(message, cause, details) {
1012
- super(message, "NETWORK_ERROR", void 0, details, cause);
1013
- this.name = "NetworkError";
1014
- }
1015
- };
1016
- /**
1017
- * Error thrown when contract returns an error result
1018
- */
1019
- var ContractExecutionError = class extends ContractError {
1020
- constructor(label, errorValue) {
1021
- super(`Contract execution failed: ${JSON.stringify(errorValue)}`, "CONTRACT_ERROR", label, errorValue);
1022
- this.errorValue = errorValue;
1023
- this.name = "ContractExecutionError";
1024
- }
1025
- };
1026
- /**
1027
- * Error thrown for Ink LangError
1028
- */
1029
- var LangError = class extends ContractError {
1030
- constructor(label, variant) {
1031
- const variantName = variant === 1 ? "CouldNotReadInput" : `Unknown(${variant})`;
1032
- super(`Ink LangError: ${variantName}`, "LANG_ERROR", label, {
1033
- variant,
1034
- variantName
1035
- });
1036
- this.variant = variant;
1037
- this.name = "LangError";
1038
- }
1039
- };
1040
- /**
1041
- * Error thrown when request times out
1042
- */
1043
- var TimeoutError = class extends ContractError {
1044
- constructor(label, timeoutMs) {
1045
- super(`Request timed out after ${timeoutMs}ms`, "TIMEOUT_ERROR", label, { timeoutMs });
1046
- this.timeoutMs = timeoutMs;
1047
- this.name = "TimeoutError";
1048
- }
1049
- };
1050
- /**
1051
- * Error thrown when request is aborted
1052
- */
1053
- var AbortedError = class extends ContractError {
1054
- constructor(label, reason) {
1055
- super(reason || "Request was aborted", "ABORTED", label, { reason });
1056
- this.name = "AbortedError";
1057
- }
1058
- };
1059
- /**
1060
- * Error thrown for signer-related issues
1061
- */
1062
- var SignerError = class extends ContractError {
1063
- constructor(message, details) {
1064
- super(message, "SIGNER_ERROR", void 0, details);
1065
- this.name = "SignerError";
1066
- }
1067
- };
1068
- /**
1069
- * Error thrown when transaction submission fails
1070
- */
1071
- var TransactionError = class extends ContractError {
1072
- constructor(label, message, txHash, details) {
1073
- super(message, "TX_ERROR", label, {
1074
- ...details,
1075
- txHash
1076
- });
1077
- this.txHash = txHash;
1078
- this.name = "TransactionError";
1079
- }
1080
- };
1081
- /**
1082
- * Type guard to check if an error is a ContractError
1083
- */
1084
- function isContractError(error) {
1085
- return error instanceof ContractError;
1086
- }
915
+ //#region src/rpc.ts
1087
916
  /**
1088
- * Type guard to check for specific error types
917
+ * Create a type-safe RPC proxy from a PolkadotClient
918
+ *
919
+ * This wraps the client's `_request` method with a Proxy that provides
920
+ * a dot-syntax interface with proper TypeScript types.
921
+ *
922
+ * @param client - The PolkadotClient instance
923
+ * @returns A type-safe RPC proxy object
924
+ *
925
+ * @example
926
+ * ```ts
927
+ * const rpc = createTypedRpc(client);
928
+ *
929
+ * // Dot syntax with full type inference
930
+ * const hash = await rpc.chain_getBlockHash(12345);
931
+ * // hash: HexString | null
932
+ *
933
+ * const header = await rpc.chain_getHeader(hash);
934
+ * // header: BlockHeader | null
935
+ *
936
+ * const result = await rpc.state_call("ContractsApi_call", message, blockHash);
937
+ * // result: HexString
938
+ * ```
1089
939
  */
1090
- function isErrorType(error, type) {
1091
- return isContractError(error) && error.type === type;
940
+ function createTypedRpc(client) {
941
+ return new Proxy({}, { get(_target, prop) {
942
+ return (...args) => client._request(prop, args);
943
+ } });
1092
944
  }
1093
945
 
1094
946
  //#endregion
1095
947
  //#region src/contract.ts
1096
948
  /**
949
+ * Decode response data using papi's value codec with proper result unwrapping.
950
+ * This helper handles the common pattern of wrapping inner data in an Ok variant
951
+ * and extracting the actual value from papi's decoded result.
952
+ *
953
+ * @param innerData - The raw response bytes to decode
954
+ * @param codec - The papi codec with value.dec method
955
+ * @param method - Method name for error context
956
+ * @returns Decoded value or error
957
+ */
958
+ function decodeWithPapiFallback(innerData, codec, method) {
959
+ try {
960
+ const fullResult = new Uint8Array(1 + innerData.length);
961
+ fullResult[0] = 0;
962
+ fullResult.set(innerData, 1);
963
+ const papiResult = codec.value.dec(fullResult);
964
+ if (papiResult !== null && typeof papiResult === "object" && "success" in papiResult && "value" in papiResult) {
965
+ if (papiResult.success) return {
966
+ success: true,
967
+ value: papiResult.value
968
+ };
969
+ return {
970
+ success: false,
971
+ error: new DecodeError$1(method, `Contract returned error: ${JSON.stringify(papiResult.value)}`, papiResult.value)
972
+ };
973
+ }
974
+ return {
975
+ success: true,
976
+ value: papiResult
977
+ };
978
+ } catch (error) {
979
+ return {
980
+ success: false,
981
+ error: new DecodeError$1(method, `Failed to decode response: ${error instanceof Error ? error.message : String(error)}`, { error })
982
+ };
983
+ }
984
+ }
985
+ /**
1097
986
  * Patch LangError type in ink metadata to fix the missing index 0 variant issue.
1098
987
  * Uses structuredClone for efficient deep cloning.
1099
988
  */
@@ -1131,7 +1020,7 @@ function createTimeout(ms, label) {
1131
1020
  return {
1132
1021
  promise: new Promise((_, reject) => {
1133
1022
  timeoutId = setTimeout(() => {
1134
- reject(new TimeoutError(label, ms));
1023
+ reject(new TimeoutError$1(label, ms));
1135
1024
  }, ms);
1136
1025
  }),
1137
1026
  clear: () => clearTimeout(timeoutId)
@@ -1141,14 +1030,14 @@ function createTimeout(ms, label) {
1141
1030
  * Check if AbortSignal is aborted and throw if so
1142
1031
  */
1143
1032
  function checkAborted(signal, label) {
1144
- if (signal?.aborted) throw new AbortedError(label, signal.reason);
1033
+ if (signal?.aborted) throw new AbortedError$1(label, signal.reason);
1145
1034
  }
1146
1035
  /**
1147
1036
  * Create a D9 Ink Contract instance
1148
1037
  */
1149
1038
  function createD9InkContract(descriptor, address, options) {
1150
1039
  const { client, typedApi, defaultQueryOptions = {}, defaultSendOptions = {} } = options;
1151
- if (!descriptor.metadata) throw new MetadataError("Contract descriptor must include metadata");
1040
+ if (!descriptor.metadata) throw new MetadataError$1("Contract descriptor must include metadata");
1152
1041
  const patchedMetadata = patchLangErrorInMetadata(descriptor.metadata);
1153
1042
  const builder = getInkDynamicBuilder(getInkLookup(patchedMetadata));
1154
1043
  const patchedDescriptor = {
@@ -1163,6 +1052,7 @@ function createD9InkContract(descriptor, address, options) {
1163
1052
  codecRegistry = /* @__PURE__ */ new Map();
1164
1053
  }
1165
1054
  const addressBytes = ss58ToBytes(address);
1055
+ const rpc = createTypedRpc(client);
1166
1056
  const messageCodecCache = /* @__PURE__ */ new Map();
1167
1057
  function getMessageCodec(label) {
1168
1058
  const cached = messageCodecCache.get(label);
@@ -1193,11 +1083,7 @@ function createD9InkContract(descriptor, address, options) {
1193
1083
  const blockHash = at ?? (await client.getFinalizedBlock()).hash;
1194
1084
  checkAborted(signal, method);
1195
1085
  const executeCall = async () => {
1196
- return fromHex(await client._request("state_call", [
1197
- "ContractsApi_call",
1198
- message$1,
1199
- blockHash
1200
- ]));
1086
+ return fromHex(await rpc.state_call("ContractsApi_call", message$1, blockHash));
1201
1087
  };
1202
1088
  let rawResponse;
1203
1089
  if (timeout) {
@@ -1212,11 +1098,11 @@ function createD9InkContract(descriptor, address, options) {
1212
1098
  const callResult = decodeContractCallResult(rawResponse);
1213
1099
  if (!callResult.success) return {
1214
1100
  success: false,
1215
- error: new ContractError(`Contract execution failed: ${callResult.debugMessage}`, "CONTRACT_ERROR", method)
1101
+ error: new ContractError$1(`Contract execution failed: ${callResult.debugMessage}`, "CONTRACT_ERROR", method)
1216
1102
  };
1217
1103
  if (isLangError(callResult.data)) return {
1218
1104
  success: false,
1219
- error: new LangError(method, callResult.data[1] ?? 1)
1105
+ error: new LangError$1(method, callResult.data[1] ?? 1)
1220
1106
  };
1221
1107
  const innerData = unwrapInkResult(callResult.data);
1222
1108
  let decodedResponse;
@@ -1225,35 +1111,20 @@ function createD9InkContract(descriptor, address, options) {
1225
1111
  decodedResponse = decoder.dec(innerData);
1226
1112
  } catch (decodeError) {
1227
1113
  console.warn("D9InkContract: Failed to decode response:", decodeError);
1228
- const fullResult = new Uint8Array(1 + innerData.length);
1229
- fullResult[0] = 0;
1230
- fullResult.set(innerData, 1);
1231
- try {
1232
- const papiResult = codec.value.dec(fullResult);
1233
- if (papiResult !== null && typeof papiResult === "object" && "success" in papiResult && "value" in papiResult) if (papiResult.success) decodedResponse = papiResult.value;
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
- }
1114
+ const fallbackResult = decodeWithPapiFallback(innerData, codec, method);
1115
+ if (!fallbackResult.success) return {
1116
+ success: false,
1117
+ error: fallbackResult.error
1118
+ };
1119
+ decodedResponse = fallbackResult.value;
1245
1120
  }
1246
1121
  else {
1247
- const fullResult = new Uint8Array(1 + innerData.length);
1248
- fullResult[0] = 0;
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 {
1122
+ const fallbackResult = decodeWithPapiFallback(innerData, codec, method);
1123
+ if (!fallbackResult.success) return {
1253
1124
  success: false,
1254
- error: new DecodeError(method, `Contract returned error: ${JSON.stringify(papiResult.value)}`, papiResult.value)
1125
+ error: fallbackResult.error
1255
1126
  };
1256
- else decodedResponse = papiResult;
1127
+ decodedResponse = fallbackResult.value;
1257
1128
  }
1258
1129
  return {
1259
1130
  success: true,
@@ -1270,13 +1141,13 @@ function createD9InkContract(descriptor, address, options) {
1270
1141
  })
1271
1142
  };
1272
1143
  } catch (error) {
1273
- if (error instanceof ContractError) return {
1144
+ if (error instanceof ContractError$1) return {
1274
1145
  success: false,
1275
1146
  error
1276
1147
  };
1277
1148
  return {
1278
1149
  success: false,
1279
- error: new ContractError(error instanceof Error ? error.message : String(error), "NETWORK_ERROR", method)
1150
+ error: new ContractError$1(error instanceof Error ? error.message : String(error), "NETWORK_ERROR", method)
1280
1151
  };
1281
1152
  }
1282
1153
  }
@@ -1293,17 +1164,13 @@ function createD9InkContract(descriptor, address, options) {
1293
1164
  return {
1294
1165
  getEncodedData: () => callData,
1295
1166
  async signAndSubmit(signer) {
1296
- if (!typedApi) throw new TransactionError(method, "typedApi is required for transaction submission. Pass typedApi in SDK options.");
1167
+ if (!typedApi) throw new TransactionError$1(method, "typedApi is required for transaction submission. Pass typedApi in SDK options.");
1297
1168
  try {
1298
1169
  let gas = gasLimit;
1299
1170
  if (!gas) {
1300
1171
  const message$1 = encodeContractCall(originBytes, addressBytes, callData, value);
1301
1172
  const blockHash = (await client.getFinalizedBlock()).hash;
1302
- gas = decodeContractCallResult(fromHex(await client._request("state_call", [
1303
- "ContractsApi_call",
1304
- message$1,
1305
- blockHash
1306
- ]))).gas.gasRequired;
1173
+ gas = decodeContractCallResult(fromHex(await rpc.state_call("ContractsApi_call", message$1, blockHash))).gas.gasRequired;
1307
1174
  }
1308
1175
  const txResult = await typedApi.tx.Contracts.call({
1309
1176
  dest: {
@@ -1346,22 +1213,31 @@ function createD9InkContract(descriptor, address, options) {
1346
1213
  return createSendableTransaction(method, sendOptions);
1347
1214
  }
1348
1215
  /**
1349
- * Create storage query interface
1216
+ * Create storage query interface.
1217
+ *
1218
+ * @deprecated Storage queries are not yet implemented. This API is exposed for
1219
+ * future compatibility but will throw errors if used. Use contract messages
1220
+ * (query/send) to read contract state instead.
1221
+ *
1222
+ * @returns ContractStorage interface with unimplemented methods
1350
1223
  */
1351
1224
  function getStorage() {
1225
+ const notImplementedWarning = (method) => {
1226
+ console.warn(`[D9InkContract] ${method}() is not implemented. Storage queries are planned for a future release. Use contract messages to read state instead.`);
1227
+ };
1352
1228
  return {
1353
1229
  async getRoot() {
1354
- console.warn("D9InkContract: getRoot not implemented");
1230
+ notImplementedWarning("getRoot");
1355
1231
  return {
1356
1232
  success: false,
1357
- value: new ContractError("Storage queries not yet implemented", "METADATA_ERROR")
1233
+ value: new ContractError$1("Storage queries not yet implemented. Use contract messages to read state.", "METADATA_ERROR")
1358
1234
  };
1359
1235
  },
1360
1236
  async getNested(path, ..._keys) {
1361
- console.warn("D9InkContract: getNested not implemented");
1237
+ notImplementedWarning("getNested");
1362
1238
  return {
1363
1239
  success: false,
1364
- value: new ContractError(`Storage query for "${path}" not yet implemented`, "METADATA_ERROR")
1240
+ value: new ContractError$1(`Storage query for "${path}" not yet implemented. Use contract messages to read state.`, "METADATA_ERROR")
1365
1241
  };
1366
1242
  }
1367
1243
  };
@@ -1412,37 +1288,6 @@ function createD9InkContract(descriptor, address, options) {
1412
1288
  };
1413
1289
  }
1414
1290
 
1415
- //#endregion
1416
- //#region src/rpc.ts
1417
- /**
1418
- * Create a type-safe RPC request function from a PolkadotClient
1419
- *
1420
- * This wraps the client's `_request` method with proper TypeScript types,
1421
- * providing autocomplete for known RPC methods and type inference for
1422
- * parameters and return values.
1423
- *
1424
- * @param client - The PolkadotClient instance
1425
- * @returns A type-safe RPC request function
1426
- *
1427
- * @example
1428
- * ```ts
1429
- * const rpc = createTypedRpc(client);
1430
- *
1431
- * // Autocomplete for method names, typed params and return
1432
- * const hash = await rpc("chain_getBlockHash", [12345]);
1433
- * // hash: HexString | null
1434
- *
1435
- * const header = await rpc("chain_getHeader", [hash]);
1436
- * // header: BlockHeader | null
1437
- *
1438
- * // Custom methods still work with explicit types
1439
- * const custom = await rpc<MyType>("my_custom_method", [arg]);
1440
- * ```
1441
- */
1442
- function createTypedRpc(client) {
1443
- return ((method, params) => client._request(method, params));
1444
- }
1445
-
1446
1291
  //#endregion
1447
1292
  //#region src/sdk.ts
1448
1293
  /**
@@ -1980,5 +1825,5 @@ function gasExceedsLimit(gas, limit) {
1980
1825
  }
1981
1826
 
1982
1827
  //#endregion
1983
- export { AbortedError, ContractCallParser, ContractError, ContractEventParser, ContractExecutionError, D9_DECIMALS, D9_SS58_PREFIX, D9_SYMBOL, DecodeError, EncodeError, InkCodecs, LangError, MetadataError, NetworkError, SignerError, TimeoutError, TransactionError, USDT_DECIMALS, USDT_SYMBOL, applyGasMargin, buildAllEventDecoders, buildAllMessageDecoders, buildEventDecoder, buildMessageDecoder, compareGasWeight, createAsciiEventTopic, createCodecRegistry, createContractEventStream, createD9InkContract, createD9InkSdk, createMessageBuilder, createNativeTransferStream, createPSP22TransferStream, createTypedRpc, decodeContractCallResult, decodeInkValue, decodeResult, encodeCall, encodeContractCall, encodeContractCallWithLimits, estimateTransactionCost, formatGasInfo, gasExceedsLimit, getEventSignature, isCallType, isContractError, isErrorType, isEventType, isLangError, unwrapInkResult };
1828
+ export { AbortedError, ContractCallParser, ContractError, ContractEventParser, ContractExecutionError, DecodeError, EncodeError, InkCodecs, LangError, MetadataError, NetworkError, SignerError, TimeoutError, TransactionError, applyGasMargin, buildAllEventDecoders, buildAllMessageDecoders, buildEventDecoder, buildMessageDecoder, compareGasWeight, createAsciiEventTopic, createCodecRegistry, createContractEventStream, createD9InkContract, createD9InkSdk, createMessageBuilder, createNativeTransferStream, createPSP22TransferStream, createTypedRpc, decodeContractCallResult, decodeInkValue, encodeCall, encodeContractCall, encodeContractCallWithLimits, estimateTransactionCost, formatGasInfo, gasExceedsLimit, getEventSignature, isCallType, isContractError, isErrorType, isEventType, isLangError, unwrapInkResult };
1984
1829
  //# sourceMappingURL=index.mjs.map