@hardkas/kaspa-rpc 0.8.4-alpha → 0.8.9-alpha

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.d.ts CHANGED
@@ -275,7 +275,7 @@ interface KaspaRpcClient {
275
275
  healthCheck(): Promise<KaspaRpcHealth>;
276
276
  getBalanceByAddress(address: string): Promise<KaspaAddressBalance>;
277
277
  getUtxosByAddress(address: string): Promise<KaspaRpcUtxo[]>;
278
- submitTransaction(rawTransaction: string): Promise<KaspaSubmitTransactionResult>;
278
+ submitTransaction(rawTransaction: unknown): Promise<KaspaSubmitTransactionResult>;
279
279
  getMempoolEntry(txId: string): Promise<MempoolEntry | null>;
280
280
  getTransaction(txId: string): Promise<unknown | null>;
281
281
  getBlockDagInfo(): Promise<BlockDagInfo>;
@@ -288,18 +288,21 @@ declare class JsonWrpcKaspaClient implements KaspaRpcClient {
288
288
  private readonly timeoutMs;
289
289
  private requestId;
290
290
  constructor(options: JsonWrpcKaspaClientOptions);
291
+ private rpcFlavor;
292
+ private preflightPromise;
293
+ private detectFlavor;
294
+ private callMethod;
291
295
  getInfo(): Promise<KaspaNodeInfo>;
292
296
  healthCheck(): Promise<KaspaRpcHealth>;
293
297
  getBalanceByAddress(address: string): Promise<KaspaAddressBalance>;
294
298
  getUtxosByAddress(address: string): Promise<KaspaRpcUtxo[]>;
295
- submitTransaction(rawTransaction: string): Promise<KaspaSubmitTransactionResult>;
299
+ submitTransaction(rawTransaction: unknown): Promise<KaspaSubmitTransactionResult>;
296
300
  getMempoolEntry(txId: string): Promise<MempoolEntry | null>;
297
301
  getTransaction(txId: string): Promise<unknown | null>;
298
302
  getBlockDagInfo(): Promise<BlockDagInfo>;
299
303
  getServerInfo(): Promise<ServerInfo>;
300
304
  close(): Promise<void>;
301
- private safeRequest;
302
- private request;
305
+ private requestRaw;
303
306
  private connect;
304
307
  }
305
308
  declare function mapKaspaNodeInfo(result: any): KaspaNodeInfo;
@@ -315,7 +318,7 @@ declare class MockKaspaRpcClient implements KaspaRpcClient {
315
318
  getBalanceByAddress(address: string): Promise<KaspaAddressBalance>;
316
319
  getUtxosByAddress(address: string): Promise<KaspaRpcUtxo[]>;
317
320
  setUtxos(address: string, utxos: KaspaRpcUtxo[]): void;
318
- submitTransaction(rawTransaction: string): Promise<KaspaSubmitTransactionResult>;
321
+ submitTransaction(rawTransaction: unknown): Promise<KaspaSubmitTransactionResult>;
319
322
  getMempoolEntry(_txId: string): Promise<MempoolEntry | null>;
320
323
  getTransaction(_txId: string): Promise<unknown | null>;
321
324
  getBlockDagInfo(): Promise<BlockDagInfo>;
package/dist/index.js CHANGED
@@ -310,8 +310,51 @@ var KaspaJsonRpcClient = class {
310
310
  }
311
311
  }
312
312
  async submitTransaction(rawTx) {
313
+ let txObj = rawTx;
314
+ try {
315
+ while (typeof txObj === "string" && txObj.startsWith("{")) {
316
+ const parsed = JSON.parse(txObj);
317
+ if (parsed && typeof parsed === "object") {
318
+ if ("tx" in parsed) txObj = parsed.tx;
319
+ else if ("inner" in parsed) txObj = parsed.inner;
320
+ else txObj = parsed;
321
+ } else {
322
+ txObj = parsed;
323
+ }
324
+ }
325
+ while (txObj && typeof txObj === "object" && !Array.isArray(txObj) && ("tx" in txObj || "inner" in txObj)) {
326
+ if ("tx" in txObj) txObj = txObj.tx;
327
+ else if ("inner" in txObj) txObj = txObj.inner;
328
+ }
329
+ const txAny = txObj;
330
+ if (txAny && typeof txAny === "object") {
331
+ txAny.mass = txAny.mass || 0;
332
+ if (txAny.payload === void 0) txAny.payload = "";
333
+ if (txAny.outputs && Array.isArray(txAny.outputs)) {
334
+ txAny.outputs.forEach((output) => {
335
+ const amount = output.amount !== void 0 ? output.amount : output.value;
336
+ output.value = typeof amount === "string" ? Number(amount) : amount;
337
+ delete output.amount;
338
+ if (output.scriptPublicKey && typeof output.scriptPublicKey === "object") {
339
+ const spk = output.scriptPublicKey;
340
+ const versionHex = (spk.version || 0).toString(16).padStart(4, "0");
341
+ const scriptHex = spk.script || spk.scriptPublicKey || "";
342
+ output.scriptPublicKey = versionHex + scriptHex;
343
+ }
344
+ });
345
+ }
346
+ if (txAny.inputs && Array.isArray(txAny.inputs)) {
347
+ txAny.inputs.forEach((input) => {
348
+ if (typeof input.sequence === "string") input.sequence = Number(input.sequence);
349
+ if (typeof input.sigOpCount === "string") input.sigOpCount = Number(input.sigOpCount);
350
+ });
351
+ }
352
+ }
353
+ } catch (e) {
354
+ }
313
355
  const result = await this.callRpc("submitTransactionRequest", {
314
- transaction: rawTx
356
+ transaction: txObj,
357
+ allowOrphan: false
315
358
  });
316
359
  return { transactionId: result.transactionId };
317
360
  }
@@ -778,27 +821,40 @@ var JsonWrpcKaspaClient = class {
778
821
  this.rpcUrl = options.rpcUrl;
779
822
  this.timeoutMs = options.timeoutMs ?? 1e4;
780
823
  }
824
+ rpcFlavor = null;
825
+ preflightPromise = null;
826
+ async detectFlavor() {
827
+ if (this.rpcFlavor) return;
828
+ if (this.preflightPromise) return this.preflightPromise;
829
+ this.preflightPromise = (async () => {
830
+ try {
831
+ const ws = await this.connect();
832
+ const res = await this.requestRaw("getServerInfo", {});
833
+ this.rpcFlavor = "wrpc";
834
+ } catch (e) {
835
+ if (e.message && e.message.includes("Method not found")) {
836
+ this.rpcFlavor = "legacy";
837
+ } else {
838
+ this.rpcFlavor = "wrpc";
839
+ }
840
+ }
841
+ })();
842
+ return this.preflightPromise;
843
+ }
844
+ async callMethod(wrpcName, legacyName, params = {}) {
845
+ await this.detectFlavor();
846
+ const method = this.rpcFlavor === "legacy" ? legacyName : wrpcName;
847
+ return this.requestRaw(method, params);
848
+ }
781
849
  async getInfo() {
782
- const response = await this.safeRequest([
783
- "getInfo",
784
- "getInfoRequest",
785
- "GetInfo",
786
- "get_info"
787
- ]);
850
+ const response = await this.callMethod("getInfo", "getInfoRequest");
788
851
  const info = mapKaspaNodeInfo(response);
789
852
  if (info.virtualDaaScore === void 0) {
790
853
  try {
791
- const dagResponse = await this.safeRequest([
792
- "getBlockDagInfo",
793
- "getBlockDagInfoRequest",
794
- "GetBlockDagInfo",
795
- "get_block_dag_info"
796
- ]);
854
+ const dagResponse = await this.callMethod("getBlockDagInfo", "getBlockDagInfoRequest");
797
855
  const dagData = dagResponse?.params || dagResponse;
798
856
  if (dagData && typeof dagData === "object" && "virtualDaaScore" in dagData) {
799
- info.virtualDaaScore = BigInt(
800
- dagData.virtualDaaScore
801
- );
857
+ info.virtualDaaScore = BigInt(dagData.virtualDaaScore);
802
858
  }
803
859
  } catch (e) {
804
860
  }
@@ -824,55 +880,61 @@ var JsonWrpcKaspaClient = class {
824
880
  }
825
881
  }
826
882
  async getBalanceByAddress(address) {
827
- const response = await this.safeRequest(
828
- [
829
- "getBalancesByAddresses",
830
- "getBalancesByAddressesRequest",
831
- "getBalanceByAddressRequest",
832
- "GetBalancesByAddresses",
833
- "get_balances_by_addresses",
834
- "GetBalanceByAddress",
835
- "getBalanceByAddress",
836
- "get_balance_by_address"
837
- ],
838
- { addresses: [address], address }
839
- );
883
+ await this.detectFlavor();
884
+ let response;
885
+ if (this.rpcFlavor === "legacy") {
886
+ response = await this.callMethod("getBalanceByAddress", "getBalanceByAddressRequest", { address });
887
+ } else {
888
+ response = await this.callMethod("getBalancesByAddresses", "getBalancesByAddressesRequest", { addresses: [address] });
889
+ }
840
890
  return mapKaspaAddressBalance(response, address);
841
891
  }
842
892
  async getUtxosByAddress(address) {
843
- const response = await this.safeRequest(
844
- [
845
- "getUtxosByAddresses",
846
- "getUtxosByAddressesRequest",
847
- "getUtxosByAddressRequest",
848
- "GetUtxosByAddresses",
849
- "get_utxos_by_addresses",
850
- "GetUtxosByAddress",
851
- "getUtxosByAddress",
852
- "get_utxos_by_address"
853
- ],
854
- { addresses: [address], address }
855
- );
893
+ const response = await this.callMethod("getUtxosByAddresses", "getUtxosByAddressesRequest", { addresses: [address] });
856
894
  return mapKaspaRpcUtxos(response, address);
857
895
  }
858
896
  async submitTransaction(rawTransaction) {
859
- const response = await this.safeRequest(
860
- [
861
- "submitTransaction",
862
- "submitTransactionRequest",
863
- "SubmitTransaction",
864
- "submit_transaction"
865
- ],
866
- { transaction: rawTransaction, transactionHex: rawTransaction, rawTransaction }
867
- );
897
+ let txObj = rawTransaction;
898
+ try {
899
+ while (typeof txObj === "string" && txObj.startsWith("{")) {
900
+ const parsed = JSON.parse(txObj);
901
+ if (parsed && typeof parsed === "object") {
902
+ if ("tx" in parsed) txObj = parsed.tx;
903
+ else if ("inner" in parsed) txObj = parsed.inner;
904
+ else txObj = parsed;
905
+ } else {
906
+ txObj = parsed;
907
+ }
908
+ }
909
+ while (txObj && typeof txObj === "object" && !Array.isArray(txObj) && ("tx" in txObj || "inner" in txObj)) {
910
+ if ("tx" in txObj) txObj = txObj.tx;
911
+ else if ("inner" in txObj) txObj = txObj.inner;
912
+ }
913
+ const txAny = txObj;
914
+ if (txAny && typeof txAny === "object" && txAny.outputs && Array.isArray(txAny.outputs)) {
915
+ txAny.outputs.forEach((output) => {
916
+ if (typeof output.amount === "string") {
917
+ output.amount = Number(output.amount);
918
+ }
919
+ if (typeof output.value === "string") {
920
+ output.value = Number(output.value);
921
+ }
922
+ });
923
+ }
924
+ if (txAny && typeof txAny === "object" && txAny.inputs && Array.isArray(txAny.inputs)) {
925
+ txAny.inputs.forEach((input) => {
926
+ if (typeof input.sequence === "string") input.sequence = Number(input.sequence);
927
+ if (typeof input.sigOpCount === "string") input.sigOpCount = Number(input.sigOpCount);
928
+ });
929
+ }
930
+ } catch (e) {
931
+ }
932
+ const response = await this.callMethod("submitTransaction", "submitTransactionRequest", { transaction: txObj, allowOrphan: false });
868
933
  return mapKaspaSubmitTransactionResult(response);
869
934
  }
870
935
  async getMempoolEntry(txId) {
871
936
  try {
872
- const response = await this.safeRequest(
873
- ["getMempoolEntryRequest", "getMempoolEntry"],
874
- { txId, transactionId: txId }
875
- );
937
+ const response = await this.callMethod("getMempoolEntry", "getMempoolEntryRequest", { transactionId: txId, includeOrphanPool: true, filterTransactionPool: false });
876
938
  if (!response) return null;
877
939
  const resObj = response;
878
940
  return {
@@ -885,11 +947,7 @@ var JsonWrpcKaspaClient = class {
885
947
  }
886
948
  async getTransaction(txId) {
887
949
  try {
888
- const response = await this.safeRequest(
889
- ["getTransactionRequest", "getTransaction"],
890
- { txId, transactionId: txId }
891
- );
892
- return response;
950
+ return await this.callMethod("getTransaction", "getTransactionRequest", { transactionId: txId });
893
951
  } catch (e) {
894
952
  return null;
895
953
  }
@@ -920,41 +978,7 @@ var JsonWrpcKaspaClient = class {
920
978
  this.socket = null;
921
979
  }
922
980
  }
923
- async safeRequest(methods, params = {}) {
924
- let lastError = null;
925
- for (const method of methods) {
926
- try {
927
- let actualParams = params;
928
- const lowerMethod = method.toLowerCase();
929
- const pObj = params;
930
- if (lowerMethod.includes("addresses") || lowerMethod.endsWith("s")) {
931
- if (pObj.address && !pObj.addresses) {
932
- actualParams = { addresses: [pObj.address] };
933
- } else if (pObj.addresses) {
934
- actualParams = { addresses: pObj.addresses };
935
- }
936
- } else if (pObj.addresses && !pObj.address) {
937
- actualParams = { address: pObj.addresses[0] };
938
- } else if (pObj.address) {
939
- actualParams = { address: pObj.address };
940
- }
941
- try {
942
- return await this.request(method, actualParams);
943
- } catch (e) {
944
- if (e.message?.includes("deserialization")) {
945
- const arrayParams = Object.values(actualParams);
946
- return await this.request(method, arrayParams);
947
- }
948
- throw e;
949
- }
950
- } catch (error) {
951
- lastError = error;
952
- continue;
953
- }
954
- }
955
- throw lastError ?? new Error(`Methods failed: ${methods.join(", ")}`);
956
- }
957
- async request(method, params = {}) {
981
+ async requestRaw(method, params = {}) {
958
982
  const ws = await this.connect();
959
983
  const id = this.requestId++;
960
984
  const payload = JSON.stringify({
@@ -1112,7 +1136,7 @@ function mapKaspaSubmitTransactionResult(result) {
1112
1136
  if (!result) return { raw: result };
1113
1137
  return {
1114
1138
  transactionId: result.transactionId || result.transaction_id || result.txId || result.tx_id,
1115
- accepted: result.accepted !== void 0 ? result.accepted : result.isAccepted || result.success,
1139
+ accepted: result.accepted !== void 0 ? result.accepted : result.isAccepted !== void 0 ? result.isAccepted : result.success !== void 0 ? result.success : !!(result.transactionId || result.transaction_id || result.txId || result.tx_id),
1116
1140
  raw: result
1117
1141
  };
1118
1142
  }
package/package.json CHANGED
@@ -1,16 +1,20 @@
1
1
  {
2
2
  "name": "@hardkas/kaspa-rpc",
3
- "version": "0.8.4-alpha",
3
+ "version": "0.8.9-alpha",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "exports": {
8
- ".": "./dist/index.js"
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "default": "./dist/index.js"
12
+ }
9
13
  },
10
14
  "dependencies": {
11
15
  "ws": "^8.18.0",
12
- "@hardkas/core": "0.8.4-alpha",
13
- "@hardkas/tx-builder": "0.8.4-alpha"
16
+ "@hardkas/core": "0.8.9-alpha",
17
+ "@hardkas/tx-builder": "0.8.9-alpha"
14
18
  },
15
19
  "devDependencies": {
16
20
  "@types/ws": "^8.5.13",