genlayer-js 0.12.0 → 0.13.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/CHANGELOG.md +14 -0
- package/README.md +30 -1
- package/dist/index.cjs +138 -10
- package/dist/index.js +138 -10
- package/package.json +1 -1
- package/src/contracts/actions.ts +1 -1
- package/src/transactions/actions.ts +155 -7
- package/tests/client.test.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
## 0.13.0 (2025-07-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* simplify transaction receipt ([#101](https://github.com/genlayerlabs/genlayer-js/issues/101)) ([be78ac6](https://github.com/genlayerlabs/genlayer-js/commit/be78ac6b5871a4d61349bacf87b5fb0da61b1a90))
|
|
9
|
+
|
|
10
|
+
## 0.12.1 (2025-07-21)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* default transaction hash variant ([#100](https://github.com/genlayerlabs/genlayer-js/issues/100)) ([d8926b1](https://github.com/genlayerlabs/genlayer-js/commit/d8926b16f8983df805da713091297a5d353e9332))
|
|
16
|
+
|
|
3
17
|
## 0.12.0 (2025-07-15)
|
|
4
18
|
|
|
5
19
|
|
package/README.md
CHANGED
|
@@ -38,6 +38,31 @@ const transactionHash = "0x...";
|
|
|
38
38
|
const transaction = await client.getTransaction({ hash: transactionHash })
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
### Waiting for Transaction Receipt
|
|
42
|
+
```typescript
|
|
43
|
+
import { localnet } from 'genlayer-js/chains';
|
|
44
|
+
import { createClient } from "genlayer-js";
|
|
45
|
+
import { TransactionStatus } from "genlayer-js/types";
|
|
46
|
+
|
|
47
|
+
const client = createClient({
|
|
48
|
+
chain: localnet,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Get simplified receipt (default - removes binary data, keeps execution results)
|
|
52
|
+
const receipt = await client.waitForTransactionReceipt({
|
|
53
|
+
hash: "0x...",
|
|
54
|
+
status: TransactionStatus.FINALIZED,
|
|
55
|
+
fullTransaction: false // Default - simplified for readability
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Get complete receipt with all fields
|
|
59
|
+
const fullReceipt = await client.waitForTransactionReceipt({
|
|
60
|
+
hash: "0x...",
|
|
61
|
+
status: TransactionStatus.FINALIZED,
|
|
62
|
+
fullTransaction: true // Complete receipt with all internal data
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
41
66
|
### Reading a contract
|
|
42
67
|
```typescript
|
|
43
68
|
import { localnet } from 'genlayer-js/chains';
|
|
@@ -74,7 +99,11 @@ const transactionHash = await client.writeContract({
|
|
|
74
99
|
value: 0, // value is optional, if you want to send some native token to the contract
|
|
75
100
|
});
|
|
76
101
|
|
|
77
|
-
const receipt = await client.waitForTransactionReceipt({
|
|
102
|
+
const receipt = await client.waitForTransactionReceipt({
|
|
103
|
+
hash: txHash,
|
|
104
|
+
status: TransactionStatus.FINALIZED, // or ACCEPTED
|
|
105
|
+
fullTransaction: false // False by default - returns simplified receipt for better readability
|
|
106
|
+
})
|
|
78
107
|
|
|
79
108
|
```
|
|
80
109
|
## 🚀 Key Features
|
package/dist/index.cjs
CHANGED
|
@@ -437,7 +437,7 @@ var contractActions = (client, publicClient) => {
|
|
|
437
437
|
args: callArgs,
|
|
438
438
|
kwargs,
|
|
439
439
|
leaderOnly = false,
|
|
440
|
-
transactionHashVariant = "latest-
|
|
440
|
+
transactionHashVariant = "latest-nonfinal" /* LATEST_NONFINAL */
|
|
441
441
|
} = args;
|
|
442
442
|
const encodedData = [encode(makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
|
|
443
443
|
const serializedData = serialize(encodedData);
|
|
@@ -684,12 +684,55 @@ function resultToUserFriendlyJson(cd64) {
|
|
|
684
684
|
|
|
685
685
|
// src/transactions/actions.ts
|
|
686
686
|
|
|
687
|
+
var FIELDS_TO_REMOVE = [
|
|
688
|
+
"raw",
|
|
689
|
+
"contract_state",
|
|
690
|
+
"base64",
|
|
691
|
+
"consensus_history",
|
|
692
|
+
"tx_data",
|
|
693
|
+
"eq_blocks_outputs",
|
|
694
|
+
"r",
|
|
695
|
+
"s",
|
|
696
|
+
"v",
|
|
697
|
+
"created_timestamp",
|
|
698
|
+
"current_timestamp",
|
|
699
|
+
"tx_execution_hash",
|
|
700
|
+
"random_seed",
|
|
701
|
+
"states",
|
|
702
|
+
"contract_code",
|
|
703
|
+
"appeal_failed",
|
|
704
|
+
"appeal_leader_timeout",
|
|
705
|
+
"appeal_processing_time",
|
|
706
|
+
"appeal_undetermined",
|
|
707
|
+
"appealed",
|
|
708
|
+
"timestamp_appeal",
|
|
709
|
+
"config_rotation_rounds",
|
|
710
|
+
"rotation_count",
|
|
711
|
+
"queue_position",
|
|
712
|
+
"queue_type",
|
|
713
|
+
"leader_timeout_validators",
|
|
714
|
+
"triggered_by",
|
|
715
|
+
"num_of_initial_validators",
|
|
716
|
+
"timestamp_awaiting_finalization",
|
|
717
|
+
"last_vote_timestamp",
|
|
718
|
+
"read_state_block_range",
|
|
719
|
+
"tx_slot",
|
|
720
|
+
"blockHash",
|
|
721
|
+
"blockNumber",
|
|
722
|
+
"to",
|
|
723
|
+
"transactionIndex"
|
|
724
|
+
];
|
|
725
|
+
var FIELD_NAME_MAPPINGS = {
|
|
726
|
+
statusName: "status_name",
|
|
727
|
+
typeHex: "type"
|
|
728
|
+
};
|
|
687
729
|
var receiptActions = (client, publicClient) => ({
|
|
688
730
|
waitForTransactionReceipt: async ({
|
|
689
731
|
hash,
|
|
690
732
|
status = "ACCEPTED" /* ACCEPTED */,
|
|
691
733
|
interval = transactionsConfig.waitInterval,
|
|
692
|
-
retries = transactionsConfig.retries
|
|
734
|
+
retries = transactionsConfig.retries,
|
|
735
|
+
fullTransaction = false
|
|
693
736
|
}) => {
|
|
694
737
|
const transaction = await client.getTransaction({
|
|
695
738
|
hash
|
|
@@ -701,10 +744,14 @@ var receiptActions = (client, publicClient) => ({
|
|
|
701
744
|
const transactionStatusFinalized = _chunkH4ZYXVV2cjs.transactionsStatusNameToNumber["FINALIZED" /* FINALIZED */];
|
|
702
745
|
const requestedStatus = _chunkH4ZYXVV2cjs.transactionsStatusNameToNumber[status];
|
|
703
746
|
if (transactionStatusString === requestedStatus || status === "ACCEPTED" /* ACCEPTED */ && transactionStatusString === transactionStatusFinalized) {
|
|
747
|
+
let finalTransaction = transaction;
|
|
704
748
|
if (client.chain.id === _chunkZKBMABRAcjs.localnet.id) {
|
|
705
|
-
|
|
749
|
+
finalTransaction = _decodeLocalnetTransaction(transaction);
|
|
750
|
+
}
|
|
751
|
+
if (!fullTransaction) {
|
|
752
|
+
return _simplifyTransactionReceipt(finalTransaction);
|
|
706
753
|
}
|
|
707
|
-
return
|
|
754
|
+
return finalTransaction;
|
|
708
755
|
}
|
|
709
756
|
if (retries === 0) {
|
|
710
757
|
throw new Error("Transaction status is not " + status);
|
|
@@ -714,7 +761,8 @@ var receiptActions = (client, publicClient) => ({
|
|
|
714
761
|
hash,
|
|
715
762
|
status,
|
|
716
763
|
interval,
|
|
717
|
-
retries: retries - 1
|
|
764
|
+
retries: retries - 1,
|
|
765
|
+
fullTransaction
|
|
718
766
|
});
|
|
719
767
|
}
|
|
720
768
|
});
|
|
@@ -814,6 +862,77 @@ var _decodeTransaction = (tx) => {
|
|
|
814
862
|
};
|
|
815
863
|
return decodedTx;
|
|
816
864
|
};
|
|
865
|
+
var _simplifyTransactionReceipt = (tx) => {
|
|
866
|
+
const simplifyObject = (obj, path = "") => {
|
|
867
|
+
if (obj === null || obj === void 0) return obj;
|
|
868
|
+
if (Array.isArray(obj)) {
|
|
869
|
+
return obj.map((item) => simplifyObject(item, path)).filter((item) => item !== void 0);
|
|
870
|
+
}
|
|
871
|
+
if (typeof obj === "object") {
|
|
872
|
+
const result = {};
|
|
873
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
874
|
+
const currentPath = path ? `${path}.${key}` : key;
|
|
875
|
+
if (FIELDS_TO_REMOVE.includes(key)) {
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
if (key === "node_config" && !path.includes("consensus_data")) {
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
881
|
+
if (key === "consensus_data" && typeof value === "object" && value !== null) {
|
|
882
|
+
const simplifiedConsensus = {};
|
|
883
|
+
if ("votes" in value) {
|
|
884
|
+
simplifiedConsensus.votes = value.votes;
|
|
885
|
+
}
|
|
886
|
+
if ("leader_receipt" in value && Array.isArray(value.leader_receipt)) {
|
|
887
|
+
simplifiedConsensus.leader_receipt = value.leader_receipt.map((receipt) => {
|
|
888
|
+
const simplifiedReceipt = {};
|
|
889
|
+
["execution_result", "genvm_result", "mode", "vote", "node_config"].forEach((field) => {
|
|
890
|
+
if (field in receipt) {
|
|
891
|
+
simplifiedReceipt[field] = receipt[field];
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
if (receipt.calldata && typeof receipt.calldata === "object" && "readable" in receipt.calldata) {
|
|
895
|
+
simplifiedReceipt.calldata = { readable: receipt.calldata.readable };
|
|
896
|
+
}
|
|
897
|
+
if (receipt.eq_outputs) {
|
|
898
|
+
simplifiedReceipt.eq_outputs = simplifyObject(receipt.eq_outputs, currentPath);
|
|
899
|
+
}
|
|
900
|
+
if (receipt.result) {
|
|
901
|
+
simplifiedReceipt.result = simplifyObject(receipt.result, currentPath);
|
|
902
|
+
}
|
|
903
|
+
return simplifiedReceipt;
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
if ("validators" in value && Array.isArray(value.validators)) {
|
|
907
|
+
const simplifiedValidators = value.validators.map((validator) => {
|
|
908
|
+
const simplifiedValidator = {};
|
|
909
|
+
["execution_result", "genvm_result", "mode", "vote", "node_config"].forEach((field) => {
|
|
910
|
+
if (field in validator) {
|
|
911
|
+
simplifiedValidator[field] = validator[field];
|
|
912
|
+
}
|
|
913
|
+
});
|
|
914
|
+
return simplifiedValidator;
|
|
915
|
+
}).filter((validator) => Object.keys(validator).length > 0);
|
|
916
|
+
if (simplifiedValidators.length > 0) {
|
|
917
|
+
simplifiedConsensus.validators = simplifiedValidators;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
result[key] = simplifiedConsensus;
|
|
921
|
+
continue;
|
|
922
|
+
}
|
|
923
|
+
const simplifiedValue = simplifyObject(value, currentPath);
|
|
924
|
+
const shouldInclude = simplifiedValue !== void 0 && !(typeof simplifiedValue === "object" && simplifiedValue !== null && Object.keys(simplifiedValue).length === 0);
|
|
925
|
+
if (shouldInclude || simplifiedValue === 0) {
|
|
926
|
+
const mappedKey = FIELD_NAME_MAPPINGS[key] || key;
|
|
927
|
+
result[mappedKey] = simplifiedValue;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
return result;
|
|
931
|
+
}
|
|
932
|
+
return obj;
|
|
933
|
+
};
|
|
934
|
+
return simplifyObject({ ...tx });
|
|
935
|
+
};
|
|
817
936
|
var _decodeLocalnetTransaction = (tx) => {
|
|
818
937
|
if (!tx.data) return tx;
|
|
819
938
|
try {
|
|
@@ -831,11 +950,20 @@ var _decodeLocalnetTransaction = (tx) => {
|
|
|
831
950
|
};
|
|
832
951
|
}
|
|
833
952
|
if (receipt.eq_outputs) {
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
953
|
+
const decodedOutputs = {};
|
|
954
|
+
for (const [key, value] of Object.entries(receipt.eq_outputs)) {
|
|
955
|
+
if (typeof value === "object" && value !== null) {
|
|
956
|
+
decodedOutputs[key] = value;
|
|
957
|
+
} else {
|
|
958
|
+
try {
|
|
959
|
+
decodedOutputs[key] = resultToUserFriendlyJson(value);
|
|
960
|
+
} catch (e) {
|
|
961
|
+
console.warn(`Error decoding eq_output ${key}: ${e}`);
|
|
962
|
+
decodedOutputs[key] = value;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
receipt.eq_outputs = decodedOutputs;
|
|
839
967
|
}
|
|
840
968
|
});
|
|
841
969
|
}
|
package/dist/index.js
CHANGED
|
@@ -437,7 +437,7 @@ var contractActions = (client, publicClient) => {
|
|
|
437
437
|
args: callArgs,
|
|
438
438
|
kwargs,
|
|
439
439
|
leaderOnly = false,
|
|
440
|
-
transactionHashVariant = "latest-
|
|
440
|
+
transactionHashVariant = "latest-nonfinal" /* LATEST_NONFINAL */
|
|
441
441
|
} = args;
|
|
442
442
|
const encodedData = [encode(makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
|
|
443
443
|
const serializedData = serialize(encodedData);
|
|
@@ -684,12 +684,55 @@ function resultToUserFriendlyJson(cd64) {
|
|
|
684
684
|
|
|
685
685
|
// src/transactions/actions.ts
|
|
686
686
|
import { fromRlp, fromHex as fromHex2 } from "viem";
|
|
687
|
+
var FIELDS_TO_REMOVE = [
|
|
688
|
+
"raw",
|
|
689
|
+
"contract_state",
|
|
690
|
+
"base64",
|
|
691
|
+
"consensus_history",
|
|
692
|
+
"tx_data",
|
|
693
|
+
"eq_blocks_outputs",
|
|
694
|
+
"r",
|
|
695
|
+
"s",
|
|
696
|
+
"v",
|
|
697
|
+
"created_timestamp",
|
|
698
|
+
"current_timestamp",
|
|
699
|
+
"tx_execution_hash",
|
|
700
|
+
"random_seed",
|
|
701
|
+
"states",
|
|
702
|
+
"contract_code",
|
|
703
|
+
"appeal_failed",
|
|
704
|
+
"appeal_leader_timeout",
|
|
705
|
+
"appeal_processing_time",
|
|
706
|
+
"appeal_undetermined",
|
|
707
|
+
"appealed",
|
|
708
|
+
"timestamp_appeal",
|
|
709
|
+
"config_rotation_rounds",
|
|
710
|
+
"rotation_count",
|
|
711
|
+
"queue_position",
|
|
712
|
+
"queue_type",
|
|
713
|
+
"leader_timeout_validators",
|
|
714
|
+
"triggered_by",
|
|
715
|
+
"num_of_initial_validators",
|
|
716
|
+
"timestamp_awaiting_finalization",
|
|
717
|
+
"last_vote_timestamp",
|
|
718
|
+
"read_state_block_range",
|
|
719
|
+
"tx_slot",
|
|
720
|
+
"blockHash",
|
|
721
|
+
"blockNumber",
|
|
722
|
+
"to",
|
|
723
|
+
"transactionIndex"
|
|
724
|
+
];
|
|
725
|
+
var FIELD_NAME_MAPPINGS = {
|
|
726
|
+
statusName: "status_name",
|
|
727
|
+
typeHex: "type"
|
|
728
|
+
};
|
|
687
729
|
var receiptActions = (client, publicClient) => ({
|
|
688
730
|
waitForTransactionReceipt: async ({
|
|
689
731
|
hash,
|
|
690
732
|
status = "ACCEPTED" /* ACCEPTED */,
|
|
691
733
|
interval = transactionsConfig.waitInterval,
|
|
692
|
-
retries = transactionsConfig.retries
|
|
734
|
+
retries = transactionsConfig.retries,
|
|
735
|
+
fullTransaction = false
|
|
693
736
|
}) => {
|
|
694
737
|
const transaction = await client.getTransaction({
|
|
695
738
|
hash
|
|
@@ -701,10 +744,14 @@ var receiptActions = (client, publicClient) => ({
|
|
|
701
744
|
const transactionStatusFinalized = transactionsStatusNameToNumber["FINALIZED" /* FINALIZED */];
|
|
702
745
|
const requestedStatus = transactionsStatusNameToNumber[status];
|
|
703
746
|
if (transactionStatusString === requestedStatus || status === "ACCEPTED" /* ACCEPTED */ && transactionStatusString === transactionStatusFinalized) {
|
|
747
|
+
let finalTransaction = transaction;
|
|
704
748
|
if (client.chain.id === localnet.id) {
|
|
705
|
-
|
|
749
|
+
finalTransaction = _decodeLocalnetTransaction(transaction);
|
|
750
|
+
}
|
|
751
|
+
if (!fullTransaction) {
|
|
752
|
+
return _simplifyTransactionReceipt(finalTransaction);
|
|
706
753
|
}
|
|
707
|
-
return
|
|
754
|
+
return finalTransaction;
|
|
708
755
|
}
|
|
709
756
|
if (retries === 0) {
|
|
710
757
|
throw new Error("Transaction status is not " + status);
|
|
@@ -714,7 +761,8 @@ var receiptActions = (client, publicClient) => ({
|
|
|
714
761
|
hash,
|
|
715
762
|
status,
|
|
716
763
|
interval,
|
|
717
|
-
retries: retries - 1
|
|
764
|
+
retries: retries - 1,
|
|
765
|
+
fullTransaction
|
|
718
766
|
});
|
|
719
767
|
}
|
|
720
768
|
});
|
|
@@ -814,6 +862,77 @@ var _decodeTransaction = (tx) => {
|
|
|
814
862
|
};
|
|
815
863
|
return decodedTx;
|
|
816
864
|
};
|
|
865
|
+
var _simplifyTransactionReceipt = (tx) => {
|
|
866
|
+
const simplifyObject = (obj, path = "") => {
|
|
867
|
+
if (obj === null || obj === void 0) return obj;
|
|
868
|
+
if (Array.isArray(obj)) {
|
|
869
|
+
return obj.map((item) => simplifyObject(item, path)).filter((item) => item !== void 0);
|
|
870
|
+
}
|
|
871
|
+
if (typeof obj === "object") {
|
|
872
|
+
const result = {};
|
|
873
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
874
|
+
const currentPath = path ? `${path}.${key}` : key;
|
|
875
|
+
if (FIELDS_TO_REMOVE.includes(key)) {
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
if (key === "node_config" && !path.includes("consensus_data")) {
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
881
|
+
if (key === "consensus_data" && typeof value === "object" && value !== null) {
|
|
882
|
+
const simplifiedConsensus = {};
|
|
883
|
+
if ("votes" in value) {
|
|
884
|
+
simplifiedConsensus.votes = value.votes;
|
|
885
|
+
}
|
|
886
|
+
if ("leader_receipt" in value && Array.isArray(value.leader_receipt)) {
|
|
887
|
+
simplifiedConsensus.leader_receipt = value.leader_receipt.map((receipt) => {
|
|
888
|
+
const simplifiedReceipt = {};
|
|
889
|
+
["execution_result", "genvm_result", "mode", "vote", "node_config"].forEach((field) => {
|
|
890
|
+
if (field in receipt) {
|
|
891
|
+
simplifiedReceipt[field] = receipt[field];
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
if (receipt.calldata && typeof receipt.calldata === "object" && "readable" in receipt.calldata) {
|
|
895
|
+
simplifiedReceipt.calldata = { readable: receipt.calldata.readable };
|
|
896
|
+
}
|
|
897
|
+
if (receipt.eq_outputs) {
|
|
898
|
+
simplifiedReceipt.eq_outputs = simplifyObject(receipt.eq_outputs, currentPath);
|
|
899
|
+
}
|
|
900
|
+
if (receipt.result) {
|
|
901
|
+
simplifiedReceipt.result = simplifyObject(receipt.result, currentPath);
|
|
902
|
+
}
|
|
903
|
+
return simplifiedReceipt;
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
if ("validators" in value && Array.isArray(value.validators)) {
|
|
907
|
+
const simplifiedValidators = value.validators.map((validator) => {
|
|
908
|
+
const simplifiedValidator = {};
|
|
909
|
+
["execution_result", "genvm_result", "mode", "vote", "node_config"].forEach((field) => {
|
|
910
|
+
if (field in validator) {
|
|
911
|
+
simplifiedValidator[field] = validator[field];
|
|
912
|
+
}
|
|
913
|
+
});
|
|
914
|
+
return simplifiedValidator;
|
|
915
|
+
}).filter((validator) => Object.keys(validator).length > 0);
|
|
916
|
+
if (simplifiedValidators.length > 0) {
|
|
917
|
+
simplifiedConsensus.validators = simplifiedValidators;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
result[key] = simplifiedConsensus;
|
|
921
|
+
continue;
|
|
922
|
+
}
|
|
923
|
+
const simplifiedValue = simplifyObject(value, currentPath);
|
|
924
|
+
const shouldInclude = simplifiedValue !== void 0 && !(typeof simplifiedValue === "object" && simplifiedValue !== null && Object.keys(simplifiedValue).length === 0);
|
|
925
|
+
if (shouldInclude || simplifiedValue === 0) {
|
|
926
|
+
const mappedKey = FIELD_NAME_MAPPINGS[key] || key;
|
|
927
|
+
result[mappedKey] = simplifiedValue;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
return result;
|
|
931
|
+
}
|
|
932
|
+
return obj;
|
|
933
|
+
};
|
|
934
|
+
return simplifyObject({ ...tx });
|
|
935
|
+
};
|
|
817
936
|
var _decodeLocalnetTransaction = (tx) => {
|
|
818
937
|
if (!tx.data) return tx;
|
|
819
938
|
try {
|
|
@@ -831,11 +950,20 @@ var _decodeLocalnetTransaction = (tx) => {
|
|
|
831
950
|
};
|
|
832
951
|
}
|
|
833
952
|
if (receipt.eq_outputs) {
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
953
|
+
const decodedOutputs = {};
|
|
954
|
+
for (const [key, value] of Object.entries(receipt.eq_outputs)) {
|
|
955
|
+
if (typeof value === "object" && value !== null) {
|
|
956
|
+
decodedOutputs[key] = value;
|
|
957
|
+
} else {
|
|
958
|
+
try {
|
|
959
|
+
decodedOutputs[key] = resultToUserFriendlyJson(value);
|
|
960
|
+
} catch (e) {
|
|
961
|
+
console.warn(`Error decoding eq_output ${key}: ${e}`);
|
|
962
|
+
decodedOutputs[key] = value;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
receipt.eq_outputs = decodedOutputs;
|
|
839
967
|
}
|
|
840
968
|
});
|
|
841
969
|
}
|
package/package.json
CHANGED
package/src/contracts/actions.ts
CHANGED
|
@@ -88,7 +88,7 @@ export const contractActions = (client: GenLayerClient<GenLayerChain>, publicCli
|
|
|
88
88
|
args: callArgs,
|
|
89
89
|
kwargs,
|
|
90
90
|
leaderOnly = false,
|
|
91
|
-
transactionHashVariant = TransactionHashVariant.
|
|
91
|
+
transactionHashVariant = TransactionHashVariant.LATEST_NONFINAL,
|
|
92
92
|
} = args;
|
|
93
93
|
|
|
94
94
|
const encodedData = [calldata.encode(makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
|
|
@@ -20,17 +20,40 @@ import {Abi, PublicClient, fromRlp, fromHex, Hex, Address} from "viem";
|
|
|
20
20
|
import * as calldataAbi from "@/abi/calldata";
|
|
21
21
|
import {localnet} from "@/chains/localnet";
|
|
22
22
|
|
|
23
|
+
// Fields to remove from simplified transaction receipts
|
|
24
|
+
const FIELDS_TO_REMOVE = [
|
|
25
|
+
"raw", "contract_state", "base64", "consensus_history", "tx_data",
|
|
26
|
+
"eq_blocks_outputs", "r", "s", "v", "created_timestamp",
|
|
27
|
+
"current_timestamp", "tx_execution_hash", "random_seed", "states",
|
|
28
|
+
"contract_code", "appeal_failed", "appeal_leader_timeout",
|
|
29
|
+
"appeal_processing_time", "appeal_undetermined", "appealed",
|
|
30
|
+
"timestamp_appeal", "config_rotation_rounds", "rotation_count",
|
|
31
|
+
"queue_position", "queue_type", "leader_timeout_validators",
|
|
32
|
+
"triggered_by", "num_of_initial_validators",
|
|
33
|
+
"timestamp_awaiting_finalization", "last_vote_timestamp",
|
|
34
|
+
"read_state_block_range", "tx_slot", "blockHash", "blockNumber",
|
|
35
|
+
"to", "transactionIndex"
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
// Field name mappings for cross-language compatibility with genlayer-py
|
|
39
|
+
const FIELD_NAME_MAPPINGS: Record<string, string> = {
|
|
40
|
+
statusName: "status_name",
|
|
41
|
+
typeHex: "type"
|
|
42
|
+
};
|
|
43
|
+
|
|
23
44
|
export const receiptActions = (client: GenLayerClient<GenLayerChain>, publicClient: PublicClient) => ({
|
|
24
45
|
waitForTransactionReceipt: async ({
|
|
25
46
|
hash,
|
|
26
47
|
status = TransactionStatus.ACCEPTED,
|
|
27
48
|
interval = transactionsConfig.waitInterval,
|
|
28
49
|
retries = transactionsConfig.retries,
|
|
50
|
+
fullTransaction = false,
|
|
29
51
|
}: {
|
|
30
52
|
hash: TransactionHash;
|
|
31
53
|
status: TransactionStatus;
|
|
32
54
|
interval?: number;
|
|
33
55
|
retries?: number;
|
|
56
|
+
fullTransaction?: boolean;
|
|
34
57
|
}): Promise<GenLayerTransaction> => {
|
|
35
58
|
const transaction = await client.getTransaction({
|
|
36
59
|
hash,
|
|
@@ -46,10 +69,14 @@ export const receiptActions = (client: GenLayerClient<GenLayerChain>, publicClie
|
|
|
46
69
|
transactionStatusString === requestedStatus ||
|
|
47
70
|
(status === TransactionStatus.ACCEPTED && transactionStatusString === transactionStatusFinalized)
|
|
48
71
|
) {
|
|
72
|
+
let finalTransaction = transaction;
|
|
49
73
|
if (client.chain.id === localnet.id) {
|
|
50
|
-
|
|
74
|
+
finalTransaction = _decodeLocalnetTransaction(transaction as unknown as GenLayerTransaction);
|
|
75
|
+
}
|
|
76
|
+
if (!fullTransaction) {
|
|
77
|
+
return _simplifyTransactionReceipt(finalTransaction as GenLayerTransaction);
|
|
51
78
|
}
|
|
52
|
-
return
|
|
79
|
+
return finalTransaction;
|
|
53
80
|
}
|
|
54
81
|
|
|
55
82
|
if (retries === 0) {
|
|
@@ -62,6 +89,7 @@ export const receiptActions = (client: GenLayerClient<GenLayerChain>, publicClie
|
|
|
62
89
|
status,
|
|
63
90
|
interval,
|
|
64
91
|
retries: retries - 1,
|
|
92
|
+
fullTransaction,
|
|
65
93
|
});
|
|
66
94
|
},
|
|
67
95
|
});
|
|
@@ -183,6 +211,117 @@ const _decodeTransaction = (tx: GenLayerRawTransaction): GenLayerTransaction =>
|
|
|
183
211
|
return decodedTx as GenLayerTransaction;
|
|
184
212
|
};
|
|
185
213
|
|
|
214
|
+
const _simplifyTransactionReceipt = (tx: GenLayerTransaction): GenLayerTransaction => {
|
|
215
|
+
/**
|
|
216
|
+
* Simplify transaction receipt by removing non-essential fields while preserving functionality.
|
|
217
|
+
*
|
|
218
|
+
* Removes: Binary data, internal timestamps, appeal fields, processing details, historical data
|
|
219
|
+
* Preserves: Transaction IDs, status, execution results, node configs, readable data
|
|
220
|
+
*/
|
|
221
|
+
const simplifyObject = (obj: any, path = ""): any => {
|
|
222
|
+
if (obj === null || obj === undefined) return obj;
|
|
223
|
+
|
|
224
|
+
if (Array.isArray(obj)) {
|
|
225
|
+
return obj.map(item => simplifyObject(item, path)).filter(item => item !== undefined);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (typeof obj === "object") {
|
|
229
|
+
const result: any = {};
|
|
230
|
+
|
|
231
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
232
|
+
const currentPath = path ? `${path}.${key}` : key;
|
|
233
|
+
|
|
234
|
+
// Always remove these fields
|
|
235
|
+
if (FIELDS_TO_REMOVE.includes(key)) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Remove node_config only from top level (keep it in consensus_data)
|
|
240
|
+
if (key === "node_config" && !path.includes("consensus_data")) {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Special handling for consensus_data - keep execution results and votes
|
|
245
|
+
if (key === "consensus_data" && typeof value === "object" && value !== null) {
|
|
246
|
+
const simplifiedConsensus: any = {};
|
|
247
|
+
|
|
248
|
+
// Keep votes
|
|
249
|
+
if ("votes" in value) {
|
|
250
|
+
simplifiedConsensus.votes = value.votes;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Process leader_receipt to keep only essential fields
|
|
254
|
+
if ("leader_receipt" in value && Array.isArray(value.leader_receipt)) {
|
|
255
|
+
simplifiedConsensus.leader_receipt = value.leader_receipt.map((receipt: any) => {
|
|
256
|
+
const simplifiedReceipt: any = {};
|
|
257
|
+
|
|
258
|
+
// Keep essential execution info
|
|
259
|
+
["execution_result", "genvm_result", "mode", "vote", "node_config"].forEach(field => {
|
|
260
|
+
if (field in receipt) {
|
|
261
|
+
simplifiedReceipt[field] = receipt[field];
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// Keep readable calldata
|
|
266
|
+
if (receipt.calldata && typeof receipt.calldata === "object" && "readable" in receipt.calldata) {
|
|
267
|
+
simplifiedReceipt.calldata = { readable: receipt.calldata.readable };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Keep readable outputs
|
|
271
|
+
if (receipt.eq_outputs) {
|
|
272
|
+
simplifiedReceipt.eq_outputs = simplifyObject(receipt.eq_outputs, currentPath);
|
|
273
|
+
}
|
|
274
|
+
if (receipt.result) {
|
|
275
|
+
simplifiedReceipt.result = simplifyObject(receipt.result, currentPath);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return simplifiedReceipt;
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Process validators to keep execution results
|
|
283
|
+
if ("validators" in value && Array.isArray(value.validators)) {
|
|
284
|
+
const simplifiedValidators = value.validators.map((validator: any) => {
|
|
285
|
+
const simplifiedValidator: any = {};
|
|
286
|
+
["execution_result", "genvm_result", "mode", "vote", "node_config"].forEach(field => {
|
|
287
|
+
if (field in validator) {
|
|
288
|
+
simplifiedValidator[field] = validator[field];
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
return simplifiedValidator;
|
|
292
|
+
}).filter((validator: any) => Object.keys(validator).length > 0);
|
|
293
|
+
|
|
294
|
+
if (simplifiedValidators.length > 0) {
|
|
295
|
+
simplifiedConsensus.validators = simplifiedValidators;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
result[key] = simplifiedConsensus;
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const simplifiedValue = simplifyObject(value, currentPath);
|
|
304
|
+
// Include the value if it's not undefined and not an empty object
|
|
305
|
+
// Special case: include numeric 0 values (like value: 0)
|
|
306
|
+
const shouldInclude = simplifiedValue !== undefined &&
|
|
307
|
+
!(typeof simplifiedValue === "object" && simplifiedValue !== null && Object.keys(simplifiedValue).length === 0);
|
|
308
|
+
|
|
309
|
+
if (shouldInclude || simplifiedValue === 0) {
|
|
310
|
+
// Map field names for cross-language compatibility
|
|
311
|
+
const mappedKey = FIELD_NAME_MAPPINGS[key] || key;
|
|
312
|
+
result[mappedKey] = simplifiedValue;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return obj;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
return simplifyObject({...tx});
|
|
323
|
+
};
|
|
324
|
+
|
|
186
325
|
const _decodeLocalnetTransaction = (tx: GenLayerTransaction): GenLayerTransaction => {
|
|
187
326
|
if (!tx.data) return tx;
|
|
188
327
|
try {
|
|
@@ -200,11 +339,20 @@ const _decodeLocalnetTransaction = (tx: GenLayerTransaction): GenLayerTransactio
|
|
|
200
339
|
};
|
|
201
340
|
}
|
|
202
341
|
if (receipt.eq_outputs) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
342
|
+
const decodedOutputs: any = {};
|
|
343
|
+
for (const [key, value] of Object.entries(receipt.eq_outputs)) {
|
|
344
|
+
if (typeof value === "object" && value !== null) {
|
|
345
|
+
decodedOutputs[key] = value;
|
|
346
|
+
} else {
|
|
347
|
+
try {
|
|
348
|
+
decodedOutputs[key] = resultToUserFriendlyJson(value as string);
|
|
349
|
+
} catch (e) {
|
|
350
|
+
console.warn(`Error decoding eq_output ${key}: ${e}`);
|
|
351
|
+
decodedOutputs[key] = value;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
receipt.eq_outputs = decodedOutputs;
|
|
208
356
|
}
|
|
209
357
|
});
|
|
210
358
|
}
|
package/tests/client.test.ts
CHANGED
|
@@ -164,7 +164,7 @@ describe("Client Overrides", () => {
|
|
|
164
164
|
to: contractAddress,
|
|
165
165
|
from: accountAddressString, // Expecting the address string directly
|
|
166
166
|
data: expect.any(String),
|
|
167
|
-
transaction_hash_variant: TransactionHashVariant.
|
|
167
|
+
transaction_hash_variant: TransactionHashVariant.LATEST_NONFINAL,
|
|
168
168
|
},
|
|
169
169
|
]);
|
|
170
170
|
});
|