Skip to content

Commit

Permalink
feat AuthV1 (#182)
Browse files Browse the repository at this point in the history
* chore: Update example

* chore: Update Example

* feat: V1Auth

* feat: V1Auth generate

* feat: V1Auth createObject Approval

* Create shaggy-experts-approve.md
  • Loading branch information
rrr523 authored Jul 24, 2023
1 parent f67dd05 commit 1b803da
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 23 deletions.
6 changes: 6 additions & 0 deletions .changeset/shaggy-experts-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@demo/wallet": patch
"@bnb-chain/greenfield-chain-sdk": patch
---

feat: Add AuthV1 for SP API (createObject)
65 changes: 56 additions & 9 deletions examples/nextjs/src/components/batch/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import {
PermissionTypes,
} from '@bnb-chain/greenfield-chain-sdk';
import { Wallet } from '@ethersproject/wallet';
import { ChangeEvent } from 'react';
import { FileHandler } from '@bnb-chain/greenfiled-file-handle';
import { useState } from 'react';
import { parseEther } from 'viem';
import { useAccount } from 'wagmi';

export const FeeGrant = () => {
const { address } = useAccount();
const [file, setFile] = useState<File>();
const [bucketName, setBucketName] = useState<string>('');
const [objectName, setObjectName] = useState<string>('');
const [wallet, setWallet] = useState<Wallet | null>(null);
Expand All @@ -36,6 +39,16 @@ export const FeeGrant = () => {
}}
/>
<br />
<input
type="file"
placeholder="select a file"
onChange={(e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
setFile(e.target.files[0]);
}
}}
/>
<br />
<button
onClick={async () => {
if (!address) return;
Expand Down Expand Up @@ -96,25 +109,39 @@ export const FeeGrant = () => {
<br />
<button
onClick={async () => {
if (!address || !wallet) return;
if (!address || !wallet || !file) return;

const granteeAddr = wallet.address;
const privateKey = wallet.privateKey;

const spInfo = await selectSp();
const createFolderTx = await client.object.createFolder({
bucketName,
objectName: objectName + '/',

console.log('spInfo', spInfo);
console.log('temp account', granteeAddr, privateKey);

const fileBytes = await file.arrayBuffer();
const hashResult = await FileHandler.getPieceHashRoots(new Uint8Array(fileBytes));
const { contentLength, expectCheckSums } = hashResult;

const createObjectTx = await client.object.createObject({
bucketName: bucketName,
objectName: objectName,
spInfo,
contentLength,
expectCheckSums,
fileType: file.type,
creator: granteeAddr,
signType: 'authTypeV2',
signType: 'authTypeV1',
privateKey: privateKey,
});

const simulateInfo = await createFolderTx.simulate({
const simulateInfo = await createObjectTx.simulate({
denom: 'BNB',
});

console.log('simulateInfo', simulateInfo);
const txres = await createFolderTx.broadcast({

const res = await createObjectTx.broadcast({
denom: 'BNB',
gasLimit: Number(simulateInfo?.gasLimit),
gasPrice: simulateInfo?.gasPrice || '5000000000',
Expand All @@ -123,11 +150,31 @@ export const FeeGrant = () => {
privateKey,
});

console.log('txres', txres);
if (res.code === 0) {
alert('success');
}

const uploadRes = await client.object.uploadObject({
bucketName: bucketName,
objectName: objectName,
body: file,
txnHash: res.transactionHash,
endpoint: spInfo.endpoint,
signType: 'authTypeV2',
});
console.log('uploadRes', uploadRes);

if (txres.code === 0) {
if (uploadRes.code === 0) {
alert('success');
}
// const txres = await createFolderTx.broadcast({
// denom: 'BNB',
// gasLimit: Number(simulateInfo?.gasLimit),
// gasPrice: simulateInfo?.gasPrice || '5000000000',
// payer: granteeAddr,
// granter: address,
// privateKey,
// });
}}
>
create object
Expand Down
5 changes: 4 additions & 1 deletion examples/nextjs/src/components/object/create/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ export const CreateObject = () => {
expectCheckSums,
fileType: file.type,
creator: address,
signType: 'authTypeV2',
// signType: 'authTypeV2',
signType: 'authTypeV1',
privateKey: '0x6547492644d0136f76ef65e3bd04a77d079ed38028f747700c6c6063564d7032',
});

const simulateInfo = await createObjectTx.simulate({
Expand All @@ -78,6 +80,7 @@ export const CreateObject = () => {
gasPrice: simulateInfo?.gasPrice || '5000000000',
payer: address,
granter: '',
// privateKey: '0x6547492644d0136f76ef65e3bd04a77d079ed38028f747700c6c6063564d7032',
});

const uploadRes = await client.object.uploadObject({
Expand Down
64 changes: 54 additions & 10 deletions packages/chain-sdk/src/api/objectt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ import { MsgCancelCreateObjectSDKTypeEIP712 } from '@/messages/greenfield/storag
import { MsgCreateObjectSDKTypeEIP712 } from '@/messages/greenfield/storage/MsgCreateObject';
import { MsgDeleteObjectSDKTypeEIP712 } from '@/messages/greenfield/storage/MsgDeleteObject';
import { MsgUpdateObjectInfoSDKTypeEIP712 } from '@/messages/greenfield/storage/MsgUpdateObjectInfo';
import { getAuthorizationAuthTypeV2 } from '@/utils/auth';
import { fetchWithTimeout, METHOD_GET, METHOD_PUT, NORMAL_ERROR_CODE } from '@/utils/http';
import { getAuthorizationAuthTypeV1, getAuthorizationAuthTypeV2, ReqMeta } from '@/utils/auth';
import {
EMPTY_STRING_SHA256,
fetchWithTimeout,
METHOD_GET,
METHOD_PUT,
NORMAL_ERROR_CODE,
} from '@/utils/http';
import {
ActionType,
Principal,
Expand All @@ -29,7 +35,9 @@ import {
MsgUpdateObjectInfo,
} from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/tx';
import { bytesFromBase64 } from '@bnb-chain/greenfield-cosmos-types/helpers';
import { bufferToHex } from '@ethereumjs/util';
import { Headers } from 'cross-fetch';
import { utf8ToBytes } from 'ethereum-cryptography/utils';
import { container, delay, inject, singleton } from 'tsyringe';
import {
GRNToString,
Expand All @@ -51,7 +59,11 @@ import {
TPutObject,
TxResponse,
} from '../types';
import { decodeObjectFromHexString, encodeObjectToHexString } from '../utils/encoding';
import {
decodeFromHex,
decodeObjectFromHexString,
encodeObjectToHexString,
} from '../utils/encoding';
import {
generateUrlByBucketName,
isValidBucketName,
Expand Down Expand Up @@ -161,33 +173,65 @@ export class Objectt implements IObject {
throw new Error('empty creator address');
}

// must sort (Go SDK)
const msg: ICreateObjectMsgType = {
bucket_name: bucketName,
// content_type: fileType,
content_type: 'application/octet-stream',
creator: creator,
expect_checksums: expectCheckSums,
object_name: objectName,
content_type: fileType,
payload_size: contentLength.toString(),
bucket_name: bucketName,
visibility,
primary_sp_approval: {
expired_height: '0',
sig: '',
global_virtual_group_family_id: 0,
sig: null,
},
expect_checksums: expectCheckSums,
redundancy_type: redundancyType,
visibility,
};
const url = spInfo.endpoint + '/greenfield/admin/v1/get-approval?action=CreateObject';
const path = '/greenfield/admin/v1/get-approval';
const query = 'action=CreateObject';
const url = `${spInfo.endpoint}${path}?${query}`;

const unSignedMessageInHex = encodeObjectToHexString(msg);

let headerContent: TKeyValue = {
'X-Gnfd-Unsigned-Msg': unSignedMessageInHex,
};

if (!configParam.signType || configParam.signType === 'authTypeV2') {
const Authorization = getAuthorizationAuthTypeV2();
headerContent = {
...headerContent,
Authorization,
};
} else if (configParam.signType === 'authTypeV1') {
// const date = new Date().toISOString();
const reqMeta: Partial<ReqMeta> = {
contentSHA256: EMPTY_STRING_SHA256,
txnMsg: unSignedMessageInHex,
method: METHOD_GET,
url: {
hostname: new URL(spInfo.endpoint).hostname,
query,
path,
},
date: '',
// contentType: fileType,
};

const v1Auth = getAuthorizationAuthTypeV1(reqMeta, configParam.privateKey);

headerContent = {
'X-Gnfd-Unsigned-Msg': unSignedMessageInHex,
// 'Content-Type': fileType,
'Content-Type': 'application/octet-stream',
'X-Gnfd-Content-Sha256': EMPTY_STRING_SHA256,
'X-Gnfd-Date': '',
Authorization: v1Auth,
};
// console.log(x)
} else if (configParam.signType === 'offChainAuth') {
const { seedString, domain } = configParam;
const { code, body, statusCode } = await this.offChainAuthClient.sign(seedString);
Expand Down Expand Up @@ -280,7 +324,7 @@ export class Objectt implements IObject {
redundancyType: redundancyTypeFromJSON(signedMsg.redundancy_type),
primarySpApproval: {
expiredHeight: Long.fromString(signedMsg.primary_sp_approval.expired_height),
sig: bytesFromBase64(signedMsg.primary_sp_approval.sig),
sig: bytesFromBase64(signedMsg.primary_sp_approval.sig || ''),
globalVirtualGroupFamilyId: signedMsg.primary_sp_approval.global_virtual_group_family_id,
},
};
Expand Down
12 changes: 10 additions & 2 deletions packages/chain-sdk/src/types/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,19 @@ export type TCreateObjectByOffChainAuth = TBaseGetCreateObject & {
seedString: string;
};

export type TCreateObjectByAuthTypeV1 = TBaseGetCreateObject & {
signType?: 'authTypeV1';
privateKey: string;
};

export type TCreateObjectByAuthTypeV2 = TBaseGetCreateObject & {
signType?: 'authTypeV2';
};

export type TCreateObject = TCreateObjectByOffChainAuth | TCreateObjectByAuthTypeV2;
export type TCreateObject =
| TCreateObjectByOffChainAuth
| TCreateObjectByAuthTypeV1
| TCreateObjectByAuthTypeV2;

export interface ICreateObjectMsgType {
creator: string;
Expand All @@ -167,7 +175,7 @@ export interface ICreateObjectMsgType {
content_type: string;
primary_sp_approval: {
expired_height: string;
sig: string;
sig: string | null;
global_virtual_group_family_id: number;
};
expect_checksums: string[];
Expand Down
Loading

0 comments on commit 1b803da

Please sign in to comment.