@snapshot-labs/snapshot.js 0.14.9 → 0.14.10
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/snapshot.cjs.js +155 -57
- package/dist/snapshot.esm.js +155 -57
- package/dist/snapshot.min.js +1 -1
- package/dist/src/multicall/starknet.d.ts +1 -1
- package/dist/src/voting/rankedChoice.d.ts +64 -0
- package/package.json +1 -1
- package/src/multicall/starknet.ts +70 -58
- package/src/networks.json +2 -2
- package/src/voting/rankedChoice.spec.js +172 -4
- package/src/voting/rankedChoice.ts +87 -7
package/dist/snapshot.cjs.js
CHANGED
|
@@ -1722,7 +1722,7 @@ var networks = {
|
|
|
1722
1722
|
url: "https://explorer.celo.org"
|
|
1723
1723
|
},
|
|
1724
1724
|
start: 6599803,
|
|
1725
|
-
logo: "ipfs://
|
|
1725
|
+
logo: "ipfs://bafkreidvcofeczigbjr7ddapgdugwso6v2l4iolfxys7qg6kfvu2uduyva"
|
|
1726
1726
|
},
|
|
1727
1727
|
"43113": {
|
|
1728
1728
|
key: "43113",
|
|
@@ -2664,12 +2664,51 @@ function irv(ballots, rounds) {
|
|
|
2664
2664
|
])
|
|
2665
2665
|
.filter((ballot) => ballot[0].length > 0), rounds);
|
|
2666
2666
|
}
|
|
2667
|
+
/**
|
|
2668
|
+
* Runs the complete Instant Runoff Voting (IRV) algorithm and returns the final results.
|
|
2669
|
+
*
|
|
2670
|
+
* Executes all elimination rounds until a winner is determined or fewer than 3 candidates remain.
|
|
2671
|
+
* Each round eliminates the candidate with the fewest votes and redistributes their votes
|
|
2672
|
+
* to voters' next preferences.
|
|
2673
|
+
*
|
|
2674
|
+
* @param votes - Array of valid ranked choice votes to process
|
|
2675
|
+
* @returns Array of tuples representing the final candidate rankings, sorted by vote count (highest first).
|
|
2676
|
+
* Each tuple contains [candidateIndex, [totalBalance, scoresArray]] where:
|
|
2677
|
+
* - totalBalance: Sum of voting power from all voters who support this candidate
|
|
2678
|
+
* - scoresArray: Breakdown of that voting power by voting strategy
|
|
2679
|
+
* The relationship: totalBalance === scoresArray.reduce((a,b) => a + b, 0)
|
|
2680
|
+
*
|
|
2681
|
+
* @example
|
|
2682
|
+
* // Returns final results after IRV elimination rounds
|
|
2683
|
+
* // [["2", [150, [60,50,40]]], ["1", [120, [70,30,20]]], ...]
|
|
2684
|
+
* // Candidate 2 wins with 150 total voting power (60+50+40 from 3 strategies)
|
|
2685
|
+
* // Candidate 1 has 120 total voting power (70+30+20 from 3 strategies)
|
|
2686
|
+
*/
|
|
2667
2687
|
function getFinalRound(votes) {
|
|
2668
2688
|
const rounds = irv(votes.map((vote) => [vote.choice, vote.balance, vote.scores]), []);
|
|
2669
2689
|
const finalRound = rounds[rounds.length - 1];
|
|
2670
2690
|
return finalRound.sortedByHighest;
|
|
2671
2691
|
}
|
|
2672
|
-
|
|
2692
|
+
/**
|
|
2693
|
+
* Converts IRV final results into a simple array of scores indexed by proposal choice order.
|
|
2694
|
+
*
|
|
2695
|
+
* Takes the ranked results from getFinalRound() (sorted by winner) and transforms them
|
|
2696
|
+
* into an array where each position corresponds to the original proposal choice index.
|
|
2697
|
+
* This allows easy lookup of any candidate's final vote total by their position in the proposal.
|
|
2698
|
+
*
|
|
2699
|
+
* @param votes - Array of valid ranked choice votes to process
|
|
2700
|
+
* @param proposal - Proposal object containing the choices array
|
|
2701
|
+
* @returns Array of total voting power for each choice, indexed by proposal order.
|
|
2702
|
+
* Position 0 = first choice's votes, position 1 = second choice's votes, etc.
|
|
2703
|
+
*
|
|
2704
|
+
* @example
|
|
2705
|
+
* // proposal.choices = ['Alice', 'Bob', 'Carol', 'David']
|
|
2706
|
+
* // After IRV: Bob won (150), David 2nd (120), Alice 3rd (100), Carol 4th (80)
|
|
2707
|
+
* // Returns: [100, 150, 80, 120]
|
|
2708
|
+
* // ↑ ↑ ↑ ↑
|
|
2709
|
+
* // Alice Bob Carol David (proposal order)
|
|
2710
|
+
*/
|
|
2711
|
+
function getFinalScoresByChoice(votes, proposal) {
|
|
2673
2712
|
const finalRound = getFinalRound(votes);
|
|
2674
2713
|
return proposal.choices.map((choice, i) => finalRound
|
|
2675
2714
|
.filter((res) => Number(res[0]) === i + 1)
|
|
@@ -2698,7 +2737,7 @@ class RankedChoiceVoting {
|
|
|
2698
2737
|
return this.votes.filter((vote) => RankedChoiceVoting.isValidChoice(vote.choice, this.proposal.choices));
|
|
2699
2738
|
}
|
|
2700
2739
|
getScores() {
|
|
2701
|
-
return
|
|
2740
|
+
return getFinalScoresByChoice(this.getValidVotes(), this.proposal);
|
|
2702
2741
|
}
|
|
2703
2742
|
getScoresByStrategy() {
|
|
2704
2743
|
const finalRound = getFinalRound(this.getValidVotes());
|
|
@@ -2708,15 +2747,56 @@ class RankedChoiceVoting {
|
|
|
2708
2747
|
.reduce((a, b) => a + (b[1][1][sI] || 0), 0);
|
|
2709
2748
|
}));
|
|
2710
2749
|
}
|
|
2750
|
+
/**
|
|
2751
|
+
* Returns the total voting power from all submitted votes, including invalid ones.
|
|
2752
|
+
*
|
|
2753
|
+
* This method sums the balance (voting power) from ALL votes submitted to the proposal,
|
|
2754
|
+
* regardless of whether they have valid choice arrays. This is useful for calculating
|
|
2755
|
+
* total participation, quorum requirements, and percentage of total voting power.
|
|
2756
|
+
*
|
|
2757
|
+
* Note: This differs from IRV final results which only include valid votes. Invalid votes
|
|
2758
|
+
* are excluded from IRV calculations but their voting power is still counted here for
|
|
2759
|
+
* participation metrics.
|
|
2760
|
+
*
|
|
2761
|
+
* @returns Total voting power from all votes (valid + invalid)
|
|
2762
|
+
*
|
|
2763
|
+
* @example
|
|
2764
|
+
* // votes = [
|
|
2765
|
+
* // { choice: [1,2,3,4], balance: 1000 }, // Valid
|
|
2766
|
+
* // { choice: [1,5,2], balance: 500 }, // Invalid (index 5)
|
|
2767
|
+
* // { choice: [2,1,4,3], balance: 750 } // Valid
|
|
2768
|
+
* // ]
|
|
2769
|
+
* // Returns: 2250 (includes invalid vote's 500 balance)
|
|
2770
|
+
*/
|
|
2711
2771
|
getScoresTotal() {
|
|
2712
2772
|
return this.votes.reduce((a, b) => a + b.balance, 0);
|
|
2713
2773
|
}
|
|
2774
|
+
/**
|
|
2775
|
+
* Converts the selected choice indices into a human-readable string representation.
|
|
2776
|
+
*
|
|
2777
|
+
* Note: This method supports partial ranking where not all available choices
|
|
2778
|
+
* need to be selected. The ordinal positions (1st, 2nd, etc.) reflect the
|
|
2779
|
+
* order of valid selections only. Invalid choice indices are filtered out.
|
|
2780
|
+
*
|
|
2781
|
+
* @returns A formatted string showing the ranked choices with ordinal positions.
|
|
2782
|
+
* Only valid choices are included, invalid indices are silently ignored.
|
|
2783
|
+
*
|
|
2784
|
+
* @example
|
|
2785
|
+
* // With choices ['Alice', 'Bob', 'Carol', 'David'] and selected [1, 3, 2]
|
|
2786
|
+
* // Returns: "(1st) Alice, (2nd) Carol, (3rd) Bob"
|
|
2787
|
+
*
|
|
2788
|
+
* @example
|
|
2789
|
+
* // Partial ranking with choices ['Alice', 'Bob', 'Carol', 'David'] and selected [4, 1]
|
|
2790
|
+
* // Returns: "(1st) David, (2nd) Alice"
|
|
2791
|
+
*
|
|
2792
|
+
* @example
|
|
2793
|
+
* // With invalid choice index 5 in selected [1, 5]
|
|
2794
|
+
* // Returns: "(1st) Alice" - invalid choice 5 is filtered out
|
|
2795
|
+
*/
|
|
2714
2796
|
getChoiceString() {
|
|
2715
2797
|
return this.selected
|
|
2716
|
-
.map((choice) =>
|
|
2717
|
-
|
|
2718
|
-
return this.proposal.choices[choice - 1];
|
|
2719
|
-
})
|
|
2798
|
+
.map((choice) => this.proposal.choices[choice - 1])
|
|
2799
|
+
.filter(Boolean)
|
|
2720
2800
|
.map((el, i) => `(${getNumberWithOrdinal(i + 1)}) ${el}`)
|
|
2721
2801
|
.join(', ');
|
|
2722
2802
|
}
|
|
@@ -3095,59 +3175,76 @@ function parseStarknetResult(rawResult, functionAbi) {
|
|
|
3095
3175
|
rawResult.length === 0) {
|
|
3096
3176
|
return rawResult;
|
|
3097
3177
|
}
|
|
3098
|
-
|
|
3099
|
-
const
|
|
3178
|
+
// Parse each output according to its type
|
|
3179
|
+
const outputs = functionAbi.outputs;
|
|
3180
|
+
const results = [];
|
|
3181
|
+
let rawIndex = 0; // Track position in rawResult array
|
|
3100
3182
|
try {
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3183
|
+
for (let outputIndex = 0; outputIndex < outputs.length; outputIndex++) {
|
|
3184
|
+
const output = outputs[outputIndex];
|
|
3185
|
+
const rawValue = rawResult[rawIndex];
|
|
3186
|
+
switch (output.type) {
|
|
3187
|
+
case 'core::felt252':
|
|
3188
|
+
try {
|
|
3189
|
+
results.push(starknet$1.shortString.decodeShortString(rawValue));
|
|
3190
|
+
}
|
|
3191
|
+
catch (_a) {
|
|
3192
|
+
results.push(rawValue);
|
|
3193
|
+
}
|
|
3194
|
+
rawIndex++;
|
|
3195
|
+
break;
|
|
3196
|
+
case 'core::integer::u8':
|
|
3197
|
+
case 'core::integer::u16':
|
|
3198
|
+
case 'core::integer::u32':
|
|
3199
|
+
case 'core::integer::u64':
|
|
3200
|
+
results.push(parseInt(rawValue, 16));
|
|
3201
|
+
rawIndex++;
|
|
3202
|
+
break;
|
|
3203
|
+
case 'core::integer::u128':
|
|
3204
|
+
case 'core::integer::usize':
|
|
3205
|
+
results.push(BigInt(rawValue).toString());
|
|
3206
|
+
rawIndex++;
|
|
3207
|
+
break;
|
|
3208
|
+
case 'core::integer::u256':
|
|
3209
|
+
results.push(starknet$1.uint256.uint256ToBN({
|
|
3210
|
+
low: rawValue,
|
|
3211
|
+
high: rawResult[rawIndex + 1] || '0x0'
|
|
3212
|
+
}));
|
|
3213
|
+
rawIndex += 2; // u256 uses two slots
|
|
3214
|
+
break;
|
|
3215
|
+
case 'core::integer::i8':
|
|
3216
|
+
case 'core::integer::i16':
|
|
3217
|
+
case 'core::integer::i32':
|
|
3218
|
+
case 'core::integer::i64':
|
|
3219
|
+
results.push(parseInt(rawValue, 16));
|
|
3220
|
+
rawIndex++;
|
|
3221
|
+
break;
|
|
3222
|
+
case 'core::integer::i128':
|
|
3223
|
+
results.push(BigInt(rawValue).toString());
|
|
3224
|
+
rawIndex++;
|
|
3225
|
+
break;
|
|
3226
|
+
case 'core::bool':
|
|
3227
|
+
results.push(rawValue === '0x1' || rawValue === '0x01');
|
|
3228
|
+
rawIndex++;
|
|
3229
|
+
break;
|
|
3230
|
+
case 'core::starknet::contract_address::ContractAddress':
|
|
3231
|
+
case 'core::starknet::class_hash::ClassHash':
|
|
3232
|
+
case 'core::starknet::storage_access::StorageAddress':
|
|
3233
|
+
results.push(rawValue);
|
|
3234
|
+
rawIndex++;
|
|
3235
|
+
break;
|
|
3236
|
+
case 'core::bytes_31::bytes31':
|
|
3237
|
+
results.push(rawValue);
|
|
3238
|
+
rawIndex++;
|
|
3239
|
+
break;
|
|
3240
|
+
default:
|
|
3241
|
+
results.push(rawValue);
|
|
3242
|
+
rawIndex++;
|
|
3243
|
+
}
|
|
3147
3244
|
}
|
|
3245
|
+
return results;
|
|
3148
3246
|
}
|
|
3149
3247
|
catch (_b) {
|
|
3150
|
-
// Fallback to raw result if parsing fails
|
|
3151
3248
|
return rawResult;
|
|
3152
3249
|
}
|
|
3153
3250
|
}
|
|
@@ -3200,7 +3297,8 @@ function multicall$1(address_1, provider_1, abi_1, calls_1, limit_1) {
|
|
|
3200
3297
|
return callResults.map((result, index) => {
|
|
3201
3298
|
const [, functionName] = calls[index];
|
|
3202
3299
|
const functionAbi = abi.find((item) => item.name === functionName);
|
|
3203
|
-
|
|
3300
|
+
const parsedResult = parseStarknetResult(result, functionAbi);
|
|
3301
|
+
return parsedResult;
|
|
3204
3302
|
});
|
|
3205
3303
|
});
|
|
3206
3304
|
}
|
package/dist/snapshot.esm.js
CHANGED
|
@@ -1712,7 +1712,7 @@ var networks = {
|
|
|
1712
1712
|
url: "https://explorer.celo.org"
|
|
1713
1713
|
},
|
|
1714
1714
|
start: 6599803,
|
|
1715
|
-
logo: "ipfs://
|
|
1715
|
+
logo: "ipfs://bafkreidvcofeczigbjr7ddapgdugwso6v2l4iolfxys7qg6kfvu2uduyva"
|
|
1716
1716
|
},
|
|
1717
1717
|
"43113": {
|
|
1718
1718
|
key: "43113",
|
|
@@ -2654,12 +2654,51 @@ function irv(ballots, rounds) {
|
|
|
2654
2654
|
])
|
|
2655
2655
|
.filter((ballot) => ballot[0].length > 0), rounds);
|
|
2656
2656
|
}
|
|
2657
|
+
/**
|
|
2658
|
+
* Runs the complete Instant Runoff Voting (IRV) algorithm and returns the final results.
|
|
2659
|
+
*
|
|
2660
|
+
* Executes all elimination rounds until a winner is determined or fewer than 3 candidates remain.
|
|
2661
|
+
* Each round eliminates the candidate with the fewest votes and redistributes their votes
|
|
2662
|
+
* to voters' next preferences.
|
|
2663
|
+
*
|
|
2664
|
+
* @param votes - Array of valid ranked choice votes to process
|
|
2665
|
+
* @returns Array of tuples representing the final candidate rankings, sorted by vote count (highest first).
|
|
2666
|
+
* Each tuple contains [candidateIndex, [totalBalance, scoresArray]] where:
|
|
2667
|
+
* - totalBalance: Sum of voting power from all voters who support this candidate
|
|
2668
|
+
* - scoresArray: Breakdown of that voting power by voting strategy
|
|
2669
|
+
* The relationship: totalBalance === scoresArray.reduce((a,b) => a + b, 0)
|
|
2670
|
+
*
|
|
2671
|
+
* @example
|
|
2672
|
+
* // Returns final results after IRV elimination rounds
|
|
2673
|
+
* // [["2", [150, [60,50,40]]], ["1", [120, [70,30,20]]], ...]
|
|
2674
|
+
* // Candidate 2 wins with 150 total voting power (60+50+40 from 3 strategies)
|
|
2675
|
+
* // Candidate 1 has 120 total voting power (70+30+20 from 3 strategies)
|
|
2676
|
+
*/
|
|
2657
2677
|
function getFinalRound(votes) {
|
|
2658
2678
|
const rounds = irv(votes.map((vote) => [vote.choice, vote.balance, vote.scores]), []);
|
|
2659
2679
|
const finalRound = rounds[rounds.length - 1];
|
|
2660
2680
|
return finalRound.sortedByHighest;
|
|
2661
2681
|
}
|
|
2662
|
-
|
|
2682
|
+
/**
|
|
2683
|
+
* Converts IRV final results into a simple array of scores indexed by proposal choice order.
|
|
2684
|
+
*
|
|
2685
|
+
* Takes the ranked results from getFinalRound() (sorted by winner) and transforms them
|
|
2686
|
+
* into an array where each position corresponds to the original proposal choice index.
|
|
2687
|
+
* This allows easy lookup of any candidate's final vote total by their position in the proposal.
|
|
2688
|
+
*
|
|
2689
|
+
* @param votes - Array of valid ranked choice votes to process
|
|
2690
|
+
* @param proposal - Proposal object containing the choices array
|
|
2691
|
+
* @returns Array of total voting power for each choice, indexed by proposal order.
|
|
2692
|
+
* Position 0 = first choice's votes, position 1 = second choice's votes, etc.
|
|
2693
|
+
*
|
|
2694
|
+
* @example
|
|
2695
|
+
* // proposal.choices = ['Alice', 'Bob', 'Carol', 'David']
|
|
2696
|
+
* // After IRV: Bob won (150), David 2nd (120), Alice 3rd (100), Carol 4th (80)
|
|
2697
|
+
* // Returns: [100, 150, 80, 120]
|
|
2698
|
+
* // ↑ ↑ ↑ ↑
|
|
2699
|
+
* // Alice Bob Carol David (proposal order)
|
|
2700
|
+
*/
|
|
2701
|
+
function getFinalScoresByChoice(votes, proposal) {
|
|
2663
2702
|
const finalRound = getFinalRound(votes);
|
|
2664
2703
|
return proposal.choices.map((choice, i) => finalRound
|
|
2665
2704
|
.filter((res) => Number(res[0]) === i + 1)
|
|
@@ -2688,7 +2727,7 @@ class RankedChoiceVoting {
|
|
|
2688
2727
|
return this.votes.filter((vote) => RankedChoiceVoting.isValidChoice(vote.choice, this.proposal.choices));
|
|
2689
2728
|
}
|
|
2690
2729
|
getScores() {
|
|
2691
|
-
return
|
|
2730
|
+
return getFinalScoresByChoice(this.getValidVotes(), this.proposal);
|
|
2692
2731
|
}
|
|
2693
2732
|
getScoresByStrategy() {
|
|
2694
2733
|
const finalRound = getFinalRound(this.getValidVotes());
|
|
@@ -2698,15 +2737,56 @@ class RankedChoiceVoting {
|
|
|
2698
2737
|
.reduce((a, b) => a + (b[1][1][sI] || 0), 0);
|
|
2699
2738
|
}));
|
|
2700
2739
|
}
|
|
2740
|
+
/**
|
|
2741
|
+
* Returns the total voting power from all submitted votes, including invalid ones.
|
|
2742
|
+
*
|
|
2743
|
+
* This method sums the balance (voting power) from ALL votes submitted to the proposal,
|
|
2744
|
+
* regardless of whether they have valid choice arrays. This is useful for calculating
|
|
2745
|
+
* total participation, quorum requirements, and percentage of total voting power.
|
|
2746
|
+
*
|
|
2747
|
+
* Note: This differs from IRV final results which only include valid votes. Invalid votes
|
|
2748
|
+
* are excluded from IRV calculations but their voting power is still counted here for
|
|
2749
|
+
* participation metrics.
|
|
2750
|
+
*
|
|
2751
|
+
* @returns Total voting power from all votes (valid + invalid)
|
|
2752
|
+
*
|
|
2753
|
+
* @example
|
|
2754
|
+
* // votes = [
|
|
2755
|
+
* // { choice: [1,2,3,4], balance: 1000 }, // Valid
|
|
2756
|
+
* // { choice: [1,5,2], balance: 500 }, // Invalid (index 5)
|
|
2757
|
+
* // { choice: [2,1,4,3], balance: 750 } // Valid
|
|
2758
|
+
* // ]
|
|
2759
|
+
* // Returns: 2250 (includes invalid vote's 500 balance)
|
|
2760
|
+
*/
|
|
2701
2761
|
getScoresTotal() {
|
|
2702
2762
|
return this.votes.reduce((a, b) => a + b.balance, 0);
|
|
2703
2763
|
}
|
|
2764
|
+
/**
|
|
2765
|
+
* Converts the selected choice indices into a human-readable string representation.
|
|
2766
|
+
*
|
|
2767
|
+
* Note: This method supports partial ranking where not all available choices
|
|
2768
|
+
* need to be selected. The ordinal positions (1st, 2nd, etc.) reflect the
|
|
2769
|
+
* order of valid selections only. Invalid choice indices are filtered out.
|
|
2770
|
+
*
|
|
2771
|
+
* @returns A formatted string showing the ranked choices with ordinal positions.
|
|
2772
|
+
* Only valid choices are included, invalid indices are silently ignored.
|
|
2773
|
+
*
|
|
2774
|
+
* @example
|
|
2775
|
+
* // With choices ['Alice', 'Bob', 'Carol', 'David'] and selected [1, 3, 2]
|
|
2776
|
+
* // Returns: "(1st) Alice, (2nd) Carol, (3rd) Bob"
|
|
2777
|
+
*
|
|
2778
|
+
* @example
|
|
2779
|
+
* // Partial ranking with choices ['Alice', 'Bob', 'Carol', 'David'] and selected [4, 1]
|
|
2780
|
+
* // Returns: "(1st) David, (2nd) Alice"
|
|
2781
|
+
*
|
|
2782
|
+
* @example
|
|
2783
|
+
* // With invalid choice index 5 in selected [1, 5]
|
|
2784
|
+
* // Returns: "(1st) Alice" - invalid choice 5 is filtered out
|
|
2785
|
+
*/
|
|
2704
2786
|
getChoiceString() {
|
|
2705
2787
|
return this.selected
|
|
2706
|
-
.map((choice) =>
|
|
2707
|
-
|
|
2708
|
-
return this.proposal.choices[choice - 1];
|
|
2709
|
-
})
|
|
2788
|
+
.map((choice) => this.proposal.choices[choice - 1])
|
|
2789
|
+
.filter(Boolean)
|
|
2710
2790
|
.map((el, i) => `(${getNumberWithOrdinal(i + 1)}) ${el}`)
|
|
2711
2791
|
.join(', ');
|
|
2712
2792
|
}
|
|
@@ -3085,59 +3165,76 @@ function parseStarknetResult(rawResult, functionAbi) {
|
|
|
3085
3165
|
rawResult.length === 0) {
|
|
3086
3166
|
return rawResult;
|
|
3087
3167
|
}
|
|
3088
|
-
|
|
3089
|
-
const
|
|
3168
|
+
// Parse each output according to its type
|
|
3169
|
+
const outputs = functionAbi.outputs;
|
|
3170
|
+
const results = [];
|
|
3171
|
+
let rawIndex = 0; // Track position in rawResult array
|
|
3090
3172
|
try {
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3173
|
+
for (let outputIndex = 0; outputIndex < outputs.length; outputIndex++) {
|
|
3174
|
+
const output = outputs[outputIndex];
|
|
3175
|
+
const rawValue = rawResult[rawIndex];
|
|
3176
|
+
switch (output.type) {
|
|
3177
|
+
case 'core::felt252':
|
|
3178
|
+
try {
|
|
3179
|
+
results.push(shortString.decodeShortString(rawValue));
|
|
3180
|
+
}
|
|
3181
|
+
catch (_a) {
|
|
3182
|
+
results.push(rawValue);
|
|
3183
|
+
}
|
|
3184
|
+
rawIndex++;
|
|
3185
|
+
break;
|
|
3186
|
+
case 'core::integer::u8':
|
|
3187
|
+
case 'core::integer::u16':
|
|
3188
|
+
case 'core::integer::u32':
|
|
3189
|
+
case 'core::integer::u64':
|
|
3190
|
+
results.push(parseInt(rawValue, 16));
|
|
3191
|
+
rawIndex++;
|
|
3192
|
+
break;
|
|
3193
|
+
case 'core::integer::u128':
|
|
3194
|
+
case 'core::integer::usize':
|
|
3195
|
+
results.push(BigInt(rawValue).toString());
|
|
3196
|
+
rawIndex++;
|
|
3197
|
+
break;
|
|
3198
|
+
case 'core::integer::u256':
|
|
3199
|
+
results.push(uint256.uint256ToBN({
|
|
3200
|
+
low: rawValue,
|
|
3201
|
+
high: rawResult[rawIndex + 1] || '0x0'
|
|
3202
|
+
}));
|
|
3203
|
+
rawIndex += 2; // u256 uses two slots
|
|
3204
|
+
break;
|
|
3205
|
+
case 'core::integer::i8':
|
|
3206
|
+
case 'core::integer::i16':
|
|
3207
|
+
case 'core::integer::i32':
|
|
3208
|
+
case 'core::integer::i64':
|
|
3209
|
+
results.push(parseInt(rawValue, 16));
|
|
3210
|
+
rawIndex++;
|
|
3211
|
+
break;
|
|
3212
|
+
case 'core::integer::i128':
|
|
3213
|
+
results.push(BigInt(rawValue).toString());
|
|
3214
|
+
rawIndex++;
|
|
3215
|
+
break;
|
|
3216
|
+
case 'core::bool':
|
|
3217
|
+
results.push(rawValue === '0x1' || rawValue === '0x01');
|
|
3218
|
+
rawIndex++;
|
|
3219
|
+
break;
|
|
3220
|
+
case 'core::starknet::contract_address::ContractAddress':
|
|
3221
|
+
case 'core::starknet::class_hash::ClassHash':
|
|
3222
|
+
case 'core::starknet::storage_access::StorageAddress':
|
|
3223
|
+
results.push(rawValue);
|
|
3224
|
+
rawIndex++;
|
|
3225
|
+
break;
|
|
3226
|
+
case 'core::bytes_31::bytes31':
|
|
3227
|
+
results.push(rawValue);
|
|
3228
|
+
rawIndex++;
|
|
3229
|
+
break;
|
|
3230
|
+
default:
|
|
3231
|
+
results.push(rawValue);
|
|
3232
|
+
rawIndex++;
|
|
3233
|
+
}
|
|
3137
3234
|
}
|
|
3235
|
+
return results;
|
|
3138
3236
|
}
|
|
3139
3237
|
catch (_b) {
|
|
3140
|
-
// Fallback to raw result if parsing fails
|
|
3141
3238
|
return rawResult;
|
|
3142
3239
|
}
|
|
3143
3240
|
}
|
|
@@ -3190,7 +3287,8 @@ function multicall$1(address_1, provider_1, abi_1, calls_1, limit_1) {
|
|
|
3190
3287
|
return callResults.map((result, index) => {
|
|
3191
3288
|
const [, functionName] = calls[index];
|
|
3192
3289
|
const functionAbi = abi.find((item) => item.name === functionName);
|
|
3193
|
-
|
|
3290
|
+
const parsedResult = parseStarknetResult(result, functionAbi);
|
|
3291
|
+
return parsedResult;
|
|
3194
3292
|
});
|
|
3195
3293
|
});
|
|
3196
3294
|
}
|