@phala/cloud 0.1.0 → 0.1.1-beta.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.
Files changed (82) hide show
  1. package/dist/actions/{add_compose_hash.d.ts → blockchains/add_compose_hash.d.ts} +1 -2
  2. package/dist/actions/{deploy_app_auth.d.ts → blockchains/deploy_app_auth.d.ts} +1 -2
  3. package/dist/actions/{commit_cvm_compose_file_update.d.ts → cvms/commit_cvm_compose_file_update.d.ts} +10 -11
  4. package/dist/actions/{commit_cvm_provision.d.ts → cvms/commit_cvm_provision.d.ts} +14 -15
  5. package/dist/actions/{get_cvm_compose_file.d.ts → cvms/get_cvm_compose_file.d.ts} +74 -6
  6. package/dist/actions/cvms/get_cvm_info.d.ts +85 -0
  7. package/dist/actions/{get_cvm_list.d.ts → cvms/get_cvm_list.d.ts} +48 -49
  8. package/dist/actions/{provision_cvm.d.ts → cvms/provision_cvm.d.ts} +16 -17
  9. package/dist/actions/{provision_cvm_compose_file_update.d.ts → cvms/provision_cvm_compose_file_update.d.ts} +153 -18
  10. package/dist/actions/get_available_nodes.d.ts +0 -1
  11. package/dist/actions/get_current_user.d.ts +35 -16
  12. package/dist/actions/index.d.ts +13 -14
  13. package/dist/actions/{get_app_env_encrypt_pubkey.d.ts → kms/get_app_env_encrypt_pubkey.d.ts} +8 -9
  14. package/dist/actions/{get_kms_info.d.ts → kms/get_kms_info.d.ts} +6 -22
  15. package/dist/actions/{get_kms_list.d.ts → kms/get_kms_list.d.ts} +6 -35
  16. package/dist/actions/list-instance-types.d.ts +0 -1
  17. package/dist/actions/workspaces/get_workspace.d.ts +0 -1
  18. package/dist/actions/workspaces/list_workspaces.d.ts +0 -1
  19. package/dist/chunk-O5QBIXBA.mjs +1128 -0
  20. package/dist/client.d.ts +0 -1
  21. package/dist/create-client.d.ts +311 -0
  22. package/dist/create-client.js +1143 -0
  23. package/dist/create-client.mjs +74 -0
  24. package/dist/index.d.ts +0 -1
  25. package/dist/index.js +870 -888
  26. package/dist/index.mjs +126 -1133
  27. package/dist/parse_dotenv.d.ts +0 -1
  28. package/dist/types/app_compose.d.ts +0 -1
  29. package/dist/types/client.d.ts +0 -1
  30. package/dist/types/common.d.ts +0 -1
  31. package/dist/types/cvm_info.d.ts +34 -35
  32. package/dist/types/index.d.ts +0 -1
  33. package/dist/types/kms_info.d.ts +0 -1
  34. package/dist/types/supported_chains.d.ts +0 -1
  35. package/dist/utils/as-hex.d.ts +0 -1
  36. package/dist/utils/client-factories.d.ts +0 -1
  37. package/dist/utils/define-action.d.ts +7 -8
  38. package/dist/utils/get_compose_hash.d.ts +0 -1
  39. package/dist/utils/get_error_message.d.ts +0 -1
  40. package/dist/utils/index.d.ts +0 -1
  41. package/dist/utils/network.d.ts +0 -1
  42. package/dist/utils/transaction.d.ts +0 -1
  43. package/dist/utils/validate-parameters.d.ts +0 -1
  44. package/package.json +70 -66
  45. package/dist/actions/add_compose_hash.d.ts.map +0 -1
  46. package/dist/actions/commit_cvm_compose_file_update.d.ts.map +0 -1
  47. package/dist/actions/commit_cvm_provision.d.ts.map +0 -1
  48. package/dist/actions/deploy_app_auth.d.ts.map +0 -1
  49. package/dist/actions/get_app_env_encrypt_pubkey.d.ts.map +0 -1
  50. package/dist/actions/get_available_nodes.d.ts.map +0 -1
  51. package/dist/actions/get_current_user.d.ts.map +0 -1
  52. package/dist/actions/get_cvm_compose_file.d.ts.map +0 -1
  53. package/dist/actions/get_cvm_info.d.ts +0 -172
  54. package/dist/actions/get_cvm_info.d.ts.map +0 -1
  55. package/dist/actions/get_cvm_list.d.ts.map +0 -1
  56. package/dist/actions/get_kms_info.d.ts.map +0 -1
  57. package/dist/actions/get_kms_list.d.ts.map +0 -1
  58. package/dist/actions/index.d.ts.map +0 -1
  59. package/dist/actions/list-instance-types.d.ts.map +0 -1
  60. package/dist/actions/provision_cvm.d.ts.map +0 -1
  61. package/dist/actions/provision_cvm_compose_file_update.d.ts.map +0 -1
  62. package/dist/actions/workspaces/get_workspace.d.ts.map +0 -1
  63. package/dist/actions/workspaces/list_workspaces.d.ts.map +0 -1
  64. package/dist/client.d.ts.map +0 -1
  65. package/dist/index.d.ts.map +0 -1
  66. package/dist/parse_dotenv.d.ts.map +0 -1
  67. package/dist/types/app_compose.d.ts.map +0 -1
  68. package/dist/types/client.d.ts.map +0 -1
  69. package/dist/types/common.d.ts.map +0 -1
  70. package/dist/types/cvm_info.d.ts.map +0 -1
  71. package/dist/types/index.d.ts.map +0 -1
  72. package/dist/types/kms_info.d.ts.map +0 -1
  73. package/dist/types/supported_chains.d.ts.map +0 -1
  74. package/dist/utils/as-hex.d.ts.map +0 -1
  75. package/dist/utils/client-factories.d.ts.map +0 -1
  76. package/dist/utils/define-action.d.ts.map +0 -1
  77. package/dist/utils/get_compose_hash.d.ts.map +0 -1
  78. package/dist/utils/get_error_message.d.ts.map +0 -1
  79. package/dist/utils/index.d.ts.map +0 -1
  80. package/dist/utils/network.d.ts.map +0 -1
  81. package/dist/utils/transaction.d.ts.map +0 -1
  82. package/dist/utils/validate-parameters.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -576,39 +576,6 @@ var CvmLegacyDetailSchema = import_zod3.z.object({
576
576
  // src/actions/get_current_user.ts
577
577
  var import_zod4 = require("zod");
578
578
 
579
- // src/utils/index.ts
580
- var import_encrypt_env_vars = require("@phala/dstack-sdk/encrypt-env-vars");
581
-
582
- // src/utils/get_error_message.ts
583
- function getErrorMessage(error) {
584
- if (typeof error.detail === "string") {
585
- return error.detail;
586
- }
587
- if (Array.isArray(error.detail)) {
588
- if (error.detail.length > 0) {
589
- return error.detail[0]?.msg || "Validation error";
590
- }
591
- return "Validation error";
592
- }
593
- if (typeof error.detail === "object" && error.detail !== null) {
594
- return JSON.stringify(error.detail);
595
- }
596
- return "Unknown error occurred";
597
- }
598
-
599
- // src/utils/as-hex.ts
600
- var import_viem = require("viem");
601
- function asHex(value) {
602
- if (typeof value === "string") {
603
- if (value.startsWith("0x") && (0, import_viem.isHex)(value)) {
604
- return value;
605
- } else if ((0, import_viem.isHex)(`0x${value}`)) {
606
- return `0x${value}`;
607
- }
608
- }
609
- throw new Error(`Invalid hex value: ${value}`);
610
- }
611
-
612
579
  // src/utils/validate-parameters.ts
613
580
  function validateActionParameters(parameters) {
614
581
  if (parameters?.schema !== void 0 && parameters?.schema !== false) {
@@ -641,943 +608,958 @@ function safeValidateActionParameters(parameters) {
641
608
  return void 0;
642
609
  }
643
610
 
644
- // src/utils/network.ts
645
- var NetworkError = class extends Error {
646
- constructor(message, code, details) {
647
- super(message);
648
- this.code = code;
649
- this.details = details;
650
- this.name = "NetworkError";
651
- }
652
- };
653
- var WalletError = class extends Error {
654
- constructor(message, code, details) {
655
- super(message);
656
- this.code = code;
657
- this.details = details;
658
- this.name = "WalletError";
659
- }
660
- };
661
- var TransactionError = class extends Error {
662
- constructor(message, hash, details) {
663
- super(message);
664
- this.hash = hash;
665
- this.details = details;
666
- this.name = "TransactionError";
611
+ // src/utils/define-action.ts
612
+ function defineSimpleAction(schema, fn) {
613
+ function action(client, parameters) {
614
+ return _actionImpl(client, parameters);
667
615
  }
668
- };
669
- function createNetworkClients(publicClient, walletClient, address, chainId) {
670
- return {
671
- publicClient,
672
- walletClient,
673
- address,
674
- chainId
675
- };
676
- }
677
- async function checkNetworkStatus(clients, targetChainId) {
678
- try {
679
- const currentChainId = await clients.walletClient.getChainId();
680
- return {
681
- isCorrectNetwork: currentChainId === targetChainId,
682
- currentChainId
683
- };
684
- } catch (error) {
685
- throw new NetworkError(
686
- `Failed to check network status: ${error instanceof Error ? error.message : "Unknown error"}`,
687
- "NETWORK_CHECK_FAILED",
688
- error
689
- );
616
+ async function _actionImpl(client, parameters) {
617
+ validateActionParameters(parameters);
618
+ const response = await fn(client);
619
+ if (parameters?.schema === false) {
620
+ return response;
621
+ }
622
+ const actualSchema = parameters?.schema || schema;
623
+ return actualSchema.parse(response);
690
624
  }
691
- }
692
- async function checkBalance(publicClient, address, minBalance) {
693
- try {
694
- const balance = await publicClient.getBalance({ address });
695
- return {
696
- address,
697
- balance,
698
- sufficient: minBalance ? balance >= minBalance : true,
699
- required: minBalance
700
- };
701
- } catch (error) {
702
- throw new NetworkError(
703
- `Failed to check balance: ${error instanceof Error ? error.message : "Unknown error"}`,
704
- "BALANCE_CHECK_FAILED",
705
- error
706
- );
625
+ function safeAction(client, parameters) {
626
+ return _safeActionImpl(client, parameters);
707
627
  }
708
- }
709
- async function waitForTransactionReceipt(publicClient, hash, options = {}) {
710
- const {
711
- timeout = 6e4,
712
- // 60 seconds default
713
- pollingInterval = 2e3,
714
- // 2 seconds default
715
- confirmations = 1
716
- } = options;
717
- const startTime = Date.now();
718
- return new Promise((resolve, reject) => {
719
- const poll = async () => {
628
+ async function _safeActionImpl(client, parameters) {
629
+ const parameterValidationError = safeValidateActionParameters(parameters);
630
+ if (parameterValidationError) {
631
+ return parameterValidationError;
632
+ }
633
+ const httpResult = await (async () => {
720
634
  try {
721
- const receipt = await publicClient.getTransactionReceipt({ hash });
722
- if (receipt) {
723
- if (confirmations > 1) {
724
- const currentBlock = await publicClient.getBlockNumber();
725
- const confirmationCount = currentBlock - receipt.blockNumber + 1n;
726
- if (confirmationCount < BigInt(confirmations)) {
727
- const elapsed = Date.now() - startTime;
728
- if (elapsed >= timeout) {
729
- reject(
730
- new TransactionError(`Transaction confirmation timeout after ${timeout}ms`, hash)
731
- );
732
- return;
733
- }
734
- setTimeout(poll, pollingInterval);
735
- return;
736
- }
737
- }
738
- resolve(receipt);
739
- } else {
740
- const elapsed = Date.now() - startTime;
741
- if (elapsed >= timeout) {
742
- reject(new TransactionError(`Transaction receipt timeout after ${timeout}ms`, hash));
743
- return;
744
- }
745
- setTimeout(poll, pollingInterval);
746
- }
635
+ const data = await fn(client);
636
+ return { success: true, data };
747
637
  } catch (error) {
748
- const elapsed = Date.now() - startTime;
749
- if (elapsed >= timeout) {
750
- reject(
751
- new TransactionError(`Transaction receipt timeout after ${timeout}ms`, hash, error)
752
- );
753
- return;
638
+ if (error && typeof error === "object" && "isRequestError" in error) {
639
+ return { success: false, error };
754
640
  }
755
- setTimeout(poll, pollingInterval);
641
+ if (error && typeof error === "object" && "issues" in error) {
642
+ return { success: false, error };
643
+ }
644
+ return {
645
+ success: false,
646
+ error: {
647
+ name: "Error",
648
+ message: error instanceof Error ? error.message : String(error)
649
+ }
650
+ };
756
651
  }
757
- };
758
- poll();
759
- });
760
- }
761
- async function executeTransaction(clients, operation, args, options = {}) {
762
- const { timeout = 6e4, confirmations = 1, onSubmitted, onConfirmed, onError } = options;
763
- try {
764
- const hash = await operation(clients, ...args);
765
- onSubmitted?.(hash);
766
- const receipt = await waitForTransactionReceipt(clients.publicClient, hash, {
767
- timeout,
768
- confirmations
769
- });
770
- const success = receipt.status === "success";
771
- if (success) {
772
- onConfirmed?.(receipt);
773
- } else {
774
- const error = new TransactionError("Transaction failed on-chain", hash, receipt);
775
- onError?.(error, hash);
776
- throw error;
652
+ })();
653
+ if (!httpResult.success) {
654
+ return httpResult;
777
655
  }
778
- return {
779
- hash,
780
- receipt,
781
- success
782
- };
783
- } catch (error) {
784
- const txError = error instanceof TransactionError ? error : new TransactionError(
785
- `Transaction execution failed: ${error instanceof Error ? error.message : "Unknown error"}`,
786
- void 0,
787
- error
788
- );
789
- onError?.(txError, txError.hash);
790
- throw txError;
791
- }
792
- }
793
- async function extractNetworkClients(publicClient, walletClient) {
794
- try {
795
- const address = walletClient.account?.address;
796
- if (!address) {
797
- throw new WalletError("WalletClient must have an account", "NO_ACCOUNT");
656
+ if (parameters?.schema === false) {
657
+ return { success: true, data: httpResult.data };
798
658
  }
799
- const chainId = await walletClient.getChainId();
800
- return createNetworkClients(publicClient, walletClient, address, chainId);
801
- } catch (error) {
802
- throw new WalletError(
803
- `Failed to extract network clients: ${error instanceof Error ? error.message : "Unknown error"}`,
804
- "EXTRACTION_FAILED",
805
- error
806
- );
659
+ const actualSchema = parameters?.schema || schema;
660
+ return actualSchema.safeParse(httpResult.data);
807
661
  }
808
- }
809
- async function validateNetworkPrerequisites(clients, requirements) {
810
- const { targetChainId, minBalance, requiredAddress } = requirements;
811
- const networkStatus = await checkNetworkStatus(clients, targetChainId);
812
- const balanceResult = await checkBalance(clients.publicClient, clients.address, minBalance);
813
- const addressValid = requiredAddress ? clients.address.toLowerCase() === requiredAddress.toLowerCase() : true;
814
662
  return {
815
- networkValid: networkStatus.isCorrectNetwork,
816
- balanceValid: balanceResult.sufficient,
817
- addressValid,
818
- details: {
819
- currentChainId: networkStatus.currentChainId,
820
- balance: balanceResult.balance,
821
- address: clients.address
822
- }
663
+ action,
664
+ safeAction
823
665
  };
824
666
  }
825
-
826
- // src/utils/transaction.ts
827
- function createTransactionTracker() {
828
- let status = { state: "idle" };
829
- let timeoutHandle;
830
- let abortController;
831
- const updateStatus = (newStatus) => {
832
- status = { ...status, ...newStatus };
833
- };
834
- const reset = () => {
835
- if (timeoutHandle) {
836
- clearTimeout(timeoutHandle);
837
- timeoutHandle = void 0;
838
- }
839
- if (abortController) {
840
- abortController.abort();
841
- abortController = void 0;
842
- }
843
- status = { state: "idle" };
844
- };
845
- const abort = () => {
846
- if (abortController) {
847
- abortController.abort();
667
+ function defineAction(schema, fn) {
668
+ function action(client, ...args) {
669
+ const [params, parameters] = args;
670
+ return _actionImpl(client, params, parameters);
671
+ }
672
+ async function _actionImpl(client, params, parameters) {
673
+ validateActionParameters(parameters);
674
+ const response = await fn(client, params);
675
+ if (parameters?.schema === false) {
676
+ return response;
848
677
  }
849
- if (timeoutHandle) {
850
- clearTimeout(timeoutHandle);
851
- timeoutHandle = void 0;
678
+ const actualSchema = parameters?.schema || schema;
679
+ return actualSchema.parse(response);
680
+ }
681
+ function safeAction(client, ...args) {
682
+ const [params, parameters] = args;
683
+ return _safeActionImpl(client, params, parameters);
684
+ }
685
+ async function _safeActionImpl(client, params, parameters) {
686
+ const parameterValidationError = safeValidateActionParameters(parameters);
687
+ if (parameterValidationError) {
688
+ return parameterValidationError;
852
689
  }
853
- updateStatus({
854
- state: "error",
855
- aborted: true,
856
- error: "Transaction aborted by user"
857
- });
858
- };
859
- const execute = async (operation, clients, args, options = {}) => {
860
- const {
861
- timeout = 6e4,
862
- confirmations = 1,
863
- onSubmitted,
864
- onConfirmed,
865
- onError,
866
- signal
867
- } = options;
868
- try {
869
- reset();
870
- abortController = new AbortController();
871
- if (signal) {
872
- if (signal.aborted) {
873
- throw new TransactionError("Operation was aborted before execution");
690
+ const httpResult = await (async () => {
691
+ try {
692
+ const data = await fn(client, params);
693
+ return { success: true, data };
694
+ } catch (error) {
695
+ if (error && typeof error === "object" && "isRequestError" in error) {
696
+ return { success: false, error };
874
697
  }
875
- signal.addEventListener("abort", () => {
876
- abort();
877
- });
878
- }
879
- updateStatus({
880
- state: "submitting",
881
- startTime: Date.now(),
882
- error: void 0,
883
- hash: void 0,
884
- receipt: void 0,
885
- aborted: false
886
- });
887
- if (abortController.signal.aborted) {
888
- throw new TransactionError("Transaction aborted");
889
- }
890
- const hash = await operation(clients, ...args);
891
- if (abortController.signal.aborted) {
892
- throw new TransactionError("Transaction aborted after submission", hash);
893
- }
894
- updateStatus({
895
- state: "pending",
896
- hash,
897
- submitTime: Date.now()
898
- });
899
- onSubmitted?.(hash);
900
- if (timeout > 0) {
901
- timeoutHandle = setTimeout(() => {
902
- if (status.state === "pending" && !abortController?.signal.aborted) {
903
- updateStatus({
904
- state: "timeout",
905
- error: `Transaction timeout after ${timeout}ms`
906
- });
698
+ if (error && typeof error === "object" && "issues" in error) {
699
+ return { success: false, error };
700
+ }
701
+ return {
702
+ success: false,
703
+ error: {
704
+ name: "Error",
705
+ message: error instanceof Error ? error.message : String(error)
907
706
  }
908
- }, timeout);
909
- }
910
- const receipt = await Promise.race([
911
- waitForTransactionReceipt(clients.publicClient, hash, { timeout, confirmations }),
912
- new Promise((_, reject) => {
913
- abortController?.signal.addEventListener("abort", () => {
914
- reject(new TransactionError("Transaction aborted while waiting for receipt", hash));
915
- });
916
- })
917
- ]);
918
- if (timeoutHandle) {
919
- clearTimeout(timeoutHandle);
920
- timeoutHandle = void 0;
921
- }
922
- const success = receipt.status === "success";
923
- updateStatus({
924
- state: success ? "success" : "error",
925
- receipt,
926
- confirmTime: Date.now(),
927
- error: success ? void 0 : "Transaction failed on-chain"
928
- });
929
- if (success) {
930
- onConfirmed?.(receipt);
931
- } else {
932
- const error = new TransactionError("Transaction failed on-chain", hash, receipt);
933
- onError?.(error, hash);
934
- throw error;
707
+ };
935
708
  }
936
- return {
937
- hash,
938
- receipt,
939
- success
940
- };
941
- } catch (error) {
942
- const txError = error instanceof TransactionError ? error : new TransactionError(
943
- `Transaction execution failed: ${error instanceof Error ? error.message : "Unknown error"}`,
944
- status.hash,
945
- error
946
- );
947
- updateStatus({
948
- state: "error",
949
- error: txError.message
950
- });
951
- onError?.(txError, status.hash);
952
- throw txError;
709
+ })();
710
+ if (!httpResult.success) {
711
+ return httpResult;
953
712
  }
954
- };
713
+ if (parameters?.schema === false) {
714
+ return { success: true, data: httpResult.data };
715
+ }
716
+ const actualSchema = parameters?.schema || schema;
717
+ return actualSchema.safeParse(httpResult.data);
718
+ }
955
719
  return {
956
- get status() {
957
- return { ...status };
958
- },
959
- get isIdle() {
960
- return status.state === "idle";
961
- },
962
- get isSubmitting() {
963
- return status.state === "submitting";
964
- },
965
- get isPending() {
966
- return status.state === "pending";
967
- },
968
- get isSuccess() {
969
- return status.state === "success";
970
- },
971
- get isError() {
972
- return status.state === "error";
973
- },
974
- get isTimeout() {
975
- return status.state === "timeout";
976
- },
977
- get isAborted() {
978
- return status.aborted === true;
979
- },
980
- get isComplete() {
981
- return ["success", "error", "timeout"].includes(status.state);
982
- },
983
- abort,
984
- reset,
985
- execute
720
+ action,
721
+ safeAction
986
722
  };
987
723
  }
988
- async function executeBatchTransactions(operations, clients, batchOptions) {
989
- const { mode, failFast = false, onProgress } = batchOptions;
990
- const results = [];
991
- if (mode === "sequential") {
992
- for (let i = 0; i < operations.length; i++) {
993
- const op = operations[i];
994
- if (!op) continue;
995
- const { operation, args, options } = op;
996
- try {
997
- const tracker = createTransactionTracker();
998
- const result = await tracker.execute(operation, clients, args, options);
999
- results.push(result);
1000
- onProgress?.(i + 1, operations.length, results);
1001
- } catch (error) {
1002
- const txError = error instanceof Error ? error : new Error(String(error));
1003
- results.push(txError);
1004
- onProgress?.(i + 1, operations.length, results);
1005
- if (failFast) {
1006
- for (let j = i + 1; j < operations.length; j++) {
1007
- results.push(new Error("Cancelled due to previous failure"));
1008
- }
1009
- break;
1010
- }
724
+
725
+ // src/actions/get_current_user.ts
726
+ var CurrentUserSchema = import_zod4.z.object({
727
+ username: import_zod4.z.string(),
728
+ email: import_zod4.z.string(),
729
+ credits: import_zod4.z.number(),
730
+ granted_credits: import_zod4.z.number(),
731
+ avatar: import_zod4.z.string(),
732
+ team_name: import_zod4.z.string(),
733
+ team_tier: import_zod4.z.string()
734
+ }).passthrough();
735
+ var { action: getCurrentUser, safeAction: safeGetCurrentUser } = defineSimpleAction(
736
+ CurrentUserSchema,
737
+ async (client) => {
738
+ return await client.get("/auth/me");
739
+ }
740
+ );
741
+
742
+ // src/actions/get_available_nodes.ts
743
+ var import_zod5 = require("zod");
744
+ var AvailableOSImageSchema = import_zod5.z.object({
745
+ name: import_zod5.z.string(),
746
+ is_dev: import_zod5.z.boolean(),
747
+ version: import_zod5.z.union([
748
+ import_zod5.z.tuple([import_zod5.z.number(), import_zod5.z.number(), import_zod5.z.number()]),
749
+ import_zod5.z.tuple([import_zod5.z.number(), import_zod5.z.number(), import_zod5.z.number(), import_zod5.z.number()])
750
+ ]),
751
+ os_image_hash: import_zod5.z.string().nullable().optional()
752
+ }).passthrough();
753
+ var TeepodCapacitySchema = import_zod5.z.object({
754
+ teepod_id: import_zod5.z.number(),
755
+ name: import_zod5.z.string(),
756
+ listed: import_zod5.z.boolean(),
757
+ resource_score: import_zod5.z.number(),
758
+ remaining_vcpu: import_zod5.z.number(),
759
+ remaining_memory: import_zod5.z.number(),
760
+ remaining_cvm_slots: import_zod5.z.number(),
761
+ images: import_zod5.z.array(AvailableOSImageSchema),
762
+ support_onchain_kms: import_zod5.z.boolean().optional(),
763
+ fmspc: import_zod5.z.string().nullable().optional(),
764
+ device_id: import_zod5.z.string().nullable().optional(),
765
+ region_identifier: import_zod5.z.string().nullable().optional(),
766
+ default_kms: import_zod5.z.string().nullable().optional(),
767
+ kms_list: import_zod5.z.array(import_zod5.z.string()).default([])
768
+ }).passthrough();
769
+ var ResourceThresholdSchema = import_zod5.z.object({
770
+ max_instances: import_zod5.z.number().nullable().optional(),
771
+ max_vcpu: import_zod5.z.number().nullable().optional(),
772
+ max_memory: import_zod5.z.number().nullable().optional(),
773
+ max_disk: import_zod5.z.number().nullable().optional()
774
+ }).passthrough();
775
+ var AvailableNodesSchema = import_zod5.z.object({
776
+ tier: import_zod5.z.string(),
777
+ // TeamTier is string enum
778
+ capacity: ResourceThresholdSchema,
779
+ nodes: import_zod5.z.array(TeepodCapacitySchema),
780
+ kms_list: import_zod5.z.array(KmsInfoSchema)
781
+ }).passthrough();
782
+ var { action: getAvailableNodes, safeAction: safeGetAvailableNodes } = defineSimpleAction(
783
+ AvailableNodesSchema,
784
+ async (client) => {
785
+ return await client.get("/teepods/available");
786
+ }
787
+ );
788
+
789
+ // src/actions/cvms/provision_cvm.ts
790
+ var import_zod6 = require("zod");
791
+ var ProvisionCvmSchema = import_zod6.z.object({
792
+ app_id: import_zod6.z.string().nullable().optional(),
793
+ app_env_encrypt_pubkey: import_zod6.z.string().nullable().optional(),
794
+ compose_hash: import_zod6.z.string(),
795
+ fmspc: import_zod6.z.string().nullable().optional(),
796
+ device_id: import_zod6.z.string().nullable().optional(),
797
+ os_image_hash: import_zod6.z.string().nullable().optional(),
798
+ teepod_id: import_zod6.z.number().nullable().optional(),
799
+ // Will be transformed to node_id
800
+ node_id: import_zod6.z.number().nullable().optional(),
801
+ kms_id: import_zod6.z.string().nullable().optional()
802
+ }).passthrough().transform((data) => {
803
+ if ("teepod_id" in data && data.teepod_id !== void 0) {
804
+ const { teepod_id, ...rest } = data;
805
+ return { ...rest, node_id: teepod_id };
806
+ }
807
+ return data;
808
+ });
809
+ var ProvisionCvmRequestSchema = import_zod6.z.object({
810
+ node_id: import_zod6.z.number().optional(),
811
+ // recommended
812
+ teepod_id: import_zod6.z.number().optional(),
813
+ // deprecated, for compatibility
814
+ name: import_zod6.z.string(),
815
+ image: import_zod6.z.string(),
816
+ vcpu: import_zod6.z.number(),
817
+ memory: import_zod6.z.number(),
818
+ disk_size: import_zod6.z.number(),
819
+ compose_file: import_zod6.z.object({
820
+ allowed_envs: import_zod6.z.array(import_zod6.z.string()).optional(),
821
+ pre_launch_script: import_zod6.z.string().optional(),
822
+ docker_compose_file: import_zod6.z.string().optional(),
823
+ name: import_zod6.z.string().optional(),
824
+ kms_enabled: import_zod6.z.boolean().optional(),
825
+ public_logs: import_zod6.z.boolean().optional(),
826
+ public_sysinfo: import_zod6.z.boolean().optional(),
827
+ gateway_enabled: import_zod6.z.boolean().optional(),
828
+ // recommended
829
+ tproxy_enabled: import_zod6.z.boolean().optional()
830
+ // deprecated, for compatibility
831
+ }),
832
+ listed: import_zod6.z.boolean().optional(),
833
+ instance_type: import_zod6.z.string().nullable().optional(),
834
+ kms_id: import_zod6.z.string().optional(),
835
+ env_keys: import_zod6.z.array(import_zod6.z.string()).optional()
836
+ }).passthrough();
837
+ function autofillComposeFileName(appCompose) {
838
+ if (appCompose.compose_file && !appCompose.compose_file.name) {
839
+ return {
840
+ ...appCompose,
841
+ compose_file: {
842
+ ...appCompose.compose_file,
843
+ name: appCompose.name
1011
844
  }
845
+ };
846
+ }
847
+ return appCompose;
848
+ }
849
+ function handleGatewayCompatibility(appCompose) {
850
+ if (!appCompose.compose_file) {
851
+ return appCompose;
852
+ }
853
+ const composeFile = { ...appCompose.compose_file };
854
+ if (typeof composeFile.gateway_enabled === "boolean" && typeof composeFile.tproxy_enabled === "boolean") {
855
+ delete composeFile.tproxy_enabled;
856
+ } else if (typeof composeFile.tproxy_enabled === "boolean" && typeof composeFile.gateway_enabled === "undefined") {
857
+ composeFile.gateway_enabled = composeFile.tproxy_enabled;
858
+ delete composeFile.tproxy_enabled;
859
+ if (typeof window !== "undefined" ? window.console : globalThis.console) {
860
+ console.warn(
861
+ "[phala/cloud] tproxy_enabled is deprecated, please use gateway_enabled instead. See docs for migration."
862
+ );
1012
863
  }
1013
- } else {
1014
- const promises = operations.map(async ({ operation, args, options }) => {
1015
- try {
1016
- const tracker = createTransactionTracker();
1017
- return await tracker.execute(operation, clients, args, options);
1018
- } catch (error) {
1019
- return error instanceof Error ? error : new Error(String(error));
1020
- }
1021
- });
1022
- const allResults = await Promise.allSettled(promises);
1023
- results.push(...allResults.map((r) => r.status === "fulfilled" ? r.value : r.reason));
1024
- onProgress?.(operations.length, operations.length, results);
1025
864
  }
1026
- const successCount = results.filter((r) => !(r instanceof Error)).length;
1027
- const errorCount = results.length - successCount;
1028
865
  return {
1029
- results,
1030
- successCount,
1031
- errorCount,
1032
- allSuccessful: errorCount === 0
866
+ ...appCompose,
867
+ compose_file: composeFile
1033
868
  };
1034
869
  }
1035
- async function executeTransactionWithRetry(operation, clients, args, options = {}, retryOptions = {}) {
1036
- const {
1037
- maxRetries = 3,
1038
- initialDelay = 1e3,
1039
- maxDelay = 1e4,
1040
- backoffFactor = 2,
1041
- retryCondition = () => true
1042
- } = retryOptions;
1043
- let lastError;
1044
- let delay = initialDelay;
1045
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
1046
- try {
1047
- const tracker = createTransactionTracker();
1048
- return await tracker.execute(operation, clients, args, options);
1049
- } catch (error) {
1050
- lastError = error instanceof Error ? error : new Error(String(error));
1051
- if (attempt === maxRetries) {
1052
- break;
1053
- }
1054
- if (!retryCondition(lastError)) {
1055
- break;
1056
- }
1057
- await new Promise((resolve) => setTimeout(resolve, delay));
1058
- delay = Math.min(delay * backoffFactor, maxDelay);
870
+ var { action: provisionCvm, safeAction: safeProvisionCvm } = defineAction(ProvisionCvmSchema, async (client, appCompose) => {
871
+ const body = handleGatewayCompatibility(autofillComposeFileName(appCompose));
872
+ let requestBody = { ...body };
873
+ if (typeof body.node_id === "number") {
874
+ requestBody = { ...body, teepod_id: body.node_id };
875
+ delete requestBody.node_id;
876
+ } else if (typeof body.teepod_id === "number") {
877
+ console.warn("[phala/cloud] teepod_id is deprecated, please use node_id instead.");
878
+ }
879
+ return await client.post("/cvms/provision", requestBody);
880
+ });
881
+
882
+ // src/actions/cvms/commit_cvm_provision.ts
883
+ var import_zod7 = require("zod");
884
+ var CommitCvmProvisionSchema = import_zod7.z.object({
885
+ id: import_zod7.z.number(),
886
+ name: import_zod7.z.string(),
887
+ status: import_zod7.z.string(),
888
+ teepod_id: import_zod7.z.number(),
889
+ teepod: import_zod7.z.object({
890
+ id: import_zod7.z.number(),
891
+ name: import_zod7.z.string()
892
+ }).nullable(),
893
+ user_id: import_zod7.z.number().nullable(),
894
+ app_id: import_zod7.z.string().nullable(),
895
+ vm_uuid: import_zod7.z.string().nullable(),
896
+ instance_id: import_zod7.z.string().nullable(),
897
+ app_url: import_zod7.z.string().nullable(),
898
+ base_image: import_zod7.z.string().nullable(),
899
+ vcpu: import_zod7.z.number(),
900
+ memory: import_zod7.z.number(),
901
+ disk_size: import_zod7.z.number(),
902
+ manifest_version: import_zod7.z.number().nullable(),
903
+ version: import_zod7.z.string().nullable(),
904
+ runner: import_zod7.z.string().nullable(),
905
+ docker_compose_file: import_zod7.z.string().nullable(),
906
+ features: import_zod7.z.array(import_zod7.z.string()).nullable(),
907
+ created_at: import_zod7.z.string(),
908
+ encrypted_env_pubkey: import_zod7.z.string().nullable().optional(),
909
+ app_auth_contract_address: import_zod7.z.string().nullable().optional(),
910
+ deployer_address: import_zod7.z.string().nullable().optional()
911
+ }).passthrough();
912
+ var CommitCvmProvisionRequestSchema = import_zod7.z.object({
913
+ encrypted_env: import_zod7.z.string().optional().nullable(),
914
+ app_id: import_zod7.z.string(),
915
+ compose_hash: import_zod7.z.string().optional(),
916
+ kms_id: import_zod7.z.string().optional(),
917
+ contract_address: import_zod7.z.string().optional(),
918
+ deployer_address: import_zod7.z.string().optional(),
919
+ env_keys: import_zod7.z.array(import_zod7.z.string()).optional().nullable()
920
+ }).passthrough();
921
+ var { action: commitCvmProvision, safeAction: safeCommitCvmProvision } = defineAction(CommitCvmProvisionSchema, async (client, payload) => {
922
+ return await client.post("/cvms", payload);
923
+ });
924
+
925
+ // src/actions/blockchains/deploy_app_auth.ts
926
+ var import_zod8 = require("zod");
927
+ var import_viem3 = require("viem");
928
+ var import_accounts2 = require("viem/accounts");
929
+
930
+ // src/utils/index.ts
931
+ var import_encrypt_env_vars = require("@phala/dstack-sdk/encrypt-env-vars");
932
+
933
+ // src/utils/get_error_message.ts
934
+ function getErrorMessage(error) {
935
+ if (typeof error.detail === "string") {
936
+ return error.detail;
937
+ }
938
+ if (Array.isArray(error.detail)) {
939
+ if (error.detail.length > 0) {
940
+ return error.detail[0]?.msg || "Validation error";
1059
941
  }
942
+ return "Validation error";
1060
943
  }
1061
- throw lastError;
944
+ if (typeof error.detail === "object" && error.detail !== null) {
945
+ return JSON.stringify(error.detail);
946
+ }
947
+ return "Unknown error occurred";
1062
948
  }
1063
- async function estimateTransactionGas(clients, transaction, options = {}) {
1064
- const {
1065
- gasLimitMultiplier = 1.2,
1066
- maxFeePerGasMultiplier = 1.1,
1067
- priorityFeeMultiplier = 1.1
1068
- } = options;
1069
- try {
1070
- const estimatedGas = await clients.publicClient.estimateGas(transaction);
1071
- const gasLimit = BigInt(Math.ceil(Number(estimatedGas) * gasLimitMultiplier));
1072
- let maxFeePerGas;
1073
- let maxPriorityFeePerGas;
1074
- try {
1075
- const feeData = await clients.publicClient.estimateFeesPerGas();
1076
- if (feeData.maxFeePerGas) {
1077
- maxFeePerGas = BigInt(Math.ceil(Number(feeData.maxFeePerGas) * maxFeePerGasMultiplier));
1078
- }
1079
- if (feeData.maxPriorityFeePerGas) {
1080
- maxPriorityFeePerGas = BigInt(
1081
- Math.ceil(Number(feeData.maxPriorityFeePerGas) * priorityFeeMultiplier)
1082
- );
1083
- }
1084
- } catch (error) {
949
+
950
+ // src/utils/as-hex.ts
951
+ var import_viem = require("viem");
952
+ function asHex(value) {
953
+ if (typeof value === "string") {
954
+ if (value.startsWith("0x") && (0, import_viem.isHex)(value)) {
955
+ return value;
956
+ } else if ((0, import_viem.isHex)(`0x${value}`)) {
957
+ return `0x${value}`;
1085
958
  }
1086
- return {
1087
- gasLimit,
1088
- maxFeePerGas,
1089
- maxPriorityFeePerGas
1090
- };
1091
- } catch (error) {
1092
- throw new TransactionError(
1093
- `Gas estimation failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1094
- void 0,
1095
- error
1096
- );
1097
959
  }
960
+ throw new Error(`Invalid hex value: ${value}`);
1098
961
  }
1099
962
 
1100
- // src/utils/client-factories.ts
1101
- var import_viem2 = require("viem");
1102
- var import_accounts = require("viem/accounts");
1103
- function isBrowser() {
1104
- return typeof window !== "undefined" && typeof window.ethereum !== "undefined";
1105
- }
1106
- function getEthereumProvider() {
1107
- if (!isBrowser()) return null;
1108
- const ethereum = window.ethereum;
1109
- return ethereum || null;
963
+ // src/utils/network.ts
964
+ var NetworkError = class extends Error {
965
+ constructor(message, code, details) {
966
+ super(message);
967
+ this.code = code;
968
+ this.details = details;
969
+ this.name = "NetworkError";
970
+ }
971
+ };
972
+ var WalletError = class extends Error {
973
+ constructor(message, code, details) {
974
+ super(message);
975
+ this.code = code;
976
+ this.details = details;
977
+ this.name = "WalletError";
978
+ }
979
+ };
980
+ var TransactionError = class extends Error {
981
+ constructor(message, hash, details) {
982
+ super(message);
983
+ this.hash = hash;
984
+ this.details = details;
985
+ this.name = "TransactionError";
986
+ }
987
+ };
988
+ function createNetworkClients(publicClient, walletClient, address, chainId) {
989
+ return {
990
+ publicClient,
991
+ walletClient,
992
+ address,
993
+ chainId
994
+ };
1110
995
  }
1111
- function createClientsFromPrivateKey(chain, privateKey, rpcUrl) {
996
+ async function checkNetworkStatus(clients, targetChainId) {
1112
997
  try {
1113
- const account = (0, import_accounts.privateKeyToAccount)(privateKey);
1114
- const publicClient = (0, import_viem2.createPublicClient)({
1115
- chain,
1116
- transport: (0, import_viem2.http)(rpcUrl || chain.rpcUrls.default.http[0])
1117
- });
1118
- const walletClient = (0, import_viem2.createWalletClient)({
1119
- account,
1120
- chain,
1121
- transport: (0, import_viem2.http)(rpcUrl || chain.rpcUrls.default.http[0])
1122
- });
1123
- return createNetworkClients(publicClient, walletClient, account.address, chain.id);
998
+ const currentChainId = await clients.walletClient.getChainId();
999
+ return {
1000
+ isCorrectNetwork: currentChainId === targetChainId,
1001
+ currentChainId
1002
+ };
1124
1003
  } catch (error) {
1125
- throw new WalletError(
1126
- `Failed to create clients from private key: ${error instanceof Error ? error.message : "Unknown error"}`,
1127
- "CLIENT_CREATION_FAILED",
1004
+ throw new NetworkError(
1005
+ `Failed to check network status: ${error instanceof Error ? error.message : "Unknown error"}`,
1006
+ "NETWORK_CHECK_FAILED",
1128
1007
  error
1129
1008
  );
1130
1009
  }
1131
1010
  }
1132
- async function createClientsFromBrowser(chain, rpcUrl) {
1133
- if (!isBrowser()) {
1134
- throw new WalletError(
1135
- "Browser wallet connection is only available in browser environment",
1136
- "NOT_BROWSER_ENVIRONMENT"
1137
- );
1138
- }
1139
- const provider = getEthereumProvider();
1140
- if (!provider) {
1141
- throw new WalletError(
1142
- "No Ethereum provider found. Please install a wallet like MetaMask.",
1143
- "NO_PROVIDER"
1144
- );
1145
- }
1011
+ async function checkBalance(publicClient, address, minBalance) {
1146
1012
  try {
1147
- const accounts = await provider.request({
1148
- method: "eth_requestAccounts"
1149
- });
1150
- if (!accounts || accounts.length === 0) {
1151
- throw new WalletError("No accounts available", "NO_ACCOUNTS");
1152
- }
1153
- const address = accounts[0];
1154
- const chainId = await provider.request({ method: "eth_chainId" });
1155
- const currentChainId = parseInt(chainId, 16);
1156
- if (currentChainId !== chain.id) {
1157
- await switchToNetwork(provider, chain.id);
1158
- }
1159
- const publicClient = (0, import_viem2.createPublicClient)({
1160
- chain,
1161
- transport: (0, import_viem2.http)(rpcUrl || chain.rpcUrls.default.http[0])
1162
- });
1163
- const walletClient = (0, import_viem2.createWalletClient)({
1164
- account: address,
1165
- chain,
1166
- transport: (0, import_viem2.custom)(provider)
1167
- });
1168
- return createNetworkClients(publicClient, walletClient, address, chain.id);
1013
+ const balance = await publicClient.getBalance({ address });
1014
+ return {
1015
+ address,
1016
+ balance,
1017
+ sufficient: minBalance ? balance >= minBalance : true,
1018
+ required: minBalance
1019
+ };
1169
1020
  } catch (error) {
1170
- if (error instanceof WalletError || error instanceof NetworkError) {
1171
- throw error;
1172
- }
1173
- throw new WalletError(
1174
- `Failed to connect browser wallet: ${error instanceof Error ? error.message : "Unknown error"}`,
1175
- "BROWSER_CONNECTION_FAILED",
1021
+ throw new NetworkError(
1022
+ `Failed to check balance: ${error instanceof Error ? error.message : "Unknown error"}`,
1023
+ "BALANCE_CHECK_FAILED",
1176
1024
  error
1177
1025
  );
1178
1026
  }
1179
1027
  }
1180
- async function switchToNetwork(provider, chainId) {
1028
+ async function waitForTransactionReceipt(publicClient, hash, options = {}) {
1029
+ const {
1030
+ timeout = 6e4,
1031
+ // 60 seconds default
1032
+ pollingInterval = 2e3,
1033
+ // 2 seconds default
1034
+ confirmations = 1
1035
+ } = options;
1036
+ const startTime = Date.now();
1037
+ return new Promise((resolve, reject) => {
1038
+ const poll = async () => {
1039
+ try {
1040
+ const receipt = await publicClient.getTransactionReceipt({ hash });
1041
+ if (receipt) {
1042
+ if (confirmations > 1) {
1043
+ const currentBlock = await publicClient.getBlockNumber();
1044
+ const confirmationCount = currentBlock - receipt.blockNumber + 1n;
1045
+ if (confirmationCount < BigInt(confirmations)) {
1046
+ const elapsed = Date.now() - startTime;
1047
+ if (elapsed >= timeout) {
1048
+ reject(
1049
+ new TransactionError(`Transaction confirmation timeout after ${timeout}ms`, hash)
1050
+ );
1051
+ return;
1052
+ }
1053
+ setTimeout(poll, pollingInterval);
1054
+ return;
1055
+ }
1056
+ }
1057
+ resolve(receipt);
1058
+ } else {
1059
+ const elapsed = Date.now() - startTime;
1060
+ if (elapsed >= timeout) {
1061
+ reject(new TransactionError(`Transaction receipt timeout after ${timeout}ms`, hash));
1062
+ return;
1063
+ }
1064
+ setTimeout(poll, pollingInterval);
1065
+ }
1066
+ } catch (error) {
1067
+ const elapsed = Date.now() - startTime;
1068
+ if (elapsed >= timeout) {
1069
+ reject(
1070
+ new TransactionError(`Transaction receipt timeout after ${timeout}ms`, hash, error)
1071
+ );
1072
+ return;
1073
+ }
1074
+ setTimeout(poll, pollingInterval);
1075
+ }
1076
+ };
1077
+ poll();
1078
+ });
1079
+ }
1080
+ async function executeTransaction(clients, operation, args, options = {}) {
1081
+ const { timeout = 6e4, confirmations = 1, onSubmitted, onConfirmed, onError } = options;
1181
1082
  try {
1182
- await provider.request({
1183
- method: "wallet_switchEthereumChain",
1184
- params: [{ chainId: `0x${chainId.toString(16)}` }]
1083
+ const hash = await operation(clients, ...args);
1084
+ onSubmitted?.(hash);
1085
+ const receipt = await waitForTransactionReceipt(clients.publicClient, hash, {
1086
+ timeout,
1087
+ confirmations
1185
1088
  });
1186
- } catch (error) {
1187
- const errorObj = error;
1188
- if (errorObj.code === 4902) {
1189
- throw new NetworkError(
1190
- `Network ${chainId} not found in wallet. Please add it manually.`,
1191
- "NETWORK_NOT_FOUND",
1192
- error
1193
- );
1089
+ const success = receipt.status === "success";
1090
+ if (success) {
1091
+ onConfirmed?.(receipt);
1092
+ } else {
1093
+ const error = new TransactionError("Transaction failed on-chain", hash, receipt);
1094
+ onError?.(error, hash);
1095
+ throw error;
1194
1096
  }
1195
- throw new NetworkError(
1196
- `Failed to switch network: ${errorObj.message || "Unknown error"}`,
1197
- "NETWORK_SWITCH_FAILED",
1097
+ return {
1098
+ hash,
1099
+ receipt,
1100
+ success
1101
+ };
1102
+ } catch (error) {
1103
+ const txError = error instanceof TransactionError ? error : new TransactionError(
1104
+ `Transaction execution failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1105
+ void 0,
1198
1106
  error
1199
1107
  );
1108
+ onError?.(txError, txError.hash);
1109
+ throw txError;
1200
1110
  }
1201
1111
  }
1202
- async function addNetwork(provider, config) {
1112
+ async function extractNetworkClients(publicClient, walletClient) {
1203
1113
  try {
1204
- await provider.request({
1205
- method: "wallet_addEthereumChain",
1206
- params: [
1207
- {
1208
- chainId: `0x${config.chainId.toString(16)}`,
1209
- chainName: config.name,
1210
- rpcUrls: [config.rpcUrl],
1211
- blockExplorerUrls: config.blockExplorer ? [config.blockExplorer] : void 0,
1212
- nativeCurrency: {
1213
- name: "ETH",
1214
- symbol: "ETH",
1215
- decimals: 18
1216
- }
1217
- }
1218
- ]
1219
- });
1114
+ const address = walletClient.account?.address;
1115
+ if (!address) {
1116
+ throw new WalletError("WalletClient must have an account", "NO_ACCOUNT");
1117
+ }
1118
+ const chainId = await walletClient.getChainId();
1119
+ return createNetworkClients(publicClient, walletClient, address, chainId);
1220
1120
  } catch (error) {
1221
- const errorObj = error;
1222
- throw new NetworkError(
1223
- `Failed to add network: ${errorObj.message || "Unknown error"}`,
1224
- "NETWORK_ADD_FAILED",
1121
+ throw new WalletError(
1122
+ `Failed to extract network clients: ${error instanceof Error ? error.message : "Unknown error"}`,
1123
+ "EXTRACTION_FAILED",
1225
1124
  error
1226
1125
  );
1227
1126
  }
1228
1127
  }
1229
- async function autoCreateClients(chain, options = {}) {
1230
- const { privateKey, rpcUrl, preferBrowser = false } = options;
1231
- if (privateKey) {
1232
- return createClientsFromPrivateKey(chain, privateKey, rpcUrl);
1233
- }
1234
- if (isBrowser() && (preferBrowser || !privateKey)) {
1235
- return createClientsFromBrowser(chain, rpcUrl);
1236
- }
1237
- throw new WalletError(
1238
- "No wallet connection method available. Provide a private key for server-side usage or use in browser environment.",
1239
- "NO_CONNECTION_METHOD"
1240
- );
1241
- }
1242
-
1243
- // src/actions/get_current_user.ts
1244
- var CurrentUserSchema = import_zod4.z.object({
1245
- username: import_zod4.z.string(),
1246
- email: import_zod4.z.string(),
1247
- credits: import_zod4.z.number(),
1248
- granted_credits: import_zod4.z.number(),
1249
- avatar: import_zod4.z.string(),
1250
- team_name: import_zod4.z.string(),
1251
- team_tier: import_zod4.z.string()
1252
- }).passthrough();
1253
- async function getCurrentUser(client, parameters) {
1254
- validateActionParameters(parameters);
1255
- const response = await client.get("/auth/me");
1256
- if (parameters?.schema === false) {
1257
- return response;
1258
- }
1259
- const schema = parameters?.schema || CurrentUserSchema;
1260
- return schema.parse(response);
1261
- }
1262
- async function safeGetCurrentUser(client, parameters) {
1263
- const parameterValidationError = safeValidateActionParameters(parameters);
1264
- if (parameterValidationError) {
1265
- return parameterValidationError;
1266
- }
1267
- const httpResult = await client.safeGet("/auth/me");
1268
- if (!httpResult.success) {
1269
- return httpResult;
1270
- }
1271
- if (parameters?.schema === false) {
1272
- return { success: true, data: httpResult.data };
1273
- }
1274
- const schema = parameters?.schema || CurrentUserSchema;
1275
- return schema.safeParse(httpResult.data);
1128
+ async function validateNetworkPrerequisites(clients, requirements) {
1129
+ const { targetChainId, minBalance, requiredAddress } = requirements;
1130
+ const networkStatus = await checkNetworkStatus(clients, targetChainId);
1131
+ const balanceResult = await checkBalance(clients.publicClient, clients.address, minBalance);
1132
+ const addressValid = requiredAddress ? clients.address.toLowerCase() === requiredAddress.toLowerCase() : true;
1133
+ return {
1134
+ networkValid: networkStatus.isCorrectNetwork,
1135
+ balanceValid: balanceResult.sufficient,
1136
+ addressValid,
1137
+ details: {
1138
+ currentChainId: networkStatus.currentChainId,
1139
+ balance: balanceResult.balance,
1140
+ address: clients.address
1141
+ }
1142
+ };
1276
1143
  }
1277
1144
 
1278
- // src/actions/get_available_nodes.ts
1279
- var import_zod5 = require("zod");
1280
-
1281
- // src/utils/define-action.ts
1282
- function defineSimpleAction(schema, fn) {
1283
- function action(client, parameters) {
1284
- return _actionImpl(client, parameters);
1285
- }
1286
- async function _actionImpl(client, parameters) {
1287
- validateActionParameters(parameters);
1288
- const response = await fn(client);
1289
- if (parameters?.schema === false) {
1290
- return response;
1145
+ // src/utils/transaction.ts
1146
+ function createTransactionTracker() {
1147
+ let status = { state: "idle" };
1148
+ let timeoutHandle;
1149
+ let abortController;
1150
+ const updateStatus = (newStatus) => {
1151
+ status = { ...status, ...newStatus };
1152
+ };
1153
+ const reset = () => {
1154
+ if (timeoutHandle) {
1155
+ clearTimeout(timeoutHandle);
1156
+ timeoutHandle = void 0;
1291
1157
  }
1292
- const actualSchema = parameters?.schema || schema;
1293
- return actualSchema.parse(response);
1294
- }
1295
- function safeAction(client, parameters) {
1296
- return _safeActionImpl(client, parameters);
1297
- }
1298
- async function _safeActionImpl(client, parameters) {
1299
- const parameterValidationError = safeValidateActionParameters(parameters);
1300
- if (parameterValidationError) {
1301
- return parameterValidationError;
1158
+ if (abortController) {
1159
+ abortController.abort();
1160
+ abortController = void 0;
1302
1161
  }
1303
- const httpResult = await (async () => {
1304
- try {
1305
- const data = await fn(client);
1306
- return { success: true, data };
1307
- } catch (error) {
1308
- if (error && typeof error === "object" && "isRequestError" in error) {
1309
- return { success: false, error };
1310
- }
1311
- if (error && typeof error === "object" && "issues" in error) {
1312
- return { success: false, error };
1162
+ status = { state: "idle" };
1163
+ };
1164
+ const abort = () => {
1165
+ if (abortController) {
1166
+ abortController.abort();
1167
+ }
1168
+ if (timeoutHandle) {
1169
+ clearTimeout(timeoutHandle);
1170
+ timeoutHandle = void 0;
1171
+ }
1172
+ updateStatus({
1173
+ state: "error",
1174
+ aborted: true,
1175
+ error: "Transaction aborted by user"
1176
+ });
1177
+ };
1178
+ const execute = async (operation, clients, args, options = {}) => {
1179
+ const {
1180
+ timeout = 6e4,
1181
+ confirmations = 1,
1182
+ onSubmitted,
1183
+ onConfirmed,
1184
+ onError,
1185
+ signal
1186
+ } = options;
1187
+ try {
1188
+ reset();
1189
+ abortController = new AbortController();
1190
+ if (signal) {
1191
+ if (signal.aborted) {
1192
+ throw new TransactionError("Operation was aborted before execution");
1313
1193
  }
1314
- return {
1315
- success: false,
1316
- error: {
1317
- name: "Error",
1318
- message: error instanceof Error ? error.message : String(error)
1194
+ signal.addEventListener("abort", () => {
1195
+ abort();
1196
+ });
1197
+ }
1198
+ updateStatus({
1199
+ state: "submitting",
1200
+ startTime: Date.now(),
1201
+ error: void 0,
1202
+ hash: void 0,
1203
+ receipt: void 0,
1204
+ aborted: false
1205
+ });
1206
+ if (abortController.signal.aborted) {
1207
+ throw new TransactionError("Transaction aborted");
1208
+ }
1209
+ const hash = await operation(clients, ...args);
1210
+ if (abortController.signal.aborted) {
1211
+ throw new TransactionError("Transaction aborted after submission", hash);
1212
+ }
1213
+ updateStatus({
1214
+ state: "pending",
1215
+ hash,
1216
+ submitTime: Date.now()
1217
+ });
1218
+ onSubmitted?.(hash);
1219
+ if (timeout > 0) {
1220
+ timeoutHandle = setTimeout(() => {
1221
+ if (status.state === "pending" && !abortController?.signal.aborted) {
1222
+ updateStatus({
1223
+ state: "timeout",
1224
+ error: `Transaction timeout after ${timeout}ms`
1225
+ });
1319
1226
  }
1320
- };
1227
+ }, timeout);
1321
1228
  }
1322
- })();
1323
- if (!httpResult.success) {
1324
- return httpResult;
1325
- }
1326
- if (parameters?.schema === false) {
1327
- return { success: true, data: httpResult.data };
1229
+ const receipt = await Promise.race([
1230
+ waitForTransactionReceipt(clients.publicClient, hash, { timeout, confirmations }),
1231
+ new Promise((_, reject) => {
1232
+ abortController?.signal.addEventListener("abort", () => {
1233
+ reject(new TransactionError("Transaction aborted while waiting for receipt", hash));
1234
+ });
1235
+ })
1236
+ ]);
1237
+ if (timeoutHandle) {
1238
+ clearTimeout(timeoutHandle);
1239
+ timeoutHandle = void 0;
1240
+ }
1241
+ const success = receipt.status === "success";
1242
+ updateStatus({
1243
+ state: success ? "success" : "error",
1244
+ receipt,
1245
+ confirmTime: Date.now(),
1246
+ error: success ? void 0 : "Transaction failed on-chain"
1247
+ });
1248
+ if (success) {
1249
+ onConfirmed?.(receipt);
1250
+ } else {
1251
+ const error = new TransactionError("Transaction failed on-chain", hash, receipt);
1252
+ onError?.(error, hash);
1253
+ throw error;
1254
+ }
1255
+ return {
1256
+ hash,
1257
+ receipt,
1258
+ success
1259
+ };
1260
+ } catch (error) {
1261
+ const txError = error instanceof TransactionError ? error : new TransactionError(
1262
+ `Transaction execution failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1263
+ status.hash,
1264
+ error
1265
+ );
1266
+ updateStatus({
1267
+ state: "error",
1268
+ error: txError.message
1269
+ });
1270
+ onError?.(txError, status.hash);
1271
+ throw txError;
1328
1272
  }
1329
- const actualSchema = parameters?.schema || schema;
1330
- return actualSchema.safeParse(httpResult.data);
1331
- }
1273
+ };
1332
1274
  return {
1333
- action,
1334
- safeAction
1275
+ get status() {
1276
+ return { ...status };
1277
+ },
1278
+ get isIdle() {
1279
+ return status.state === "idle";
1280
+ },
1281
+ get isSubmitting() {
1282
+ return status.state === "submitting";
1283
+ },
1284
+ get isPending() {
1285
+ return status.state === "pending";
1286
+ },
1287
+ get isSuccess() {
1288
+ return status.state === "success";
1289
+ },
1290
+ get isError() {
1291
+ return status.state === "error";
1292
+ },
1293
+ get isTimeout() {
1294
+ return status.state === "timeout";
1295
+ },
1296
+ get isAborted() {
1297
+ return status.aborted === true;
1298
+ },
1299
+ get isComplete() {
1300
+ return ["success", "error", "timeout"].includes(status.state);
1301
+ },
1302
+ abort,
1303
+ reset,
1304
+ execute
1335
1305
  };
1336
1306
  }
1337
- function defineAction(schema, fn) {
1338
- function action(client, ...args) {
1339
- const [params, parameters] = args;
1340
- return _actionImpl(client, params, parameters);
1341
- }
1342
- async function _actionImpl(client, params, parameters) {
1343
- validateActionParameters(parameters);
1344
- const response = await fn(client, params);
1345
- if (parameters?.schema === false) {
1346
- return response;
1347
- }
1348
- const actualSchema = parameters?.schema || schema;
1349
- return actualSchema.parse(response);
1350
- }
1351
- function safeAction(client, ...args) {
1352
- const [params, parameters] = args;
1353
- return _safeActionImpl(client, params, parameters);
1354
- }
1355
- async function _safeActionImpl(client, params, parameters) {
1356
- const parameterValidationError = safeValidateActionParameters(parameters);
1357
- if (parameterValidationError) {
1358
- return parameterValidationError;
1359
- }
1360
- const httpResult = await (async () => {
1307
+ async function executeBatchTransactions(operations, clients, batchOptions) {
1308
+ const { mode, failFast = false, onProgress } = batchOptions;
1309
+ const results = [];
1310
+ if (mode === "sequential") {
1311
+ for (let i = 0; i < operations.length; i++) {
1312
+ const op = operations[i];
1313
+ if (!op) continue;
1314
+ const { operation, args, options } = op;
1361
1315
  try {
1362
- const data = await fn(client, params);
1363
- return { success: true, data };
1316
+ const tracker = createTransactionTracker();
1317
+ const result = await tracker.execute(operation, clients, args, options);
1318
+ results.push(result);
1319
+ onProgress?.(i + 1, operations.length, results);
1364
1320
  } catch (error) {
1365
- if (error && typeof error === "object" && "isRequestError" in error) {
1366
- return { success: false, error };
1367
- }
1368
- if (error && typeof error === "object" && "issues" in error) {
1369
- return { success: false, error };
1370
- }
1371
- return {
1372
- success: false,
1373
- error: {
1374
- name: "Error",
1375
- message: error instanceof Error ? error.message : String(error)
1321
+ const txError = error instanceof Error ? error : new Error(String(error));
1322
+ results.push(txError);
1323
+ onProgress?.(i + 1, operations.length, results);
1324
+ if (failFast) {
1325
+ for (let j = i + 1; j < operations.length; j++) {
1326
+ results.push(new Error("Cancelled due to previous failure"));
1376
1327
  }
1377
- };
1328
+ break;
1329
+ }
1378
1330
  }
1379
- })();
1380
- if (!httpResult.success) {
1381
- return httpResult;
1382
- }
1383
- if (parameters?.schema === false) {
1384
- return { success: true, data: httpResult.data };
1385
1331
  }
1386
- const actualSchema = parameters?.schema || schema;
1387
- return actualSchema.safeParse(httpResult.data);
1332
+ } else {
1333
+ const promises = operations.map(async ({ operation, args, options }) => {
1334
+ try {
1335
+ const tracker = createTransactionTracker();
1336
+ return await tracker.execute(operation, clients, args, options);
1337
+ } catch (error) {
1338
+ return error instanceof Error ? error : new Error(String(error));
1339
+ }
1340
+ });
1341
+ const allResults = await Promise.allSettled(promises);
1342
+ results.push(...allResults.map((r) => r.status === "fulfilled" ? r.value : r.reason));
1343
+ onProgress?.(operations.length, operations.length, results);
1388
1344
  }
1345
+ const successCount = results.filter((r) => !(r instanceof Error)).length;
1346
+ const errorCount = results.length - successCount;
1389
1347
  return {
1390
- action,
1391
- safeAction
1348
+ results,
1349
+ successCount,
1350
+ errorCount,
1351
+ allSuccessful: errorCount === 0
1392
1352
  };
1393
1353
  }
1394
-
1395
- // src/actions/get_available_nodes.ts
1396
- var AvailableOSImageSchema = import_zod5.z.object({
1397
- name: import_zod5.z.string(),
1398
- is_dev: import_zod5.z.boolean(),
1399
- version: import_zod5.z.union([
1400
- import_zod5.z.tuple([import_zod5.z.number(), import_zod5.z.number(), import_zod5.z.number()]),
1401
- import_zod5.z.tuple([import_zod5.z.number(), import_zod5.z.number(), import_zod5.z.number(), import_zod5.z.number()])
1402
- ]),
1403
- os_image_hash: import_zod5.z.string().nullable().optional()
1404
- }).passthrough();
1405
- var TeepodCapacitySchema = import_zod5.z.object({
1406
- teepod_id: import_zod5.z.number(),
1407
- name: import_zod5.z.string(),
1408
- listed: import_zod5.z.boolean(),
1409
- resource_score: import_zod5.z.number(),
1410
- remaining_vcpu: import_zod5.z.number(),
1411
- remaining_memory: import_zod5.z.number(),
1412
- remaining_cvm_slots: import_zod5.z.number(),
1413
- images: import_zod5.z.array(AvailableOSImageSchema),
1414
- support_onchain_kms: import_zod5.z.boolean().optional(),
1415
- fmspc: import_zod5.z.string().nullable().optional(),
1416
- device_id: import_zod5.z.string().nullable().optional(),
1417
- region_identifier: import_zod5.z.string().nullable().optional(),
1418
- default_kms: import_zod5.z.string().nullable().optional(),
1419
- kms_list: import_zod5.z.array(import_zod5.z.string()).default([])
1420
- }).passthrough();
1421
- var ResourceThresholdSchema = import_zod5.z.object({
1422
- max_instances: import_zod5.z.number().nullable().optional(),
1423
- max_vcpu: import_zod5.z.number().nullable().optional(),
1424
- max_memory: import_zod5.z.number().nullable().optional(),
1425
- max_disk: import_zod5.z.number().nullable().optional()
1426
- }).passthrough();
1427
- var AvailableNodesSchema = import_zod5.z.object({
1428
- tier: import_zod5.z.string(),
1429
- // TeamTier is string enum
1430
- capacity: ResourceThresholdSchema,
1431
- nodes: import_zod5.z.array(TeepodCapacitySchema),
1432
- kms_list: import_zod5.z.array(KmsInfoSchema)
1433
- }).passthrough();
1434
- var { action: getAvailableNodes, safeAction: safeGetAvailableNodes } = defineSimpleAction(
1435
- AvailableNodesSchema,
1436
- async (client) => {
1437
- return await client.get("/teepods/available");
1438
- }
1439
- );
1440
-
1441
- // src/actions/provision_cvm.ts
1442
- var import_zod6 = require("zod");
1443
- var ProvisionCvmSchema = import_zod6.z.object({
1444
- app_id: import_zod6.z.string().nullable().optional(),
1445
- app_env_encrypt_pubkey: import_zod6.z.string().nullable().optional(),
1446
- compose_hash: import_zod6.z.string(),
1447
- fmspc: import_zod6.z.string().nullable().optional(),
1448
- device_id: import_zod6.z.string().nullable().optional(),
1449
- os_image_hash: import_zod6.z.string().nullable().optional(),
1450
- teepod_id: import_zod6.z.number().nullable().optional(),
1451
- // Will be transformed to node_id
1452
- node_id: import_zod6.z.number().nullable().optional(),
1453
- kms_id: import_zod6.z.string().nullable().optional()
1454
- }).passthrough().transform((data) => {
1455
- if ("teepod_id" in data && data.teepod_id !== void 0) {
1456
- const { teepod_id, ...rest } = data;
1457
- return { ...rest, node_id: teepod_id };
1458
- }
1459
- return data;
1460
- });
1461
- var ProvisionCvmRequestSchema = import_zod6.z.object({
1462
- node_id: import_zod6.z.number().optional(),
1463
- // recommended
1464
- teepod_id: import_zod6.z.number().optional(),
1465
- // deprecated, for compatibility
1466
- name: import_zod6.z.string(),
1467
- image: import_zod6.z.string(),
1468
- vcpu: import_zod6.z.number(),
1469
- memory: import_zod6.z.number(),
1470
- disk_size: import_zod6.z.number(),
1471
- compose_file: import_zod6.z.object({
1472
- allowed_envs: import_zod6.z.array(import_zod6.z.string()).optional(),
1473
- pre_launch_script: import_zod6.z.string().optional(),
1474
- docker_compose_file: import_zod6.z.string().optional(),
1475
- name: import_zod6.z.string().optional(),
1476
- kms_enabled: import_zod6.z.boolean().optional(),
1477
- public_logs: import_zod6.z.boolean().optional(),
1478
- public_sysinfo: import_zod6.z.boolean().optional(),
1479
- gateway_enabled: import_zod6.z.boolean().optional(),
1480
- // recommended
1481
- tproxy_enabled: import_zod6.z.boolean().optional()
1482
- // deprecated, for compatibility
1483
- }),
1484
- listed: import_zod6.z.boolean().optional(),
1485
- instance_type: import_zod6.z.string().nullable().optional(),
1486
- kms_id: import_zod6.z.string().optional(),
1487
- env_keys: import_zod6.z.array(import_zod6.z.string()).optional()
1488
- }).passthrough();
1489
- function autofillComposeFileName(appCompose) {
1490
- if (appCompose.compose_file && !appCompose.compose_file.name) {
1491
- return {
1492
- ...appCompose,
1493
- compose_file: {
1494
- ...appCompose.compose_file,
1495
- name: appCompose.name
1354
+ async function executeTransactionWithRetry(operation, clients, args, options = {}, retryOptions = {}) {
1355
+ const {
1356
+ maxRetries = 3,
1357
+ initialDelay = 1e3,
1358
+ maxDelay = 1e4,
1359
+ backoffFactor = 2,
1360
+ retryCondition = () => true
1361
+ } = retryOptions;
1362
+ let lastError;
1363
+ let delay = initialDelay;
1364
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1365
+ try {
1366
+ const tracker = createTransactionTracker();
1367
+ return await tracker.execute(operation, clients, args, options);
1368
+ } catch (error) {
1369
+ lastError = error instanceof Error ? error : new Error(String(error));
1370
+ if (attempt === maxRetries) {
1371
+ break;
1372
+ }
1373
+ if (!retryCondition(lastError)) {
1374
+ break;
1375
+ }
1376
+ await new Promise((resolve) => setTimeout(resolve, delay));
1377
+ delay = Math.min(delay * backoffFactor, maxDelay);
1378
+ }
1379
+ }
1380
+ throw lastError;
1381
+ }
1382
+ async function estimateTransactionGas(clients, transaction, options = {}) {
1383
+ const {
1384
+ gasLimitMultiplier = 1.2,
1385
+ maxFeePerGasMultiplier = 1.1,
1386
+ priorityFeeMultiplier = 1.1
1387
+ } = options;
1388
+ try {
1389
+ const estimatedGas = await clients.publicClient.estimateGas(transaction);
1390
+ const gasLimit = BigInt(Math.ceil(Number(estimatedGas) * gasLimitMultiplier));
1391
+ let maxFeePerGas;
1392
+ let maxPriorityFeePerGas;
1393
+ try {
1394
+ const feeData = await clients.publicClient.estimateFeesPerGas();
1395
+ if (feeData.maxFeePerGas) {
1396
+ maxFeePerGas = BigInt(Math.ceil(Number(feeData.maxFeePerGas) * maxFeePerGasMultiplier));
1397
+ }
1398
+ if (feeData.maxPriorityFeePerGas) {
1399
+ maxPriorityFeePerGas = BigInt(
1400
+ Math.ceil(Number(feeData.maxPriorityFeePerGas) * priorityFeeMultiplier)
1401
+ );
1496
1402
  }
1403
+ } catch (error) {
1404
+ }
1405
+ return {
1406
+ gasLimit,
1407
+ maxFeePerGas,
1408
+ maxPriorityFeePerGas
1497
1409
  };
1410
+ } catch (error) {
1411
+ throw new TransactionError(
1412
+ `Gas estimation failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1413
+ void 0,
1414
+ error
1415
+ );
1498
1416
  }
1499
- return appCompose;
1500
1417
  }
1501
- function handleGatewayCompatibility(appCompose) {
1502
- if (!appCompose.compose_file) {
1503
- return appCompose;
1418
+
1419
+ // src/utils/client-factories.ts
1420
+ var import_viem2 = require("viem");
1421
+ var import_accounts = require("viem/accounts");
1422
+ function isBrowser() {
1423
+ return typeof window !== "undefined" && typeof window.ethereum !== "undefined";
1424
+ }
1425
+ function getEthereumProvider() {
1426
+ if (!isBrowser()) return null;
1427
+ const ethereum = window.ethereum;
1428
+ return ethereum || null;
1429
+ }
1430
+ function createClientsFromPrivateKey(chain, privateKey, rpcUrl) {
1431
+ try {
1432
+ const account = (0, import_accounts.privateKeyToAccount)(privateKey);
1433
+ const publicClient = (0, import_viem2.createPublicClient)({
1434
+ chain,
1435
+ transport: (0, import_viem2.http)(rpcUrl || chain.rpcUrls.default.http[0])
1436
+ });
1437
+ const walletClient = (0, import_viem2.createWalletClient)({
1438
+ account,
1439
+ chain,
1440
+ transport: (0, import_viem2.http)(rpcUrl || chain.rpcUrls.default.http[0])
1441
+ });
1442
+ return createNetworkClients(publicClient, walletClient, account.address, chain.id);
1443
+ } catch (error) {
1444
+ throw new WalletError(
1445
+ `Failed to create clients from private key: ${error instanceof Error ? error.message : "Unknown error"}`,
1446
+ "CLIENT_CREATION_FAILED",
1447
+ error
1448
+ );
1504
1449
  }
1505
- const composeFile = { ...appCompose.compose_file };
1506
- if (typeof composeFile.gateway_enabled === "boolean" && typeof composeFile.tproxy_enabled === "boolean") {
1507
- delete composeFile.tproxy_enabled;
1508
- } else if (typeof composeFile.tproxy_enabled === "boolean" && typeof composeFile.gateway_enabled === "undefined") {
1509
- composeFile.gateway_enabled = composeFile.tproxy_enabled;
1510
- delete composeFile.tproxy_enabled;
1511
- if (typeof window !== "undefined" ? window.console : globalThis.console) {
1512
- console.warn(
1513
- "[phala/cloud] tproxy_enabled is deprecated, please use gateway_enabled instead. See docs for migration."
1450
+ }
1451
+ async function createClientsFromBrowser(chain, rpcUrl) {
1452
+ if (!isBrowser()) {
1453
+ throw new WalletError(
1454
+ "Browser wallet connection is only available in browser environment",
1455
+ "NOT_BROWSER_ENVIRONMENT"
1456
+ );
1457
+ }
1458
+ const provider = getEthereumProvider();
1459
+ if (!provider) {
1460
+ throw new WalletError(
1461
+ "No Ethereum provider found. Please install a wallet like MetaMask.",
1462
+ "NO_PROVIDER"
1463
+ );
1464
+ }
1465
+ try {
1466
+ const accounts = await provider.request({
1467
+ method: "eth_requestAccounts"
1468
+ });
1469
+ if (!accounts || accounts.length === 0) {
1470
+ throw new WalletError("No accounts available", "NO_ACCOUNTS");
1471
+ }
1472
+ const address = accounts[0];
1473
+ const chainId = await provider.request({ method: "eth_chainId" });
1474
+ const currentChainId = parseInt(chainId, 16);
1475
+ if (currentChainId !== chain.id) {
1476
+ await switchToNetwork(provider, chain.id);
1477
+ }
1478
+ const publicClient = (0, import_viem2.createPublicClient)({
1479
+ chain,
1480
+ transport: (0, import_viem2.http)(rpcUrl || chain.rpcUrls.default.http[0])
1481
+ });
1482
+ const walletClient = (0, import_viem2.createWalletClient)({
1483
+ account: address,
1484
+ chain,
1485
+ transport: (0, import_viem2.custom)(provider)
1486
+ });
1487
+ return createNetworkClients(publicClient, walletClient, address, chain.id);
1488
+ } catch (error) {
1489
+ if (error instanceof WalletError || error instanceof NetworkError) {
1490
+ throw error;
1491
+ }
1492
+ throw new WalletError(
1493
+ `Failed to connect browser wallet: ${error instanceof Error ? error.message : "Unknown error"}`,
1494
+ "BROWSER_CONNECTION_FAILED",
1495
+ error
1496
+ );
1497
+ }
1498
+ }
1499
+ async function switchToNetwork(provider, chainId) {
1500
+ try {
1501
+ await provider.request({
1502
+ method: "wallet_switchEthereumChain",
1503
+ params: [{ chainId: `0x${chainId.toString(16)}` }]
1504
+ });
1505
+ } catch (error) {
1506
+ const errorObj = error;
1507
+ if (errorObj.code === 4902) {
1508
+ throw new NetworkError(
1509
+ `Network ${chainId} not found in wallet. Please add it manually.`,
1510
+ "NETWORK_NOT_FOUND",
1511
+ error
1514
1512
  );
1515
1513
  }
1514
+ throw new NetworkError(
1515
+ `Failed to switch network: ${errorObj.message || "Unknown error"}`,
1516
+ "NETWORK_SWITCH_FAILED",
1517
+ error
1518
+ );
1516
1519
  }
1517
- return {
1518
- ...appCompose,
1519
- compose_file: composeFile
1520
- };
1521
1520
  }
1522
- var { action: provisionCvm, safeAction: safeProvisionCvm } = defineAction(ProvisionCvmSchema, async (client, appCompose) => {
1523
- const body = handleGatewayCompatibility(autofillComposeFileName(appCompose));
1524
- let requestBody = { ...body };
1525
- if (typeof body.node_id === "number") {
1526
- requestBody = { ...body, teepod_id: body.node_id };
1527
- delete requestBody.node_id;
1528
- } else if (typeof body.teepod_id === "number") {
1529
- console.warn("[phala/cloud] teepod_id is deprecated, please use node_id instead.");
1521
+ async function addNetwork(provider, config) {
1522
+ try {
1523
+ await provider.request({
1524
+ method: "wallet_addEthereumChain",
1525
+ params: [
1526
+ {
1527
+ chainId: `0x${config.chainId.toString(16)}`,
1528
+ chainName: config.name,
1529
+ rpcUrls: [config.rpcUrl],
1530
+ blockExplorerUrls: config.blockExplorer ? [config.blockExplorer] : void 0,
1531
+ nativeCurrency: {
1532
+ name: "ETH",
1533
+ symbol: "ETH",
1534
+ decimals: 18
1535
+ }
1536
+ }
1537
+ ]
1538
+ });
1539
+ } catch (error) {
1540
+ const errorObj = error;
1541
+ throw new NetworkError(
1542
+ `Failed to add network: ${errorObj.message || "Unknown error"}`,
1543
+ "NETWORK_ADD_FAILED",
1544
+ error
1545
+ );
1530
1546
  }
1531
- return await client.post("/cvms/provision", requestBody);
1532
- });
1533
-
1534
- // src/actions/commit_cvm_provision.ts
1535
- var import_zod7 = require("zod");
1536
- var CommitCvmProvisionSchema = import_zod7.z.object({
1537
- id: import_zod7.z.number(),
1538
- name: import_zod7.z.string(),
1539
- status: import_zod7.z.string(),
1540
- teepod_id: import_zod7.z.number(),
1541
- teepod: import_zod7.z.object({
1542
- id: import_zod7.z.number(),
1543
- name: import_zod7.z.string()
1544
- }).nullable(),
1545
- user_id: import_zod7.z.number().nullable(),
1546
- app_id: import_zod7.z.string().nullable(),
1547
- vm_uuid: import_zod7.z.string().nullable(),
1548
- instance_id: import_zod7.z.string().nullable(),
1549
- app_url: import_zod7.z.string().nullable(),
1550
- base_image: import_zod7.z.string().nullable(),
1551
- vcpu: import_zod7.z.number(),
1552
- memory: import_zod7.z.number(),
1553
- disk_size: import_zod7.z.number(),
1554
- manifest_version: import_zod7.z.number().nullable(),
1555
- version: import_zod7.z.string().nullable(),
1556
- runner: import_zod7.z.string().nullable(),
1557
- docker_compose_file: import_zod7.z.string().nullable(),
1558
- features: import_zod7.z.array(import_zod7.z.string()).nullable(),
1559
- created_at: import_zod7.z.string(),
1560
- encrypted_env_pubkey: import_zod7.z.string().nullable().optional(),
1561
- app_auth_contract_address: import_zod7.z.string().nullable().optional(),
1562
- deployer_address: import_zod7.z.string().nullable().optional()
1563
- }).passthrough();
1564
- var CommitCvmProvisionRequestSchema = import_zod7.z.object({
1565
- encrypted_env: import_zod7.z.string().optional().nullable(),
1566
- app_id: import_zod7.z.string(),
1567
- compose_hash: import_zod7.z.string().optional(),
1568
- kms_id: import_zod7.z.string().optional(),
1569
- contract_address: import_zod7.z.string().optional(),
1570
- deployer_address: import_zod7.z.string().optional(),
1571
- env_keys: import_zod7.z.array(import_zod7.z.string()).optional().nullable()
1572
- }).passthrough();
1573
- var { action: commitCvmProvision, safeAction: safeCommitCvmProvision } = defineAction(CommitCvmProvisionSchema, async (client, payload) => {
1574
- return await client.post("/cvms", payload);
1575
- });
1547
+ }
1548
+ async function autoCreateClients(chain, options = {}) {
1549
+ const { privateKey, rpcUrl, preferBrowser = false } = options;
1550
+ if (privateKey) {
1551
+ return createClientsFromPrivateKey(chain, privateKey, rpcUrl);
1552
+ }
1553
+ if (isBrowser() && (preferBrowser || !privateKey)) {
1554
+ return createClientsFromBrowser(chain, rpcUrl);
1555
+ }
1556
+ throw new WalletError(
1557
+ "No wallet connection method available. Provide a private key for server-side usage or use in browser environment.",
1558
+ "NO_CONNECTION_METHOD"
1559
+ );
1560
+ }
1576
1561
 
1577
- // src/actions/deploy_app_auth.ts
1578
- var import_zod8 = require("zod");
1579
- var import_viem3 = require("viem");
1580
- var import_accounts2 = require("viem/accounts");
1562
+ // src/actions/blockchains/deploy_app_auth.ts
1581
1563
  var kmsAuthAbi = [
1582
1564
  {
1583
1565
  inputs: [
@@ -1905,7 +1887,7 @@ async function safeDeployAppAuth(request, parameters) {
1905
1887
  }
1906
1888
  }
1907
1889
 
1908
- // src/actions/add_compose_hash.ts
1890
+ // src/actions/blockchains/add_compose_hash.ts
1909
1891
  var import_zod9 = require("zod");
1910
1892
  var import_viem4 = require("viem");
1911
1893
  var import_accounts3 = require("viem/accounts");
@@ -2166,7 +2148,7 @@ async function safeAddComposeHash(request, parameters) {
2166
2148
  }
2167
2149
  }
2168
2150
 
2169
- // src/actions/get_cvm_compose_file.ts
2151
+ // src/actions/cvms/get_cvm_compose_file.ts
2170
2152
  var import_zod11 = require("zod");
2171
2153
 
2172
2154
  // src/types/app_compose.ts
@@ -2184,7 +2166,7 @@ var LooseAppComposeSchema = import_zod10.z.object({
2184
2166
  pre_launch_script: import_zod10.z.string().optional()
2185
2167
  }).passthrough();
2186
2168
 
2187
- // src/actions/get_cvm_compose_file.ts
2169
+ // src/actions/cvms/get_cvm_compose_file.ts
2188
2170
  var GetCvmComposeFileRequestSchema = import_zod11.z.object({
2189
2171
  id: import_zod11.z.string().optional(),
2190
2172
  uuid: import_zod11.z.string().regex(/^[0-9a-f]{8}[-]?[0-9a-f]{4}[-]?4[0-9a-f]{3}[-]?[89ab][0-9a-f]{3}[-]?[0-9a-f]{12}$/i).optional(),
@@ -2208,7 +2190,7 @@ var { action: getCvmComposeFile, safeAction: safeGetCvmComposeFile } = defineAct
2208
2190
  return await client.get(`/cvms/${validatedRequest.cvmId}/compose_file`);
2209
2191
  });
2210
2192
 
2211
- // src/actions/provision_cvm_compose_file_update.ts
2193
+ // src/actions/cvms/provision_cvm_compose_file_update.ts
2212
2194
  var import_zod12 = require("zod");
2213
2195
  var ProvisionCvmComposeFileUpdateRequestSchema = import_zod12.z.object({
2214
2196
  id: import_zod12.z.string().optional(),
@@ -2246,7 +2228,7 @@ var { action: provisionCvmComposeFileUpdate, safeAction: safeProvisionCvmCompose
2246
2228
  );
2247
2229
  });
2248
2230
 
2249
- // src/actions/commit_cvm_compose_file_update.ts
2231
+ // src/actions/cvms/commit_cvm_compose_file_update.ts
2250
2232
  var import_zod13 = require("zod");
2251
2233
  var CommitCvmComposeFileUpdateRequestSchema = import_zod13.z.object({
2252
2234
  id: import_zod13.z.string().optional(),
@@ -2287,7 +2269,7 @@ var { action: commitCvmComposeFileUpdate, safeAction: safeCommitCvmComposeFileUp
2287
2269
  }
2288
2270
  );
2289
2271
 
2290
- // src/actions/get_app_env_encrypt_pubkey.ts
2272
+ // src/actions/kms/get_app_env_encrypt_pubkey.ts
2291
2273
  var import_zod14 = require("zod");
2292
2274
  var GetAppEnvEncryptPubKeyRequestSchema = import_zod14.z.object({
2293
2275
  kms: import_zod14.z.string().min(1, "KMS ID or slug is required"),
@@ -2305,7 +2287,7 @@ var { action: getAppEnvEncryptPubKey, safeAction: safeGetAppEnvEncryptPubKey } =
2305
2287
  return await client.get(`/kms/${validatedRequest.kms}/pubkey/${validatedRequest.app_id}`);
2306
2288
  });
2307
2289
 
2308
- // src/actions/get_cvm_info.ts
2290
+ // src/actions/cvms/get_cvm_info.ts
2309
2291
  var import_zod15 = require("zod");
2310
2292
  var GetCvmInfoRequestSchema = import_zod15.z.object({
2311
2293
  id: import_zod15.z.string().optional(),
@@ -2330,7 +2312,7 @@ var { action: getCvmInfo, safeAction: safeGetCvmInfo } = defineAction(CvmLegacyD
2330
2312
  return await client.get(`/cvms/${validatedRequest.cvmId}`);
2331
2313
  });
2332
2314
 
2333
- // src/actions/get_cvm_list.ts
2315
+ // src/actions/cvms/get_cvm_list.ts
2334
2316
  var import_zod16 = require("zod");
2335
2317
  var GetCvmListRequestSchema = import_zod16.z.object({
2336
2318
  page: import_zod16.z.number().int().min(1).optional(),
@@ -2349,7 +2331,7 @@ var { action: getCvmList, safeAction: safeGetCvmList } = defineAction(GetCvmList
2349
2331
  return await client.get("/cvms/paginated", { params: validatedRequest });
2350
2332
  });
2351
2333
 
2352
- // src/actions/get_kms_info.ts
2334
+ // src/actions/kms/get_kms_info.ts
2353
2335
  var import_zod17 = require("zod");
2354
2336
  var GetKmsInfoRequestSchema = import_zod17.z.object({
2355
2337
  kms_id: import_zod17.z.string().min(1, "KMS ID is required")
@@ -2359,7 +2341,7 @@ var { action: getKmsInfo, safeAction: safeGetKmsInfo } = defineAction(KmsInfoSch
2359
2341
  return await client.get(`/kms/${validatedRequest.kms_id}`);
2360
2342
  });
2361
2343
 
2362
- // src/actions/get_kms_list.ts
2344
+ // src/actions/kms/get_kms_list.ts
2363
2345
  var import_zod18 = require("zod");
2364
2346
  var GetKmsListRequestSchema = import_zod18.z.object({
2365
2347
  page: import_zod18.z.number().int().min(1).optional(),