genlayer-js 0.17.1 → 0.18.1
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/dist/{index-BIyk5Fv7.d.ts → index-BJebZa37.d.ts} +10 -0
- package/dist/{index-DrEvzYFA.d.cts → index-C_GfhvDJ.d.cts} +10 -0
- package/dist/index.cjs +102 -20
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +90 -8
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/client/client.ts +9 -4
- package/src/contracts/actions.ts +22 -3
- package/src/transactions/actions.ts +20 -0
- package/src/transactions/decoders.ts +1 -2
- package/src/types/clients.ts +8 -0
- package/src/utils/jsonifier.ts +72 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
## 0.18.1 (2025-09-11)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* replace hardcoded gas 21000 ([#115](https://github.com/genlayerlabs/genlayer-js/issues/115)) ([8eacd5d](https://github.com/genlayerlabs/genlayer-js/commit/8eacd5dbba9ae85f0232ec525076582ea8b6b045))
|
|
9
|
+
|
|
10
|
+
## 0.18.0 (2025-09-04)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* format in genlayer js to convert to an object ([#107](https://github.com/genlayerlabs/genlayer-js/issues/107)) ([3ca4076](https://github.com/genlayerlabs/genlayer-js/commit/3ca40765bc03e8d7174c8e337e6104ccea455e5a))
|
|
16
|
+
|
|
3
17
|
## 0.17.1 (2025-09-03)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -313,6 +313,9 @@ type GenLayerMethod = {
|
|
|
313
313
|
} | {
|
|
314
314
|
method: "eth_getTransactionCount";
|
|
315
315
|
params: [address: Address, block: string];
|
|
316
|
+
} | {
|
|
317
|
+
method: "eth_estimateGas";
|
|
318
|
+
params: [transactionParams: any];
|
|
316
319
|
} | {
|
|
317
320
|
method: "gen_call";
|
|
318
321
|
params: [requestParams: any];
|
|
@@ -332,6 +335,7 @@ type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<Client<Transpor
|
|
|
332
335
|
[key: string]: CalldataEncodable;
|
|
333
336
|
};
|
|
334
337
|
rawReturn?: RawReturn;
|
|
338
|
+
jsonSafeReturn?: boolean;
|
|
335
339
|
transactionHashVariant?: TransactionHashVariant;
|
|
336
340
|
}) => Promise<RawReturn extends true ? `0x${string}` : CalldataEncodable>;
|
|
337
341
|
writeContract: (args: {
|
|
@@ -374,6 +378,12 @@ type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<Client<Transpor
|
|
|
374
378
|
getCurrentNonce: (args: {
|
|
375
379
|
address: Address;
|
|
376
380
|
}) => Promise<number>;
|
|
381
|
+
estimateTransactionGas: (transactionParams: {
|
|
382
|
+
from?: Address;
|
|
383
|
+
to: Address;
|
|
384
|
+
data?: `0x${string}`;
|
|
385
|
+
value?: bigint;
|
|
386
|
+
}) => Promise<bigint>;
|
|
377
387
|
waitForTransactionReceipt: (args: {
|
|
378
388
|
hash: TransactionHash;
|
|
379
389
|
status?: TransactionStatus;
|
|
@@ -313,6 +313,9 @@ type GenLayerMethod = {
|
|
|
313
313
|
} | {
|
|
314
314
|
method: "eth_getTransactionCount";
|
|
315
315
|
params: [address: Address, block: string];
|
|
316
|
+
} | {
|
|
317
|
+
method: "eth_estimateGas";
|
|
318
|
+
params: [transactionParams: any];
|
|
316
319
|
} | {
|
|
317
320
|
method: "gen_call";
|
|
318
321
|
params: [requestParams: any];
|
|
@@ -332,6 +335,7 @@ type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<Client<Transpor
|
|
|
332
335
|
[key: string]: CalldataEncodable;
|
|
333
336
|
};
|
|
334
337
|
rawReturn?: RawReturn;
|
|
338
|
+
jsonSafeReturn?: boolean;
|
|
335
339
|
transactionHashVariant?: TransactionHashVariant;
|
|
336
340
|
}) => Promise<RawReturn extends true ? `0x${string}` : CalldataEncodable>;
|
|
337
341
|
writeContract: (args: {
|
|
@@ -374,6 +378,12 @@ type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<Client<Transpor
|
|
|
374
378
|
getCurrentNonce: (args: {
|
|
375
379
|
address: Address;
|
|
376
380
|
}) => Promise<number>;
|
|
381
|
+
estimateTransactionGas: (transactionParams: {
|
|
382
|
+
from?: Address;
|
|
383
|
+
to: Address;
|
|
384
|
+
data?: `0x${string}`;
|
|
385
|
+
value?: bigint;
|
|
386
|
+
}) => Promise<bigint>;
|
|
377
387
|
waitForTransactionReceipt: (args: {
|
|
378
388
|
hash: TransactionHash;
|
|
379
389
|
status?: TransactionStatus;
|
package/dist/index.cjs
CHANGED
|
@@ -419,6 +419,7 @@ var calldata = calldata_exports;
|
|
|
419
419
|
var transactions = transactions_exports;
|
|
420
420
|
|
|
421
421
|
// src/utils/jsonifier.ts
|
|
422
|
+
|
|
422
423
|
function b64ToArray(b64) {
|
|
423
424
|
return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
424
425
|
}
|
|
@@ -457,6 +458,54 @@ function resultToUserFriendlyJson(cd64) {
|
|
|
457
458
|
payload
|
|
458
459
|
};
|
|
459
460
|
}
|
|
461
|
+
function toJsonSafeDeep(value) {
|
|
462
|
+
return _toJsonSafeDeep(value, /* @__PURE__ */ new WeakSet());
|
|
463
|
+
}
|
|
464
|
+
function _toJsonSafeDeep(value, seen) {
|
|
465
|
+
if (value === null || value === void 0) {
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
const primitiveType = typeof value;
|
|
469
|
+
if (primitiveType === "string" || primitiveType === "boolean" || primitiveType === "number") {
|
|
470
|
+
return value;
|
|
471
|
+
}
|
|
472
|
+
if (primitiveType === "bigint") {
|
|
473
|
+
const big = value;
|
|
474
|
+
const abs = big < 0n ? -big : big;
|
|
475
|
+
const maxSafe = 9007199254740991n;
|
|
476
|
+
return abs <= maxSafe ? Number(big) : big.toString();
|
|
477
|
+
}
|
|
478
|
+
if (typeof value === "object") {
|
|
479
|
+
if (seen.has(value)) {
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
seen.add(value);
|
|
483
|
+
if (value instanceof Uint8Array) {
|
|
484
|
+
return _viem.toHex.call(void 0, value);
|
|
485
|
+
}
|
|
486
|
+
if (value instanceof Array) {
|
|
487
|
+
return value.map((v) => _toJsonSafeDeep(v, seen));
|
|
488
|
+
}
|
|
489
|
+
if (value instanceof Map) {
|
|
490
|
+
const obj = {};
|
|
491
|
+
for (const [k, v] of value.entries()) {
|
|
492
|
+
obj[k] = _toJsonSafeDeep(v, seen);
|
|
493
|
+
}
|
|
494
|
+
return obj;
|
|
495
|
+
}
|
|
496
|
+
if (value instanceof _chunkH4ZYXVV2cjs.CalldataAddress) {
|
|
497
|
+
return _viem.toHex.call(void 0, value.bytes);
|
|
498
|
+
}
|
|
499
|
+
if (Object.getPrototypeOf(value) === Object.prototype) {
|
|
500
|
+
const obj = {};
|
|
501
|
+
for (const [k, v] of Object.entries(value)) {
|
|
502
|
+
obj[k] = _toJsonSafeDeep(v, seen);
|
|
503
|
+
}
|
|
504
|
+
return obj;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return value;
|
|
508
|
+
}
|
|
460
509
|
|
|
461
510
|
// src/contracts/actions.ts
|
|
462
511
|
var contractActions = (client, publicClient) => {
|
|
@@ -499,6 +548,7 @@ var contractActions = (client, publicClient) => {
|
|
|
499
548
|
functionName,
|
|
500
549
|
args: callArgs,
|
|
501
550
|
kwargs,
|
|
551
|
+
jsonSafeReturn = false,
|
|
502
552
|
leaderOnly = false,
|
|
503
553
|
transactionHashVariant = "latest-nonfinal" /* LATEST_NONFINAL */
|
|
504
554
|
} = args;
|
|
@@ -521,7 +571,11 @@ var contractActions = (client, publicClient) => {
|
|
|
521
571
|
return prefixedResult;
|
|
522
572
|
}
|
|
523
573
|
const resultBinary = _viem.fromHex.call(void 0, prefixedResult, "bytes");
|
|
524
|
-
|
|
574
|
+
const decoded = decode(resultBinary);
|
|
575
|
+
if (!jsonSafeReturn) {
|
|
576
|
+
return decoded;
|
|
577
|
+
}
|
|
578
|
+
return toJsonSafeDeep(decoded);
|
|
525
579
|
},
|
|
526
580
|
simulateWriteContract: async (args) => {
|
|
527
581
|
const {
|
|
@@ -676,16 +730,28 @@ var _sendTransaction = async ({
|
|
|
676
730
|
}
|
|
677
731
|
const validatedSenderAccount = validateAccount(senderAccount);
|
|
678
732
|
const nonce = await client.getCurrentNonce({ address: validatedSenderAccount.address });
|
|
733
|
+
let estimatedGas;
|
|
734
|
+
try {
|
|
735
|
+
estimatedGas = await client.estimateTransactionGas({
|
|
736
|
+
from: validatedSenderAccount.address,
|
|
737
|
+
to: _optionalChain([client, 'access', _20 => _20.chain, 'access', _21 => _21.consensusMainContract, 'optionalAccess', _22 => _22.address]),
|
|
738
|
+
data: encodedData,
|
|
739
|
+
value
|
|
740
|
+
});
|
|
741
|
+
} catch (error) {
|
|
742
|
+
console.warn("Gas estimation failed, using fallback value:", error);
|
|
743
|
+
estimatedGas = 200000n;
|
|
744
|
+
}
|
|
679
745
|
const transactionRequest = await client.prepareTransactionRequest({
|
|
680
746
|
account: validatedSenderAccount,
|
|
681
|
-
to: _optionalChain([client, 'access',
|
|
747
|
+
to: _optionalChain([client, 'access', _23 => _23.chain, 'access', _24 => _24.consensusMainContract, 'optionalAccess', _25 => _25.address]),
|
|
682
748
|
data: encodedData,
|
|
683
749
|
type: "legacy",
|
|
684
750
|
nonce: Number(nonce),
|
|
685
751
|
value,
|
|
686
|
-
gas:
|
|
752
|
+
gas: estimatedGas
|
|
687
753
|
});
|
|
688
|
-
if (_optionalChain([validatedSenderAccount, 'optionalAccess',
|
|
754
|
+
if (_optionalChain([validatedSenderAccount, 'optionalAccess', _26 => _26.type]) !== "local") {
|
|
689
755
|
const formattedRequest = {
|
|
690
756
|
from: transactionRequest.from,
|
|
691
757
|
to: transactionRequest.to,
|
|
@@ -698,7 +764,7 @@ var _sendTransaction = async ({
|
|
|
698
764
|
params: [formattedRequest]
|
|
699
765
|
});
|
|
700
766
|
}
|
|
701
|
-
if (!_optionalChain([validatedSenderAccount, 'optionalAccess',
|
|
767
|
+
if (!_optionalChain([validatedSenderAccount, 'optionalAccess', _27 => _27.signTransaction])) {
|
|
702
768
|
throw new Error("Account does not support signTransaction");
|
|
703
769
|
}
|
|
704
770
|
const serializedTransaction = await validatedSenderAccount.signTransaction(transactionRequest);
|
|
@@ -708,7 +774,7 @@ var _sendTransaction = async ({
|
|
|
708
774
|
throw new Error("Transaction reverted");
|
|
709
775
|
}
|
|
710
776
|
const newTxEvents = _viem.parseEventLogs.call(void 0, {
|
|
711
|
-
abi: _optionalChain([client, 'access',
|
|
777
|
+
abi: _optionalChain([client, 'access', _28 => _28.chain, 'access', _29 => _29.consensusMainContract, 'optionalAccess', _30 => _30.abi]),
|
|
712
778
|
eventName: "NewTransaction",
|
|
713
779
|
logs: receipt.logs
|
|
714
780
|
});
|
|
@@ -921,7 +987,7 @@ var simplifyTransactionReceipt = (tx) => {
|
|
|
921
987
|
var decodeLocalnetTransaction = (tx) => {
|
|
922
988
|
if (!tx.data) return tx;
|
|
923
989
|
try {
|
|
924
|
-
const leaderReceipt = _optionalChain([tx, 'access',
|
|
990
|
+
const leaderReceipt = _optionalChain([tx, 'access', _31 => _31.consensus_data, 'optionalAccess', _32 => _32.leader_receipt]);
|
|
925
991
|
if (leaderReceipt) {
|
|
926
992
|
const receipts = Array.isArray(leaderReceipt) ? leaderReceipt : [leaderReceipt];
|
|
927
993
|
receipts.forEach((receipt) => {
|
|
@@ -952,7 +1018,7 @@ var decodeLocalnetTransaction = (tx) => {
|
|
|
952
1018
|
}
|
|
953
1019
|
});
|
|
954
1020
|
}
|
|
955
|
-
if (_optionalChain([tx, 'access',
|
|
1021
|
+
if (_optionalChain([tx, 'access', _33 => _33.data, 'optionalAccess', _34 => _34.calldata]) && typeof tx.data.calldata === "string") {
|
|
956
1022
|
tx.data.calldata = {
|
|
957
1023
|
base64: tx.data.calldata,
|
|
958
1024
|
...calldataToUserFriendlyJson(b64ToArray(tx.data.calldata))
|
|
@@ -1015,8 +1081,8 @@ var transactionActions = (client, publicClient) => ({
|
|
|
1015
1081
|
return decodeLocalnetTransaction(transaction2);
|
|
1016
1082
|
}
|
|
1017
1083
|
const transaction = await publicClient.readContract({
|
|
1018
|
-
address: _optionalChain([client, 'access',
|
|
1019
|
-
abi: _optionalChain([client, 'access',
|
|
1084
|
+
address: _optionalChain([client, 'access', _35 => _35.chain, 'access', _36 => _36.consensusDataContract, 'optionalAccess', _37 => _37.address]),
|
|
1085
|
+
abi: _optionalChain([client, 'access', _38 => _38.chain, 'access', _39 => _39.consensusDataContract, 'optionalAccess', _40 => _40.abi]),
|
|
1020
1086
|
functionName: "getTransactionData",
|
|
1021
1087
|
args: [
|
|
1022
1088
|
hash,
|
|
@@ -1025,6 +1091,19 @@ var transactionActions = (client, publicClient) => ({
|
|
|
1025
1091
|
]
|
|
1026
1092
|
});
|
|
1027
1093
|
return decodeTransaction(transaction);
|
|
1094
|
+
},
|
|
1095
|
+
estimateTransactionGas: async (transactionParams) => {
|
|
1096
|
+
const formattedParams = {
|
|
1097
|
+
from: transactionParams.from || _optionalChain([client, 'access', _41 => _41.account, 'optionalAccess', _42 => _42.address]),
|
|
1098
|
+
to: transactionParams.to,
|
|
1099
|
+
data: transactionParams.data || "0x",
|
|
1100
|
+
value: transactionParams.value ? `0x${transactionParams.value.toString(16)}` : "0x0"
|
|
1101
|
+
};
|
|
1102
|
+
const gasHex = await client.request({
|
|
1103
|
+
method: "eth_estimateGas",
|
|
1104
|
+
params: [formattedParams]
|
|
1105
|
+
});
|
|
1106
|
+
return BigInt(gasHex);
|
|
1028
1107
|
}
|
|
1029
1108
|
});
|
|
1030
1109
|
|
|
@@ -1057,7 +1136,7 @@ var connect = async (client, network = "studionet", snapSource = "npm") => {
|
|
|
1057
1136
|
chainName: selectedNetwork.name,
|
|
1058
1137
|
rpcUrls: selectedNetwork.rpcUrls.default.http,
|
|
1059
1138
|
nativeCurrency: selectedNetwork.nativeCurrency,
|
|
1060
|
-
blockExplorerUrls: [_optionalChain([selectedNetwork, 'access',
|
|
1139
|
+
blockExplorerUrls: [_optionalChain([selectedNetwork, 'access', _43 => _43.blockExplorers, 'optionalAccess', _44 => _44.default, 'access', _45 => _45.url])]
|
|
1061
1140
|
};
|
|
1062
1141
|
const currentChainId = await window.ethereum.request({ method: "eth_chainId" });
|
|
1063
1142
|
if (currentChainId !== chainIdHex) {
|
|
@@ -1091,10 +1170,10 @@ var metamaskClient = async (snapSource = "npm") => {
|
|
|
1091
1170
|
}
|
|
1092
1171
|
const isFlask = async () => {
|
|
1093
1172
|
try {
|
|
1094
|
-
const clientVersion = await _optionalChain([window, 'access',
|
|
1173
|
+
const clientVersion = await _optionalChain([window, 'access', _46 => _46.ethereum, 'optionalAccess', _47 => _47.request, 'call', _48 => _48({
|
|
1095
1174
|
method: "web3_clientVersion"
|
|
1096
1175
|
})]);
|
|
1097
|
-
return _optionalChain([clientVersion, 'optionalAccess',
|
|
1176
|
+
return _optionalChain([clientVersion, 'optionalAccess', _49 => _49.includes, 'call', _50 => _50("flask")]);
|
|
1098
1177
|
} catch (error) {
|
|
1099
1178
|
console.error("Error detecting Flask:", error);
|
|
1100
1179
|
return false;
|
|
@@ -1102,7 +1181,7 @@ var metamaskClient = async (snapSource = "npm") => {
|
|
|
1102
1181
|
};
|
|
1103
1182
|
const installedSnaps = async () => {
|
|
1104
1183
|
try {
|
|
1105
|
-
return await _optionalChain([window, 'access',
|
|
1184
|
+
return await _optionalChain([window, 'access', _51 => _51.ethereum, 'optionalAccess', _52 => _52.request, 'call', _53 => _53({
|
|
1106
1185
|
method: "wallet_getSnaps"
|
|
1107
1186
|
})]);
|
|
1108
1187
|
} catch (error) {
|
|
@@ -1137,10 +1216,10 @@ function walletActions(client) {
|
|
|
1137
1216
|
function chainActions(client) {
|
|
1138
1217
|
return {
|
|
1139
1218
|
initializeConsensusSmartContract: async (forceReset = false) => {
|
|
1140
|
-
if (_optionalChain([client, 'access',
|
|
1219
|
+
if (_optionalChain([client, 'access', _54 => _54.chain, 'optionalAccess', _55 => _55.id]) === _chunkZKBMABRAcjs.testnetAsimov.id) {
|
|
1141
1220
|
return;
|
|
1142
1221
|
}
|
|
1143
|
-
if (!forceReset && _optionalChain([client, 'access',
|
|
1222
|
+
if (!forceReset && _optionalChain([client, 'access', _56 => _56.chain, 'access', _57 => _57.consensusMainContract, 'optionalAccess', _58 => _58.address]) && _optionalChain([client, 'access', _59 => _59.chain, 'access', _60 => _60.consensusMainContract, 'optionalAccess', _61 => _61.abi])) {
|
|
1144
1223
|
return;
|
|
1145
1224
|
}
|
|
1146
1225
|
const contractsResponse = await fetch(client.chain.rpcUrls.default.http[0], {
|
|
@@ -1225,12 +1304,15 @@ var createClient = (config = { chain: _chunkZKBMABRAcjs.localnet }) => {
|
|
|
1225
1304
|
...config.account ? { account: config.account } : {}
|
|
1226
1305
|
});
|
|
1227
1306
|
const clientWithBasicActions = baseClient.extend(_viem.publicActions).extend(_viem.walletActions).extend((client) => accountActions(client));
|
|
1228
|
-
const
|
|
1307
|
+
const clientWithTransactionActions = {
|
|
1229
1308
|
...clientWithBasicActions,
|
|
1230
|
-
...
|
|
1309
|
+
...transactionActions(clientWithBasicActions, publicClient),
|
|
1231
1310
|
...chainActions(clientWithBasicActions),
|
|
1232
|
-
...walletActions(clientWithBasicActions)
|
|
1233
|
-
|
|
1311
|
+
...walletActions(clientWithBasicActions)
|
|
1312
|
+
};
|
|
1313
|
+
const clientWithAllActions = {
|
|
1314
|
+
...clientWithTransactionActions,
|
|
1315
|
+
...contractActions(clientWithTransactionActions, publicClient)
|
|
1234
1316
|
};
|
|
1235
1317
|
const finalClient = {
|
|
1236
1318
|
...clientWithAllActions,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as viem from 'viem';
|
|
2
2
|
import { Account, Address, Hex } from 'viem';
|
|
3
3
|
import { G as GenLayerChain } from './chains-BYSCF33g.cjs';
|
|
4
|
-
import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement } from './index-
|
|
4
|
+
import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement } from './index-C_GfhvDJ.cjs';
|
|
5
5
|
import * as abitype from 'abitype';
|
|
6
6
|
import * as viem__types_types_authorization from 'viem/_types/types/authorization';
|
|
7
7
|
import * as viem_accounts from 'viem/accounts';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as viem from 'viem';
|
|
2
2
|
import { Account, Address, Hex } from 'viem';
|
|
3
3
|
import { G as GenLayerChain } from './chains-BYSCF33g.js';
|
|
4
|
-
import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement } from './index-
|
|
4
|
+
import { G as GenLayerClient, D as DecodedDeployData, a as DecodedCallData, b as GenLayerRawTransaction, c as GenLayerTransaction, C as CalldataEncodable, T as TransactionDataElement } from './index-BJebZa37.js';
|
|
5
5
|
import * as abitype from 'abitype';
|
|
6
6
|
import * as viem__types_types_authorization from 'viem/_types/types/authorization';
|
|
7
7
|
import * as viem_accounts from 'viem/accounts';
|
package/dist/index.js
CHANGED
|
@@ -407,7 +407,7 @@ function serialize(data) {
|
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
// src/contracts/actions.ts
|
|
410
|
-
import { fromHex, toHex as
|
|
410
|
+
import { fromHex, toHex as toHex3, zeroAddress, encodeFunctionData, parseEventLogs } from "viem";
|
|
411
411
|
|
|
412
412
|
// src/abi/index.ts
|
|
413
413
|
var abi_exports = {};
|
|
@@ -419,6 +419,7 @@ var calldata = calldata_exports;
|
|
|
419
419
|
var transactions = transactions_exports;
|
|
420
420
|
|
|
421
421
|
// src/utils/jsonifier.ts
|
|
422
|
+
import { toHex as toHex2 } from "viem";
|
|
422
423
|
function b64ToArray(b64) {
|
|
423
424
|
return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
424
425
|
}
|
|
@@ -457,6 +458,54 @@ function resultToUserFriendlyJson(cd64) {
|
|
|
457
458
|
payload
|
|
458
459
|
};
|
|
459
460
|
}
|
|
461
|
+
function toJsonSafeDeep(value) {
|
|
462
|
+
return _toJsonSafeDeep(value, /* @__PURE__ */ new WeakSet());
|
|
463
|
+
}
|
|
464
|
+
function _toJsonSafeDeep(value, seen) {
|
|
465
|
+
if (value === null || value === void 0) {
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
const primitiveType = typeof value;
|
|
469
|
+
if (primitiveType === "string" || primitiveType === "boolean" || primitiveType === "number") {
|
|
470
|
+
return value;
|
|
471
|
+
}
|
|
472
|
+
if (primitiveType === "bigint") {
|
|
473
|
+
const big = value;
|
|
474
|
+
const abs = big < 0n ? -big : big;
|
|
475
|
+
const maxSafe = 9007199254740991n;
|
|
476
|
+
return abs <= maxSafe ? Number(big) : big.toString();
|
|
477
|
+
}
|
|
478
|
+
if (typeof value === "object") {
|
|
479
|
+
if (seen.has(value)) {
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
seen.add(value);
|
|
483
|
+
if (value instanceof Uint8Array) {
|
|
484
|
+
return toHex2(value);
|
|
485
|
+
}
|
|
486
|
+
if (value instanceof Array) {
|
|
487
|
+
return value.map((v) => _toJsonSafeDeep(v, seen));
|
|
488
|
+
}
|
|
489
|
+
if (value instanceof Map) {
|
|
490
|
+
const obj = {};
|
|
491
|
+
for (const [k, v] of value.entries()) {
|
|
492
|
+
obj[k] = _toJsonSafeDeep(v, seen);
|
|
493
|
+
}
|
|
494
|
+
return obj;
|
|
495
|
+
}
|
|
496
|
+
if (value instanceof CalldataAddress) {
|
|
497
|
+
return toHex2(value.bytes);
|
|
498
|
+
}
|
|
499
|
+
if (Object.getPrototypeOf(value) === Object.prototype) {
|
|
500
|
+
const obj = {};
|
|
501
|
+
for (const [k, v] of Object.entries(value)) {
|
|
502
|
+
obj[k] = _toJsonSafeDeep(v, seen);
|
|
503
|
+
}
|
|
504
|
+
return obj;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return value;
|
|
508
|
+
}
|
|
460
509
|
|
|
461
510
|
// src/contracts/actions.ts
|
|
462
511
|
var contractActions = (client, publicClient) => {
|
|
@@ -488,7 +537,7 @@ var contractActions = (client, publicClient) => {
|
|
|
488
537
|
}
|
|
489
538
|
const schema = await client.request({
|
|
490
539
|
method: "gen_getContractSchemaForCode",
|
|
491
|
-
params: [
|
|
540
|
+
params: [toHex3(contractCode)]
|
|
492
541
|
});
|
|
493
542
|
return schema;
|
|
494
543
|
},
|
|
@@ -499,6 +548,7 @@ var contractActions = (client, publicClient) => {
|
|
|
499
548
|
functionName,
|
|
500
549
|
args: callArgs,
|
|
501
550
|
kwargs,
|
|
551
|
+
jsonSafeReturn = false,
|
|
502
552
|
leaderOnly = false,
|
|
503
553
|
transactionHashVariant = "latest-nonfinal" /* LATEST_NONFINAL */
|
|
504
554
|
} = args;
|
|
@@ -521,7 +571,11 @@ var contractActions = (client, publicClient) => {
|
|
|
521
571
|
return prefixedResult;
|
|
522
572
|
}
|
|
523
573
|
const resultBinary = fromHex(prefixedResult, "bytes");
|
|
524
|
-
|
|
574
|
+
const decoded = decode(resultBinary);
|
|
575
|
+
if (!jsonSafeReturn) {
|
|
576
|
+
return decoded;
|
|
577
|
+
}
|
|
578
|
+
return toJsonSafeDeep(decoded);
|
|
525
579
|
},
|
|
526
580
|
simulateWriteContract: async (args) => {
|
|
527
581
|
const {
|
|
@@ -676,6 +730,18 @@ var _sendTransaction = async ({
|
|
|
676
730
|
}
|
|
677
731
|
const validatedSenderAccount = validateAccount(senderAccount);
|
|
678
732
|
const nonce = await client.getCurrentNonce({ address: validatedSenderAccount.address });
|
|
733
|
+
let estimatedGas;
|
|
734
|
+
try {
|
|
735
|
+
estimatedGas = await client.estimateTransactionGas({
|
|
736
|
+
from: validatedSenderAccount.address,
|
|
737
|
+
to: client.chain.consensusMainContract?.address,
|
|
738
|
+
data: encodedData,
|
|
739
|
+
value
|
|
740
|
+
});
|
|
741
|
+
} catch (error) {
|
|
742
|
+
console.warn("Gas estimation failed, using fallback value:", error);
|
|
743
|
+
estimatedGas = 200000n;
|
|
744
|
+
}
|
|
679
745
|
const transactionRequest = await client.prepareTransactionRequest({
|
|
680
746
|
account: validatedSenderAccount,
|
|
681
747
|
to: client.chain.consensusMainContract?.address,
|
|
@@ -683,7 +749,7 @@ var _sendTransaction = async ({
|
|
|
683
749
|
type: "legacy",
|
|
684
750
|
nonce: Number(nonce),
|
|
685
751
|
value,
|
|
686
|
-
gas:
|
|
752
|
+
gas: estimatedGas
|
|
687
753
|
});
|
|
688
754
|
if (validatedSenderAccount?.type !== "local") {
|
|
689
755
|
const formattedRequest = {
|
|
@@ -1025,6 +1091,19 @@ var transactionActions = (client, publicClient) => ({
|
|
|
1025
1091
|
]
|
|
1026
1092
|
});
|
|
1027
1093
|
return decodeTransaction(transaction);
|
|
1094
|
+
},
|
|
1095
|
+
estimateTransactionGas: async (transactionParams) => {
|
|
1096
|
+
const formattedParams = {
|
|
1097
|
+
from: transactionParams.from || client.account?.address,
|
|
1098
|
+
to: transactionParams.to,
|
|
1099
|
+
data: transactionParams.data || "0x",
|
|
1100
|
+
value: transactionParams.value ? `0x${transactionParams.value.toString(16)}` : "0x0"
|
|
1101
|
+
};
|
|
1102
|
+
const gasHex = await client.request({
|
|
1103
|
+
method: "eth_estimateGas",
|
|
1104
|
+
params: [formattedParams]
|
|
1105
|
+
});
|
|
1106
|
+
return BigInt(gasHex);
|
|
1028
1107
|
}
|
|
1029
1108
|
});
|
|
1030
1109
|
|
|
@@ -1225,12 +1304,15 @@ var createClient = (config = { chain: localnet }) => {
|
|
|
1225
1304
|
...config.account ? { account: config.account } : {}
|
|
1226
1305
|
});
|
|
1227
1306
|
const clientWithBasicActions = baseClient.extend(publicActions).extend(walletActions2).extend((client) => accountActions(client));
|
|
1228
|
-
const
|
|
1307
|
+
const clientWithTransactionActions = {
|
|
1229
1308
|
...clientWithBasicActions,
|
|
1230
|
-
...
|
|
1309
|
+
...transactionActions(clientWithBasicActions, publicClient),
|
|
1231
1310
|
...chainActions(clientWithBasicActions),
|
|
1232
|
-
...walletActions(clientWithBasicActions)
|
|
1233
|
-
|
|
1311
|
+
...walletActions(clientWithBasicActions)
|
|
1312
|
+
};
|
|
1313
|
+
const clientWithAllActions = {
|
|
1314
|
+
...clientWithTransactionActions,
|
|
1315
|
+
...contractActions(clientWithTransactionActions, publicClient)
|
|
1234
1316
|
};
|
|
1235
1317
|
const finalClient = {
|
|
1236
1318
|
...clientWithAllActions,
|
package/dist/types/index.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Account, Address } from 'viem';
|
|
2
|
-
export { d as CalldataAddress, C as CalldataEncodable, i as ContractMethod, h as ContractMethodBase, f as ContractParamsArraySchemaElement, g as ContractParamsSchema, j as ContractSchema, a as DecodedCallData, D as DecodedDeployData, G as GenLayerClient, e as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, M as MethodDescription, N as Network, S as SnapSource, k as TransactionHash, s as TransactionHashVariant, m as TransactionResult, p as TransactionResultNameToNumber, l as TransactionStatus, r as TransactionType, V as VoteType, o as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, q as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-
|
|
2
|
+
export { d as CalldataAddress, C as CalldataEncodable, i as ContractMethod, h as ContractMethodBase, f as ContractParamsArraySchemaElement, g as ContractParamsSchema, j as ContractSchema, a as DecodedCallData, D as DecodedDeployData, G as GenLayerClient, e as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, M as MethodDescription, N as Network, S as SnapSource, k as TransactionHash, s as TransactionHashVariant, m as TransactionResult, p as TransactionResultNameToNumber, l as TransactionStatus, r as TransactionType, V as VoteType, o as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, q as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-C_GfhvDJ.cjs';
|
|
3
3
|
export { G as GenLayerChain } from '../chains-BYSCF33g.cjs';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Account, Address } from 'viem';
|
|
2
|
-
export { d as CalldataAddress, C as CalldataEncodable, i as ContractMethod, h as ContractMethodBase, f as ContractParamsArraySchemaElement, g as ContractParamsSchema, j as ContractSchema, a as DecodedCallData, D as DecodedDeployData, G as GenLayerClient, e as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, M as MethodDescription, N as Network, S as SnapSource, k as TransactionHash, s as TransactionHashVariant, m as TransactionResult, p as TransactionResultNameToNumber, l as TransactionStatus, r as TransactionType, V as VoteType, o as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, q as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-
|
|
2
|
+
export { d as CalldataAddress, C as CalldataEncodable, i as ContractMethod, h as ContractMethodBase, f as ContractParamsArraySchemaElement, g as ContractParamsSchema, j as ContractSchema, a as DecodedCallData, D as DecodedDeployData, G as GenLayerClient, e as GenLayerMethod, b as GenLayerRawTransaction, c as GenLayerTransaction, H as Hash, M as MethodDescription, N as Network, S as SnapSource, k as TransactionHash, s as TransactionHashVariant, m as TransactionResult, p as TransactionResultNameToNumber, l as TransactionStatus, r as TransactionType, V as VoteType, o as transactionResultNumberToName, n as transactionsStatusNameToNumber, t as transactionsStatusNumberToName, q as voteTypeNameToNumber, v as voteTypeNumberToName } from '../index-BJebZa37.js';
|
|
3
3
|
export { G as GenLayerChain } from '../chains-BYSCF33g.js';
|
package/package.json
CHANGED
package/src/client/client.ts
CHANGED
|
@@ -106,13 +106,18 @@ export const createClient = (config: ClientConfig = {chain: localnet}): GenLayer
|
|
|
106
106
|
.extend(walletActions)
|
|
107
107
|
.extend(client => accountActions(client as unknown as GenLayerClient<GenLayerChain>));
|
|
108
108
|
|
|
109
|
-
//
|
|
110
|
-
const
|
|
109
|
+
// First add transaction actions, then contract actions that depend on them
|
|
110
|
+
const clientWithTransactionActions = {
|
|
111
111
|
...clientWithBasicActions,
|
|
112
|
-
...
|
|
112
|
+
...transactionActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>, publicClient),
|
|
113
113
|
...chainActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>),
|
|
114
114
|
...genlayerWalletActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>),
|
|
115
|
-
|
|
115
|
+
} as unknown as GenLayerClient<GenLayerChain>;
|
|
116
|
+
|
|
117
|
+
// Then add contract actions that can now access transaction actions
|
|
118
|
+
const clientWithAllActions = {
|
|
119
|
+
...clientWithTransactionActions,
|
|
120
|
+
...contractActions(clientWithTransactionActions as unknown as GenLayerClient<GenLayerChain>, publicClient),
|
|
116
121
|
} as unknown as GenLayerClient<GenLayerChain>;
|
|
117
122
|
|
|
118
123
|
// Add transaction actions last, after all other actions are in place
|
package/src/contracts/actions.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
TransactionHashVariant,
|
|
12
12
|
} from "@/types";
|
|
13
13
|
import {fromHex, toHex, zeroAddress, encodeFunctionData, PublicClient, parseEventLogs} from "viem";
|
|
14
|
-
import {b64ToArray} from "@/utils/jsonifier";
|
|
14
|
+
import {toJsonSafeDeep, b64ToArray} from "@/utils/jsonifier";
|
|
15
15
|
|
|
16
16
|
export const contractActions = (client: GenLayerClient<GenLayerChain>, publicClient: PublicClient) => {
|
|
17
17
|
return {
|
|
@@ -53,6 +53,7 @@ export const contractActions = (client: GenLayerClient<GenLayerChain>, publicCli
|
|
|
53
53
|
args?: CalldataEncodable[];
|
|
54
54
|
kwargs?: Map<string, CalldataEncodable> | {[key: string]: CalldataEncodable};
|
|
55
55
|
rawReturn?: RawReturn;
|
|
56
|
+
jsonSafeReturn?: boolean;
|
|
56
57
|
leaderOnly?: boolean;
|
|
57
58
|
transactionHashVariant?: TransactionHashVariant;
|
|
58
59
|
}): Promise<RawReturn extends true ? `0x${string}` : CalldataEncodable> => {
|
|
@@ -62,6 +63,7 @@ export const contractActions = (client: GenLayerClient<GenLayerChain>, publicCli
|
|
|
62
63
|
functionName,
|
|
63
64
|
args: callArgs,
|
|
64
65
|
kwargs,
|
|
66
|
+
jsonSafeReturn = false,
|
|
65
67
|
leaderOnly = false,
|
|
66
68
|
transactionHashVariant = TransactionHashVariant.LATEST_NONFINAL,
|
|
67
69
|
} = args;
|
|
@@ -88,7 +90,12 @@ export const contractActions = (client: GenLayerClient<GenLayerChain>, publicCli
|
|
|
88
90
|
return prefixedResult;
|
|
89
91
|
}
|
|
90
92
|
const resultBinary = fromHex(prefixedResult, "bytes");
|
|
91
|
-
|
|
93
|
+
const decoded = calldata.decode(resultBinary) as any;
|
|
94
|
+
if (!jsonSafeReturn) {
|
|
95
|
+
return decoded;
|
|
96
|
+
}
|
|
97
|
+
// If jsonSafeReturn is requested, convert to JSON-safe recursively
|
|
98
|
+
return toJsonSafeDeep(decoded) as any;
|
|
92
99
|
},
|
|
93
100
|
simulateWriteContract: async <RawReturn extends boolean | undefined>(args: {
|
|
94
101
|
account?: Account;
|
|
@@ -296,6 +303,18 @@ const _sendTransaction = async ({
|
|
|
296
303
|
const validatedSenderAccount = validateAccount(senderAccount);
|
|
297
304
|
|
|
298
305
|
const nonce = await client.getCurrentNonce({address: validatedSenderAccount.address});
|
|
306
|
+
let estimatedGas: bigint;
|
|
307
|
+
try {
|
|
308
|
+
estimatedGas = await client.estimateTransactionGas({
|
|
309
|
+
from: validatedSenderAccount.address,
|
|
310
|
+
to: client.chain.consensusMainContract?.address as Address,
|
|
311
|
+
data: encodedData,
|
|
312
|
+
value: value,
|
|
313
|
+
});
|
|
314
|
+
} catch (error) {
|
|
315
|
+
console.warn("Gas estimation failed, using fallback value:", error);
|
|
316
|
+
estimatedGas = 200_000n;
|
|
317
|
+
}
|
|
299
318
|
const transactionRequest = await client.prepareTransactionRequest({
|
|
300
319
|
account: validatedSenderAccount,
|
|
301
320
|
to: client.chain.consensusMainContract?.address as Address,
|
|
@@ -303,7 +322,7 @@ const _sendTransaction = async ({
|
|
|
303
322
|
type: "legacy",
|
|
304
323
|
nonce: Number(nonce),
|
|
305
324
|
value: value,
|
|
306
|
-
gas:
|
|
325
|
+
gas: estimatedGas,
|
|
307
326
|
});
|
|
308
327
|
|
|
309
328
|
if (validatedSenderAccount?.type !== "local") {
|
|
@@ -90,6 +90,26 @@ export const transactionActions = (client: GenLayerClient<GenLayerChain>, public
|
|
|
90
90
|
})) as unknown as GenLayerRawTransaction;
|
|
91
91
|
return decodeTransaction(transaction);
|
|
92
92
|
},
|
|
93
|
+
estimateTransactionGas: async (transactionParams: {
|
|
94
|
+
from?: Address;
|
|
95
|
+
to: Address;
|
|
96
|
+
data?: `0x${string}`;
|
|
97
|
+
value?: bigint;
|
|
98
|
+
}): Promise<bigint> => {
|
|
99
|
+
const formattedParams = {
|
|
100
|
+
from: transactionParams.from || client.account?.address,
|
|
101
|
+
to: transactionParams.to,
|
|
102
|
+
data: transactionParams.data || "0x",
|
|
103
|
+
value: transactionParams.value ? `0x${transactionParams.value.toString(16)}` as `0x${string}` : "0x0" as `0x${string}`,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const gasHex = await client.request({
|
|
107
|
+
method: "eth_estimateGas",
|
|
108
|
+
params: [formattedParams],
|
|
109
|
+
}) as string;
|
|
110
|
+
|
|
111
|
+
return BigInt(gasHex);
|
|
112
|
+
},
|
|
93
113
|
});
|
|
94
114
|
|
|
95
115
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {GenLayerTransaction, GenLayerRawTransaction, DecodedCallData, DecodedDeployData} from "../types/transactions";
|
|
2
|
-
import {transactionsStatusNumberToName, transactionResultNumberToName, voteTypeNumberToName, VoteType} from "../types/transactions";
|
|
1
|
+
import {GenLayerTransaction, GenLayerRawTransaction, DecodedCallData, DecodedDeployData,transactionsStatusNumberToName, transactionResultNumberToName, voteTypeNumberToName, VoteType} from "../types/transactions";
|
|
3
2
|
import {b64ToArray, calldataToUserFriendlyJson, resultToUserFriendlyJson} from "../utils/jsonifier";
|
|
4
3
|
import {fromRlp, fromHex, Hex, Address} from "viem";
|
|
5
4
|
import * as calldataAbi from "../abi/calldata";
|
package/src/types/clients.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type GenLayerMethod =
|
|
|
18
18
|
| {method: "gen_getContractCode"; params: [address: Address]}
|
|
19
19
|
| {method: "sim_getTransactionsForAddress"; params: [address: Address, filter?: "all" | "from" | "to"]}
|
|
20
20
|
| {method: "eth_getTransactionCount"; params: [address: Address, block: string]}
|
|
21
|
+
| {method: "eth_estimateGas"; params: [transactionParams: any]}
|
|
21
22
|
| {method: "gen_call"; params: [requestParams: any]};
|
|
22
23
|
|
|
23
24
|
/*
|
|
@@ -47,6 +48,7 @@ export type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<
|
|
|
47
48
|
args?: CalldataEncodable[];
|
|
48
49
|
kwargs?: Map<string, CalldataEncodable> | {[key: string]: CalldataEncodable};
|
|
49
50
|
rawReturn?: RawReturn;
|
|
51
|
+
jsonSafeReturn?: boolean;
|
|
50
52
|
transactionHashVariant?: TransactionHashVariant;
|
|
51
53
|
}) => Promise<RawReturn extends true ? `0x${string}` : CalldataEncodable>;
|
|
52
54
|
writeContract: (args: {
|
|
@@ -79,6 +81,12 @@ export type GenLayerClient<TGenLayerChain extends GenLayerChain> = Omit<
|
|
|
79
81
|
}) => Promise<`0x${string}`>;
|
|
80
82
|
getTransaction: (args: {hash: TransactionHash}) => Promise<GenLayerTransaction>;
|
|
81
83
|
getCurrentNonce: (args: {address: Address}) => Promise<number>;
|
|
84
|
+
estimateTransactionGas: (transactionParams: {
|
|
85
|
+
from?: Address;
|
|
86
|
+
to: Address;
|
|
87
|
+
data?: `0x${string}`;
|
|
88
|
+
value?: bigint;
|
|
89
|
+
}) => Promise<bigint>;
|
|
82
90
|
waitForTransactionReceipt: (args: {
|
|
83
91
|
hash: TransactionHash;
|
|
84
92
|
status?: TransactionStatus;
|
package/src/utils/jsonifier.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import {calldata} from "@/abi";
|
|
2
|
+
import type {CalldataEncodable} from "@/types/calldata";
|
|
3
|
+
import {CalldataAddress} from "@/types/calldata";
|
|
4
|
+
import {toHex} from "viem";
|
|
2
5
|
|
|
3
6
|
|
|
4
7
|
export function b64ToArray(b64: string): Uint8Array {
|
|
@@ -44,4 +47,73 @@ export function resultToUserFriendlyJson(cd64: string): any {
|
|
|
44
47
|
status,
|
|
45
48
|
payload,
|
|
46
49
|
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Deeply converts CalldataEncodable values into JSON-serializable structures.
|
|
53
|
+
// Rules:
|
|
54
|
+
// - bigint: to number if safe, otherwise to decimal string
|
|
55
|
+
// - Uint8Array: to 0x-prefixed hex string
|
|
56
|
+
// - CalldataAddress: to 0x-prefixed hex string
|
|
57
|
+
// - Map: to Array<[key, value]> preserving order
|
|
58
|
+
// - Arrays and plain objects: converted recursively
|
|
59
|
+
export function toJsonSafeDeep<T extends CalldataEncodable>(value: T): any {
|
|
60
|
+
return _toJsonSafeDeep(value, new WeakSet());
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function _toJsonSafeDeep(value: CalldataEncodable, seen: WeakSet<object>): any {
|
|
64
|
+
if (value === null || value === undefined) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const primitiveType = typeof value;
|
|
69
|
+
if (primitiveType === "string" || primitiveType === "boolean" || primitiveType === "number") {
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (primitiveType === "bigint") {
|
|
74
|
+
const big = value as bigint;
|
|
75
|
+
const abs = big < 0n ? -big : big;
|
|
76
|
+
const maxSafe = 9007199254740991n; // Number.MAX_SAFE_INTEGER
|
|
77
|
+
return abs <= maxSafe ? Number(big) : big.toString();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Objects and structured values
|
|
81
|
+
if (typeof value === "object") {
|
|
82
|
+
if (seen.has(value as object)) {
|
|
83
|
+
// Prevent potential cycles; represent as null
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
seen.add(value as object);
|
|
87
|
+
|
|
88
|
+
if (value instanceof Uint8Array) {
|
|
89
|
+
return toHex(value);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (value instanceof Array) {
|
|
93
|
+
return value.map((v) => _toJsonSafeDeep(v as CalldataEncodable, seen));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (value instanceof Map) {
|
|
97
|
+
const obj: Record<string, any> = {};
|
|
98
|
+
for (const [k, v] of value.entries()) {
|
|
99
|
+
obj[k] = _toJsonSafeDeep(v as CalldataEncodable, seen);
|
|
100
|
+
}
|
|
101
|
+
return obj;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (value instanceof CalldataAddress) {
|
|
105
|
+
return toHex(value.bytes);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (Object.getPrototypeOf(value) === Object.prototype) {
|
|
109
|
+
const obj: Record<string, any> = {};
|
|
110
|
+
for (const [k, v] of Object.entries(value)) {
|
|
111
|
+
obj[k] = _toJsonSafeDeep(v as CalldataEncodable, seen);
|
|
112
|
+
}
|
|
113
|
+
return obj;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Fallback: return as-is (shouldn't normally reach here)
|
|
118
|
+
return value as any;
|
|
47
119
|
}
|