Skip to content

Commit

Permalink
feat: Split approval and simulate
Browse files Browse the repository at this point in the history
  • Loading branch information
rrr523 committed Jun 30, 2023
1 parent 234efdf commit 76defa7
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 88 deletions.
5 changes: 5 additions & 0 deletions .changeset/beige-trainers-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@bnb-chain/greenfield-chain-sdk': patch
---

feat: Split approval and simulate
2 changes: 1 addition & 1 deletion examples/nextjs/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const getSps = async () => {

export const selectSp = async () => {
const finalSps = await getSps();
const selectIndex = 0;
const selectIndex = 1;
const secondarySpAddresses = [
...finalSps.slice(0, selectIndex),
...finalSps.slice(selectIndex + 1),
Expand Down
23 changes: 19 additions & 4 deletions examples/nextjs/src/components/bucket/create/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export const CreateBucket = () => {
if (!address) return;

const spInfo = await selectSp();
const createBucketTx = await client.bucket.createBucket({

const { body: signedMsg } = await client.bucket.getCreateBucketApproval({
bucketName: createBucketInfo.bucketName,
creator: address,
visibility: 'VISIBILITY_TYPE_PUBLIC_READ',
Expand All @@ -37,6 +38,20 @@ export const CreateBucket = () => {
signType: 'authTypeV2',
});

if (!signedMsg) throw new Error('failed to get approval message');

const createBucketTx = await client.bucket.createBucket(
{
bucketName: createBucketInfo.bucketName,
creator: address,
visibility: 'VISIBILITY_TYPE_PUBLIC_READ',
chargedReadQuota: '0',
spInfo,
signType: 'authTypeV2',
},
signedMsg.primary_sp_approval,
);

const simulateInfo = await createBucketTx.simulate({
denom: 'BNB',
});
Expand All @@ -56,10 +71,10 @@ export const CreateBucket = () => {
}
}}
>
broadcast with simulate with authTypeV2
broadcast with simulate
</button>
<br />
<button
{/* <button
onClick={async () => {
if (!address) return;
const domain = window.location.origin;
Expand Down Expand Up @@ -97,7 +112,7 @@ export const CreateBucket = () => {
}}
>
broadcast with simulate with offChainAuth
</button>
</button> */}
</>
);
};
19 changes: 17 additions & 2 deletions examples/nextjs/src/components/object/create/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,32 @@ export const CreateObject = () => {
const hashResult = await FileHandler.getPieceHashRoots(new Uint8Array(fileBytes));
const { contentLength, expectCheckSums } = hashResult;

const createObjectTx = await client.object.createObject({
const { body: signedMsg } = await client.object.getCreateObjectApproval({
bucketName: createObjectInfo.bucketName,
objectName: createObjectInfo.objectName,
spInfo,
contentLength,
expectCheckSums,
fileType: file.type,
creator: address,
signType: 'authTypeV2',
});

if (!signedMsg) throw new Error('failed to get approval message');

const createObjectTx = await client.object.createObject(
{
bucketName: createObjectInfo.bucketName,
objectName: createObjectInfo.objectName,
spInfo,
contentLength,
expectCheckSums,
fileType: file.type,
creator: address,
signType: 'authTypeV2',
},
signedMsg.primary_sp_approval,
);

const simulateInfo = await createObjectTx.simulate({
denom: 'BNB',
});
Expand Down
69 changes: 32 additions & 37 deletions packages/chain-sdk/src/api/bucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/query';
import {
MsgCreateBucket,
MsgCreateBucketSDKType,
MsgDeleteBucket,
MsgDeletePolicy,
MsgPutPolicy,
Expand All @@ -31,6 +32,7 @@ import { Headers } from 'cross-fetch';
import Long from 'long';
import { container, delay, inject, singleton } from 'tsyringe';
import {
getApproval,
GRNToString,
MsgCreateBucketTypeUrl,
MsgDeleteBucketTypeUrl,
Expand All @@ -57,12 +59,17 @@ export interface IBucket {
/**
* returns the signature info for the approval of preCreating resources
*/
getCreateBucketApproval(params: TCreateBucket): Promise<IObjectResultType<string>>;
getCreateBucketApproval(params: TCreateBucket): Promise<IObjectResultType<ICreateBucketMsgType>>;

/**
* get approval of creating bucket and send createBucket txn to greenfield chain
*
* if approval is not supply, it will only simulate the txn
*/
createBucket(params: TCreateBucket): Promise<TxResponse>;
createBucket(
params: TCreateBucket,
approval?: ICreateBucketMsgType['primary_sp_approval'],
): Promise<TxResponse>;

/**
* query the bucketInfo on chain, return the bucket info if exists
Expand Down Expand Up @@ -212,59 +219,47 @@ export class Bucket implements IBucket {
return {
code: 0,
message: 'Get create bucket approval success.',
body: signedMsgString,
body: signedMsg,
statusCode: status,
signedMsg: signedMsg,
};
} catch (error: any) {
return { code: -1, message: error.message, statusCode: NORMAL_ERROR_CODE };
}
}

private async createBucketTx(msg: MsgCreateBucket, signedMsg: ICreateBucketMsgType) {
public async createBucket(
params: TCreateBucket,
approval?: ICreateBucketMsgType['primary_sp_approval'],
) {
const primarySpApproval = approval
? getApproval(approval.expired_height, approval.sig)
: getApproval(`${Number.MAX_VALUE}`, '');

const msg: MsgCreateBucket = {
bucketName: params.bucketName,
creator: params.creator,
visibility: visibilityTypeFromJSON(params.visibility),
primarySpAddress: params.spInfo.primarySpAddress,
primarySpApproval: primarySpApproval,
chargedReadQuota: Long.fromString(params.chargedReadQuota),
paymentAddress: '',
};

return await this.basic.tx(
MsgCreateBucketTypeUrl,
msg.creator,
MsgCreateBucketSDKTypeEIP712,
{
...signedMsg,
...MsgCreateBucket.toSDK(msg),
type: MsgCreateBucketTypeUrl,
charged_read_quota: signedMsg.charged_read_quota,
visibility: signedMsg.visibility,
primary_sp_approval: {
expired_height: signedMsg.primary_sp_approval.expired_height,
sig: signedMsg.primary_sp_approval.sig,
},
charged_read_quota: params.chargedReadQuota,
visibility: params.visibility,
primary_sp_approval: approval,
},
MsgCreateBucket.encode(msg).finish(),
);
}

public async createBucket(params: TCreateBucket) {
const { signedMsg } = await this.getCreateBucketApproval(params);

if (!signedMsg) {
throw new Error('Get create bucket approval error');
}

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),
},
chargedReadQuota: signedMsg.charged_read_quota
? Long.fromString('0')
: Long.fromString(signedMsg.charged_read_quota),
paymentAddress: '',
};

return await this.createBucketTx(msg, signedMsg);
}

public async deleteBucket(msg: MsgDeleteBucket) {
return await this.basic.tx(
MsgDeleteBucketTypeUrl,
Expand Down
118 changes: 76 additions & 42 deletions packages/chain-sdk/src/api/objectt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { bytesFromBase64 } from '@bnb-chain/greenfield-cosmos-types/helpers';
import { Headers } from 'cross-fetch';
import { container, delay, inject, singleton } from 'tsyringe';
import {
getApproval,
GRNToString,
MsgCancelCreateObjectTypeUrl,
MsgCreateObjectTypeUrl,
Expand Down Expand Up @@ -61,9 +62,14 @@ import { RpcQueryClient } from './queryclient';
import { Storage } from './storage';

export interface IObject {
getCreateObjectApproval(getApprovalParams: TCreateObject): Promise<IObjectResultType<string>>;
getCreateObjectApproval(
getApprovalParams: TCreateObject,
): Promise<IObjectResultType<ICreateObjectMsgType>>;

createObject(getApprovalParams: TCreateObject): Promise<TxResponse>;
createObject(
params: TCreateObject,
approval?: ICreateObjectMsgType['primary_sp_approval'],
): Promise<TxResponse>;

uploadObject(configParam: TPutObject): Promise<IObjectResultType<null>>;

Expand Down Expand Up @@ -214,9 +220,8 @@ export class Objectt implements IObject {
return {
code: 0,
message: 'Get create object approval success.',
body: result.headers.get('X-Gnfd-Signed-Msg') ?? '',
body: signedMsg,
statusCode: status,
signedMsg,
};
} catch (error: any) {
throw { code: -1, message: error.message, statusCode: NORMAL_ERROR_CODE };
Expand All @@ -240,28 +245,53 @@ export class Objectt implements IObject {
);
}

public async createObject(getApprovalParams: TCreateObject) {
const { signedMsg } = await this.getCreateObjectApproval(getApprovalParams);
if (!signedMsg) {
throw new Error('Get create object approval error');
}
public async createObject(
params: TCreateObject,
approval?: ICreateObjectMsgType['primary_sp_approval'],
) {
const primarySpApproval = approval
? getApproval(approval.expired_height, approval.sig)
: getApproval(`${Number.MAX_VALUE}`, '');

const {
bucketName,
creator,
objectName,
fileType,
contentLength,
expectCheckSums,
visibility = 'VISIBILITY_TYPE_PUBLIC_READ',
redundancyType = 'REDUNDANCY_EC_TYPE',
} = params;

const msg: MsgCreateObject = {
bucketName: signedMsg.bucket_name,
creator: signedMsg.creator,
objectName: signedMsg.object_name,
contentType: signedMsg.content_type,
payloadSize: Long.fromString(signedMsg.payload_size),
visibility: visibilityTypeFromJSON(signedMsg.visibility),
expectChecksums: signedMsg.expect_checksums.map((e: string) => bytesFromBase64(e)),
expectSecondarySpAddresses: signedMsg.expect_secondary_sp_addresses,
redundancyType: redundancyTypeFromJSON(signedMsg.redundancy_type),
primarySpApproval: {
expiredHeight: Long.fromString(signedMsg.primary_sp_approval.expired_height),
sig: bytesFromBase64(signedMsg.primary_sp_approval.sig),
},
bucketName,
creator,
objectName,
contentType: fileType,
payloadSize: Long.fromString(`${contentLength}`),
visibility: visibilityTypeFromJSON(visibility),
expectChecksums: expectCheckSums.map((e: string) => bytesFromBase64(e)),
expectSecondarySpAddresses: params.spInfo.secondarySpAddresses,
redundancyType: redundancyTypeFromJSON(redundancyType),
primarySpApproval,
};

return await this.createObjectTx(msg, signedMsg);
return await this.basic.tx(
MsgCreateObjectTypeUrl,
msg.creator,
MsgCreateObjectSDKTypeEIP712,
{
...MsgCreateObject.toSDK(msg),
type: MsgCreateObjectTypeUrl,
primary_sp_approval: approval,
expect_checksums: params.expectCheckSums,
payload_size: params.contentLength,
redundancy_type: params.redundancyType,
visibility: params.visibility,
},
MsgCreateObject.encode(msg).finish(),
);
}

public async uploadObject(configParam: TPutObject): Promise<IObjectResultType<null>> {
Expand Down Expand Up @@ -536,9 +566,10 @@ export class Objectt implements IObject {
}

public async createFolder(
getApprovalParams: Omit<TCreateObject, 'contentLength' | 'fileType' | 'expectCheckSums'>,
params: Omit<TCreateObject, 'contentLength' | 'fileType' | 'expectCheckSums'>,
approval?: ICreateObjectMsgType['primary_sp_approval'],
) {
if (!getApprovalParams.objectName.endsWith('/')) {
if (!params.objectName.endsWith('/')) {
throw new Error(
'failed to create folder. Folder names must end with a forward slash (/) character',
);
Expand All @@ -553,23 +584,26 @@ export class Objectt implements IObject {
const { contentLength, expectCheckSums } = hashResult;
*/

return this.createObject({
bucketName: getApprovalParams.bucketName,
objectName: getApprovalParams.objectName,
contentLength: 0,
fileType: 'text/plain',
expectCheckSums: [
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
],
creator: getApprovalParams.creator,
spInfo: getApprovalParams.spInfo,
});
return this.createObject(
{
bucketName: params.bucketName,
objectName: params.objectName,
contentLength: 0,
fileType: 'text/plain',
expectCheckSums: [
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
'47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
],
creator: params.creator,
spInfo: params.spInfo,
},
approval,
);
}

public async putObjectPolicy(
Expand Down
2 changes: 1 addition & 1 deletion packages/chain-sdk/src/types/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export type TCreateBucket = ICreateBucketByOffChainAuth | ICreateBucketByAuthTyp

export interface ISpInfo {
endpoint: string;
primarySpAddress?: string;
primarySpAddress: string;
sealAddress: string;
secondarySpAddresses: string[];
}
Expand Down
Loading

0 comments on commit 76defa7

Please sign in to comment.