diff --git a/.changeset/heavy-suits-punch.md b/.changeset/heavy-suits-punch.md
new file mode 100644
index 00000000..09bf83e2
--- /dev/null
+++ b/.changeset/heavy-suits-punch.md
@@ -0,0 +1,5 @@
+---
+'@bnb-chain/greenfield-js-sdk': minor
+---
+
+feat: Remove approval when create bucket
diff --git a/examples/nextjs/src/components/bucket/create/index.tsx b/examples/nextjs/src/components/bucket/create/index.tsx
index d85ecb20..53991b89 100644
--- a/examples/nextjs/src/components/bucket/create/index.tsx
+++ b/examples/nextjs/src/components/bucket/create/index.tsx
@@ -1,6 +1,5 @@
 import { client, selectSp } from '@/client';
-import { getOffchainAuthKeys } from '@/utils/offchainAuth';
-import { GRNToString, newBucketGRN } from '@bnb-chain/greenfield-js-sdk';
+import { GRNToString, Long, newBucketGRN, VisibilityType } from '@bnb-chain/greenfield-js-sdk';
 import { useState } from 'react';
 import { useAccount } from 'wagmi';
 
@@ -31,34 +30,14 @@ export const CreateBucket = () => {
           const spInfo = await selectSp();
           console.log('spInfo', spInfo);
 
-          const provider = await connector?.getProvider();
-          const offChainData = await getOffchainAuthKeys(address, provider);
-          // console.log('offChainData', offChainData);
-          if (!offChainData) {
-            alert('No offchain, please create offchain pairs first');
-            return;
-          }
-
-          const createBucketTx = await client.bucket.createBucket(
-            {
-              bucketName: createBucketInfo.bucketName,
-              creator: address,
-              visibility: 'VISIBILITY_TYPE_PUBLIC_READ',
-              chargedReadQuota: '0',
-              spInfo: {
-                primarySpAddress: spInfo.primarySpAddress,
-              },
-              paymentAddress: address,
-            },
-            {
-              // type: 'ECDSA',
-              // privateKey: ACCOUNT_PRIVATEKEY,
-              type: 'EDDSA',
-              domain: window.location.origin,
-              seed: offChainData.seedString,
-              address,
-            },
-          );
+          const createBucketTx = await client.bucket.createBucket({
+            bucketName: createBucketInfo.bucketName,
+            creator: address,
+            visibility: VisibilityType.VISIBILITY_TYPE_PUBLIC_READ,
+            chargedReadQuota: Long.fromString('0'),
+            paymentAddress: address,
+            primarySpAddress: spInfo.primarySpAddress,
+          });
 
           const setTagTx = await client.storage.setTag({
             operator: address,
diff --git a/packages/js-sdk/src/api/bucket.ts b/packages/js-sdk/src/api/bucket.ts
index dba8b0ce..9dd38430 100644
--- a/packages/js-sdk/src/api/bucket.ts
+++ b/packages/js-sdk/src/api/bucket.ts
@@ -24,9 +24,9 @@ import {
   MsgPutPolicy,
   MsgUpdateBucketInfo,
 } from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/tx';
+import { PickVGFStrategy } from '@bnb-chain/greenfield-cosmos-types/greenfield/virtualgroup/common';
 import { bytesFromBase64 } from '@bnb-chain/greenfield-cosmos-types/helpers';
 import { Headers } from 'cross-fetch';
-import { bytesToUtf8, hexToBytes } from 'ethereum-cryptography/utils';
 import Long from 'long';
 import { container, delay, inject, injectable } from 'tsyringe';
 import {
@@ -75,8 +75,6 @@ import { MsgDeleteBucketSDKTypeEIP712 } from '../messages/greenfield/storage/Msg
 import { MsgMigrateBucketSDKTypeEIP712 } from '../messages/greenfield/storage/MsgMigrateBucket';
 import { MsgUpdateBucketInfoSDKTypeEIP712 } from '../messages/greenfield/storage/MsgUpdateBucketInfo';
 import type {
-  CreateBucketApprovalRequest,
-  CreateBucketApprovalResponse,
   GetBucketMetaRequest,
   GetBucketMetaResponse,
   GetUserBucketsRequest,
@@ -97,12 +95,13 @@ import { verifyAddress, verifyBucketName, verifyUrl } from '../utils/asserts/s3'
 import { decodeObjectFromHexString } from '../utils/encoding';
 import { Sp } from './sp';
 import { Storage } from './storage';
+import { VirtualGroup } from './virtualGroup';
 
 export interface IBucket {
   /**
-   * get approval of creating bucket and send createBucket txn to greenfield chain
+   * send createBucket txn to greenfield chain
    */
-  createBucket(params: CreateBucketApprovalRequest, authType: AuthType): Promise<TxResponse>;
+  createBucket(msg: MsgCreateBucket): Promise<TxResponse>;
 
   deleteBucket(msg: MsgDeleteBucket): Promise<TxResponse>;
 
@@ -125,14 +124,6 @@ export interface IBucket {
     authType: AuthType,
   ): Promise<SpResponse<IQuotaProps>>;
 
-  /**
-   * returns the signature info for the approval of preCreating resources
-   */
-  getCreateBucketApproval(
-    configParam: CreateBucketApprovalRequest,
-    authType: AuthType,
-  ): Promise<SpResponse<string>>;
-
   getMigrateBucketApproval(
     params: MigrateBucketApprovalRequest,
     authType: AuthType,
@@ -197,119 +188,56 @@ export class Bucket implements IBucket {
     @inject(delay(() => TxClient)) private txClient: TxClient,
     @inject(delay(() => Sp)) private sp: Sp,
     @inject(delay(() => Storage)) private storage: Storage,
+    @inject(delay(() => VirtualGroup)) private virtualGroup: VirtualGroup,
   ) {}
 
   private queryClient = container.resolve(RpcQueryClient);
   private spClient = container.resolve(SpClient);
 
-  public async getCreateBucketApproval(
-    params: CreateBucketApprovalRequest,
-    authType: AuthType,
-  ): Promise<SpResponse<string>> {
-    const {
-      bucketName,
-      creator,
-      visibility = 'VISIBILITY_TYPE_PUBLIC_READ',
-      chargedReadQuota,
-      spInfo,
-      duration,
-      paymentAddress,
-    } = params;
-
-    try {
-      assertAuthType(authType);
-      assertStringRequire(spInfo.primarySpAddress, 'Primary sp address is missing');
-      assertStringRequire(creator, 'Empty creator address');
-      verifyBucketName(bucketName);
+  public async createBucket(msg: MsgCreateBucket) {
+    assertStringRequire(msg.primarySpAddress, 'Primary sp address is missing');
+    assertStringRequire(msg.creator, 'Empty creator address');
+    verifyBucketName(msg.bucketName);
 
-      const endpoint = await this.sp.getSPUrlByPrimaryAddr(spInfo.primarySpAddress);
-
-      const { reqMeta, optionsWithOutHeaders, url } =
-        getApprovalMetaInfo<CreateBucketApprovalResponse>(endpoint, 'CreateBucket', {
-          bucket_name: bucketName,
-          creator,
-          visibility,
-          primary_sp_address: spInfo.primarySpAddress,
-          primary_sp_approval: {
-            expired_height: '0',
-            sig: '',
-            global_virtual_group_family_id: 0,
-          },
-          charged_read_quota: chargedReadQuota,
-          payment_address: paymentAddress,
-        });
+    const { storageProvider } = await this.sp.getStorageProviderByOperatorAddress({
+      operatorAddress: msg.primarySpAddress,
+    });
 
-      const signHeaders = await this.spClient.signHeaders(reqMeta, authType);
-      const requestOptions: RequestInit = {
-        ...optionsWithOutHeaders,
-        headers: signHeaders,
-      };
+    if (!storageProvider) {
+      throw new Error(`Storage provider ${msg.primarySpAddress} not found`);
+    }
 
-      const result = await this.spClient.callApi(url, requestOptions, duration, {
-        code: -1,
-        message: 'Get create bucket approval error.',
+    const { globalVirtualGroupFamilyId } =
+      await this.virtualGroup.getSpOptimalGlobalVirtualGroupFamily({
+        spId: storageProvider.id,
+        pickVgfStrategy: PickVGFStrategy.Strategy_Maximize_Free_Store_Size,
       });
 
-      const signedMsgString = result.headers.get('X-Gnfd-Signed-Msg') || '';
-
-      return {
-        code: 0,
-        message: 'Get create bucket approval success.',
-        body: signedMsgString,
-        statusCode: result.status,
-      } as SpResponse<string>;
-    } catch (error: any) {
-      throw {
-        code: -1,
-        message: error.message,
-        statusCode: error?.statusCode || NORMAL_ERROR_CODE,
-      };
-    }
-  }
+    const createBucketMsg: MsgCreateBucket = {
+      ...msg,
+      primarySpApproval: {
+        globalVirtualGroupFamilyId: globalVirtualGroupFamilyId,
+        expiredHeight: Long.fromInt(0),
+        sig: Uint8Array.from([]),
+      },
+    };
 
-  private async createBucketTx(msg: MsgCreateBucket, signedMsg: CreateBucketApprovalResponse) {
     return await this.txClient.tx(
       MsgCreateBucketTypeUrl,
       msg.creator,
       MsgCreateBucketSDKTypeEIP712,
       {
-        ...signedMsg,
-        type: MsgCreateBucketTypeUrl,
-        charged_read_quota: signedMsg.charged_read_quota,
-        visibility: signedMsg.visibility,
-        primary_sp_approval: signedMsg.primary_sp_approval,
+        ...MsgCreateBucket.toSDK(createBucketMsg),
+        primary_sp_approval: {
+          expired_height: '0',
+          global_virtual_group_family_id: globalVirtualGroupFamilyId,
+        },
+        charged_read_quota: createBucketMsg.chargedReadQuota.toString(),
       },
-      MsgCreateBucket.encode(msg).finish(),
+      MsgCreateBucket.encode(createBucketMsg).finish(),
     );
   }
 
-  public async createBucket(params: CreateBucketApprovalRequest, authType: AuthType) {
-    assertAuthType(authType);
-    const { body } = await this.getCreateBucketApproval(params, authType);
-
-    if (!body) {
-      throw new Error('Get create bucket approval error');
-    }
-
-    const signedMsg = JSON.parse(bytesToUtf8(hexToBytes(body))) as CreateBucketApprovalResponse;
-
-    const msg: MsgCreateBucket = {
-      bucketName: signedMsg.bucket_name,
-      creator: signedMsg.creator,
-      visibility: visibilityTypeFromJSON(signedMsg.visibility),
-      primarySpAddress: signedMsg.primary_sp_address,
-      primarySpApproval: {
-        expiredHeight: Long.fromString(signedMsg.primary_sp_approval.expired_height),
-        sig: bytesFromBase64(signedMsg.primary_sp_approval.sig),
-        globalVirtualGroupFamilyId: signedMsg.primary_sp_approval.global_virtual_group_family_id,
-      },
-      chargedReadQuota: Long.fromString(signedMsg.charged_read_quota),
-      paymentAddress: signedMsg.payment_address,
-    };
-
-    return await this.createBucketTx(msg, signedMsg);
-  }
-
   public async deleteBucket(msg: MsgDeleteBucket) {
     return await this.txClient.tx(
       MsgDeleteBucketTypeUrl,
diff --git a/packages/js-sdk/src/api/virtualGroup.ts b/packages/js-sdk/src/api/virtualGroup.ts
index 9e5a4081..7c847dc3 100644
--- a/packages/js-sdk/src/api/virtualGroup.ts
+++ b/packages/js-sdk/src/api/virtualGroup.ts
@@ -8,6 +8,10 @@ import {
   QueryGlobalVirtualGroupRequest,
   QueryGlobalVirtualGroupResponse,
   QueryParamsResponse,
+  QuerySPAvailableGlobalVirtualGroupFamiliesRequest,
+  QuerySPAvailableGlobalVirtualGroupFamiliesResponse,
+  QuerySpOptimalGlobalVirtualGroupFamilyRequest,
+  QuerySpOptimalGlobalVirtualGroupFamilyResponse,
 } from '@bnb-chain/greenfield-cosmos-types/greenfield/virtualgroup/query';
 import { MsgSettle } from '@bnb-chain/greenfield-cosmos-types/greenfield/virtualgroup/tx';
 import { container, delay, inject, injectable } from 'tsyringe';
@@ -35,6 +39,14 @@ export interface IVirtualGroup {
     request: QueryGlobalVirtualGroupFamilyRequest,
   ): Promise<QueryGlobalVirtualGroupFamilyResponse>;
 
+  getSpOptimalGlobalVirtualGroupFamily(
+    request: QuerySpOptimalGlobalVirtualGroupFamilyRequest,
+  ): Promise<QuerySpOptimalGlobalVirtualGroupFamilyResponse>;
+
+  getSpAvailableGlobalVirtualGroupFamilies(
+    request: QuerySPAvailableGlobalVirtualGroupFamiliesRequest,
+  ): Promise<QuerySPAvailableGlobalVirtualGroupFamiliesResponse>;
+
   settle(address: string, msg: MsgSettle): Promise<TxResponse>;
 }
 
@@ -68,6 +80,20 @@ export class VirtualGroup implements IVirtualGroup {
     return await rpc.GlobalVirtualGroupFamily(request);
   }
 
+  public async getSpOptimalGlobalVirtualGroupFamily(
+    request: QuerySpOptimalGlobalVirtualGroupFamilyRequest,
+  ) {
+    const rpc = await this.queryClient.getVirtualGroupClient();
+    return await rpc.QuerySpOptimalGlobalVirtualGroupFamily(request);
+  }
+
+  public async getSpAvailableGlobalVirtualGroupFamilies(
+    request: QuerySPAvailableGlobalVirtualGroupFamiliesRequest,
+  ) {
+    const rpc = await this.queryClient.getVirtualGroupClient();
+    return await rpc.QuerySpAvailableGlobalVirtualGroupFamilies(request);
+  }
+
   public async settle(address: string, msg: MsgSettle) {
     return await this.txClient.tx(
       MsgSettleTypeUrl,
diff --git a/packages/js-sdk/src/messages/greenfield/storage/MsgCreateBucket.ts b/packages/js-sdk/src/messages/greenfield/storage/MsgCreateBucket.ts
index c56a2136..86c767bc 100644
--- a/packages/js-sdk/src/messages/greenfield/storage/MsgCreateBucket.ts
+++ b/packages/js-sdk/src/messages/greenfield/storage/MsgCreateBucket.ts
@@ -42,9 +42,9 @@ export const MsgCreateBucketSDKTypeEIP712 = {
       name: 'global_virtual_group_family_id',
       type: 'uint32',
     },
-    {
-      name: 'sig',
-      type: 'bytes',
-    },
+    // {
+    //   name: 'sig',
+    //   type: 'bytes',
+    // },
   ],
 };
diff --git a/packages/js-sdk/src/types/common.ts b/packages/js-sdk/src/types/common.ts
index c206a047..57dcb12b 100644
--- a/packages/js-sdk/src/types/common.ts
+++ b/packages/js-sdk/src/types/common.ts
@@ -1,6 +1,12 @@
-import * as StorageEnums from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/common';
-import * as PermissionTypes from '@bnb-chain/greenfield-cosmos-types/greenfield/permission/common';
-import * as TimestampTypes from '@bnb-chain/greenfield-cosmos-types/google/protobuf/timestamp';
+export * as TimestampTypes from '@bnb-chain/greenfield-cosmos-types/google/protobuf/timestamp';
+export * as PermissionTypes from '@bnb-chain/greenfield-cosmos-types/greenfield/permission/common';
+export * as StorageEnums from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/common';
+export {
+  BucketStatus,
+  ObjectStatus,
+  RedundancyType,
+  SourceType,
+  VisibilityType,
+} from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/common';
+export { Long };
 import Long from 'long';
-
-export { Long, StorageEnums, PermissionTypes, TimestampTypes };
diff --git a/packages/js-sdk/src/types/sp/BucketApproval.ts b/packages/js-sdk/src/types/sp/BucketApproval.ts
deleted file mode 100644
index 1ca043ba..00000000
--- a/packages/js-sdk/src/types/sp/BucketApproval.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { VisibilityType } from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/common';
-
-export type CreateBucketApprovalRequest = {
-  bucketName: string;
-  creator: string;
-  visibility: keyof typeof VisibilityType;
-  chargedReadQuota: string;
-  spInfo: {
-    primarySpAddress: string;
-  };
-  duration?: number;
-  paymentAddress: string;
-};
-
-export interface CreateBucketApprovalResponse {
-  creator: string;
-  bucket_name: string;
-  visibility: keyof typeof VisibilityType;
-  payment_address: string;
-  primary_sp_address: string;
-  primary_sp_approval: {
-    expired_height: string;
-    sig: string;
-    global_virtual_group_family_id: number;
-  };
-  charged_read_quota: string;
-}
diff --git a/packages/js-sdk/src/types/sp/index.ts b/packages/js-sdk/src/types/sp/index.ts
index cea87ef0..cd13cd0d 100644
--- a/packages/js-sdk/src/types/sp/index.ts
+++ b/packages/js-sdk/src/types/sp/index.ts
@@ -1,4 +1,3 @@
-export * from './BucketApproval';
 export * from './ErrorResponse';
 export * from './GetBucketMeta';
 export * from './GetObject';
diff --git a/packages/js-sdk/src/utils/asserts/s3.ts b/packages/js-sdk/src/utils/asserts/s3.ts
index 536c1069..87a6a5d7 100644
--- a/packages/js-sdk/src/utils/asserts/s3.ts
+++ b/packages/js-sdk/src/utils/asserts/s3.ts
@@ -114,9 +114,49 @@ const generateUrlByBucketName = (endpoint = '', bucketName: string) => {
   return endpoint.replace(`${protocol}//`, `${protocol}//${bucketName}.`);
 };
 
+const isSQLInjection = (input: string) => {
+  // Define patterns that may indicate SQL injection, especially those with a semicolon followed by common SQL keywords
+  const patterns = [
+    '(?i).*;.*select', // Matches any string with a semicolon followed by "select"
+    '(?i).*;.*insert', // Matches any string with a semicolon followed by "insert"
+    '(?i).*;.*update', // Matches any string with a semicolon followed by "update"
+    '(?i).*;.*delete', // Matches any string with a semicolon followed by "delete"
+    '(?i).*;.*drop', // Matches any string with a semicolon followed by "drop"
+    '(?i).*;.*alter', // Matches any string with a semicolon followed by "alter"
+    '/\\*.*\\*/', // Matches SQL block comment
+  ];
+
+  for (const pattern of patterns) {
+    const regex = new RegExp(pattern);
+    if (regex.test(input)) {
+      return true;
+    }
+  }
+
+  return false;
+};
+
+// CheckObjectName  This code block checks for unsupported or potentially risky formats in object names.
+// The checks are essential for ensuring the security and compatibility of the object names within the system.
+// 1. ".." in object names: Checked to prevent path traversal attacks which might access directories outside the intended scope.
+// 2. Object name being "/": The root directory should not be used as an object name due to potential security risks and ambiguity.
+// 3. "\\" in object names: Backslashes are checked because they are often not supported in UNIX-like file systems and can cause issues in path parsing.
+// 4. SQL Injection patterns in object names: Ensures that the object name does not contain patterns that could be used for SQL injection attacks, maintaining the integrity of the database.
+const checkObjectName = (objectName: string) => {
+  if (
+    objectName.includes('..') ||
+    objectName === '/' ||
+    objectName.includes('\\') ||
+    isSQLInjection(objectName)
+  ) {
+    throw new Error(`fail to check object name: ${objectName}`);
+  }
+};
+
 export {
   verifyBucketName,
   verifyObjectName,
+  checkObjectName,
   verifyAddress,
   trimString,
   verifyUrl,