diff --git a/.changeset/rich-jars-fix.md b/.changeset/rich-jars-fix.md new file mode 100644 index 00000000..6cf612ed --- /dev/null +++ b/.changeset/rich-jars-fix.md @@ -0,0 +1,5 @@ +--- +"@bnb-chain/greenfield-js-sdk": patch +--- + +feat: MsgSetBucketFlowRateLimit diff --git a/examples/nextjs/README.md b/examples/nextjs/README.md index 7b3ab018..5d034a67 100644 --- a/examples/nextjs/README.md +++ b/examples/nextjs/README.md @@ -36,7 +36,6 @@ NEXT_PUBLIC_BSC_CHAIN_ID=5601 > this is TESTNET's configuration. - Run the demo application: `npm run dev` ## Usage case @@ -46,4 +45,6 @@ Run the demo application: `npm run dev` * [withdraw](./src/components/withdraw/index.tsx) * [bucket](./src/components/bucket/index.tsx) * [object](./src/components/object/index.tsx) + * [create object with tx](./src/components/object/create/withTx.tsx) + * [create object and uploading object by delegrated agent](./src/components/object/create/delegrate.tsx) * [query](./src/components/withdraw/query.tsx) diff --git a/examples/nextjs/src/components/object/create/delegrate.tsx b/examples/nextjs/src/components/object/create/delegrate.tsx new file mode 100644 index 00000000..4c0d5197 --- /dev/null +++ b/examples/nextjs/src/components/object/create/delegrate.tsx @@ -0,0 +1,203 @@ +import { client } from '@/client'; +import { getOffchainAuthKeys } from '@/utils/offchainAuth'; +import { + bytesFromBase64, + Long, + RedundancyType, + VisibilityType, + OnProgressEvent, +} from '@bnb-chain/greenfield-js-sdk'; +import { ReedSolomon } from '@bnb-chain/reed-solomon'; +import { ChangeEvent, useState } from 'react'; +import { useAccount } from 'wagmi'; + +export const DelegrateObject = () => { + const { address, connector } = useAccount(); + const [file, setFile] = useState(); + const [txHash, setTxHash] = useState(); + const [createObjectInfo, setCreateObjectInfo] = useState({ + bucketName: '', + objectName: '', + }); + + return ( +
+ <> +

Create Object and uploading by delegated agent

+ bucket name : + { + setCreateObjectInfo({ ...createObjectInfo, bucketName: e.target.value }); + }} + /> +
+ object name : + { + setCreateObjectInfo({ ...createObjectInfo, objectName: e.target.value }); + }} + /> +
+ ) => { + if (e.target.files) { + setFile(e.target.files[0]); + } + }} + /> +
+ {' '} + +
+ +
+ + +
+ ); +}; diff --git a/examples/nextjs/src/components/object/create/index.tsx b/examples/nextjs/src/components/object/create/index.tsx index f0c3cde0..2deee545 100644 --- a/examples/nextjs/src/components/object/create/index.tsx +++ b/examples/nextjs/src/components/object/create/index.tsx @@ -3,373 +3,24 @@ import { getOffchainAuthKeys } from '@/utils/offchainAuth'; import { bytesFromBase64, Long, + OnProgressEvent, RedundancyType, VisibilityType, } from '@bnb-chain/greenfield-js-sdk'; -import { OnProgressEvent } from '@bnb-chain/greenfield-js-sdk/src/types/common'; import { ReedSolomon } from '@bnb-chain/reed-solomon'; import { ChangeEvent, useState } from 'react'; import { useAccount } from 'wagmi'; +import { CreateObjectWithTx } from './withTx'; +import { DelegrateObject } from './delegrate'; export const CreateObject = () => { - const { address, connector } = useAccount(); - const [file, setFile] = useState(); - const [txHash, setTxHash] = useState(); - const [createObjectInfo, setCreateObjectInfo] = useState({ - bucketName: '', - objectName: '', - }); - return (
- <> -

Create Object

- bucket name : - { - setCreateObjectInfo({ ...createObjectInfo, bucketName: e.target.value }); - }} - /> -
- object name : - { - setCreateObjectInfo({ ...createObjectInfo, objectName: e.target.value }); - }} - /> -
- ) => { - if (e.target.files) { - setFile(e.target.files[0]); - } - }} - /> -
- upload object with tx:{' '} - {' '} - {' '} - -
- or uploaded by delegated agent :{' '} - {' '} - -
- -
- {' '} - - +
); }; diff --git a/examples/nextjs/src/components/object/create/withTx.tsx b/examples/nextjs/src/components/object/create/withTx.tsx new file mode 100644 index 00000000..0377401e --- /dev/null +++ b/examples/nextjs/src/components/object/create/withTx.tsx @@ -0,0 +1,224 @@ +import { client } from '@/client'; +import { getOffchainAuthKeys } from '@/utils/offchainAuth'; +import { + bytesFromBase64, + Long, + OnProgressEvent, + RedundancyType, + VisibilityType, +} from '@bnb-chain/greenfield-js-sdk'; +import { ReedSolomon } from '@bnb-chain/reed-solomon'; +import { ChangeEvent, useState } from 'react'; +import { useAccount } from 'wagmi'; + +export const CreateObjectWithTx = () => { + const { address, connector } = useAccount(); + const [file, setFile] = useState(); + const [txHash, setTxHash] = useState(); + const [createObjectInfo, setCreateObjectInfo] = useState({ + bucketName: '', + objectName: '', + }); + + return ( +
+ <> +

Create Object and Upload with tx

+ bucket name : + { + setCreateObjectInfo({ ...createObjectInfo, bucketName: e.target.value }); + }} + /> +
+ object name : + { + setCreateObjectInfo({ ...createObjectInfo, objectName: e.target.value }); + }} + /> +
+ ) => { + if (e.target.files) { + setFile(e.target.files[0]); + } + }} + /> +
+ {' '} + {' '} + +
+ + +
+ ); +}; diff --git a/examples/nextjs/src/components/walletInfo/index.tsx b/examples/nextjs/src/components/walletInfo/index.tsx index d81d6858..084be5ae 100644 --- a/examples/nextjs/src/components/walletInfo/index.tsx +++ b/examples/nextjs/src/components/walletInfo/index.tsx @@ -6,7 +6,13 @@ export const WalletInfo = () => { return (
- +
); }; diff --git a/examples/nextjs/src/config/index.ts b/examples/nextjs/src/config/index.ts index ca322175..08711644 100644 --- a/examples/nextjs/src/config/index.ts +++ b/examples/nextjs/src/config/index.ts @@ -24,8 +24,8 @@ const greenFieldChain: Chain = { }, }, nativeCurrency: { - name: 'BNB', - symbol: 'BNB', + name: 'tBNB', + symbol: 'tBNB', decimals: 18, }, }; @@ -52,6 +52,9 @@ export const bscChain: Chain = { // testnet: true, }; +console.log('bscChain', bscChain); +console.log('greenFieldChain', greenFieldChain); + const connectors = connectorsForWallets( [ { @@ -66,7 +69,16 @@ const connectors = connectorsForWallets( ); export const wagmiConfig = createConfig({ - chains: [mainnet, bscChain, greenFieldChain], + chains: [ + mainnet, + bscChain, + { + ...greenFieldChain, + network: 'greenfield', + iconUrl: + 'https://github.com/wagmi-dev/wagmi/assets/5653652/44446c8c-5c72-4e89-b8eb-3042ef618eed', + }, + ], transports: { [mainnet.id]: http(), [bscChain.id]: http(), diff --git a/packages/js-sdk/src/api/bucket.ts b/packages/js-sdk/src/api/bucket.ts index 5677321c..02c1db75 100644 --- a/packages/js-sdk/src/api/bucket.ts +++ b/packages/js-sdk/src/api/bucket.ts @@ -1,10 +1,11 @@ import { - MsgToggleSPAsDelegatedAgentSDKTypeEIP712, MsgCreateBucketSDKTypeEIP712, MsgDeleteBucketSDKTypeEIP712, MsgMigrateBucketSDKTypeEIP712, + MsgToggleSPAsDelegatedAgentSDKTypeEIP712, MsgUpdateBucketInfoSDKTypeEIP712, } from '@/messages/greenfield'; +import { MsgSetBucketFlowRateLimitSDKTypeEIP712 } from '@/messages/greenfield/storage/MsgSetBucketFlowRateLimit'; import { assertAuthType, assertStringRequire } from '@/utils/asserts/params'; import { UInt64Value } from '@bnb-chain/greenfield-cosmos-types/greenfield/common/wrapper'; import { @@ -29,6 +30,7 @@ import { MsgDeletePolicy, MsgMigrateBucket, MsgPutPolicy, + MsgSetBucketFlowRateLimit, MsgToggleSPAsDelegatedAgent, MsgUpdateBucketInfo, } from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/tx'; @@ -43,10 +45,11 @@ import { MsgCreateBucketTypeUrl, MsgDeleteBucketTypeUrl, MsgMigrateBucketTypeUrl, + MsgSetBucketFlowRateLimitTypeUrl, MsgToggleSPAsDelegatedAgentTypeUrl, MsgUpdateBucketInfoTypeUrl, - newBucketGRN, TxResponse, + newBucketGRN, } from '..'; import { RpcQueryClient } from '../clients/queryclient'; import { HTTPHeaderUserAddress } from '../clients/spclient/auth'; @@ -187,6 +190,11 @@ export interface IBucket { updateBucketInfo( srcMsg: Omit & { chargedReadQuota?: string }, ): Promise; + + /** + * Get the flow rate limit of the bucket. + */ + setPaymentAccountFlowRateLimit(msg: MsgSetBucketFlowRateLimit): Promise; } @injectable() @@ -201,6 +209,16 @@ export class Bucket implements IBucket { private queryClient = container.resolve(RpcQueryClient); private spClient = container.resolve(SpClient); + public async setPaymentAccountFlowRateLimit(msg: MsgSetBucketFlowRateLimit) { + return await this.txClient.tx( + MsgSetBucketFlowRateLimitTypeUrl, + msg.operator, + MsgSetBucketFlowRateLimitSDKTypeEIP712, + MsgSetBucketFlowRateLimit.toSDK(msg), + MsgSetBucketFlowRateLimit.encode(msg).finish(), + ); + } + public async createBucket(msg: MsgCreateBucket) { assertStringRequire(msg.primarySpAddress, 'Primary sp address is missing'); assertStringRequire(msg.creator, 'Empty creator address'); diff --git a/packages/js-sdk/src/constants/typeUrl.ts b/packages/js-sdk/src/constants/typeUrl.ts index 931f793d..207bf7e9 100644 --- a/packages/js-sdk/src/constants/typeUrl.ts +++ b/packages/js-sdk/src/constants/typeUrl.ts @@ -35,6 +35,7 @@ export const AllowedMsgAllowanceTypeUrl = '/cosmos.feegrant.v1beta1.AllowedMsgAl export const MsgEditValidatorTypeUrl = '/cosmos.staking.v1beta1.MsgEditValidator'; export const MsgCreateValidatorTypeUrl = '/cosmos.staking.v1beta1.MsgCreateValidator'; export const MsgVoteTypeUrl = '/cosmos.gov.v1.MsgVote'; +export const MsgSetBucketFlowRateLimitTypeUrl = '/greenfield.storage.MsgSetBucketFlowRateLimit'; export const MsgSubmitProposalTypeUrl = '/cosmos.gov.v1.MsgSubmitProposal'; export const MsgWithdrawDelegatorRewardTypeUrl = '/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward'; diff --git a/packages/js-sdk/src/messages/greenfield/storage/MsgSetBucketFlowRateLimit.ts b/packages/js-sdk/src/messages/greenfield/storage/MsgSetBucketFlowRateLimit.ts new file mode 100644 index 00000000..9207dd5f --- /dev/null +++ b/packages/js-sdk/src/messages/greenfield/storage/MsgSetBucketFlowRateLimit.ts @@ -0,0 +1,28 @@ +export const MsgSetBucketFlowRateLimitSDKTypeEIP712 = { + Msg1: [ + { + name: 'bucket_name', + type: 'string', + }, + { + name: 'bucket_owner', + type: 'string', + }, + { + name: 'flow_rate_limit', + type: 'string', + }, + { + name: 'operator', + type: 'string', + }, + { + name: 'payment_address', + type: 'string', + }, + { + name: 'type', + type: 'string', + }, + ], +}; diff --git a/packages/js-sdk/tests/storage.spec.ts b/packages/js-sdk/tests/storage.spec.ts index 1c192c9f..796b00bb 100644 --- a/packages/js-sdk/tests/storage.spec.ts +++ b/packages/js-sdk/tests/storage.spec.ts @@ -2,6 +2,7 @@ import { describe, expect, test } from '@jest/globals'; import { bytesFromBase64, Long, RedundancyType, VisibilityType } from '../src'; import { ACCOUNT_ADDRESS, ACCOUNT_PRIVATEKEY } from './env'; import { client, generateString, selectSp } from './utils'; +import { Account } from '../src/api/account'; const BUCKET_NAME = generateString(10); const OBJECT_NAME = generateString(10); @@ -151,4 +152,33 @@ describe('storageTx', () => { expect(res.code).toEqual(0); }, 300000); }); + + describe('payment', () => { + test('setPaymentAccountFlowRateLimit', async () => { + const tx = await client.bucket.setPaymentAccountFlowRateLimit({ + bucketName: 'dfg', + bucketOwner: ACCOUNT_ADDRESS, + operator: ACCOUNT_ADDRESS, + paymentAddress: ACCOUNT_ADDRESS, + flowRateLimit: '1000', + }); + + const simulateInfo = await tx.simulate({ + denom: 'BNB', + }); + + expect(simulateInfo).not.toBeNull(); + + const res = await tx.broadcast({ + denom: 'BNB', + gasLimit: Number(simulateInfo?.gasLimit), + gasPrice: simulateInfo?.gasPrice || '5000000000', + payer: ACCOUNT_ADDRESS, + granter: '', + privateKey: ACCOUNT_PRIVATEKEY, + }); + + expect(res.code).toEqual(0); + }); + }); });