@0xobelisk/sui-client 1.2.0-pre.99 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -50,11 +50,17 @@ var src_exports = {};
50
50
  __export(src_exports, {
51
51
  BcsType: () => import_bcs4.BcsType,
52
52
  Dubhe: () => Dubhe,
53
+ MAINNET_DUBHE_FRAMEWORK_PACKAGE_ID: () => MAINNET_DUBHE_FRAMEWORK_PACKAGE_ID,
54
+ MAINNET_DUBHE_HUB_OBJECT_ID: () => MAINNET_DUBHE_HUB_OBJECT_ID,
53
55
  MultiSigClient: () => MultiSigClient,
54
56
  SuiAccountManager: () => SuiAccountManager,
55
57
  SuiContractFactory: () => SuiContractFactory,
56
58
  SuiTx: () => SuiTx,
59
+ TESTNET_DUBHE_FRAMEWORK_PACKAGE_ID: () => TESTNET_DUBHE_FRAMEWORK_PACKAGE_ID,
60
+ TESTNET_DUBHE_HUB_OBJECT_ID: () => TESTNET_DUBHE_HUB_OBJECT_ID,
57
61
  bcs: () => import_bcs4.bcs,
62
+ getDefaultConfig: () => getDefaultConfig,
63
+ getDefaultURL: () => getDefaultURL,
58
64
  loadMetadata: () => loadMetadata
59
65
  });
60
66
  module.exports = __toCommonJS(src_exports);
@@ -838,19 +844,26 @@ var SuiInteractor = class {
838
844
  };
839
845
 
840
846
  // src/libs/suiInteractor/defaultConfig.ts
841
- var getDefaultURL = (networkType = "testnet") => {
847
+ var TESTNET_DUBHE_FRAMEWORK_PACKAGE_ID = "0xae33be6675639d6f1a5c468ae6bbc457ae4e22e57cd7526741d6143ce219d995";
848
+ var TESTNET_DUBHE_HUB_OBJECT_ID = "0x80391929a8772aba091156fd1f099bf79240d2cf4471a14026b4aa68e3a240cc";
849
+ var MAINNET_DUBHE_FRAMEWORK_PACKAGE_ID = "0x5bc40de124588b1e3514ca50f5e7109869351c4d9544e5f0cb9d30dd47bf8de7";
850
+ var MAINNET_DUBHE_HUB_OBJECT_ID = "0x96e92d9baccfd0a2927b4f209756e1edbc18904bff34e486e4bb4a151320e1e5";
851
+ var getDefaultConfig = (networkType = "testnet") => {
842
852
  switch (networkType) {
843
- case "localnet":
853
+ case "localnet": {
854
+ const localRpc = encodeURIComponent("http://127.0.0.1:9000");
844
855
  return {
845
856
  fullNode: "http://127.0.0.1:9000",
846
857
  graphql: "http://127.0.0.1:9125",
847
858
  network: "localnet",
848
- txExplorer: "https://explorer.polymedia.app/txblock/:txHash?network=local",
849
- accountExplorer: "https://explorer.polymedia.app/address/:address?network=local",
850
- explorer: "https://explorer.polymedia.app?network=local",
859
+ txExplorer: `https://custom.suiscan.xyz/custom/tx/:txHash?network=${localRpc}`,
860
+ accountExplorer: `https://custom.suiscan.xyz/custom/account/:address?network=${localRpc}`,
861
+ explorer: `https://custom.suiscan.xyz/custom?network=${localRpc}`,
851
862
  indexerUrl: "http://127.0.0.1:3001",
852
863
  channelUrl: "http://127.0.0.1:8080"
864
+ // frameworkPackageId: undefined — set after deploying dubhe locally
853
865
  };
866
+ }
854
867
  case "devnet":
855
868
  return {
856
869
  fullNode: "https://fullnode.devnet.sui.io:443",
@@ -860,6 +873,7 @@ var getDefaultURL = (networkType = "testnet") => {
860
873
  explorer: "https://suiscan.xyz/devnet",
861
874
  indexerUrl: "http://127.0.0.1:3001",
862
875
  channelUrl: "http://127.0.0.1:8080"
876
+ // frameworkPackageId: undefined — no persistent deployment on devnet
863
877
  };
864
878
  case "testnet":
865
879
  return {
@@ -870,7 +884,9 @@ var getDefaultURL = (networkType = "testnet") => {
870
884
  accountExplorer: "https://suiscan.xyz/testnet/address/:address",
871
885
  explorer: "https://suiscan.xyz/testnet",
872
886
  indexerUrl: "http://127.0.0.1:3001",
873
- channelUrl: "http://127.0.0.1:8080"
887
+ channelUrl: "http://127.0.0.1:8080",
888
+ frameworkPackageId: TESTNET_DUBHE_FRAMEWORK_PACKAGE_ID,
889
+ dappHubId: TESTNET_DUBHE_HUB_OBJECT_ID
874
890
  };
875
891
  case "mainnet":
876
892
  return {
@@ -881,7 +897,9 @@ var getDefaultURL = (networkType = "testnet") => {
881
897
  accountExplorer: "https://suiscan.xyz/mainnet/address/:address",
882
898
  explorer: "https://suiscan.xyz/mainnet",
883
899
  indexerUrl: "http://127.0.0.1:3001",
884
- channelUrl: "http://127.0.0.1:8080"
900
+ channelUrl: "http://127.0.0.1:8080",
901
+ frameworkPackageId: MAINNET_DUBHE_FRAMEWORK_PACKAGE_ID || void 0,
902
+ dappHubId: MAINNET_DUBHE_HUB_OBJECT_ID || void 0
885
903
  };
886
904
  default:
887
905
  return {
@@ -892,10 +910,13 @@ var getDefaultURL = (networkType = "testnet") => {
892
910
  accountExplorer: "https://suiscan.xyz/testnet/address/:address",
893
911
  explorer: "https://suiscan.xyz/testnet",
894
912
  indexerUrl: "http://127.0.0.1:3001",
895
- channelUrl: "http://127.0.0.1:8080"
913
+ channelUrl: "http://127.0.0.1:8080",
914
+ frameworkPackageId: TESTNET_DUBHE_FRAMEWORK_PACKAGE_ID,
915
+ dappHubId: TESTNET_DUBHE_HUB_OBJECT_ID
896
916
  };
897
917
  }
898
918
  };
919
+ var getDefaultURL = getDefaultConfig;
899
920
 
900
921
  // src/libs/suiContractFactory/index.ts
901
922
  var SuiContractFactory = class {
@@ -1083,6 +1104,10 @@ function normalizePackageId(input) {
1083
1104
  const normalized = withoutPrefix.replace(/^0+/, "");
1084
1105
  return "0x" + normalized;
1085
1106
  }
1107
+ function normalizeDappKey(packageId) {
1108
+ const raw = packageId.replace(/^0x/, "");
1109
+ return `${raw.padStart(64, "0")}::dapp_key::DappKey`;
1110
+ }
1086
1111
 
1087
1112
  // src/errors/index.ts
1088
1113
  var ContractDataParsingError = class extends Error {
@@ -1381,6 +1406,7 @@ function createTx(meta, fn) {
1381
1406
  }
1382
1407
  );
1383
1408
  }
1409
+ var SUI_CLOCK_OBJECT_ID = "0x0000000000000000000000000000000000000000000000000000000000000006";
1384
1410
  var _query, _tx, _object, _exec, _read, _getVectorDepth, _bcs, _bcsenum, _processKeyParameter, processKeyParameter_fn;
1385
1411
  var Dubhe = class {
1386
1412
  /**
@@ -1396,6 +1422,7 @@ var Dubhe = class {
1396
1422
  * @param packageId
1397
1423
  * @param metadata
1398
1424
  * @param channelUrl, the base URL for Dubhe Channel API, optional
1425
+ * @param frameworkPackageId, the published package ID of the dubhe framework, required for proxy operations
1399
1426
  */
1400
1427
  constructor({
1401
1428
  mnemonics,
@@ -1403,8 +1430,12 @@ var Dubhe = class {
1403
1430
  networkType,
1404
1431
  fullnodeUrls,
1405
1432
  packageId,
1433
+ dappKey: dappKeyParam,
1406
1434
  metadata,
1407
- channelUrl
1435
+ channelUrl,
1436
+ frameworkPackageId,
1437
+ dappStorageId,
1438
+ dappHubId
1408
1439
  } = {}) {
1409
1440
  // async getTransactions({
1410
1441
  // first,
@@ -2105,7 +2136,7 @@ var Dubhe = class {
2105
2136
  };
2106
2137
  });
2107
2138
  networkType = networkType ?? "mainnet";
2108
- const defaultParams = getDefaultURL(networkType);
2139
+ const defaultParams = getDefaultConfig(networkType);
2109
2140
  this.accountManager = new SuiAccountManager({ mnemonics, secretKey });
2110
2141
  fullnodeUrls = fullnodeUrls || [defaultParams.fullNode];
2111
2142
  this.suiInteractor = new SuiInteractor(fullnodeUrls, networkType);
@@ -2113,6 +2144,11 @@ var Dubhe = class {
2113
2144
  baseUrl: channelUrl || defaultParams.channelUrl
2114
2145
  });
2115
2146
  this.packageId = packageId ? normalizePackageId(packageId) : void 0;
2147
+ this.dappKey = dappKeyParam;
2148
+ const networkDefault = defaultParams.frameworkPackageId;
2149
+ this.frameworkPackageId = frameworkPackageId ? normalizePackageId(frameworkPackageId) : networkDefault ? normalizePackageId(networkDefault) : void 0;
2150
+ this.dappStorageId = dappStorageId;
2151
+ this.dappHubId = dappHubId;
2116
2152
  if (metadata !== void 0) {
2117
2153
  this.metadata = metadata;
2118
2154
  const maxLoopNum = 5;
@@ -2403,6 +2439,27 @@ var Dubhe = class {
2403
2439
  getPackageId() {
2404
2440
  return this.contractFactory.packageId;
2405
2441
  }
2442
+ /**
2443
+ * Return the fully-qualified Move type string for this DApp's `DappKey`.
2444
+ *
2445
+ * The format matches what `std::type_name::get<DappKey>()` returns on-chain:
2446
+ * `<64-char-zero-padded-address>::dapp_key::DappKey`
2447
+ *
2448
+ * Use this whenever you need to pass a type argument or build a `target`
2449
+ * string that references the DApp's DappKey type.
2450
+ *
2451
+ * @example
2452
+ * ```typescript
2453
+ * tx.moveCall({
2454
+ * target: `${frameworkPackageId}::dapp_system::settle_writes`,
2455
+ * typeArguments: [contract.getDappKey()],
2456
+ * arguments: [...],
2457
+ * });
2458
+ * ```
2459
+ */
2460
+ getDappKey() {
2461
+ return this.dappKey;
2462
+ }
2406
2463
  getMetadata() {
2407
2464
  return this.contractFactory.metadata;
2408
2465
  }
@@ -2410,7 +2467,7 @@ var Dubhe = class {
2410
2467
  return this.suiInteractor.network;
2411
2468
  }
2412
2469
  getNetworkConfig() {
2413
- return getDefaultURL(this.getNetwork());
2470
+ return getDefaultConfig(this.getNetwork());
2414
2471
  }
2415
2472
  getTxExplorerUrl(txHash) {
2416
2473
  return this.getNetworkConfig().txExplorer.replace(":txHash", txHash);
@@ -2436,7 +2493,7 @@ var Dubhe = class {
2436
2493
  const fullnodeUrlsChanged = config.fullnodeUrls !== void 0;
2437
2494
  if (networkChanged || fullnodeUrlsChanged) {
2438
2495
  const newNetworkType = config.networkType ?? this.suiInteractor.network;
2439
- const defaultParams = getDefaultURL(newNetworkType);
2496
+ const defaultParams = getDefaultConfig(newNetworkType);
2440
2497
  const newFullnodeUrls = config.fullnodeUrls || [defaultParams.fullNode];
2441
2498
  this.suiInteractor = new SuiInteractor(newFullnodeUrls, newNetworkType);
2442
2499
  }
@@ -2447,6 +2504,9 @@ var Dubhe = class {
2447
2504
  }
2448
2505
  const packageIdChanged = config.packageId !== void 0 && config.packageId !== this.packageId;
2449
2506
  const metadataChanged = config.metadata !== void 0 && config.metadata !== this.metadata;
2507
+ if (config.dappKey !== void 0) {
2508
+ this.dappKey = config.dappKey;
2509
+ }
2450
2510
  if (packageIdChanged || metadataChanged) {
2451
2511
  if (config.packageId !== void 0) {
2452
2512
  this.packageId = normalizePackageId(config.packageId);
@@ -2638,11 +2698,8 @@ var Dubhe = class {
2638
2698
  if (account && account.startsWith("0x")) {
2639
2699
  account = account.slice(2);
2640
2700
  }
2641
- if (packageId && packageId.startsWith("0x")) {
2642
- packageId = packageId.slice(2);
2643
- }
2644
2701
  const payload = {
2645
- dapp_key: `${packageId}::dapp_key::DappKey`,
2702
+ dapp_key: normalizeDappKey(packageId ?? ""),
2646
2703
  account,
2647
2704
  table,
2648
2705
  key
@@ -2681,22 +2738,16 @@ var Dubhe = class {
2681
2738
  * );
2682
2739
  */
2683
2740
  async subscribeChannelTable({
2684
- packageId,
2741
+ packageId: _packageId,
2685
2742
  account,
2686
2743
  table,
2687
2744
  key
2688
2745
  } = {}, options) {
2689
- packageId = packageId || this.packageId;
2690
- if (account !== void 0) {
2691
- if (account.startsWith("0x")) {
2692
- account = account.slice(2);
2693
- }
2694
- }
2695
- if (packageId && packageId.startsWith("0x")) {
2696
- packageId = packageId.slice(2);
2746
+ if (account !== void 0 && account.startsWith("0x")) {
2747
+ account = account.slice(2);
2697
2748
  }
2698
2749
  const payload = {
2699
- dapp_key: `${packageId}::dapp_key::DappKey`
2750
+ dapp_key: this.dappKey
2700
2751
  };
2701
2752
  if (account !== void 0) {
2702
2753
  payload.account = account;
@@ -2873,6 +2924,761 @@ var Dubhe = class {
2873
2924
  async entity_key_from_u256(x) {
2874
2925
  return numberToAddressHex(x);
2875
2926
  }
2927
+ // ─── UserStorage helpers ────────────────────────────────────────────────────
2928
+ /**
2929
+ * Call the DApp's generated `user_storage_init::init_user_storage` entry function,
2930
+ * which creates and shares a `UserStorage` object for the signer.
2931
+ *
2932
+ * Each DApp exposes this entry point under its own package ID.
2933
+ * On Sui, the `UserStorage` object is shared immediately so all transactions
2934
+ * can reference it without knowing the object ID in advance.
2935
+ *
2936
+ * @param dappHubId Object ID of the DappHub shared object
2937
+ * @param dappStorageId Object ID of the DApp's DappStorage shared object
2938
+ */
2939
+ async initUserStorage({
2940
+ dappHubId,
2941
+ dappStorageId: dappStorageIdParam,
2942
+ derivePathParams,
2943
+ onSuccess,
2944
+ onError
2945
+ }) {
2946
+ const storageId = dappStorageIdParam ?? this.dappStorageId;
2947
+ if (!storageId) {
2948
+ throw new Error(
2949
+ "dappStorageId is required for initUserStorage. Pass it directly or set it in the Dubhe constructor."
2950
+ );
2951
+ }
2952
+ const pkg = this.packageId;
2953
+ if (!pkg)
2954
+ throw new Error("packageId is required for initUserStorage.");
2955
+ const tx = new import_transactions3.Transaction();
2956
+ tx.moveCall({
2957
+ target: `${pkg}::user_storage_init::init_user_storage`,
2958
+ arguments: [tx.object(dappHubId), tx.object(storageId)]
2959
+ });
2960
+ return this.signAndSendTxn({
2961
+ tx,
2962
+ derivePathParams,
2963
+ onSuccess,
2964
+ onError
2965
+ });
2966
+ }
2967
+ /**
2968
+ * Activate a session key for the signer's `UserStorage`.
2969
+ *
2970
+ * The signer must be the `canonical_owner` of the `UserStorage` object.
2971
+ * Calls `<frameworkPackageId>::dapp_system::activate_session<DappKey>`.
2972
+ *
2973
+ * @param userStorageId Object ID of the UserStorage to activate a session for
2974
+ * @param sessionWallet Sui address of the session wallet
2975
+ * @param durationMs Session duration in milliseconds ([60_000, 604_800_000])
2976
+ * @param clockObjectId Object ID of the Sui Clock (default: 0x6)
2977
+ */
2978
+ async activateSession({
2979
+ userStorageId,
2980
+ sessionWallet,
2981
+ durationMs,
2982
+ dappHubId: dappHubIdParam,
2983
+ clockObjectId,
2984
+ derivePathParams,
2985
+ onSuccess,
2986
+ onError
2987
+ }) {
2988
+ const fwPkg = this.frameworkPackageId;
2989
+ if (!fwPkg) {
2990
+ throw new Error(
2991
+ 'frameworkPackageId is required for activateSession. Set it in the Dubhe constructor ({ frameworkPackageId: "0x..." }).'
2992
+ );
2993
+ }
2994
+ const typeArg = this.dappKey;
2995
+ if (!typeArg) {
2996
+ throw new Error(
2997
+ 'dappKey is required for activateSession. Set it in the Dubhe constructor ({ packageId: "0x..." }).'
2998
+ );
2999
+ }
3000
+ const hubId = dappHubIdParam ?? this.dappHubId;
3001
+ if (!hubId) {
3002
+ throw new Error(
3003
+ 'dappHubId is required for activateSession. Pass it directly or set it in the Dubhe constructor ({ dappHubId: "0x..." }).'
3004
+ );
3005
+ }
3006
+ const clockId = clockObjectId ?? SUI_CLOCK_OBJECT_ID;
3007
+ const tx = new import_transactions3.Transaction();
3008
+ tx.moveCall({
3009
+ target: `${fwPkg}::dapp_system::activate_session`,
3010
+ typeArguments: [typeArg],
3011
+ arguments: [
3012
+ tx.object(hubId),
3013
+ tx.object(userStorageId),
3014
+ tx.pure.address(sessionWallet),
3015
+ tx.pure.u64(durationMs),
3016
+ tx.object(clockId)
3017
+ ]
3018
+ });
3019
+ return this.signAndSendTxn({
3020
+ tx,
3021
+ derivePathParams,
3022
+ onSuccess,
3023
+ onError
3024
+ });
3025
+ }
3026
+ /**
3027
+ * Deactivate the current session key on a `UserStorage`.
3028
+ *
3029
+ * Allowed callers:
3030
+ * - The `canonical_owner` (revoke at any time).
3031
+ * - The session key itself (voluntary sign-out).
3032
+ * - Anyone, once the session has expired.
3033
+ *
3034
+ * Calls `<frameworkPackageId>::dapp_system::deactivate_session<DappKey>`.
3035
+ *
3036
+ * @param userStorageId Object ID of the UserStorage to deactivate the session on
3037
+ */
3038
+ async deactivateSession({
3039
+ userStorageId,
3040
+ dappHubId: dappHubIdParam,
3041
+ derivePathParams,
3042
+ onSuccess,
3043
+ onError
3044
+ }) {
3045
+ const fwPkg = this.frameworkPackageId;
3046
+ if (!fwPkg) {
3047
+ throw new Error(
3048
+ 'frameworkPackageId is required for deactivateSession. Set it in the Dubhe constructor ({ frameworkPackageId: "0x..." }).'
3049
+ );
3050
+ }
3051
+ const typeArg = this.dappKey;
3052
+ if (!typeArg) {
3053
+ throw new Error(
3054
+ 'dappKey is required for deactivateSession. Set it in the Dubhe constructor ({ packageId: "0x..." }).'
3055
+ );
3056
+ }
3057
+ const hubId = dappHubIdParam ?? this.dappHubId;
3058
+ if (!hubId) {
3059
+ throw new Error(
3060
+ 'dappHubId is required for deactivateSession. Pass it directly or set it in the Dubhe constructor ({ dappHubId: "0x..." }).'
3061
+ );
3062
+ }
3063
+ const tx = new import_transactions3.Transaction();
3064
+ tx.moveCall({
3065
+ target: `${fwPkg}::dapp_system::deactivate_session`,
3066
+ typeArguments: [typeArg],
3067
+ arguments: [tx.object(hubId), tx.object(userStorageId)]
3068
+ });
3069
+ return this.signAndSendTxn({
3070
+ tx,
3071
+ derivePathParams,
3072
+ onSuccess,
3073
+ onError
3074
+ });
3075
+ }
3076
+ /**
3077
+ * Look up the `UserStorage` object ID for the given address in this DApp.
3078
+ *
3079
+ * Scans the transaction history for `user_storage_init::init_user_storage`
3080
+ * calls from the given address and extracts the created `UserStorage` object
3081
+ * ID from the transaction's object changes.
3082
+ *
3083
+ * Returns the object ID on success, or `null` when:
3084
+ * - `packageId` or `frameworkPackageId` is not set.
3085
+ * - The user has not yet called `initUserStorage`.
3086
+ *
3087
+ * @param userAddress Sui address to look up (with or without 0x prefix).
3088
+ */
3089
+ async getUserStorageId(userAddress) {
3090
+ const pkg = this.packageId;
3091
+ const fwPkg = this.frameworkPackageId;
3092
+ if (!pkg || !fwPkg)
3093
+ return null;
3094
+ const normalizedUser = userAddress.startsWith("0x") ? userAddress : `0x${userAddress}`;
3095
+ const expectedType = `${fwPkg}::dapp_service::UserStorage`;
3096
+ let cursor = null;
3097
+ let hasNextPage = true;
3098
+ while (hasNextPage) {
3099
+ const result = await this.suiInteractor.currentClient.queryTransactionBlocks({
3100
+ filter: {
3101
+ MoveFunction: {
3102
+ package: pkg,
3103
+ module: "user_storage_init",
3104
+ function: "init_user_storage"
3105
+ }
3106
+ },
3107
+ options: { showObjectChanges: true },
3108
+ ...cursor !== null && cursor !== void 0 ? { cursor } : {},
3109
+ limit: 50
3110
+ });
3111
+ for (const tx of result.data) {
3112
+ if (!tx.objectChanges)
3113
+ continue;
3114
+ const created = tx.objectChanges.find(
3115
+ (c) => c.type === "created" && typeof c.objectType === "string" && c.objectType === expectedType && c.sender === normalizedUser
3116
+ );
3117
+ if (created?.objectId)
3118
+ return created.objectId;
3119
+ }
3120
+ hasNextPage = result.hasNextPage;
3121
+ cursor = result.nextCursor ?? null;
3122
+ }
3123
+ return null;
3124
+ }
3125
+ /**
3126
+ * Fetch and return the on-chain fields of a `UserStorage` shared object.
3127
+ *
3128
+ * The returned object mirrors Move's `UserStorage` struct plus two
3129
+ * convenience fields computed from the raw counters:
3130
+ * - `unsettled_count` = write_count − settled_count
3131
+ * - `unsettled_bytes` = write_bytes − settled_bytes
3132
+ *
3133
+ * @param userStorageId Object ID of the UserStorage to inspect.
3134
+ */
3135
+ async getUserStorageFields(userStorageId) {
3136
+ const obj = await this.suiInteractor.getObject(userStorageId);
3137
+ const fields = obj?.content?.fields ?? {};
3138
+ const writeCount = BigInt(fields.write_count ?? 0);
3139
+ const settledCount = BigInt(fields.settled_count ?? 0);
3140
+ const writeBytes = BigInt(fields.write_bytes ?? 0);
3141
+ const settledBytes = BigInt(fields.settled_bytes ?? 0);
3142
+ return {
3143
+ objectId: userStorageId,
3144
+ dapp_key: fields.dapp_key ?? "",
3145
+ canonical_owner: fields.canonical_owner ?? "",
3146
+ session_key: fields.session_key ?? "",
3147
+ session_expires_at: BigInt(fields.session_expires_at ?? 0),
3148
+ write_count: writeCount,
3149
+ settled_count: settledCount,
3150
+ write_bytes: writeBytes,
3151
+ settled_bytes: settledBytes,
3152
+ unsettled_count: writeCount - settledCount,
3153
+ unsettled_bytes: writeBytes - settledBytes
3154
+ };
3155
+ }
3156
+ /**
3157
+ * Fetch and return the on-chain fields of a `DappStorage` shared object.
3158
+ *
3159
+ * Covers the full metadata + fee/credit subset of the Move struct.
3160
+ *
3161
+ * @param dappStorageId Object ID of the DappStorage to inspect.
3162
+ */
3163
+ /**
3164
+ * Read the framework-level fields from the DappHub shared object.
3165
+ *
3166
+ * Key fields:
3167
+ * - `treasury` — address that directly receives framework fee income
3168
+ * - `pending_treasury` — queued treasury address during two-step rotation
3169
+ * - `framework_admin` — address that can update framework configuration
3170
+ * - `version` — current framework version
3171
+ */
3172
+ async getDappHubFields(dappHubId) {
3173
+ const obj = await this.suiInteractor.getObject(dappHubId);
3174
+ const fields = obj?.content?.fields ?? {};
3175
+ const feeConfig = fields.fee_config?.fields ?? fields.fee_config ?? {};
3176
+ const adminConfig = fields.admin_config?.fields ?? fields.admin_config ?? {};
3177
+ return {
3178
+ objectId: dappHubId,
3179
+ version: Number(fields.version ?? 0),
3180
+ framework_admin: adminConfig.admin ?? fields.framework_admin ?? "",
3181
+ treasury: feeConfig.treasury ?? fields.treasury ?? "",
3182
+ pending_treasury: feeConfig.pending_treasury ?? fields.pending_treasury ?? ""
3183
+ };
3184
+ }
3185
+ async getDappStorageFields(dappStorageId) {
3186
+ const obj = await this.suiInteractor.getObject(dappStorageId);
3187
+ const fields = obj?.content?.fields ?? {};
3188
+ return {
3189
+ objectId: dappStorageId,
3190
+ dapp_key: fields.dapp_key ?? "",
3191
+ name: fields.name ?? "",
3192
+ description: fields.description ?? "",
3193
+ website_url: fields.website_url ?? "",
3194
+ admin: fields.admin ?? "",
3195
+ version: Number(fields.version ?? 0),
3196
+ paused: Boolean(fields.paused),
3197
+ free_credit: BigInt(fields.free_credit ?? 0),
3198
+ free_credit_expires_at: BigInt(fields.free_credit_expires_at ?? 0),
3199
+ credit_pool: BigInt(fields.credit_pool ?? 0),
3200
+ min_credit_to_unsuspend: BigInt(fields.min_credit_to_unsuspend ?? 0),
3201
+ suspended: Boolean(fields.suspended),
3202
+ total_settled: BigInt(fields.total_settled ?? 0),
3203
+ base_fee_per_write: BigInt(fields.base_fee_per_write ?? 0),
3204
+ bytes_fee_per_byte: BigInt(fields.bytes_fee_per_byte ?? 0),
3205
+ settlement_mode: Number(fields.settlement_mode ?? 0),
3206
+ write_fee_dapp_share_bps: Number(fields.write_fee_dapp_share_bps ?? 0)
3207
+ };
3208
+ }
3209
+ /**
3210
+ * Append a `dapp_system::settle_writes` moveCall to an existing PTB.
3211
+ *
3212
+ * Does NOT send the transaction — call this before your own moveCall(s) to
3213
+ * settle any accumulated write debt within the same PTB at no extra round-trip.
3214
+ *
3215
+ * The framework function never aborts due to insufficient credit (it silently
3216
+ * skips or partially settles), so prepending this to any PTB is always safe.
3217
+ *
3218
+ * @param tx The Transaction object to append the moveCall to.
3219
+ * @param dappHubId Object ID of the DappHub shared object.
3220
+ * @param dappStorageId Object ID of the DApp's DappStorage (falls back to constructor value).
3221
+ * @param userStorageId Object ID of the user's UserStorage shared object.
3222
+ */
3223
+ buildSettleWritesTx(tx, {
3224
+ dappHubId,
3225
+ dappStorageId: dappStorageIdParam,
3226
+ userStorageId
3227
+ }) {
3228
+ const fwPkg = this.frameworkPackageId;
3229
+ if (!fwPkg) {
3230
+ throw new Error(
3231
+ 'frameworkPackageId is required for buildSettleWritesTx. Set it in the Dubhe constructor ({ frameworkPackageId: "0x..." }).'
3232
+ );
3233
+ }
3234
+ const storageId = dappStorageIdParam ?? this.dappStorageId;
3235
+ if (!storageId) {
3236
+ throw new Error(
3237
+ "dappStorageId is required for buildSettleWritesTx. Pass it directly or set it in the Dubhe constructor."
3238
+ );
3239
+ }
3240
+ const typeArg = this.dappKey;
3241
+ if (!typeArg) {
3242
+ throw new Error(
3243
+ 'dappKey is required for buildSettleWritesTx. Set it in the Dubhe constructor ({ packageId: "0x..." }).'
3244
+ );
3245
+ }
3246
+ tx.moveCall({
3247
+ target: `${fwPkg}::dapp_system::settle_writes`,
3248
+ typeArguments: [typeArg],
3249
+ arguments: [tx.object(dappHubId), tx.object(storageId), tx.object(userStorageId)]
3250
+ });
3251
+ }
3252
+ /**
3253
+ * Settle accumulated write debt for a user (standalone transaction).
3254
+ *
3255
+ * Builds a PTB containing a single `dapp_system::settle_writes` call and
3256
+ * sends it. For embedding settlement into an existing PTB, use
3257
+ * `buildSettleWritesTx` instead.
3258
+ *
3259
+ * This is safe to call at any time — the framework function never aborts
3260
+ * due to insufficient credit; it silently skips or partially settles.
3261
+ *
3262
+ * @param dappHubId Object ID of the DappHub shared object.
3263
+ * @param dappStorageId Object ID of the DApp's DappStorage shared object.
3264
+ * @param userStorageId Object ID of the user's UserStorage shared object.
3265
+ */
3266
+ async settleWrites({
3267
+ dappHubId,
3268
+ dappStorageId,
3269
+ userStorageId,
3270
+ derivePathParams,
3271
+ onSuccess,
3272
+ onError
3273
+ }) {
3274
+ const tx = new import_transactions3.Transaction();
3275
+ this.buildSettleWritesTx(tx, { dappHubId, dappStorageId, userStorageId });
3276
+ return this.signAndSendTxn({
3277
+ tx,
3278
+ derivePathParams,
3279
+ onSuccess,
3280
+ onError
3281
+ });
3282
+ }
3283
+ /**
3284
+ * Recharge a DApp's credit pool by paying with the framework's accepted coin type.
3285
+ *
3286
+ * Wraps `dapp_system::recharge_credit<DappKey, CoinType>`. Any account may call
3287
+ * this — no admin restriction. Payment is forwarded to the framework treasury and
3288
+ * the DApp's `credit_pool` is increased by the coin value.
3289
+ *
3290
+ * Only valid in DAPP_SUBSIDIZES settlement mode. Aborts with
3291
+ * `wrong_settlement_mode` if the DApp is in USER_PAYS mode.
3292
+ *
3293
+ * @param dappHubId Object ID of the DappHub shared object.
3294
+ * @param dappStorageId Object ID of the DApp's DappStorage shared object.
3295
+ * @param coinObjectId Object ID of the Coin to use as payment.
3296
+ * @param coinType Move type of the coin (default: "0x2::sui::SUI").
3297
+ */
3298
+ async rechargeCredit({
3299
+ dappHubId,
3300
+ dappStorageId: dappStorageIdParam,
3301
+ coinObjectId,
3302
+ coinType = "0x2::sui::SUI",
3303
+ derivePathParams,
3304
+ onSuccess,
3305
+ onError
3306
+ }) {
3307
+ const fwPkg = this.frameworkPackageId;
3308
+ if (!fwPkg) {
3309
+ throw new Error(
3310
+ 'frameworkPackageId is required for rechargeCredit. Set it in the Dubhe constructor ({ frameworkPackageId: "0x..." }).'
3311
+ );
3312
+ }
3313
+ const storageId = dappStorageIdParam ?? this.dappStorageId;
3314
+ if (!storageId) {
3315
+ throw new Error(
3316
+ "dappStorageId is required for rechargeCredit. Pass it directly or set it in the Dubhe constructor."
3317
+ );
3318
+ }
3319
+ const typeArg = this.dappKey;
3320
+ if (!typeArg) {
3321
+ throw new Error(
3322
+ 'dappKey is required for rechargeCredit. Set it in the Dubhe constructor ({ packageId: "0x..." }).'
3323
+ );
3324
+ }
3325
+ const tx = new import_transactions3.Transaction();
3326
+ tx.moveCall({
3327
+ target: `${fwPkg}::dapp_system::recharge_credit`,
3328
+ typeArguments: [typeArg, coinType],
3329
+ arguments: [tx.object(dappHubId), tx.object(storageId), tx.object(coinObjectId)]
3330
+ });
3331
+ return this.signAndSendTxn({
3332
+ tx,
3333
+ derivePathParams,
3334
+ onSuccess,
3335
+ onError
3336
+ });
3337
+ }
3338
+ /**
3339
+ * Append a `dapp_system::settle_writes_user_pays` moveCall to an existing PTB.
3340
+ *
3341
+ * Splits `maxPaymentMist` MIST from `tx.gas` as the payment coin, then calls
3342
+ * `settle_writes_user_pays`. The framework returns any overpayment automatically,
3343
+ * so it is safe to over-estimate. This lets a session key pay for settlement
3344
+ * inline without requiring a separate owned Coin object.
3345
+ *
3346
+ * @param tx The Transaction object to append the moveCall to.
3347
+ * @param dappHubId Object ID of the DappHub shared object.
3348
+ * @param dappStorageId Object ID of the DApp's DappStorage (falls back to constructor value).
3349
+ * @param userStorageId Object ID of the user's UserStorage shared object.
3350
+ * @param maxPaymentMist Upper bound for the payment in MIST (default: 50_000_000 = 0.05 SUI).
3351
+ * @param coinType Move type of the payment coin (default: "0x2::sui::SUI").
3352
+ */
3353
+ buildSettleWritesUserPaysTx(tx, {
3354
+ dappHubId,
3355
+ dappStorageId: dappStorageIdParam,
3356
+ userStorageId,
3357
+ maxPaymentMist = 50000000n,
3358
+ coinType = "0x2::sui::SUI"
3359
+ }) {
3360
+ const fwPkg = this.frameworkPackageId;
3361
+ if (!fwPkg) {
3362
+ throw new Error(
3363
+ 'frameworkPackageId is required for buildSettleWritesUserPaysTx. Set it in the Dubhe constructor ({ frameworkPackageId: "0x..." }).'
3364
+ );
3365
+ }
3366
+ const storageId = dappStorageIdParam ?? this.dappStorageId;
3367
+ if (!storageId) {
3368
+ throw new Error(
3369
+ "dappStorageId is required for buildSettleWritesUserPaysTx. Pass it directly or set it in the Dubhe constructor."
3370
+ );
3371
+ }
3372
+ const typeArg = this.dappKey;
3373
+ if (!typeArg) {
3374
+ throw new Error(
3375
+ 'dappKey is required for buildSettleWritesUserPaysTx. Set it in the Dubhe constructor ({ packageId: "0x..." }).'
3376
+ );
3377
+ }
3378
+ const [paymentCoin] = tx.splitCoins(tx.gas, [tx.pure.u64(maxPaymentMist)]);
3379
+ const changeCoin = tx.moveCall({
3380
+ target: `${fwPkg}::dapp_system::settle_writes_user_pays`,
3381
+ typeArguments: [typeArg, coinType],
3382
+ arguments: [tx.object(dappHubId), tx.object(storageId), tx.object(userStorageId), paymentCoin]
3383
+ });
3384
+ tx.mergeCoins(tx.gas, [changeCoin]);
3385
+ }
3386
+ /**
3387
+ * Settle accumulated write debt where the user pays directly (USER_PAYS mode).
3388
+ *
3389
+ * Wraps `dapp_system::settle_writes_user_pays<DappKey, CoinType>`. The exact
3390
+ * cost is computed on-chain; any overpayment from the coin is returned to the
3391
+ * sender after settlement.
3392
+ *
3393
+ * Aborts if:
3394
+ * - The DApp is not in USER_PAYS mode (`wrong_settlement_mode`)
3395
+ * - The coin type does not match the accepted type (`wrong_payment_coin_type`)
3396
+ * - The coin value is less than the total cost (`insufficient_credit`)
3397
+ *
3398
+ * @param dappHubId Object ID of the DappHub shared object.
3399
+ * @param dappStorageId Object ID of the DApp's DappStorage shared object.
3400
+ * @param userStorageId Object ID of the user's UserStorage shared object.
3401
+ * @param coinObjectId Object ID of the Coin to use as payment.
3402
+ * @param coinType Move type of the coin (default: "0x2::sui::SUI").
3403
+ */
3404
+ async settleWritesUserPays({
3405
+ dappHubId,
3406
+ dappStorageId: dappStorageIdParam,
3407
+ userStorageId,
3408
+ coinObjectId,
3409
+ coinType = "0x2::sui::SUI",
3410
+ derivePathParams,
3411
+ onSuccess,
3412
+ onError
3413
+ }) {
3414
+ const fwPkg = this.frameworkPackageId;
3415
+ if (!fwPkg) {
3416
+ throw new Error(
3417
+ 'frameworkPackageId is required for settleWritesUserPays. Set it in the Dubhe constructor ({ frameworkPackageId: "0x..." }).'
3418
+ );
3419
+ }
3420
+ const storageId = dappStorageIdParam ?? this.dappStorageId;
3421
+ if (!storageId) {
3422
+ throw new Error(
3423
+ "dappStorageId is required for settleWritesUserPays. Pass it directly or set it in the Dubhe constructor."
3424
+ );
3425
+ }
3426
+ const typeArg = this.dappKey;
3427
+ if (!typeArg) {
3428
+ throw new Error(
3429
+ 'dappKey is required for settleWritesUserPays. Set it in the Dubhe constructor ({ packageId: "0x..." }).'
3430
+ );
3431
+ }
3432
+ const tx = new import_transactions3.Transaction();
3433
+ tx.moveCall({
3434
+ target: `${fwPkg}::dapp_system::settle_writes_user_pays`,
3435
+ typeArguments: [typeArg, coinType],
3436
+ arguments: [
3437
+ tx.object(dappHubId),
3438
+ tx.object(storageId),
3439
+ tx.object(userStorageId),
3440
+ tx.object(coinObjectId)
3441
+ ]
3442
+ });
3443
+ return this.signAndSendTxn({
3444
+ tx,
3445
+ derivePathParams,
3446
+ onSuccess,
3447
+ onError
3448
+ });
3449
+ }
3450
+ /**
3451
+ * Query `WritesSettled` events from the Sui full node.
3452
+ *
3453
+ * Returns the most recent settlement events across ALL users of this DApp.
3454
+ * Each event captures one user's write debt settlement: number of writes,
3455
+ * bytes, and the amount charged (`paid_cost`).
3456
+ *
3457
+ * Note: Sui full nodes may prune old events. For long-term history use a
3458
+ * dedicated indexer table (`writes_settled_history`).
3459
+ *
3460
+ * @param limit Max events to return (default: 30, max: 50).
3461
+ * @param cursor Pagination cursor from a previous response.
3462
+ */
3463
+ async queryWritesSettledEvents(limit = 30, cursor) {
3464
+ const fwPkg = this.frameworkPackageId;
3465
+ if (!fwPkg)
3466
+ return [];
3467
+ try {
3468
+ const resp = await this.suiInteractor.currentClient.queryEvents({
3469
+ query: { MoveEventType: `${fwPkg}::dubhe_events::WritesSettled` },
3470
+ cursor,
3471
+ limit: Math.min(limit, 50),
3472
+ order: "descending"
3473
+ });
3474
+ return (resp.data ?? []).map((ev) => {
3475
+ const p = ev.parsedJson ?? {};
3476
+ return {
3477
+ txDigest: ev.id?.txDigest ?? "",
3478
+ eventSeq: ev.id?.eventSeq ?? "",
3479
+ timestampMs: Number(ev.timestampMs ?? 0),
3480
+ dappKey: p.dapp_key ?? "",
3481
+ account: p.account ?? "",
3482
+ writes: Number(p.writes ?? 0),
3483
+ bytes: String(p.bytes ?? "0"),
3484
+ freeCost: String(p.free_cost ?? "0"),
3485
+ paidCost: String(p.paid_cost ?? "0")
3486
+ };
3487
+ });
3488
+ } catch {
3489
+ return [];
3490
+ }
3491
+ }
3492
+ /**
3493
+ * Query `MarketplaceFeeSettled` events from the Sui full node.
3494
+ *
3495
+ * Each event records the fee split for a completed marketplace purchase:
3496
+ * total fee, framework treasury share, and DApp revenue share.
3497
+ *
3498
+ * @param limit Max events to return (default: 30, max: 50).
3499
+ * @param cursor Pagination cursor from a previous response.
3500
+ */
3501
+ async queryMarketplaceFeeSettledEvents(limit = 30, cursor) {
3502
+ const fwPkg = this.frameworkPackageId;
3503
+ if (!fwPkg)
3504
+ return [];
3505
+ try {
3506
+ const resp = await this.suiInteractor.currentClient.queryEvents({
3507
+ query: { MoveEventType: `${fwPkg}::dubhe_events::MarketplaceFeeSettled` },
3508
+ cursor,
3509
+ limit: Math.min(limit, 50),
3510
+ order: "descending"
3511
+ });
3512
+ return (resp.data ?? []).map((ev) => {
3513
+ const p = ev.parsedJson ?? {};
3514
+ return {
3515
+ txDigest: ev.id?.txDigest ?? "",
3516
+ eventSeq: ev.id?.eventSeq ?? "",
3517
+ timestampMs: Number(ev.timestampMs ?? 0),
3518
+ dappKey: p.dapp_key ?? "",
3519
+ listingId: p.listing_id ?? "",
3520
+ coinType: p.coin_type ?? "",
3521
+ totalFee: String(p.total_fee ?? "0"),
3522
+ treasuryAmount: String(p.treasury_amount ?? "0"),
3523
+ dappAmount: String(p.dapp_amount ?? "0")
3524
+ };
3525
+ });
3526
+ } catch {
3527
+ return [];
3528
+ }
3529
+ }
3530
+ /**
3531
+ * Read the DApp's accumulated revenue balance directly from the chain.
3532
+ *
3533
+ * `dapp_revenue` is stored as a dynamic field (`DappRevenueKey<CoinType>`)
3534
+ * on the DappStorage object — it is NOT a top-level field, so `getObject`
3535
+ * alone cannot return it. This method calls `getDynamicFields` to locate
3536
+ * the correct child object and returns its balance.
3537
+ *
3538
+ * Returns 0n when the dynamic field has never been created (no revenue yet).
3539
+ *
3540
+ * @param dappStorageId Object ID of the DApp's DappStorage shared object.
3541
+ * @param coinType Move type of the revenue coin (default: "0x2::sui::SUI").
3542
+ */
3543
+ async getDappRevenueBalance(dappStorageId, coinType = "0x2::sui::SUI") {
3544
+ const client = this.suiInteractor.currentClient;
3545
+ const coinTail = coinType.split("::").slice(-2).join("::");
3546
+ try {
3547
+ let cursor = void 0;
3548
+ do {
3549
+ const page = await client.getDynamicFields({
3550
+ parentId: dappStorageId,
3551
+ cursor,
3552
+ limit: 50
3553
+ });
3554
+ for (const field of page.data) {
3555
+ const nameType = field.name?.type ?? "";
3556
+ if (nameType.includes("DappRevenueKey") && nameType.includes(coinTail)) {
3557
+ const fieldObj = await client.getDynamicFieldObject({
3558
+ parentId: dappStorageId,
3559
+ name: field.name
3560
+ });
3561
+ const innerFields = fieldObj?.data?.content?.fields ?? {};
3562
+ const balValue = innerFields?.value?.fields?.value ?? // nested Balance struct
3563
+ innerFields?.value ?? 0;
3564
+ return BigInt(balValue);
3565
+ }
3566
+ }
3567
+ cursor = page.nextCursor;
3568
+ if (!page.hasNextPage)
3569
+ break;
3570
+ } while (cursor);
3571
+ } catch {
3572
+ }
3573
+ return 0n;
3574
+ }
3575
+ /**
3576
+ * Withdraw all accumulated DApp revenue to the DApp admin address.
3577
+ *
3578
+ * Wraps `dapp_system::withdraw_dapp_revenue<DappKey, CoinType>`.
3579
+ * The entire revenue balance is transferred to the DApp admin on-chain.
3580
+ * Aborts if the balance is zero (`no_revenue_to_withdraw`).
3581
+ *
3582
+ * @param dappHubId Object ID of the DappHub shared object.
3583
+ * @param dappStorageId Object ID of the DApp's DappStorage shared object.
3584
+ * @param coinType Move type of the revenue coin (default: "0x2::sui::SUI").
3585
+ */
3586
+ async withdrawDappRevenue({
3587
+ dappHubId,
3588
+ dappStorageId: dappStorageIdParam,
3589
+ coinType = "0x2::sui::SUI",
3590
+ derivePathParams,
3591
+ onSuccess,
3592
+ onError
3593
+ }) {
3594
+ const fwPkg = this.frameworkPackageId;
3595
+ if (!fwPkg) {
3596
+ throw new Error(
3597
+ 'frameworkPackageId is required for withdrawDappRevenue. Set it in the Dubhe constructor ({ frameworkPackageId: "0x..." }).'
3598
+ );
3599
+ }
3600
+ const storageId = dappStorageIdParam ?? this.dappStorageId;
3601
+ if (!storageId) {
3602
+ throw new Error(
3603
+ "dappStorageId is required for withdrawDappRevenue. Pass it directly or set it in the Dubhe constructor."
3604
+ );
3605
+ }
3606
+ const typeArg = this.dappKey;
3607
+ if (!typeArg) {
3608
+ throw new Error(
3609
+ 'dappKey is required for withdrawDappRevenue. Set it in the Dubhe constructor ({ packageId: "0x..." }).'
3610
+ );
3611
+ }
3612
+ const tx = new import_transactions3.Transaction();
3613
+ tx.moveCall({
3614
+ target: `${fwPkg}::dapp_system::withdraw_dapp_revenue`,
3615
+ typeArguments: [typeArg, coinType],
3616
+ arguments: [tx.object(dappHubId), tx.object(storageId)]
3617
+ });
3618
+ return this.signAndSendTxn({
3619
+ tx,
3620
+ derivePathParams,
3621
+ onSuccess,
3622
+ onError
3623
+ });
3624
+ }
3625
+ /**
3626
+ * Return a combined settlement health snapshot for a user.
3627
+ *
3628
+ * Fetches `UserStorage` fields (always) and optionally `DappStorage` fields
3629
+ * (when `dappStorageId` is supplied) to produce high-level diagnostic values:
3630
+ *
3631
+ * - `utilizationPct` — how close the user is to the 2 000-write hard limit
3632
+ * - `isAtRisk` — utilization >= 80 % (settlement recommended soon)
3633
+ * - `isBlocked` — utilization >= 100 % (writes will be rejected)
3634
+ * - `estimatedWritesAffordable` — writes the credit pool can still cover
3635
+ * - `creditAtRisk` — fewer than 500 writes of credit remaining
3636
+ *
3637
+ * @param userStorageId Object ID of the user's UserStorage shared object.
3638
+ * @param dappStorageId Object ID of the DApp's DappStorage (optional).
3639
+ */
3640
+ async getSettlementHealth({
3641
+ userStorageId,
3642
+ dappStorageId
3643
+ }) {
3644
+ const WRITE_LIMIT = 2000n;
3645
+ const userFields = await this.getUserStorageFields(userStorageId);
3646
+ const unsettledCount = userFields.unsettled_count;
3647
+ const utilizationPct = Number(unsettledCount * 100n / WRITE_LIMIT);
3648
+ const result = {
3649
+ unsettledCount,
3650
+ writeLimit: WRITE_LIMIT,
3651
+ utilizationPct,
3652
+ isAtRisk: utilizationPct >= 80,
3653
+ isBlocked: utilizationPct >= 100
3654
+ };
3655
+ if (dappStorageId) {
3656
+ const dappFields = await this.getDappStorageFields(dappStorageId);
3657
+ const creditPool = dappFields.credit_pool;
3658
+ const baseFeePerWrite = dappFields.base_fee_per_write;
3659
+ const estimatedWritesAffordable = baseFeePerWrite > 0n ? creditPool / baseFeePerWrite : BigInt(Number.MAX_SAFE_INTEGER);
3660
+ result.creditPool = creditPool;
3661
+ result.baseFeePerWrite = baseFeePerWrite;
3662
+ result.estimatedWritesAffordable = estimatedWritesAffordable;
3663
+ result.creditAtRisk = estimatedWritesAffordable < 500n;
3664
+ }
3665
+ return result;
3666
+ }
3667
+ // ─── Private helpers ─────────────────────────────────────────────────────────
3668
+ /**
3669
+ * Return the default network configuration for the given network type.
3670
+ *
3671
+ * Useful for reading `frameworkPackageId` without instantiating a full client:
3672
+ *
3673
+ * ```ts
3674
+ * const { frameworkPackageId } = Dubhe.getDefaultConfig('testnet');
3675
+ * // → '0x8817b...' (known constant for testnet/mainnet)
3676
+ * // → undefined (for localnet/devnet — supply after local deployment)
3677
+ * ```
3678
+ */
3679
+ static getDefaultConfig(networkType) {
3680
+ return getDefaultConfig(networkType);
3681
+ }
2876
3682
  // async formatData(type: string, value: Buffer | number[] | Uint8Array) {
2877
3683
  // const u8Value = Uint8Array.from(value);
2878
3684
  // return bcs.de(type, u8Value);
@@ -2979,11 +3785,17 @@ async function loadMetadata(networkType, packageId, fullnodeUrls) {
2979
3785
  0 && (module.exports = {
2980
3786
  BcsType,
2981
3787
  Dubhe,
3788
+ MAINNET_DUBHE_FRAMEWORK_PACKAGE_ID,
3789
+ MAINNET_DUBHE_HUB_OBJECT_ID,
2982
3790
  MultiSigClient,
2983
3791
  SuiAccountManager,
2984
3792
  SuiContractFactory,
2985
3793
  SuiTx,
3794
+ TESTNET_DUBHE_FRAMEWORK_PACKAGE_ID,
3795
+ TESTNET_DUBHE_HUB_OBJECT_ID,
2986
3796
  bcs,
3797
+ getDefaultConfig,
3798
+ getDefaultURL,
2987
3799
  loadMetadata,
2988
3800
  ...require("@mysten/sui/client"),
2989
3801
  ...require("@mysten/sui/utils"),