From e254e56603fd4b08db07597abd592e974ee1af56 Mon Sep 17 00:00:00 2001 From: rk <59029880+rrr523@users.noreply.github.com> Date: Fri, 3 May 2024 01:40:12 +0800 Subject: [PATCH] Release 2.0.0 (#538) * chore: [ci] release (alpha) (#231) Co-authored-by: github-actions[bot] * Feat/auth (#232) * feat: Compatibility new payment api * feat: Compatibility updateGroupMember api * chore: Update example * feat: Feegrant api add timestamp * feat: EDDSA Sign * feat: Remove log (#234) * chore: [ci] release (alpha) (#233) Co-authored-by: github-actions[bot] * fix: Feegrant add expiration time (#235) * fix: Feegrant add expiration time * chore(example): GetAllowence support pagination * refactor (#236) * refactor: Tx * fix: Type * feat: Add Group API * feat: Update Sp API * feat: Bucket add authType * feat: and add params * fix: Types * feat: Change type * chore: [ci] release (alpha) (#237) Co-authored-by: github-actions[bot] * Fix/read quota (#238) * fix: CreateBucketApproval * feat: ReadQuota * chore(example): Update Example * chore: [ci] release (alpha) (#239) Co-authored-by: github-actions[bot] * XML response (#240) * feat: Return XML type * feat: CreateBucket Add payment address * chore: [ci] release (alpha) (#241) Co-authored-by: github-actions[bot] * fix: XMLParser force array not object (#242) * Feat/export req (#243) * fix: XMLParser force array not object * fix: XMLParser force array not object * chore: [ci] release (alpha) (#244) Co-authored-by: github-actions[bot] * feat: Export types (#245) * Export types (#247) * feat: Export types * fix: Hex number convert to string not big number * chore: [ci] release (alpha) (#246) Co-authored-by: github-actions[bot] * Feat/up and down (#248) * feat: Upload Object add AuthType * feat: Download s3 object * feat: Migrate Bucket add authType * feat: SpClient expose makeHeaders method * chore: Update constant pathj * chore: [ci] release (alpha) (#249) Co-authored-by: github-actions[bot] * Feat/xml null (#250) * feat: Add default XML value * feat: Add default XML value * chore: [ci] release (alpha) (#251) Co-authored-by: github-actions[bot] * Fix/gap time (#252) * fix: Gap time * fix: Gap time * Feat/meta (#254) * feat: GetBucketMeta * feat: Object Meta * Create curly-fishes-bow.md * chore: [ci] release (alpha) (#253) Co-authored-by: github-actions[bot] * Refactor/sp client (#255) * chore: Exact parseError * feat: Remove deps * chore: Structor * feat: Refeactor Sp Client * chore: [ci] release (alpha) (#256) Co-authored-by: github-actions[bot] * feat: Custom HTTP method (#257) * feat: Custom HTTP method * chore(example): Update * chore: [ci] release (alpha) (#258) Co-authored-by: github-actions[bot] * chore(docs): Update README (#259) * chore: Add comment (#260) * fix: Sp types (#261) * Feat/upload progress (#263) * fix: GfSpGetUserBucketsResponse Bucket types * feat: Cross fetch * chore: [ci] release (alpha) (#262) Co-authored-by: github-actions[bot] * fix: EncodePath (#264) * chore: [ci] release (alpha) (#265) Co-authored-by: github-actions[bot] * fix: Download http method (#266) * fix: Download http method (#267) * chore: [ci] release (alpha) (#268) Co-authored-by: github-actions[bot] * feat: New API getObjectPreviewUrl (#270) * chore: [ci] release (alpha) (#271) Co-authored-by: github-actions[bot] * fix: XML type align to go struct (#272) * feat: Optional endpoint param (#273) * chore: [ci] release (alpha) (#274) Co-authored-by: github-actions[bot] * fix: XML parse boolean (#275) * chore: [ci] release (alpha) (#276) Co-authored-by: github-actions[bot] * fix: Common Prefix parse as array (#277) * chore: [ci] release (alpha) (#278) Co-authored-by: github-actions[bot] * test: Parse XML test case (#279) * feat: Migrate bucket (#280) * fix: Create bucket quota params (#282) * chore: [ci] release (alpha) (#281) Co-authored-by: github-actions[bot] * feat: Replace xml2js to fast-xml-parse (#283) * Feat/update bucket info (#284) * feat: Update Bucket Info API * chore(example): Update * chore: [ci] release (alpha) (#285) Co-authored-by: github-actions[bot] * fix: EncodePath function (#286) * fix: Convert enum to number (#287) * chore: [ci] release (alpha) (#288) Co-authored-by: github-actions[bot] * feat: Add listReadRecords api * feat: ListGroups API * feat: ListObjectsByIds API * feat: ListBucketsByIds api * feat: Add verifyPermission api * feat: ListGroupsMembers * feat: ListUserGroups api * feat: Add listUserOwnedGroups api * chore: [ci] release (alpha) * feat: Sort query (#292) * feat: Sort query * Create healthy-chicken-beam.md * chore: [ci] release (alpha) (#293) Co-authored-by: github-actions[bot] * chore(exmaple): Group (#294) * docs: Update API (#295) * chore: Pre Exit (#296) * Pre exit (#297) * chore: Pre Exit * chore: Pre Exit * chore: [ci] release (#298) Co-authored-by: github-actions[bot] * chore: Pre Enter (#299) * Refactor/sp (#302) * feat: Auth expiry timestamp add default value * refactor: Sp types * fix: Expire time * feat: Upgrade TinyGo version * Refactor/sp (#305) * feat: Auth expiry timestamp add default value * refactor: Sp types * fix: Expire time * feat: Upgrade TinyGo version * refactor: Sp metainfo * chore: Update Example * chore: [ci] release (alpha) (#303) Co-authored-by: github-actions[bot] * fix: Build (#306) * chore: Update Deps (#308) * chore: [ci] release (alpha) (#307) Co-authored-by: github-actions[bot] * docs: Update README (#309) * Feat/validator (#310) * feat: EditValidator * feat: Add proposal api * refactor: TxClient * feat: Bucket listBucketsByPaymentAccount api * fix: Proposal and Validator API * feat: ListUserPaymentAccount api * chore: [ci] release (alpha) (#311) Co-authored-by: github-actions[bot] * chore: Nodejs example update * test: Test case update * chore: README update * feat: ListBuckets * fix: QueryClient and TxClient is not singleton * chore: Upgrade types * fix: PutPolicy * feat: ListObjectPolicies api * chore: [ci] release (alpha) * fix: IOC (#314) fix: All class use injectable * chore: [ci] release (alpha) (#315) Co-authored-by: github-actions[bot] * chore: Update exmaple (#316) * feat: Distribution API (#317) * chore: [ci] release (alpha) (#318) Co-authored-by: github-actions[bot] * feat: MsgSettle (#319) * feat: MsgSettle * Create fast-houses-do.md * chore: [ci] release (alpha) (#320) Co-authored-by: github-actions[bot] * chore(example): Update custom tx (#321) * chore: [ci] release (alpha) (#322) Co-authored-by: github-actions[bot] * chore: Github Action issue close (#323) * feat: Bucket headBucketExtra api (#324) * chore: [ci] release (alpha) (#325) Co-authored-by: github-actions[bot] * chore: Nodejs Example update (#326) * chore: Example Update (#327) * Chore/example (#328) * chore: Example Update * chore: Example Update * chore: Update (#329) * feat: Custom Tx (#330) * chore: [ci] release (alpha) (#331) Co-authored-by: github-actions[bot] * fix: Delete Policy (#332) * chore: [ci] release (alpha) (#333) Co-authored-by: github-actions[bot] * Feat/create app (#334) * feat: Template Init * feat: Template Init * feat: Create App Commander * chore: [ci] release (alpha) (#335) Co-authored-by: github-actions[bot] * feat: Create App Commander (#336) * chore: [ci] release (alpha) (#337) Co-authored-by: github-actions[bot] * chore: Update README (#338) * feat: Add vite template (#339) * chore: [ci] release (alpha) (#340) Co-authored-by: github-actions[bot] * release 0.2.5 (#341) chore: Pre Exit * chore: [ci] release (#342) Co-authored-by: github-actions[bot] * chore: Enter pre (#343) * chore(docs): Update README (#344) * Chore/package (#346) * chore: Update package.json * chore: Update package.json * Chore/package js sdk (#347) * chore: Update deps * chore: Update deps * chore: [ci] release (alpha) (#348) Co-authored-by: github-actions[bot] * Chore/update deps (#349) * chore: Update deps * chore: Update deps * Docs site ! (#350) * feat: Docs init * feat: Docs init * chore: Update README * docs: Update Docs * chore: Update deps * chore: Update docs * chore: Update docs * chore: Update * docs: Update * docs: Update * docs: Update * docs: Update Crosschain doc * chore: Update docs * chore: Pre exit (#351) * chore: [ci] release (#352) Co-authored-by: github-actions[bot] * feat: Custom Tx support any type! (#355) * chore: Pre enter (#357) * chore: [ci] release (alpha) (#356) Co-authored-by: github-actions[bot] * fix: Offchain auth ei.data undefined (#358) * fix: Offchain auth ei.data undefined * Create witty-bikes-flash.md --------- Co-authored-by: rrr523 <59029880+rrr523@users.noreply.github.com> * chore: [ci] release (alpha) (#359) Co-authored-by: github-actions[bot] * fix: Offchain auth ei.data undefined (#360) * fix: Offchain auth ei.data undefined * Create ten-maps-travel.md --------- Co-authored-by: rrr523 <59029880+rrr523@users.noreply.github.com> * chore: [ci] release (alpha) (#361) Co-authored-by: github-actions[bot] * chore: Release 1.0.0 (#365) * chore: [ci] release (alpha) (#366) Co-authored-by: github-actions[bot] * chore: Pre exit (#367) * chore: [ci] release (#368) Co-authored-by: github-actions[bot] * chore: Pre enter * fix(types): Payment listUserPaymentAccounts return response (#370) * fix(types): Payment listUserPaymentAccounts return response * fix(types): Payment listUserPaymentAccounts return response * Create chilly-pens-listen.md * chore: [ci] release (alpha) (#371) Co-authored-by: github-actions[bot] * chore: Update doc url (#372) * chore: Pre exit (#377) * chore: [ci] release (#378) Co-authored-by: github-actions[bot] * fix: Replace legacy method (#381) * fix: Replace legacy method * Create cool-shoes-visit.md --------- Co-authored-by: rrr523 <59029880+rrr523@users.noreply.github.com> * chore: Update Deps (#382) * docs: Update README (#384) * chore: [ci] release (#383) Co-authored-by: github-actions[bot] * Feat/new msg tag (#413) * feat: Upgrade types to 0.4.0-alpha-25 * feat: Create Group with tags * feat: SetTag tx * chore(example): Update Group Tag * feat: Create Bucket with tags * chore(example): Create bucket with tags * refactor: Rename Object class name * feat: Create Object with tags * chore(example): Create Object with tags * chore: Enter pre changeset * chore: Minor Changeset * chore: [ci] release (alpha) (#414) Co-authored-by: github-actions[bot] * Chore/update create tags (#415) * chore(example): Nodejs example update new create tx * docs: Update Docs - new create tx * chore: Remove engines filed (#418) * Feat/js reed solomon (#422) * feat: Js implement reed solomon * docs: Update README * docs: Update README * Create beige-beds-lay.md * feat: Empty buffer * chore: Update params * feat: Nodejs support worker * feat: Nodejs support worker * feat: Add types * chore: Update Nodejs example * chore: Update docs and example * chore: [ci] release (alpha) (#419) Co-authored-by: github-actions[bot] * chore: Update example (#423) * feat: Add SP Api types (#424) * chore: [ci] release (alpha) (#425) Co-authored-by: github-actions[bot] * feat: Add bucket meta type (#426) * feat: Add bucket meta type (#427) * chore: [ci] release (alpha) (#428) Co-authored-by: github-actions[bot] * Feat/rs webworker (#429) * chore: Update example, using reed solomon * chore: Update Rollup config * chore: Benchmark * docs: Update README * feat: Support WebWorker * chore: [ci] release (alpha) (#430) Co-authored-by: github-actions[bot] * Feat/rs webworker (#431) * chore: Update example, using reed solomon * chore: Update Rollup config * chore: Benchmark * docs: Update README * feat: Support WebWorker * feat: Add types * chore: Add benchmark * Merge branch 'alpha' into feat/rs_webworker * chore: [ci] release (alpha) (#432) Co-authored-by: github-actions[bot] * chore: Exit pre * chore: [ci] release (#433) Co-authored-by: github-actions[bot] * chore: Enter alpha * Feat/new tag (#461) * Fix/sp tag type (#444) * fix: Sp types * fix: Sp types (cherry picked from commit eb75e4d2716d97249bc9f57f20861368ca73204c) * fix: Tag compatibility (#443) (cherry picked from commit 7a2e9d263648c1032f3422235518eb748d99eeab) * feat: Upgrade cosmos type to 0.4.0 alpha 30 * chore: Update feegranet example * feat: Add SetTag API * chore: [ci] release (alpha) (#462) Co-authored-by: github-actions[bot] * chore: Pnpm install --no-frozen-lockfile * chore: [ci] release (alpha) (#463) Co-authored-by: github-actions[bot] * feat: Sp Api types (#464) * chore: [ci] release (alpha) (#465) Co-authored-by: github-actions[bot] * chore: Pre Exit (#468) * chore: [ci] release (#469) Co-authored-by: github-actions[bot] * chore: Pnpm install --no-frozen-lockfile * simply offchainauth (ED25519) (#489) * feat: Register pub key * feat: Replace zk crypto with ed25519 * chore: Remove file * chore: Remove console * chore: Changeset file * feat: Remove Client wasm url param * chore/ remove file (#490) * feat: Register pub key * feat: Replace zk crypto with ed25519 * chore: Remove file * chore: Remove console * chore: Changeset file * feat: Remove Client wasm url param * chore: Update Example * chore: Remove file * chore: Alpha mode * chore: Merge in alpha (#492) * chore: Merge in alpha * chore: Changeset file * Create heavy-dolphins-obey.md * Update heavy-dolphins-obey.md * chore: [ci] release (alpha) (#493) * chore: [ci] release (alpha) * Update CHANGELOG.md --------- Co-authored-by: github-actions[bot] Co-authored-by: rk <59029880+rrr523@users.noreply.github.com> * chore: Pnpm lockfile * Changeset release/alpha (#494) * chore: [ci] release (alpha) * Update CHANGELOG.md --------- Co-authored-by: github-actions[bot] * docs: Update REAMDE (#495) * Feat/preview api (#496) * feat: Preview Api * feat: Preview Api * chore: [ci] release (alpha) (#497) Co-authored-by: github-actions[bot] * feat: Upgrade types to 31 * feat: Remove Approval when creating bucket * feat: Remove Approval when creating object * chore: [ci] release (alpha) * feat: Delegate upload * feat: Add visibility params * feat: Add toggleSpAsDelegatedAgent API * feat: Resumable Object Upload * chore: [ci] release (alpha) * docs: Example all update * chore: Test case update * chore: Update README * docs(docusaurus): Update API refs * chore: Remove deprecated packages * feat: DelegatedCreateFolder api * chore: [ci] release (alpha) * chore(docs): Update docs * feat: Sp response add offchainstatus and SpAsDelegatedAgentDisabled * feat: Bucket.getBucketReadQuota add monthly field * chore: [ci] release (alpha) * fix: OffChainStatus type * fix: Delegated create folder response return parse error * chore: [ci] release (alpha) (#514) Co-authored-by: github-actions[bot] * Fix/vgf strategy (#520) fix: Change Vgf Strategy * chore: [ci] release (alpha) (#521) Co-authored-by: github-actions[bot] * fix: Fetch timeout * fix: Statement's expirationTime compatibility * chore: [ci] release (alpha) (#527) Co-authored-by: github-actions[bot] * chore: Update Deps * Feat/upload progress (#529) * chore: Install superagent * feat: Support upload progress * feat: Compatibility with Nodejs and Browser * chore: Update example * Create lucky-insects-reply.md * chore: [ci] release (alpha) (#530) Co-authored-by: github-actions[bot] * chore: Upgrade wagmi and rainkit (#532) * chore: Update example (#533) * feat: MsgSetBucketFlowRateLimit (#531) * feat: MsgSetBucketFlowRateLimit * chore: Import package * Create rich-jars-fix.md * chore: Upgrade action node version * Feat: BSC Cross Chain SDK (#522) * chore: Cross BSC and Gnfd init * chore: Install deps * feat: Abi files * feat: Framework * feat: Executor * test: Test case * chore(test): Test framework * feat: Hub Abi files * chore: Hub tests * feat: MultiMessage * feat: MultiMessage module * feat: Exectuor * chore: README * Create five-chefs-lay.md * chore: Assert * feat: Support Local Account and JSONRPC Account * chore(example): Cross Example * docs: Update README * test: Delete policy case * chore: Export enum * feat: Support Callback * chore: Clean deps * chore: [ci] release (alpha) (#534) Co-authored-by: github-actions[bot] * docs: Update docs (#535) * chore: Exit pre * chore: [ci] release (#536) Co-authored-by: github-actions[bot] --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: aiden-cao <104969608+aiden-cao@users.noreply.github.com> --- .github/actions/ci-setup/action.yml | 2 +- README.md | 17 +- doc-site/docs/FAQs/migrate-to-1.3.mdx | 11 + doc-site/docs/api/bucket.mdx | 68 +- doc-site/docs/api/group.mdx | 3 +- doc-site/docs/api/object.mdx | 114 +- doc-site/docs/client/greenfield.mdx | 12 +- doc-site/docs/constants/msg-type-url.mdx | 3 +- doc-site/docs/getting-started/overview.md | 15 +- doc-site/docs/types/long.mdx | 6 + doc-site/package.json | 2 +- examples/browser-file-management/CHANGELOG.md | 85 + examples/browser-file-management/README.md | 8 +- examples/browser-file-management/package.json | 6 +- .../src/client/index.ts | 4 +- .../src/components/demo/index.tsx | 60 +- examples/nextjs/CHANGELOG.md | 128 +- examples/nextjs/README.md | 3 +- examples/nextjs/package.json | 10 +- examples/nextjs/src/client/cross.ts | 16 + examples/nextjs/src/client/index.ts | 4 +- .../src/components/bucket/create/index.tsx | 39 +- .../src/components/bucket/update/index.tsx | 5 + .../nextjs/src/components/cross/index.tsx | 94 + .../nextjs/src/components/deposit/index.tsx | 4 + .../src/components/feegrant/createObj.tsx | 22 +- .../components/object/create/delegrate.tsx | 203 + .../src/components/object/create/index.tsx | 207 +- .../src/components/object/create/withTx.tsx | 224 + .../src/components/object/info/index.tsx | 3 +- .../src/components/walletInfo/index.tsx | 8 +- examples/nextjs/src/config/env.ts | 17 + examples/nextjs/src/config/index.ts | 106 +- examples/nextjs/src/pages/_app.tsx | 48 +- examples/nextjs/src/pages/cross.tsx | 27 + examples/nextjs/src/pages/index.tsx | 6 + examples/nodejs-file-management/CHANGELOG.md | 92 + examples/nodejs-file-management/README.md | 6 + examples/nodejs-file-management/package.json | 6 +- examples/nodejs-file-management/storage.js | 75 +- examples/nodejs/cases/storage.js | 98 +- packages/bsc-cross-sdk/CHANGELOG.md | 17 + packages/bsc-cross-sdk/README.md | 163 + .../bsc-cross-sdk/config/tsconfig-cjs.json | 10 + .../bsc-cross-sdk/config/tsconfig-esm.json | 9 + .../bsc-cross-sdk/config/tsconfig-test.json | 10 + packages/bsc-cross-sdk/config/tsconfig.json | 38 + .../jest.config.mjs | 1 + packages/bsc-cross-sdk/package.json | 81 + packages/bsc-cross-sdk/rollup.config.js | 72 + .../bsc-cross-sdk/src/abi/BucketHub.abi.ts | 1851 + .../bsc-cross-sdk/src/abi/CrossChain.abi.ts | 6 + .../bsc-cross-sdk/src/abi/Executor.abi.ts | 4 + .../bsc-cross-sdk/src/abi/GroupHub.abi.ts | 2132 ++ .../bsc-cross-sdk/src/abi/MultiMessage.abi.ts | 4 + .../bsc-cross-sdk/src/abi/ObjectHub.abi.ts | 1444 + .../src/abi/PermissionHub.abi.ts | 1478 + .../bsc-cross-sdk/src/abi/TokenHub.abi.ts | 4 + packages/bsc-cross-sdk/src/account/index.ts | 37 + packages/bsc-cross-sdk/src/asserts.ts | 29 + .../bsc-cross-sdk/src/client/basic/client.ts | 26 + .../bsc-cross-sdk/src/client/basic/index.ts | 1 + .../src/client/cross-chain/client.ts | 42 + .../src/client/cross-chain/index.ts | 1 + .../src/client/executor/client.ts | 45 + .../src/client/executor/index.ts | 2 + .../src/client/executor/message.ts | 88 + .../src/client/multi-message/client.ts | 293 + .../src/client/multi-message/index.ts | 1 + packages/bsc-cross-sdk/src/index.ts | 6 + packages/bsc-cross-sdk/src/types/index.ts | 114 + packages/bsc-cross-sdk/src/utils.ts | 40 + packages/bsc-cross-sdk/tests/.env.simple | 9 + packages/bsc-cross-sdk/tests/cross.spec.ts | 37 + packages/bsc-cross-sdk/tests/env.ts | 14 + packages/bsc-cross-sdk/tests/executor.spec.ts | 101 + .../bsc-cross-sdk/tests/multiMessage.spec.ts | 397 + packages/bsc-cross-sdk/tests/utils.ts | 11 + packages/file-handle/CHANGELOG.md | 129 - packages/file-handle/README.md | 46 - packages/file-handle/package.json | 70 - packages/file-handle/src/browser/index.js | 32 - packages/file-handle/src/browser/init.js | 47 - packages/file-handle/src/browser/wasm_exec.js | 608 - .../file-handle/src/browser/worker/index.js | 291 - .../src/browser/worker/wasm_exec-worker.js | 634 - packages/file-handle/src/constants.js | 3 - packages/file-handle/src/go-wasm/README.md | 7 - packages/file-handle/src/go-wasm/go.mod | 15 - packages/file-handle/src/go-wasm/go.sum | 41 - packages/file-handle/src/go-wasm/main.go | 64 - packages/file-handle/src/node/index.js | 33 - packages/file-handle/src/node/init.js | 32 - packages/file-handle/src/node/wasm_exec.js | 608 - packages/file-handle/src/utils.js | 42 - .../src/wasm/file-handle-worker.wasm | Bin 3122432 -> 0 bytes .../file-handle/src/wasm/file-handle.wasm | Bin 474223 -> 0 bytes packages/file-handle/types/expose.d.ts | 20 - packages/file-handle/types/index.d.ts | 3 - packages/file-handle/webpack.config.js | 166 - packages/js-sdk/CHANGELOG.md | 200 +- packages/js-sdk/README.md | 12 +- packages/js-sdk/package.json | 12 +- packages/js-sdk/rollup.config.js | 2 +- packages/js-sdk/src/api/bucket.ts | 191 +- packages/js-sdk/src/api/objects.ts | 690 +- packages/js-sdk/src/api/offchainauth.ts | 62 +- packages/js-sdk/src/api/virtualGroup.ts | 26 + packages/js-sdk/src/client.ts | 13 +- packages/js-sdk/src/clients/spclient/auth.ts | 18 +- packages/js-sdk/src/clients/spclient/sign.ts | 62 - .../spclient/spApis/delegatedCreateFolder.ts | 63 + .../spclient/spApis/getObjectOffset.ts | 56 + .../spclient/spApis/getObjectStatus.ts | 55 + .../src/clients/spclient/spApis/putObject.ts | 34 +- .../spclient/spApis/resumablePutObject.ts | 62 + .../spclient/spApis/updateUserAccountKey.ts | 4 +- .../js-sdk/src/clients/spclient/spClient.ts | 141 +- packages/js-sdk/src/constants/index.ts | 3 + packages/js-sdk/src/constants/typeUrl.ts | 2 + .../js-sdk/src/messages/greenfield/index.ts | 3 + .../greenfield/storage/MsgCreateBucket.ts | 8 +- .../greenfield/storage/MsgCreateObject.ts | 8 +- .../storage/MsgSetBucketFlowRateLimit.ts | 28 + .../storage/MsgToggleSPAsDelegatedAgent.ts | 16 + packages/js-sdk/src/node/adapter.ts | 21 + packages/js-sdk/src/offchainauth/index.ts | 1 - packages/js-sdk/src/offchainauth/utils.ts | 15 +- packages/js-sdk/src/types/common.ts | 22 +- .../js-sdk/src/types/sp/BucketApproval.ts | 27 - packages/js-sdk/src/types/sp/Common.ts | 122 +- .../src/types/sp/DelegateCreateFolder.ts | 15 + .../js-sdk/src/types/sp/DelegatedPubObject.ts | 14 + .../js-sdk/src/types/sp/ObjectApproval.ts | 35 - packages/js-sdk/src/types/sp/PutObject.ts | 14 +- packages/js-sdk/src/types/sp/ReadQuota.ts | 4 + packages/js-sdk/src/types/sp/UploadOffset.ts | 5 + .../js-sdk/src/types/sp/UploadProgress.ts | 6 + packages/js-sdk/src/types/sp/index.ts | 6 +- packages/js-sdk/src/types/storage.ts | 13 +- packages/js-sdk/src/utils/asserts/params.ts | 14 + packages/js-sdk/src/utils/asserts/s3.ts | 40 + packages/js-sdk/tests/storage.spec.ts | 95 +- packages/js-sdk/tests/upload.spec.ts | 48 + packages/zk-crypto/CHANGELOG.md | 125 - packages/zk-crypto/README.md | 50 - packages/zk-crypto/package.json | 56 - packages/zk-crypto/src/browser/index.js | 29 - packages/zk-crypto/src/browser/init.js | 47 - packages/zk-crypto/src/browser/wasm_exec.js | 600 - packages/zk-crypto/src/node/index.js | 33 - packages/zk-crypto/src/node/init.js | 32 - packages/zk-crypto/src/node/wasm_exec.js | 600 - packages/zk-crypto/src/wasm/zk-crypto.wasm | Bin 478559 -> 0 bytes packages/zk-crypto/types/expose.d.ts | 3 - packages/zk-crypto/types/index.d.ts | 3 - packages/zk-crypto/webpack.config.js | 141 - pnpm-lock.yaml | 29106 +++++++--------- 158 files changed, 24572 insertions(+), 21917 deletions(-) create mode 100644 doc-site/docs/FAQs/migrate-to-1.3.mdx create mode 100644 doc-site/docs/types/long.mdx create mode 100644 examples/browser-file-management/CHANGELOG.md create mode 100644 examples/nextjs/src/client/cross.ts create mode 100644 examples/nextjs/src/components/cross/index.tsx create mode 100644 examples/nextjs/src/components/object/create/delegrate.tsx create mode 100644 examples/nextjs/src/components/object/create/withTx.tsx create mode 100644 examples/nextjs/src/pages/cross.tsx create mode 100644 packages/bsc-cross-sdk/CHANGELOG.md create mode 100644 packages/bsc-cross-sdk/README.md create mode 100644 packages/bsc-cross-sdk/config/tsconfig-cjs.json create mode 100644 packages/bsc-cross-sdk/config/tsconfig-esm.json create mode 100644 packages/bsc-cross-sdk/config/tsconfig-test.json create mode 100644 packages/bsc-cross-sdk/config/tsconfig.json rename packages/{file-handle => bsc-cross-sdk}/jest.config.mjs (93%) create mode 100644 packages/bsc-cross-sdk/package.json create mode 100644 packages/bsc-cross-sdk/rollup.config.js create mode 100644 packages/bsc-cross-sdk/src/abi/BucketHub.abi.ts create mode 100644 packages/bsc-cross-sdk/src/abi/CrossChain.abi.ts create mode 100644 packages/bsc-cross-sdk/src/abi/Executor.abi.ts create mode 100644 packages/bsc-cross-sdk/src/abi/GroupHub.abi.ts create mode 100644 packages/bsc-cross-sdk/src/abi/MultiMessage.abi.ts create mode 100644 packages/bsc-cross-sdk/src/abi/ObjectHub.abi.ts create mode 100644 packages/bsc-cross-sdk/src/abi/PermissionHub.abi.ts create mode 100644 packages/bsc-cross-sdk/src/abi/TokenHub.abi.ts create mode 100644 packages/bsc-cross-sdk/src/account/index.ts create mode 100644 packages/bsc-cross-sdk/src/asserts.ts create mode 100644 packages/bsc-cross-sdk/src/client/basic/client.ts create mode 100644 packages/bsc-cross-sdk/src/client/basic/index.ts create mode 100644 packages/bsc-cross-sdk/src/client/cross-chain/client.ts create mode 100644 packages/bsc-cross-sdk/src/client/cross-chain/index.ts create mode 100644 packages/bsc-cross-sdk/src/client/executor/client.ts create mode 100644 packages/bsc-cross-sdk/src/client/executor/index.ts create mode 100644 packages/bsc-cross-sdk/src/client/executor/message.ts create mode 100644 packages/bsc-cross-sdk/src/client/multi-message/client.ts create mode 100644 packages/bsc-cross-sdk/src/client/multi-message/index.ts create mode 100644 packages/bsc-cross-sdk/src/index.ts create mode 100644 packages/bsc-cross-sdk/src/types/index.ts create mode 100644 packages/bsc-cross-sdk/src/utils.ts create mode 100644 packages/bsc-cross-sdk/tests/.env.simple create mode 100644 packages/bsc-cross-sdk/tests/cross.spec.ts create mode 100644 packages/bsc-cross-sdk/tests/env.ts create mode 100644 packages/bsc-cross-sdk/tests/executor.spec.ts create mode 100644 packages/bsc-cross-sdk/tests/multiMessage.spec.ts create mode 100644 packages/bsc-cross-sdk/tests/utils.ts delete mode 100644 packages/file-handle/CHANGELOG.md delete mode 100644 packages/file-handle/README.md delete mode 100644 packages/file-handle/package.json delete mode 100644 packages/file-handle/src/browser/index.js delete mode 100644 packages/file-handle/src/browser/init.js delete mode 100644 packages/file-handle/src/browser/wasm_exec.js delete mode 100644 packages/file-handle/src/browser/worker/index.js delete mode 100644 packages/file-handle/src/browser/worker/wasm_exec-worker.js delete mode 100644 packages/file-handle/src/constants.js delete mode 100644 packages/file-handle/src/go-wasm/README.md delete mode 100644 packages/file-handle/src/go-wasm/go.mod delete mode 100644 packages/file-handle/src/go-wasm/go.sum delete mode 100644 packages/file-handle/src/go-wasm/main.go delete mode 100644 packages/file-handle/src/node/index.js delete mode 100644 packages/file-handle/src/node/init.js delete mode 100644 packages/file-handle/src/node/wasm_exec.js delete mode 100644 packages/file-handle/src/utils.js delete mode 100755 packages/file-handle/src/wasm/file-handle-worker.wasm delete mode 100644 packages/file-handle/src/wasm/file-handle.wasm delete mode 100644 packages/file-handle/types/expose.d.ts delete mode 100644 packages/file-handle/types/index.d.ts delete mode 100644 packages/file-handle/webpack.config.js delete mode 100644 packages/js-sdk/src/clients/spclient/sign.ts create mode 100644 packages/js-sdk/src/clients/spclient/spApis/delegatedCreateFolder.ts create mode 100644 packages/js-sdk/src/clients/spclient/spApis/getObjectOffset.ts create mode 100644 packages/js-sdk/src/clients/spclient/spApis/getObjectStatus.ts create mode 100644 packages/js-sdk/src/clients/spclient/spApis/resumablePutObject.ts create mode 100644 packages/js-sdk/src/messages/greenfield/storage/MsgSetBucketFlowRateLimit.ts create mode 100644 packages/js-sdk/src/messages/greenfield/storage/MsgToggleSPAsDelegatedAgent.ts create mode 100644 packages/js-sdk/src/node/adapter.ts delete mode 100644 packages/js-sdk/src/types/sp/BucketApproval.ts create mode 100644 packages/js-sdk/src/types/sp/DelegateCreateFolder.ts create mode 100644 packages/js-sdk/src/types/sp/DelegatedPubObject.ts delete mode 100644 packages/js-sdk/src/types/sp/ObjectApproval.ts create mode 100644 packages/js-sdk/src/types/sp/UploadOffset.ts create mode 100644 packages/js-sdk/src/types/sp/UploadProgress.ts create mode 100644 packages/js-sdk/tests/upload.spec.ts delete mode 100644 packages/zk-crypto/CHANGELOG.md delete mode 100644 packages/zk-crypto/README.md delete mode 100644 packages/zk-crypto/package.json delete mode 100644 packages/zk-crypto/src/browser/index.js delete mode 100644 packages/zk-crypto/src/browser/init.js delete mode 100644 packages/zk-crypto/src/browser/wasm_exec.js delete mode 100644 packages/zk-crypto/src/node/index.js delete mode 100644 packages/zk-crypto/src/node/init.js delete mode 100644 packages/zk-crypto/src/node/wasm_exec.js delete mode 100755 packages/zk-crypto/src/wasm/zk-crypto.wasm delete mode 100644 packages/zk-crypto/types/expose.d.ts delete mode 100644 packages/zk-crypto/types/index.d.ts delete mode 100644 packages/zk-crypto/webpack.config.js diff --git a/.github/actions/ci-setup/action.yml b/.github/actions/ci-setup/action.yml index 7f217a8f..ae9a53e5 100644 --- a/.github/actions/ci-setup/action.yml +++ b/.github/actions/ci-setup/action.yml @@ -5,7 +5,7 @@ runs: steps: - uses: actions/setup-node@v4 with: - node-version: '18.17.0' + node-version: '18.20.2' - uses: pnpm/action-setup@v2 name: Install pnpm id: pnpm-install diff --git a/README.md b/README.md index 16319f3c..05581308 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,24 @@ A Greenfield JS SDK is an easy-to-use tool designed to help developers build dec You can find some package documentation below: -| Package | Description | Version | +| Package | Description | Version | | --- | --- | --- | | [@bnb-chain/greenfield-js-sdk](./packages/js-sdk/README.md) | A client library for Greenfield Chain | [![npm](https://img.shields.io/npm/v/%40bnb-chain%2Fgreenfield-js-sdk?color=blue)](https://www.npmjs.com/package/@bnb-chain/greenfield-js-sdk) | | [@bnb-chain/reed-solomon](./packages/reed-solomon/README.md) | calculate file's `checksums` | [![npm](https://img.shields.io/npm/v/%40bnb-chain%2Freed-solomon?color=blue)](https://www.npmjs.com/package/@bnb-chain/reed-solomon) | -| [@bnb-chain/greenfield-zk-crypto](./packages/zk-crypto/README.md) | WASM module about sign crypto | [![npm](https://img.shields.io/npm/v/%40bnb-chain%2Fgreenfield-zk-crypto?color=blue)](https://www.npmjs.com/package/@bnb-chain/greenfield-zk-crypto) | | [@bnb-chain/create-gnfd-app](./packages/create-gnfd-app/README.md) | Create Greenfield App Quickly | [![npm](https://img.shields.io/npm/v/%40bnb-chain%2Fcreate-gnfd-app?color=blue)](https://www.npmjs.com/package/@bnb-chain/create-gnfd-app) | +| [@bnb-chain/bsc-cross-greenfield-sdk](./packages/bsc-cross-sdk/README.md) | Execute tx in BSC | [![npm](https://img.shields.io/npm/v/%40bnb-chain%2Fbsc-cross-greenfield-sdk?color=blue)](https://www.npmjs.com/package/@bnb-chain/bsc-cross-greenfield-sdk) | + +## Playground + +* [Browser](https://codesandbox.io/p/github/rrr523/greenfield-nextjs-template/main?import=true) + + ## Online Examples -* [Nextjs](https://codesandbox.io/p/github/rrr523/greenfield-nextjs-template/main) -* [Create React App](https://codesandbox.io/p/github/rrr523/greenfield-cra-template/main) +* [Nextjs](https://codesandbox.io/p/github/rrr523/greenfield-nextjs-template/main?import=true) * [Vite](https://codesandbox.io/p/github/rrr523/greenfield-vite-template/main) +* [Create React App](https://codesandbox.io/p/github/rrr523/greenfield-cra-template/main?import=true) ## Quick Start @@ -27,7 +33,7 @@ You can use [`create-gnfd-app`](./packages/create-gnfd-app/README.md) to create > npx @bnb-chain/create-gnfd-app ``` -![](./packages/create-gnfd-app/example.gif) +![quick start example](./packages/create-gnfd-app/example.gif) ## Supported JS environments @@ -44,6 +50,7 @@ You can use [`create-gnfd-app`](./packages/create-gnfd-app/README.md) to create ``` 2. Build packages: + ```bash > pnpm -F "@bnb-chain/**" build ``` diff --git a/doc-site/docs/FAQs/migrate-to-1.3.mdx b/doc-site/docs/FAQs/migrate-to-1.3.mdx new file mode 100644 index 00000000..1f3e4ac4 --- /dev/null +++ b/doc-site/docs/FAQs/migrate-to-1.3.mdx @@ -0,0 +1,11 @@ +--- +id: migrate +title: migrate to 2 +order: 1 +--- + +1. Remove `zkCryptoUrl` params when `Client` initializing. [PR: simply offchainauth (ED25519)](https://github.com/bnb-chain/greenfield-js-sdk/pull/489) + +2. `bucket.createBucket` and `object.createObject` 's params changes. [PR: remove approval when create bucket / object](https://github.com/bnb-chain/greenfield-js-sdk/pull/498) + +3. `object.uploadObject` 's params changes. [PR: upload object](https://github.com/bnb-chain/greenfield-js-sdk/pull/500) diff --git a/doc-site/docs/api/bucket.mdx b/doc-site/docs/api/bucket.mdx index 883437b2..dc894397 100644 --- a/doc-site/docs/api/bucket.mdx +++ b/doc-site/docs/api/bucket.mdx @@ -18,69 +18,23 @@ for creating bucket and sends the createBucket transaction to the Greenfield. | bucketName | bucket name | | creator | creator account address | | visibility | [VisibilityType](/types/visibility) | -| chargedReadQuota | defines the traffic quota that you read from primary sp | -| spInfo | primary sp address | +| chargedReadQuota | [Long](/types/long)defines the traffic quota that you read from primary sp | +| primarySpAddress | primary sp address | | paymentAddress | payment address | -| tags | defines a list of tags which will be set to the bucket | -| authType | [AuthType](/client/sp-client#authtype) | - - - - -```jsx +```js const tx = await client.bucket.createBucket( { bucketName: 'bucket_name', - creator: address, - visibility: 'VISIBILITY_TYPE_PUBLIC_READ', - chargedReadQuota: '0', - spInfo: { - primarySpAddress: 'primary_sp_address', - }, + creator: '0x...', + visibility: VisibilityType.VISIBILITY_TYPE_PUBLIC_READ, + chargedReadQuota: Long.fromString('0'), + primarySpAddress: '0x....', paymentAddress: address, - tags: { - tags: [], - }, - }, - // highlight-start - { - type: 'EDDSA', - domain: window.location.origin, - seed: offChainData.seedString, - address, - }, - // highlight-end -); -``` - - - - -```js -const createBucketTx = await client.bucket.createBucket( - { - bucketName: bucketName, - creator: ACCOUNT_ADDRESS, - visibility: 'VISIBILITY_TYPE_PUBLIC_READ', - chargedReadQuota: '0', - spInfo: { - primarySpAddress: spInfo.primarySpAddress, - }, - paymentAddress: ACCOUNT_ADDRESS, - }, - // highlight-start - { - type: 'ECDSA', - privateKey: ACCOUNT_PRIVATEKEY, - }, - // highlight-end + } ); ``` - - - ## deleteBucket Send DeleteBucket msg to greenfield chain and return txn hash. @@ -90,7 +44,7 @@ Send DeleteBucket msg to greenfield chain and return txn hash. | bucketName | The name of the bucket to be deleted | | operator | operator account address | -```jsx title="Browser | Nodejs" +```js const tx = await client.bucket.deleteBucket({ bucketName: bucketName, operator: address, @@ -110,7 +64,7 @@ Delete the bucket policy of the principal. | principalAddr | Principal define the roles that can grant permissions | | principalType | PrincipalType refers to the identity type of system users or entities. | -```jsx title="Browser | Nodejs" +```js const tx = await client.bucket.deleteBucketPolicy( address, bucketName, @@ -129,7 +83,7 @@ This API is used to get bucket meta by bucket name. | ---------- | ----------- | | bucketName | bucket name | -```jsx title="Browser | Nodejs" +```js const bucketInfo = await client.bucket.getBucketMeta({ bucketName: 'bucketName', }); diff --git a/doc-site/docs/api/group.mdx b/doc-site/docs/api/group.mdx index 55861562..9119f784 100644 --- a/doc-site/docs/api/group.mdx +++ b/doc-site/docs/api/group.mdx @@ -225,7 +225,8 @@ await client.group.updateGroupExtra({ -## updateGroupMember +## updateGroupMember + Update a group by adding or removing members. The sender can be the group owner or any individual account(Principle) that has been granted permission by the group owner. diff --git a/doc-site/docs/api/object.mdx b/doc-site/docs/api/object.mdx index 8c786d8f..d2677a7f 100644 --- a/doc-site/docs/api/object.mdx +++ b/doc-site/docs/api/object.mdx @@ -18,7 +18,6 @@ Send `CancelCreateObject` txn to greenfield chain. | bucketName | the name of the bucket | | objectName | the name of the object | - ## createFolder @@ -27,13 +26,11 @@ Send create empty object txn to greenfield chain. | params | description | | ---------- | -------------------------------------- | | bucketName | bucket name | -| objectName | object name | +| objectName | folder name, end with `/` | | creator | the creator of object | -| tags | defines a list of tags which will be set to the object | -| authType | [AuthType](/client/sp-client#authtype) | +| visibility | [VisibilityType](/types/visibility) | +| redundancyType | [RedundancyType](/types/redundancy) | - - ```jsx const tx = await client.object.createFolder( @@ -41,48 +38,19 @@ const tx = await client.object.createFolder( bucketName: createObjectInfo.bucketName, objectName: createObjectInfo.objectName + '/', creator: address, - tags: { - tags: [], - }, - }, - // highlight-start - { - type: 'EDDSA', - domain: window.location.origin, - seed: offChainData.seedString, - address, - }, - // highlight-end + redundancyType: RedundancyType.REDUNDANCY_EC_TYPE, + visibility: VisibilityType.VISIBILITY_TYPE_PRIVATE, + } ); ``` - - - -```js -const tx = await client.object.createFolder( - { - bucketName: bucketName, - objectName: objectName + '/', - creator: ACCOUNT_ADDRESS, - }, - // highlight-start - { - type: 'ECDSA', - privateKey: ACCOUNT_PRIVATEKEY, - }, - // highlight-end -); -``` - - - - -## createObject +## createObject + + -Get approval of creating object and send createObject txn to greenfield chain. +Creating object and send createObject txn to greenfield chain. | params | description | | --------------- | ----------------------------------------------------------------------- | @@ -90,69 +58,25 @@ Get approval of creating object and send createObject txn to greenfield chain. | objectName | object name | | creator | the creator of object | | visibility | [VisibilityType](/types/visibility) | -| fileType | [file type](https://developer.mozilla.org/en-US/docs/Web/API/File/type) | +| contentType | [file type](https://developer.mozilla.org/en-US/docs/Web/API/File/type) | | redundancyType | [RedundancyType](/types/redundancy) | -| authType | [AuthType](/client/sp-client#authtype) | -| contentLength | file content length | -| expectCheckSums | file's expectCheckSums | -| tags | defines a list of tags which will be set to the object | - - - +| payloadSize | file content [Long](/types/long)length | +| expectChecksums | file's expectChecksums | ```jsx -// https://github.com/bnb-chain/greenfield-js-sdk/blob/main/examples/nextjs/src/components/object/create/index.tsx#L76-L95 const tx = await client.object.createObject( { bucketName: 'bucket_name', objectName: 'object_name', creator: '0x...', - visibility: 'VISIBILITY_TYPE_PRIVATE', - fileType: 'json', - redundancyType: 'REDUNDANCY_EC_TYPE', - contentLength: 13311, - expectCheckSums: JSON.parse(expectCheckSums), - tags: { - tags: [], - }, - }, - // highlight-start - { - type: 'EDDSA', - domain: window.location.origin, - seed: offChainData.seedString, - address, - }, - // highlight-end + visibility: VisibilityType.VISIBILITY_TYPE_PRIVATE, + contentType: 'json', + redundancyType: RedundancyType.REDUNDANCY_EC_TYPE, + payloadSize: Long.fromInt(13311), + expectCheckSums: expectCheckSums.map((x) => bytesFromBase64(x)), + } ); ``` - - - -```js -// https://github.com/bnb-chain/greenfield-js-sdk/blob/main/examples/nodejs/cases/storage.js#L61-L76 -const tx = await client.object.createObject( - { - bucketName: bucketName, - objectName: objectName, - creator: ACCOUNT_ADDRESS, - visibility: 'VISIBILITY_TYPE_PRIVATE', - fileType: fileType, - redundancyType: 'REDUNDANCY_EC_TYPE', - contentLength, - expectCheckSums: JSON.parse(expectCheckSums), - }, - // highlight-start - { - type: 'ECDSA', - privateKey: ACCOUNT_PRIVATEKEY, - }, - // highlight-end -); -``` - - - diff --git a/doc-site/docs/client/greenfield.mdx b/doc-site/docs/client/greenfield.mdx index 25aab4e4..5bd2bad4 100644 --- a/doc-site/docs/client/greenfield.mdx +++ b/doc-site/docs/client/greenfield.mdx @@ -19,11 +19,7 @@ import TabItem from '@theme/TabItem'; ```js import { Client } from '@bnb-chain/greenfield-js-sdk'; - -const client = Client.create(GRPC_URL, String(GREEN_CHAIN_ID), { - zkCryptoUrl: - 'https://unpkg.com/@bnb-chain/greenfield-zk-crypto@0.0.3/dist/node/zk-crypto.wasm', -}); +const client = Client.create(GRPC_URL, GREEN_CHAIN_ID); ``` @@ -37,12 +33,6 @@ const client = Client.create(GRPC_URL, GREEN_CHAIN_ID); -:::tip - -The browser needs to load wasm manually. - -::: - The JS SDK consists of two parts: - Chain: https://docs.bnbchain.org/greenfield-docs/docs/api/blockchain-rest diff --git a/doc-site/docs/constants/msg-type-url.mdx b/doc-site/docs/constants/msg-type-url.mdx index 92b2d4ff..285ecf8b 100644 --- a/doc-site/docs/constants/msg-type-url.mdx +++ b/doc-site/docs/constants/msg-type-url.mdx @@ -5,5 +5,4 @@ title: Message Type URL The specific type urls you want look up. Leave empty to get all entries. -More details: -https://github.com/bnb-chain/greenfield-js-sdk/blob/alpha/packages/js-sdk/src/constants/typeUrl.ts +More details: [typeUrl](https://github.com/bnb-chain/greenfield-js-sdk/blob/alpha/packages/js-sdk/src/constants/typeUrl.ts) diff --git a/doc-site/docs/getting-started/overview.md b/doc-site/docs/getting-started/overview.md index 3cbae073..0a776d57 100644 --- a/doc-site/docs/getting-started/overview.md +++ b/doc-site/docs/getting-started/overview.md @@ -8,18 +8,23 @@ slug: / You can find some package documentation below: -| Package | Description | Version | +| Package | Description | Version | | --- | --- | --- | | [@bnb-chain/greenfield-js-sdk](https://github.com/bnb-chain/greenfield-js-sdk/tree/main/packages/js-sdk/README.md) | A client library for Greenfield Chain | [![npm](https://img.shields.io/npm/v/%40bnb-chain%2Fgreenfield-js-sdk?color=blue)](https://www.npmjs.com/package/@bnb-chain/greenfield-js-sdk) | | [@bnb-chain/reed-solomon](https://github.com/bnb-chain/greenfield-js-sdk/tree/main/packages/reed-solomon) | calculate file's `checksums` | [![npm](https://img.shields.io/npm/v/%40bnb-chain%2Freed-solomon?color=blue)](https://www.npmjs.com/package/@bnb-chain/reed-solomon) | -| [@bnb-chain/greenfield-zk-crypto](https://github.com/bnb-chain/greenfield-js-sdk/tree/main/packages/zk-crypto/README.md) | WASM module about sign crypto | [![npm](https://img.shields.io/npm/v/%40bnb-chain%2Fgreenfield-zk-crypto?color=blue)](https://www.npmjs.com/package/@bnb-chain/greenfield-zk-crypto) | | [@bnb-chain/create-gnfd-app](https://github.com/bnb-chain/greenfield-js-sdk/tree/main/packages/create-gnfd-app/README.md) | Create Greenfield App Quickly | [![npm](https://img.shields.io/npm/v/%40bnb-chain%2Fcreate-gnfd-app?color=blue)](https://www.npmjs.com/package/@bnb-chain/create-gnfd-app) | +## Playground + +* [Browser](https://codesandbox.io/p/github/rrr523/greenfield-nextjs-template/main?import=true) + + + ## Online Examples -* [Nextjs](https://codesandbox.io/p/github/rrr523/greenfield-nextjs-template/main) -* [Create React App](https://codesandbox.io/p/github/rrr523/greenfield-cra-template/main) +* [Nextjs](https://codesandbox.io/p/github/rrr523/greenfield-nextjs-template/main?import=true) * [Vite](https://codesandbox.io/p/github/rrr523/greenfield-vite-template/main) +* [Create React App](https://codesandbox.io/p/github/rrr523/greenfield-cra-template/main?import=true) ## Supported JS environments @@ -36,7 +41,7 @@ You can find some package documentation below: ``` 2. Build package: + ```bash > pnpm run build ``` - diff --git a/doc-site/docs/types/long.mdx b/doc-site/docs/types/long.mdx new file mode 100644 index 00000000..45b5da2b --- /dev/null +++ b/doc-site/docs/types/long.mdx @@ -0,0 +1,6 @@ +--- +id: long +title: Long +--- + +[long](https://www.npmjs.com/package/long): Bignumber diff --git a/doc-site/package.json b/doc-site/package.json index 47572ccd..991a700e 100644 --- a/doc-site/package.json +++ b/doc-site/package.json @@ -24,7 +24,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.0.0" + "@docusaurus/module-type-aliases": "3.1.1" }, "browserslist": { "production": [ diff --git a/examples/browser-file-management/CHANGELOG.md b/examples/browser-file-management/CHANGELOG.md new file mode 100644 index 00000000..5c1ea1cf --- /dev/null +++ b/examples/browser-file-management/CHANGELOG.md @@ -0,0 +1,85 @@ +# browser-file-management + +## 0.1.1 + +### Patch Changes + +- Updated dependencies + [[`caf93ce0cdc0a3242a35a6af82ffb3d201378821`](https://github.com/bnb-chain/greenfield-js-sdk/commit/caf93ce0cdc0a3242a35a6af82ffb3d201378821), + [`10244a56dd2da222e85bc25523d25756585dfc43`](https://github.com/bnb-chain/greenfield-js-sdk/commit/10244a56dd2da222e85bc25523d25756585dfc43), + [`83f861d9cd1837808b9e3d2f46c1142f2c6a3adc`](https://github.com/bnb-chain/greenfield-js-sdk/commit/83f861d9cd1837808b9e3d2f46c1142f2c6a3adc), + [`1990d9ffe0627e7044484a29d98ae2523ee4bb70`](https://github.com/bnb-chain/greenfield-js-sdk/commit/1990d9ffe0627e7044484a29d98ae2523ee4bb70), + [`6113b8446396c5ffecefd548523300af9869c7ea`](https://github.com/bnb-chain/greenfield-js-sdk/commit/6113b8446396c5ffecefd548523300af9869c7ea), + [`7c3bb38f6ab9066096aed218cebdf85f37db3c06`](https://github.com/bnb-chain/greenfield-js-sdk/commit/7c3bb38f6ab9066096aed218cebdf85f37db3c06), + [`c9ab316597c2b4d6f30cdcb4a6d3645096dbeecc`](https://github.com/bnb-chain/greenfield-js-sdk/commit/c9ab316597c2b4d6f30cdcb4a6d3645096dbeecc), + [`3374b4a6ed729cf6f2cf8fa5ab147a4cb5618247`](https://github.com/bnb-chain/greenfield-js-sdk/commit/3374b4a6ed729cf6f2cf8fa5ab147a4cb5618247), + [`25e8a99a319fe2129fb5d3eb2f0c8658323ed0e3`](https://github.com/bnb-chain/greenfield-js-sdk/commit/25e8a99a319fe2129fb5d3eb2f0c8658323ed0e3), + [`e789764d3f38290e47467916e610df0430c801d9`](https://github.com/bnb-chain/greenfield-js-sdk/commit/e789764d3f38290e47467916e610df0430c801d9), + [`cb9658e65e630f5ff071d415efa8d6f14cb10dea`](https://github.com/bnb-chain/greenfield-js-sdk/commit/cb9658e65e630f5ff071d415efa8d6f14cb10dea), + [`159c01fe5e4a798d23b0593497c0845e6371d7d2`](https://github.com/bnb-chain/greenfield-js-sdk/commit/159c01fe5e4a798d23b0593497c0845e6371d7d2), + [`87df8646927b390800c01d321ac2f72c04baf8f7`](https://github.com/bnb-chain/greenfield-js-sdk/commit/87df8646927b390800c01d321ac2f72c04baf8f7), + [`c7cf96f1d26b4a6fbc89b3af2e548f26883b6c3b`](https://github.com/bnb-chain/greenfield-js-sdk/commit/c7cf96f1d26b4a6fbc89b3af2e548f26883b6c3b), + [`d45791aa715a5bcef2777c3f2a2213fd8124150e`](https://github.com/bnb-chain/greenfield-js-sdk/commit/d45791aa715a5bcef2777c3f2a2213fd8124150e), + [`7b938f014c9961cf156326580bbddbb62f6c928c`](https://github.com/bnb-chain/greenfield-js-sdk/commit/7b938f014c9961cf156326580bbddbb62f6c928c), + [`acf8644ba0b893d6c0a4395845c365995b520ce1`](https://github.com/bnb-chain/greenfield-js-sdk/commit/acf8644ba0b893d6c0a4395845c365995b520ce1), + [`007a4ba9b0414825279dbfb78c74ef311f34ca65`](https://github.com/bnb-chain/greenfield-js-sdk/commit/007a4ba9b0414825279dbfb78c74ef311f34ca65)]: + - @bnb-chain/greenfield-js-sdk@2.0.0 + +## 0.1.1-alpha.6 + +### Patch Changes + +- Updated dependencies + [[`87df8646927b390800c01d321ac2f72c04baf8f7`](https://github.com/bnb-chain/greenfield-js-sdk/commit/87df8646927b390800c01d321ac2f72c04baf8f7)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.10 + +## 0.1.1-alpha.5 + +### Patch Changes + +- Updated dependencies + [[`e789764d3f38290e47467916e610df0430c801d9`](https://github.com/bnb-chain/greenfield-js-sdk/commit/e789764d3f38290e47467916e610df0430c801d9)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.9 + +## 0.1.1-alpha.4 + +### Patch Changes + +- Updated dependencies + [[`6113b84`](https://github.com/bnb-chain/greenfield-js-sdk/commit/6113b8446396c5ffecefd548523300af9869c7ea), + [`7c3bb38`](https://github.com/bnb-chain/greenfield-js-sdk/commit/7c3bb38f6ab9066096aed218cebdf85f37db3c06)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.8 + +## 0.1.1-alpha.3 + +### Patch Changes + +- Updated dependencies + [[`caf93ce`](https://github.com/bnb-chain/greenfield-js-sdk/commit/caf93ce0cdc0a3242a35a6af82ffb3d201378821)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.7 + +## 0.1.1-alpha.2 + +### Patch Changes + +- Updated dependencies + [[`cb9658e`](https://github.com/bnb-chain/greenfield-js-sdk/commit/cb9658e65e630f5ff071d415efa8d6f14cb10dea), + [`acf8644`](https://github.com/bnb-chain/greenfield-js-sdk/commit/acf8644ba0b893d6c0a4395845c365995b520ce1)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.6 + +## 0.1.1-alpha.1 + +### Patch Changes + +- Updated dependencies + [[`c9ab316`](https://github.com/bnb-chain/greenfield-js-sdk/commit/c9ab316597c2b4d6f30cdcb4a6d3645096dbeecc), + [`159c01f`](https://github.com/bnb-chain/greenfield-js-sdk/commit/159c01fe5e4a798d23b0593497c0845e6371d7d2)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.5 + +## 0.1.1-alpha.0 + +### Patch Changes + +- Updated dependencies + [[`83f861d`](https://github.com/bnb-chain/greenfield-js-sdk/commit/83f861d9cd1837808b9e3d2f46c1142f2c6a3adc)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.4 diff --git a/examples/browser-file-management/README.md b/examples/browser-file-management/README.md index e49c6586..b1763748 100644 --- a/examples/browser-file-management/README.md +++ b/examples/browser-file-management/README.md @@ -1,7 +1,11 @@ # Browser File Management ```bash -> cp .env.simple .env +> pnpm install + +> pnpm -F "@bnb-chain/**" build ``` -And then fill your account info in `.env`. +```bash +> cp .env.simple .env +``` diff --git a/examples/browser-file-management/package.json b/examples/browser-file-management/package.json index 42b38dbb..30d6be2c 100644 --- a/examples/browser-file-management/package.json +++ b/examples/browser-file-management/package.json @@ -1,6 +1,6 @@ { "name": "browser-file-management", - "version": "0.1.0", + "version": "0.1.1", "private": true, "scripts": { "dev": "next dev", @@ -9,8 +9,8 @@ "lint": "next lint" }, "dependencies": { - "@bnb-chain/greenfield-js-sdk": "latest", - "@bnb-chain/reed-solomon": "latest", + "@bnb-chain/greenfield-js-sdk": "workspace:*", + "@bnb-chain/reed-solomon": "workspace:*", "@rainbow-me/rainbowkit": "^1.3.0", "@types/node": "20.6.0", "@types/react": "18.2.21", diff --git a/examples/browser-file-management/src/client/index.ts b/examples/browser-file-management/src/client/index.ts index 5fee6955..8ea4f817 100644 --- a/examples/browser-file-management/src/client/index.ts +++ b/examples/browser-file-management/src/client/index.ts @@ -1,9 +1,7 @@ import { GREEN_CHAIN_ID, GRPC_URL } from '@/config/env'; import { Client } from '@bnb-chain/greenfield-js-sdk'; -export const client = Client.create(GRPC_URL, String(GREEN_CHAIN_ID), { - zkCryptoUrl: 'https://unpkg.com/@bnb-chain/greenfield-zk-crypto@0.0.3/dist/node/zk-crypto.wasm', -}); +export const client = Client.create(GRPC_URL, String(GREEN_CHAIN_ID)); export const getSps = async () => { const sps = await client.sp.getStorageProviders(); diff --git a/examples/browser-file-management/src/components/demo/index.tsx b/examples/browser-file-management/src/components/demo/index.tsx index 9e261edc..c62393a8 100644 --- a/examples/browser-file-management/src/components/demo/index.tsx +++ b/examples/browser-file-management/src/components/demo/index.tsx @@ -3,6 +3,12 @@ import { getOffchainAuthKeys } from '@/utils/offchainAuth'; import { useState } from 'react'; import { useAccount } from 'wagmi'; import { ReedSolomon } from '@bnb-chain/reed-solomon'; +import { + bytesFromBase64, + Long, + RedundancyType, + VisibilityType, +} from '@bnb-chain/greenfield-js-sdk'; export const Demo = () => { const { address, connector } = useAccount(); @@ -141,24 +147,14 @@ export const Demo = () => { } try { - const createBucketTx = await client.bucket.createBucket( - { - bucketName: info.bucketName, - creator: address, - visibility: 'VISIBILITY_TYPE_PUBLIC_READ', - chargedReadQuota: '0', - spInfo: { - primarySpAddress: spInfo.primarySpAddress, - }, - paymentAddress: address, - }, - { - type: 'EDDSA', - domain: window.location.origin, - seed: offChainData.seedString, - address, - }, - ); + const createBucketTx = await client.bucket.createBucket({ + bucketName: info.bucketName, + creator: address, + visibility: VisibilityType.VISIBILITY_TYPE_PUBLIC_READ, + chargedReadQuota: Long.fromString('0'), + primarySpAddress: spInfo.primarySpAddress, + paymentAddress: address, + }); const simulateInfo = await createBucketTx.simulate({ denom: 'BNB', @@ -260,24 +256,16 @@ export const Demo = () => { const expectCheckSums = rs.encode(new Uint8Array(fileBytes)); try { - const createObjectTx = await client.object.createObject( - { - bucketName: info.bucketName, - objectName: info.objectName, - creator: address, - visibility: 'VISIBILITY_TYPE_PRIVATE', - fileType: info.file.type, - redundancyType: 'REDUNDANCY_EC_TYPE', - contentLength: fileBytes.byteLength, - expectCheckSums: expectCheckSums, - }, - { - type: 'EDDSA', - domain: window.location.origin, - seed: offChainData.seedString, - address, - }, - ); + const createObjectTx = await client.object.createObject({ + bucketName: info.bucketName, + objectName: info.objectName, + creator: address, + visibility: VisibilityType.VISIBILITY_TYPE_PUBLIC_READ, + contentType: info.file.type, + redundancyType: RedundancyType.REDUNDANCY_EC_TYPE, + payloadSize: Long.fromInt(fileBytes.byteLength), + expectChecksums: expectCheckSums.map((x) => bytesFromBase64(x)), + }); const simulateInfo = await createObjectTx.simulate({ denom: 'BNB', diff --git a/examples/nextjs/CHANGELOG.md b/examples/nextjs/CHANGELOG.md index 0c5e6091..9ca8ad31 100644 --- a/examples/nextjs/CHANGELOG.md +++ b/examples/nextjs/CHANGELOG.md @@ -1,21 +1,135 @@ # @demo/wallet -## 0.0.29 +## 0.0.28 ### Patch Changes +- [#529](https://github.com/bnb-chain/greenfield-js-sdk/pull/529) + [`e789764d3f38290e47467916e610df0430c801d9`](https://github.com/bnb-chain/greenfield-js-sdk/commit/e789764d3f38290e47467916e610df0430c801d9) + Thanks [@rrr523](https://github.com/rrr523)! - feat: Uploading progress + - Updated dependencies - [[`e746b6c`](https://github.com/bnb-chain/greenfield-js-sdk/commit/e746b6c65fe4809c2ab7dc447c99f770ac747071), - [`5a3de3f`](https://github.com/bnb-chain/greenfield-js-sdk/commit/5a3de3f0349260d6d4e99640d91a53fb6b3299ff)]: - - @bnb-chain/greenfield-js-sdk@1.2.4 + [[`caf93ce0cdc0a3242a35a6af82ffb3d201378821`](https://github.com/bnb-chain/greenfield-js-sdk/commit/caf93ce0cdc0a3242a35a6af82ffb3d201378821), + [`10244a56dd2da222e85bc25523d25756585dfc43`](https://github.com/bnb-chain/greenfield-js-sdk/commit/10244a56dd2da222e85bc25523d25756585dfc43), + [`83f861d9cd1837808b9e3d2f46c1142f2c6a3adc`](https://github.com/bnb-chain/greenfield-js-sdk/commit/83f861d9cd1837808b9e3d2f46c1142f2c6a3adc), + [`1990d9ffe0627e7044484a29d98ae2523ee4bb70`](https://github.com/bnb-chain/greenfield-js-sdk/commit/1990d9ffe0627e7044484a29d98ae2523ee4bb70), + [`6fb38a9cf4fdee012308a68cec4089d56117e905`](https://github.com/bnb-chain/greenfield-js-sdk/commit/6fb38a9cf4fdee012308a68cec4089d56117e905), + [`6113b8446396c5ffecefd548523300af9869c7ea`](https://github.com/bnb-chain/greenfield-js-sdk/commit/6113b8446396c5ffecefd548523300af9869c7ea), + [`7c3bb38f6ab9066096aed218cebdf85f37db3c06`](https://github.com/bnb-chain/greenfield-js-sdk/commit/7c3bb38f6ab9066096aed218cebdf85f37db3c06), + [`c9ab316597c2b4d6f30cdcb4a6d3645096dbeecc`](https://github.com/bnb-chain/greenfield-js-sdk/commit/c9ab316597c2b4d6f30cdcb4a6d3645096dbeecc), + [`3374b4a6ed729cf6f2cf8fa5ab147a4cb5618247`](https://github.com/bnb-chain/greenfield-js-sdk/commit/3374b4a6ed729cf6f2cf8fa5ab147a4cb5618247), + [`25e8a99a319fe2129fb5d3eb2f0c8658323ed0e3`](https://github.com/bnb-chain/greenfield-js-sdk/commit/25e8a99a319fe2129fb5d3eb2f0c8658323ed0e3), + [`e789764d3f38290e47467916e610df0430c801d9`](https://github.com/bnb-chain/greenfield-js-sdk/commit/e789764d3f38290e47467916e610df0430c801d9), + [`cb9658e65e630f5ff071d415efa8d6f14cb10dea`](https://github.com/bnb-chain/greenfield-js-sdk/commit/cb9658e65e630f5ff071d415efa8d6f14cb10dea), + [`159c01fe5e4a798d23b0593497c0845e6371d7d2`](https://github.com/bnb-chain/greenfield-js-sdk/commit/159c01fe5e4a798d23b0593497c0845e6371d7d2), + [`87df8646927b390800c01d321ac2f72c04baf8f7`](https://github.com/bnb-chain/greenfield-js-sdk/commit/87df8646927b390800c01d321ac2f72c04baf8f7), + [`c7cf96f1d26b4a6fbc89b3af2e548f26883b6c3b`](https://github.com/bnb-chain/greenfield-js-sdk/commit/c7cf96f1d26b4a6fbc89b3af2e548f26883b6c3b), + [`d45791aa715a5bcef2777c3f2a2213fd8124150e`](https://github.com/bnb-chain/greenfield-js-sdk/commit/d45791aa715a5bcef2777c3f2a2213fd8124150e), + [`7b938f014c9961cf156326580bbddbb62f6c928c`](https://github.com/bnb-chain/greenfield-js-sdk/commit/7b938f014c9961cf156326580bbddbb62f6c928c), + [`acf8644ba0b893d6c0a4395845c365995b520ce1`](https://github.com/bnb-chain/greenfield-js-sdk/commit/acf8644ba0b893d6c0a4395845c365995b520ce1), + [`007a4ba9b0414825279dbfb78c74ef311f34ca65`](https://github.com/bnb-chain/greenfield-js-sdk/commit/007a4ba9b0414825279dbfb78c74ef311f34ca65)]: + - @bnb-chain/greenfield-js-sdk@2.0.0 + - @bnb-chain/bsc-cross-greenfield-sdk@0.0.2 -## 0.0.28 +## 0.0.28-alpha.10 + +### Patch Changes + +- Updated dependencies + [[`6fb38a9cf4fdee012308a68cec4089d56117e905`](https://github.com/bnb-chain/greenfield-js-sdk/commit/6fb38a9cf4fdee012308a68cec4089d56117e905), + [`87df8646927b390800c01d321ac2f72c04baf8f7`](https://github.com/bnb-chain/greenfield-js-sdk/commit/87df8646927b390800c01d321ac2f72c04baf8f7)]: + - @bnb-chain/bsc-cross-greenfield-sdk@0.0.2-alpha.0 + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.10 + +## 0.0.28-alpha.9 + +### Patch Changes + +- [#529](https://github.com/bnb-chain/greenfield-js-sdk/pull/529) + [`e789764d3f38290e47467916e610df0430c801d9`](https://github.com/bnb-chain/greenfield-js-sdk/commit/e789764d3f38290e47467916e610df0430c801d9) + Thanks [@rrr523](https://github.com/rrr523)! - feat: Uploading progress + +- Updated dependencies + [[`e789764d3f38290e47467916e610df0430c801d9`](https://github.com/bnb-chain/greenfield-js-sdk/commit/e789764d3f38290e47467916e610df0430c801d9)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.9 + +## 0.0.28-alpha.8 + +### Patch Changes + +- Updated dependencies + [[`6113b84`](https://github.com/bnb-chain/greenfield-js-sdk/commit/6113b8446396c5ffecefd548523300af9869c7ea), + [`7c3bb38`](https://github.com/bnb-chain/greenfield-js-sdk/commit/7c3bb38f6ab9066096aed218cebdf85f37db3c06)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.8 + +## 0.0.28-alpha.7 + +### Patch Changes + +- Updated dependencies + [[`caf93ce`](https://github.com/bnb-chain/greenfield-js-sdk/commit/caf93ce0cdc0a3242a35a6af82ffb3d201378821)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.7 + +## 0.0.28-alpha.6 + +### Patch Changes + +- Updated dependencies + [[`cb9658e`](https://github.com/bnb-chain/greenfield-js-sdk/commit/cb9658e65e630f5ff071d415efa8d6f14cb10dea), + [`acf8644`](https://github.com/bnb-chain/greenfield-js-sdk/commit/acf8644ba0b893d6c0a4395845c365995b520ce1)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.6 + +## 0.0.28-alpha.5 + +### Patch Changes + +- Updated dependencies + [[`c9ab316`](https://github.com/bnb-chain/greenfield-js-sdk/commit/c9ab316597c2b4d6f30cdcb4a6d3645096dbeecc), + [`159c01f`](https://github.com/bnb-chain/greenfield-js-sdk/commit/159c01fe5e4a798d23b0593497c0845e6371d7d2)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.5 + +## 0.0.28-alpha.4 + +### Patch Changes + +- Updated dependencies + [[`83f861d`](https://github.com/bnb-chain/greenfield-js-sdk/commit/83f861d9cd1837808b9e3d2f46c1142f2c6a3adc)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.4 + +## 0.0.28-alpha.3 + +### Patch Changes + +- Updated dependencies + [[`1990d9f`](https://github.com/bnb-chain/greenfield-js-sdk/commit/1990d9ffe0627e7044484a29d98ae2523ee4bb70), + [`c7cf96f`](https://github.com/bnb-chain/greenfield-js-sdk/commit/c7cf96f1d26b4a6fbc89b3af2e548f26883b6c3b), + [`7b938f0`](https://github.com/bnb-chain/greenfield-js-sdk/commit/7b938f014c9961cf156326580bbddbb62f6c928c)]: + - @bnb-chain/greenfield-js-sdk@1.3.0-alpha.3 + +## 0.0.28-alpha.2 + +### Patch Changes + +- Updated dependencies + [[`10244a5`](https://github.com/bnb-chain/greenfield-js-sdk/commit/10244a56dd2da222e85bc25523d25756585dfc43), + [`25e8a99`](https://github.com/bnb-chain/greenfield-js-sdk/commit/25e8a99a319fe2129fb5d3eb2f0c8658323ed0e3)]: + - @bnb-chain/greenfield-js-sdk@1.3.0-alpha.2 + +## 0.0.28-alpha.1 + +### Patch Changes + +- Updated dependencies + [[`007a4ba`](https://github.com/bnb-chain/greenfield-js-sdk/commit/007a4ba9b0414825279dbfb78c74ef311f34ca65)]: + - @bnb-chain/greenfield-js-sdk@1.3.0-alpha.1 + +## 0.0.28-alpha.0 ### Patch Changes - Updated dependencies - [[`b074346`](https://github.com/bnb-chain/greenfield-js-sdk/commit/b07434677781c4f224c6b9e828b8e1f1c4eab16a)]: - - @bnb-chain/greenfield-js-sdk@1.2.3 + [[`3374b4a`](https://github.com/bnb-chain/greenfield-js-sdk/commit/3374b4a6ed729cf6f2cf8fa5ab147a4cb5618247)]: + - @bnb-chain/greenfield-js-sdk@1.3.0-alpha.0 ## 0.0.27 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/package.json b/examples/nextjs/package.json index 54aabb49..c5298102 100644 --- a/examples/nextjs/package.json +++ b/examples/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@demo/wallet", - "version": "0.0.29", + "version": "0.0.28", "private": true, "scripts": { "dev": "cross-env NODE_ENV=development next dev", @@ -13,6 +13,7 @@ "dependencies": { "@bnb-chain/greenfield-cosmos-types": "0.4.0-alpha.30", "@bnb-chain/greenfield-js-sdk": "workspace:*", + "@bnb-chain/bsc-cross-greenfield-sdk": "workspace:*", "@bnb-chain/reed-solomon": "workspace:*", "@cosmjs/encoding": "^0.32.0", "@cosmjs/proto-signing": "^0.32.0", @@ -22,7 +23,8 @@ "@ethersproject/wallet": "^5.7.0", "@metamask/eth-sig-util": "^5.0.2", "@next/font": "13.1.6", - "@rainbow-me/rainbowkit": "^1.3.0", + "@rainbow-me/rainbowkit": "^2.0.5", + "@tanstack/react-query": "^5.32.0", "@types/node": "^18.7.1", "@types/react": "^18.0.17", "@types/react-dom": "^18.0.6", @@ -37,8 +39,8 @@ "react": "18.2.0", "react-dom": "18.2.0", "typescript": "^4.7.4", - "viem": "^1.0.6", - "wagmi": "^1.4.7" + "viem": "^2.9.26", + "wagmi": "^2.5.20" }, "devDependencies": { "@types/lodash": "^4.14.199", diff --git a/examples/nextjs/src/client/cross.ts b/examples/nextjs/src/client/cross.ts new file mode 100644 index 00000000..cbd80a4a --- /dev/null +++ b/examples/nextjs/src/client/cross.ts @@ -0,0 +1,16 @@ +import { BasicClientParams } from '@bnb-chain/bsc-cross-greenfield-sdk'; + +/** + * bsc testnet + */ +export const getCrossClientConfig = (address: `0x${string}`) => { + const config: BasicClientParams = { + chainConfig: 'testnet', + accountConfig: { + address, + ethereumProvider: window.ethereum, + }, + }; + + return config; +}; diff --git a/examples/nextjs/src/client/index.ts b/examples/nextjs/src/client/index.ts index aa0712cf..a86c2d99 100644 --- a/examples/nextjs/src/client/index.ts +++ b/examples/nextjs/src/client/index.ts @@ -1,9 +1,7 @@ import { GREEN_CHAIN_ID, GRPC_URL } from '@/config'; import { Client } from '@bnb-chain/greenfield-js-sdk'; -export const client = Client.create(GRPC_URL, String(GREEN_CHAIN_ID), { - zkCryptoUrl: 'https://unpkg.com/@bnb-chain/greenfield-zk-crypto@0.0.3/dist/node/zk-crypto.wasm', -}); +export const client = Client.create(GRPC_URL, String(GREEN_CHAIN_ID)); export const getSps = async () => { const sps = await client.sp.getStorageProviders(); diff --git a/examples/nextjs/src/components/bucket/create/index.tsx b/examples/nextjs/src/components/bucket/create/index.tsx index 5254db43..53991b89 100644 --- a/examples/nextjs/src/components/bucket/create/index.tsx +++ b/examples/nextjs/src/components/bucket/create/index.tsx @@ -1,7 +1,5 @@ import { client, selectSp } from '@/client'; -import { getOffchainAuthKeys } from '@/utils/offchainAuth'; -import { GRNToString, newBucketGRN, newGroupGRN } from '@bnb-chain/greenfield-js-sdk'; -import { add } from 'lodash'; +import { GRNToString, Long, newBucketGRN, VisibilityType } from '@bnb-chain/greenfield-js-sdk'; import { useState } from 'react'; import { useAccount } from 'wagmi'; @@ -32,33 +30,14 @@ export const CreateBucket = () => { const spInfo = await selectSp(); console.log('spInfo', spInfo); - const provider = await connector?.getProvider(); - const offChainData = await getOffchainAuthKeys(address, provider); - 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/examples/nextjs/src/components/bucket/update/index.tsx b/examples/nextjs/src/components/bucket/update/index.tsx index 59c2874c..7557c6d6 100644 --- a/examples/nextjs/src/components/bucket/update/index.tsx +++ b/examples/nextjs/src/components/bucket/update/index.tsx @@ -22,6 +22,11 @@ export const UpdateBucket = () => { onClick={async () => { if (!address) return; + // const toggleSpAsDelegatedAgentTx = await client.bucket.toggleSpAsDelegatedAgent({ + // bucketName: 'foo', + // operator: address, + // }); + const updateBucketTx = await client.bucket.updateBucketInfo({ bucketName: bucketName, operator: address, diff --git a/examples/nextjs/src/components/cross/index.tsx b/examples/nextjs/src/components/cross/index.tsx new file mode 100644 index 00000000..20517c3c --- /dev/null +++ b/examples/nextjs/src/components/cross/index.tsx @@ -0,0 +1,94 @@ +import { getCrossClientConfig } from '@/client/cross'; +import { + BUCKETHUB_ADDRESS, + CROSSCHAIN_ADDRESS, + EXECUTOR_ADDRESS, + GROUPHUB_ADDRESS, + MULTIMESSAGE_ADDRESS, + OBJECTHUB_ADDRESS, + PERMISSIONHUB_ADDRESS, + TOKENHUB_ADDRESS, +} from '@/config'; +import { + CrossChainClient, + ExecutorClient, + ExecutorMsg, + MultiMessageClient, +} from '@bnb-chain/bsc-cross-greenfield-sdk'; +import { useAccount } from 'wagmi'; + +export const MultiMessage = () => { + const { address } = useAccount(); + + return ( +
+

multi message

+ + +

executor

+ + +
+ ); +}; diff --git a/examples/nextjs/src/components/deposit/index.tsx b/examples/nextjs/src/components/deposit/index.tsx index 2aaee61c..bd2d9b4e 100644 --- a/examples/nextjs/src/components/deposit/index.tsx +++ b/examples/nextjs/src/components/deposit/index.tsx @@ -65,6 +65,10 @@ export const Deposit = () => { }); console.log(txHash); + + if (txHash) { + alert('deposit success'); + } }} > deposit diff --git a/examples/nextjs/src/components/feegrant/createObj.tsx b/examples/nextjs/src/components/feegrant/createObj.tsx index 905e6e14..cedc38f5 100644 --- a/examples/nextjs/src/components/feegrant/createObj.tsx +++ b/examples/nextjs/src/components/feegrant/createObj.tsx @@ -1,12 +1,16 @@ import { client } from '@/client'; import { ACCOUNT_PRIVATEKEY } from '@/config/env'; import { + bytesFromBase64, GRNToString, + Long, MsgCreateObjectTypeUrl, newBucketGRN, newObjectGRN, PermissionTypes, + RedundancyType, toTimestamp, + VisibilityType, } from '@bnb-chain/greenfield-js-sdk'; import { Wallet } from '@ethersproject/wallet'; import { ChangeEvent, useState } from 'react'; @@ -135,16 +139,16 @@ export const CreateObj = () => { creator: granteeAddr, bucketName: bucketName, objectName: objectName, - visibility: 'VISIBILITY_TYPE_PUBLIC_READ', - redundancyType: 'REDUNDANCY_EC_TYPE', - contentLength: fileBytes.byteLength, - expectCheckSums, - fileType: file.type, - }, - { - type: 'ECDSA', - privateKey: privateKey, + visibility: VisibilityType.VISIBILITY_TYPE_PRIVATE, + redundancyType: RedundancyType.REDUNDANCY_EC_TYPE, + payloadSize: Long.fromInt(fileBytes.byteLength), + expectChecksums: expectCheckSums.map((x) => bytesFromBase64(x)), + contentType: file.type, }, + // { + // type: 'ECDSA', + // privateKey: privateKey, + // }, ); const simulateInfo = await createObjectTx.simulate({ 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 ff4f04de..2deee545 100644 --- a/examples/nextjs/src/components/object/create/index.tsx +++ b/examples/nextjs/src/components/object/create/index.tsx @@ -1,207 +1,26 @@ 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'; -import { ReedSolomon } from '@bnb-chain/reed-solomon'; +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]); - } - }} - /> -
- -
- -
- - +
); }; 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/object/info/index.tsx b/examples/nextjs/src/components/object/info/index.tsx index 1205bedc..4c4ec4bc 100644 --- a/examples/nextjs/src/components/object/info/index.tsx +++ b/examples/nextjs/src/components/object/info/index.tsx @@ -1,4 +1,5 @@ import { client, selectSp } from '@/client'; +import { ACCOUNT_PRIVATEKEY } from '@/config/env'; import { getOffchainAuthKeys } from '@/utils/offchainAuth'; import { useState } from 'react'; import { useAccount } from 'wagmi'; @@ -96,7 +97,7 @@ export const ObjectInfo = () => { view: '1', 'X-Gnfd-User-Address': address, 'X-Gnfd-App-Domain': window.location.origin, - 'X-Gnfd-Expiry-Timestamp': '2023-09-03T09%3A23%3A39Z', + 'X-Gnfd-Expiry-Timestamp': '2024-03-12T09:39:22Z', }, }, { diff --git a/examples/nextjs/src/components/walletInfo/index.tsx b/examples/nextjs/src/components/walletInfo/index.tsx index bcae491a..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/env.ts b/examples/nextjs/src/config/env.ts index 21bb435e..6c8db474 100644 --- a/examples/nextjs/src/config/env.ts +++ b/examples/nextjs/src/config/env.ts @@ -12,6 +12,14 @@ const { NEXT_PUBLIC_ACCOUNT_ADDRESS, NEXT_PUBLIC_ACCOUNT_PRIVATEKEY, NEXT_PUBLIC_VALIDATOR_PRIVATEKEY, + NEXT_PUBLIC_EXECUTOR_ADDRESS, + NEXT_PUBLIC_CROSSCHAIN_ADDRESS, + NEXT_PUBLIC_MULTIMESSAGE_ADDRESS, + NEXT_PUBLIC_BUCKETHUB_ADDRESS, + NEXT_PUBLIC_OBJECTHUB_ADDRESS, + NEXT_PUBLIC_TOKENHUB_ADDRESS, + NEXT_PUBLIC_PERMISSIONHUB_ADDRESS, + NEXT_PUBLIC_GROUPHUB_ADDRESS, } = publicRuntimeConfig || {}; export const GRPC_URL = NEXT_PUBLIC_GRPC_URL; @@ -24,3 +32,12 @@ export const CROSS_CHAIN_CONTRACT_ADDRESS = NEXT_PUBLIC_CROSS_CHAIN_CONTRACT_ADD export const ACCOUNT_ADDRESS = NEXT_PUBLIC_ACCOUNT_ADDRESS; export const ACCOUNT_PRIVATEKEY = NEXT_PUBLIC_ACCOUNT_PRIVATEKEY; export const VALIDATOR_PRIVATEKEY = NEXT_PUBLIC_VALIDATOR_PRIVATEKEY; + +export const EXECUTOR_ADDRESS = NEXT_PUBLIC_EXECUTOR_ADDRESS; +export const CROSSCHAIN_ADDRESS = NEXT_PUBLIC_CROSSCHAIN_ADDRESS; +export const MULTIMESSAGE_ADDRESS = NEXT_PUBLIC_MULTIMESSAGE_ADDRESS; +export const BUCKETHUB_ADDRESS = NEXT_PUBLIC_BUCKETHUB_ADDRESS; +export const OBJECTHUB_ADDRESS = NEXT_PUBLIC_OBJECTHUB_ADDRESS; +export const TOKENHUB_ADDRESS = NEXT_PUBLIC_TOKENHUB_ADDRESS; +export const PERMISSIONHUB_ADDRESS = NEXT_PUBLIC_PERMISSIONHUB_ADDRESS; +export const GROUPHUB_ADDRESS = NEXT_PUBLIC_GROUPHUB_ADDRESS; diff --git a/examples/nextjs/src/config/index.ts b/examples/nextjs/src/config/index.ts index 0f52e1dd..8aa940ec 100644 --- a/examples/nextjs/src/config/index.ts +++ b/examples/nextjs/src/config/index.ts @@ -1,9 +1,7 @@ -import { getWalletConnectConnector, Wallet } from '@rainbow-me/rainbowkit'; -import { Chain, configureChains, mainnet } from 'wagmi'; -import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet'; -import { InjectedConnector } from 'wagmi/connectors/injected'; -import { MetaMaskConnector } from 'wagmi/connectors/metaMask'; -import { publicProvider } from 'wagmi/providers/public'; +import { connectorsForWallets } from '@rainbow-me/rainbowkit'; +import { rainbowWallet, walletConnectWallet, trustWallet } from '@rainbow-me/rainbowkit/wallets'; +import { createConfig, http } from 'wagmi'; +import { Chain, mainnet, bscGreenfield } from 'wagmi/chains'; import * as env from './env'; export const GRPC_URL = env.GRPC_URL; @@ -14,9 +12,18 @@ export const BSC_CHAIN_ID = env.BSC_CHAIN_ID; export const TOKEN_HUB_CONTRACT_ADDRESS = env.TOKEN_HUB_CONTRACT_ADDRESS; export const CROSS_CHAIN_CONTRACT_ADDRESS = env.CROSS_CHAIN_CONTRACT_ADDRESS; +export const EXECUTOR_ADDRESS = env.EXECUTOR_ADDRESS; +export const CROSSCHAIN_ADDRESS = env.CROSSCHAIN_ADDRESS; +export const MULTIMESSAGE_ADDRESS = env.MULTIMESSAGE_ADDRESS; +export const BUCKETHUB_ADDRESS = env.BUCKETHUB_ADDRESS; +export const OBJECTHUB_ADDRESS = env.OBJECTHUB_ADDRESS; +export const TOKENHUB_ADDRESS = env.TOKENHUB_ADDRESS; +export const PERMISSIONHUB_ADDRESS = env.PERMISSIONHUB_ADDRESS; +export const GROUPHUB_ADDRESS = env.GROUPHUB_ADDRESS; + const greenFieldChain: Chain = { id: GREEN_CHAIN_ID, - network: 'greenfield', + name: 'greenfield', rpcUrls: { default: { http: [GREENFIELD_RPC_URL], @@ -25,18 +32,16 @@ const greenFieldChain: Chain = { http: [GREENFIELD_RPC_URL], }, }, - name: 'greenfield', nativeCurrency: { - name: 'BNB', - symbol: 'BNB', + name: 'tBNB', + symbol: 'tBNB', decimals: 18, }, }; -const bscChain: Chain = { +export const bscChain: Chain = { id: BSC_CHAIN_ID, name: 'BSC', - network: 'QA - bsc smart chain', rpcUrls: { default: { http: [BSC_RPC_URL], @@ -56,67 +61,36 @@ const bscChain: Chain = { // testnet: true, }; -const { chains, publicClient, webSocketPublicClient } = configureChains( +console.log('bscChain', bscChain); +console.log('greenFieldChain', greenFieldChain); + +const connectors = connectorsForWallets( [ + { + groupName: 'Recommended', + wallets: [rainbowWallet, walletConnectWallet, trustWallet], + }, + ], + { + appName: 'gnfd demo', + projectId: '9bf3510aab08be54d5181a126967ee71', + }, +); + +export const wagmiConfig = createConfig({ + chains: [ mainnet, + bscChain, { ...greenFieldChain, + network: 'greenfield', iconUrl: 'https://github.com/wagmi-dev/wagmi/assets/5653652/44446c8c-5c72-4e89-b8eb-3042ef618eed', }, - bscChain, ], - [publicProvider()], -); - -const coinbaseWalletConnector = new CoinbaseWalletConnector({ - chains, - options: { - appName: 'wagmi', + transports: { + [mainnet.id]: http(), + [bscChain.id]: http(), }, + connectors, }); - -const trustWalletConnector = new InjectedConnector({ - chains, - options: { - name: 'GN', - shimDisconnect: true, - // TODO: rainbowkit conflict - getProvider: () => (typeof window !== 'undefined' ? (window as any).trustwallet : undefined), - }, -}); - -const metaMaskWalletConnector = new MetaMaskConnector({ chains }); - -export interface MyWalletOptions { - projectId: string; - chains: Chain[]; -} - -const RainbowTrustWalletConnector = ({ chains, projectId }: MyWalletOptions): Wallet => ({ - id: '_trust-wallet', - name: 'Trust Wallet', - iconUrl: 'https://my-image.xyz', - iconBackground: '#0c2f78', - downloadUrls: { - android: 'https://play.google.com/store/apps/details?id=my.wallet', - ios: 'https://apps.apple.com/us/app/my-wallet', - chrome: 'https://chrome.google.com/webstore/detail/my-wallet', - qrCode: 'https://my-wallet/qr', - }, - createConnector: () => { - return { - connector: trustWalletConnector, - }; - }, -}); - -export { - publicClient, - webSocketPublicClient, - chains, - metaMaskWalletConnector, - coinbaseWalletConnector, - trustWalletConnector, - RainbowTrustWalletConnector, -}; diff --git a/examples/nextjs/src/pages/_app.tsx b/examples/nextjs/src/pages/_app.tsx index 5d96ff63..ef729f0d 100644 --- a/examples/nextjs/src/pages/_app.tsx +++ b/examples/nextjs/src/pages/_app.tsx @@ -1,45 +1,21 @@ -import { chains, publicClient, webSocketPublicClient } from '@/config'; +import { wagmiConfig } from '@/config'; import '@/styles/globals.css'; -import { - connectorsForWallets, - getDefaultWallets, - RainbowKitProvider, -} from '@rainbow-me/rainbowkit'; +import { RainbowKitProvider } from '@rainbow-me/rainbowkit'; import '@rainbow-me/rainbowkit/styles.css'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import type { AppProps } from 'next/app'; -import { createConfig, WagmiConfig } from 'wagmi'; +import { WagmiProvider } from 'wagmi'; -const projectId = '9bf3510aab08be54d5181a126967ee71'; -const { wallets } = getDefaultWallets({ - projectId, - appName: 'greenfield js sdk demo', - chains, -}); - -const connectors = connectorsForWallets([ - ...wallets, - // { - // groupName: 'Recommended', - // wallets: [ - // trustWallet({ projectId, chains, shimDisconnect: true }), - // // RainbowTrustWalletConnector({ projectId, chains }), - // ], - // }, -]); - -const wagmiConfig = createConfig({ - autoConnect: true, - connectors, - webSocketPublicClient, - publicClient, -}); +const queryClient = new QueryClient(); export default function App({ Component, pageProps }: AppProps) { return ( - - - - - + + + + + + + ); } diff --git a/examples/nextjs/src/pages/cross.tsx b/examples/nextjs/src/pages/cross.tsx new file mode 100644 index 00000000..d780e384 --- /dev/null +++ b/examples/nextjs/src/pages/cross.tsx @@ -0,0 +1,27 @@ +import { MultiMessage } from '@/components/cross'; +import { WalletInfo } from '@/components/walletInfo'; +import { useIsMounted } from '@/hooks/useIsMounted'; +import { useAccount } from 'wagmi'; + +export default function Cross() { + const isMounted = useIsMounted(); + const { isConnected } = useAccount(); + + if (!isMounted) return null; + + return ( +
+ + +
+ + {isConnected && ( + <> +

Cross

+ + + + )} +
+ ); +} diff --git a/examples/nextjs/src/pages/index.tsx b/examples/nextjs/src/pages/index.tsx index 4ee4bf26..79ba216b 100644 --- a/examples/nextjs/src/pages/index.tsx +++ b/examples/nextjs/src/pages/index.tsx @@ -28,6 +28,12 @@ export default function Home() { Query + +
  • + + Bsc Cross-Chain Greenfield + +
  • ); diff --git a/examples/nodejs-file-management/CHANGELOG.md b/examples/nodejs-file-management/CHANGELOG.md index 4133e888..20a89179 100644 --- a/examples/nodejs-file-management/CHANGELOG.md +++ b/examples/nodejs-file-management/CHANGELOG.md @@ -1,5 +1,97 @@ # @demo/nodejs +## 0.0.27 + +### Patch Changes + +- Updated dependencies + [[`caf93ce0cdc0a3242a35a6af82ffb3d201378821`](https://github.com/bnb-chain/greenfield-js-sdk/commit/caf93ce0cdc0a3242a35a6af82ffb3d201378821), + [`10244a56dd2da222e85bc25523d25756585dfc43`](https://github.com/bnb-chain/greenfield-js-sdk/commit/10244a56dd2da222e85bc25523d25756585dfc43), + [`83f861d9cd1837808b9e3d2f46c1142f2c6a3adc`](https://github.com/bnb-chain/greenfield-js-sdk/commit/83f861d9cd1837808b9e3d2f46c1142f2c6a3adc), + [`1990d9ffe0627e7044484a29d98ae2523ee4bb70`](https://github.com/bnb-chain/greenfield-js-sdk/commit/1990d9ffe0627e7044484a29d98ae2523ee4bb70), + [`6113b8446396c5ffecefd548523300af9869c7ea`](https://github.com/bnb-chain/greenfield-js-sdk/commit/6113b8446396c5ffecefd548523300af9869c7ea), + [`7c3bb38f6ab9066096aed218cebdf85f37db3c06`](https://github.com/bnb-chain/greenfield-js-sdk/commit/7c3bb38f6ab9066096aed218cebdf85f37db3c06), + [`c9ab316597c2b4d6f30cdcb4a6d3645096dbeecc`](https://github.com/bnb-chain/greenfield-js-sdk/commit/c9ab316597c2b4d6f30cdcb4a6d3645096dbeecc), + [`3374b4a6ed729cf6f2cf8fa5ab147a4cb5618247`](https://github.com/bnb-chain/greenfield-js-sdk/commit/3374b4a6ed729cf6f2cf8fa5ab147a4cb5618247), + [`25e8a99a319fe2129fb5d3eb2f0c8658323ed0e3`](https://github.com/bnb-chain/greenfield-js-sdk/commit/25e8a99a319fe2129fb5d3eb2f0c8658323ed0e3), + [`e789764d3f38290e47467916e610df0430c801d9`](https://github.com/bnb-chain/greenfield-js-sdk/commit/e789764d3f38290e47467916e610df0430c801d9), + [`cb9658e65e630f5ff071d415efa8d6f14cb10dea`](https://github.com/bnb-chain/greenfield-js-sdk/commit/cb9658e65e630f5ff071d415efa8d6f14cb10dea), + [`159c01fe5e4a798d23b0593497c0845e6371d7d2`](https://github.com/bnb-chain/greenfield-js-sdk/commit/159c01fe5e4a798d23b0593497c0845e6371d7d2), + [`87df8646927b390800c01d321ac2f72c04baf8f7`](https://github.com/bnb-chain/greenfield-js-sdk/commit/87df8646927b390800c01d321ac2f72c04baf8f7), + [`c7cf96f1d26b4a6fbc89b3af2e548f26883b6c3b`](https://github.com/bnb-chain/greenfield-js-sdk/commit/c7cf96f1d26b4a6fbc89b3af2e548f26883b6c3b), + [`d45791aa715a5bcef2777c3f2a2213fd8124150e`](https://github.com/bnb-chain/greenfield-js-sdk/commit/d45791aa715a5bcef2777c3f2a2213fd8124150e), + [`7b938f014c9961cf156326580bbddbb62f6c928c`](https://github.com/bnb-chain/greenfield-js-sdk/commit/7b938f014c9961cf156326580bbddbb62f6c928c), + [`acf8644ba0b893d6c0a4395845c365995b520ce1`](https://github.com/bnb-chain/greenfield-js-sdk/commit/acf8644ba0b893d6c0a4395845c365995b520ce1), + [`007a4ba9b0414825279dbfb78c74ef311f34ca65`](https://github.com/bnb-chain/greenfield-js-sdk/commit/007a4ba9b0414825279dbfb78c74ef311f34ca65)]: + - @bnb-chain/greenfield-js-sdk@2.0.0 + +## 0.0.27-alpha.7 + +### Patch Changes + +- Updated dependencies + [[`87df8646927b390800c01d321ac2f72c04baf8f7`](https://github.com/bnb-chain/greenfield-js-sdk/commit/87df8646927b390800c01d321ac2f72c04baf8f7)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.10 + +## 0.0.27-alpha.6 + +### Patch Changes + +- Updated dependencies + [[`e789764d3f38290e47467916e610df0430c801d9`](https://github.com/bnb-chain/greenfield-js-sdk/commit/e789764d3f38290e47467916e610df0430c801d9)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.9 + +## 0.0.27-alpha.5 + +### Patch Changes + +- Updated dependencies + [[`6113b84`](https://github.com/bnb-chain/greenfield-js-sdk/commit/6113b8446396c5ffecefd548523300af9869c7ea), + [`7c3bb38`](https://github.com/bnb-chain/greenfield-js-sdk/commit/7c3bb38f6ab9066096aed218cebdf85f37db3c06)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.8 + +## 0.0.27-alpha.4 + +### Patch Changes + +- Updated dependencies + [[`caf93ce`](https://github.com/bnb-chain/greenfield-js-sdk/commit/caf93ce0cdc0a3242a35a6af82ffb3d201378821)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.7 + +## 0.0.27-alpha.3 + +### Patch Changes + +- Updated dependencies + [[`cb9658e`](https://github.com/bnb-chain/greenfield-js-sdk/commit/cb9658e65e630f5ff071d415efa8d6f14cb10dea), + [`acf8644`](https://github.com/bnb-chain/greenfield-js-sdk/commit/acf8644ba0b893d6c0a4395845c365995b520ce1)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.6 + +## 0.0.27-alpha.2 + +### Patch Changes + +- Updated dependencies + [[`c9ab316`](https://github.com/bnb-chain/greenfield-js-sdk/commit/c9ab316597c2b4d6f30cdcb4a6d3645096dbeecc), + [`159c01f`](https://github.com/bnb-chain/greenfield-js-sdk/commit/159c01fe5e4a798d23b0593497c0845e6371d7d2)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.5 + +## 0.0.27-alpha.1 + +### Patch Changes + +- Updated dependencies + [[`83f861d`](https://github.com/bnb-chain/greenfield-js-sdk/commit/83f861d9cd1837808b9e3d2f46c1142f2c6a3adc)]: + - @bnb-chain/greenfield-js-sdk@2.0.0-alpha.4 + +## 0.0.27-alpha.0 + +### Patch Changes + +- Updated dependencies + [[`3374b4a`](https://github.com/bnb-chain/greenfield-js-sdk/commit/3374b4a6ed729cf6f2cf8fa5ab147a4cb5618247)]: + - @bnb-chain/greenfield-js-sdk@1.3.0-alpha.0 + ## 0.0.26 ### Patch Changes diff --git a/examples/nodejs-file-management/README.md b/examples/nodejs-file-management/README.md index 104d0be6..b5e68b27 100644 --- a/examples/nodejs-file-management/README.md +++ b/examples/nodejs-file-management/README.md @@ -1,5 +1,11 @@ # Nodejs File Management +```bash +> pnpm install + +> pnpm -F "@bnb-chain/**" build +``` + ```bash > cp .env.simple .env ``` diff --git a/examples/nodejs-file-management/package.json b/examples/nodejs-file-management/package.json index 7bc9be83..19979a86 100644 --- a/examples/nodejs-file-management/package.json +++ b/examples/nodejs-file-management/package.json @@ -1,6 +1,6 @@ { "name": "@demo/nodejs", - "version": "0.0.26", + "version": "0.0.27", "type": "commonjs", "private": true, "scripts": { @@ -10,8 +10,8 @@ "author": "", "license": "ISC", "dependencies": { - "@bnb-chain/greenfield-js-sdk": "^1.2.0", - "@bnb-chain/reed-solomon": "^1.1.1", + "@bnb-chain/greenfield-js-sdk": "workspace:*", + "@bnb-chain/reed-solomon": "workspace:*", "dotenv": "^16.3.1", "mime-types": "^2.1.35" } diff --git a/examples/nodejs-file-management/storage.js b/examples/nodejs-file-management/storage.js index 5ee25d55..62b81471 100644 --- a/examples/nodejs-file-management/storage.js +++ b/examples/nodejs-file-management/storage.js @@ -2,7 +2,13 @@ require('dotenv').config(); const fs = require('node:fs'); const path = require('node:path'); const { NodeAdapterReedSolomon } = require('@bnb-chain/reed-solomon/node.adapter'); -const { Client } = require('@bnb-chain/greenfield-js-sdk'); +const { + Client, + Long, + VisibilityType, + RedundancyType, + bytesFromBase64, +} = require('@bnb-chain/greenfield-js-sdk'); const mimeTypes = require('mime-types'); const client = Client.create('https://gnfd-testnet-fullnode-tendermint-ap.bnbchain.org', '5600'); @@ -30,26 +36,19 @@ console.log('objectName', objectName); const sps = await client.sp.getStorageProviders(); // choose the first up to be the primary SP - const primarySP = sps[0].operatorAddress; + // const primarySP = sps[0].operatorAddress; + const primarySP = '0xD142052d8C0881FC7485C1270c3510BC442E05DD'; console.log('primarySP', primarySP); // create bucket - const createBucketTx = await client.bucket.createBucket( - { - bucketName: bucketName, - creator: ACCOUNT_ADDRESS, - visibility: 'VISIBILITY_TYPE_PUBLIC_READ', - chargedReadQuota: '0', - spInfo: { - primarySpAddress: primarySP, - }, - paymentAddress: ACCOUNT_ADDRESS, - }, - { - type: 'ECDSA', - privateKey: ACCOUNT_PRIVATEKEY, - }, - ); + const createBucketTx = await client.bucket.createBucket({ + bucketName: bucketName, + creator: ACCOUNT_ADDRESS, + visibility: VisibilityType.VISIBILITY_TYPE_PUBLIC_READ, + chargedReadQuota: Long.fromString('0'), + primarySpAddress: primarySP, + paymentAddress: ACCOUNT_ADDRESS, + }); const createBucketTxSimulateInfo = await createBucketTx.simulate({ denom: 'BNB', @@ -76,22 +75,16 @@ console.log('objectName', objectName); const expectCheckSums = await rs.encodeInWorker(__filename, Uint8Array.from(fileBuffer)); // create object tx - const createObjectTx = await client.object.createObject( - { - bucketName: bucketName, - objectName: objectName, - creator: ACCOUNT_ADDRESS, - visibility: 'VISIBILITY_TYPE_PRIVATE', - fileType: fileType, - redundancyType: 'REDUNDANCY_EC_TYPE', - contentLength: fileBuffer.length, - expectCheckSums, - }, - { - type: 'ECDSA', - privateKey: ACCOUNT_PRIVATEKEY, - }, - ); + const createObjectTx = await client.object.createObject({ + bucketName: bucketName, + objectName: objectName, + creator: ACCOUNT_ADDRESS, + visibility: VisibilityType.VISIBILITY_TYPE_PRIVATE, + contentType: fileType, + redundancyType: RedundancyType.REDUNDANCY_EC_TYPE, + payloadSize: Long.fromInt(fileBuffer.length), + expectChecksums: expectCheckSums.map((x) => bytesFromBase64(x)), + }); const createObjectTxSimulateInfo = await createObjectTx.simulate({ denom: 'BNB', }); @@ -114,7 +107,7 @@ console.log('objectName', objectName); { bucketName: bucketName, objectName: objectName, - body: fileBuffer, + body: createFile(filePath), txnHash: createObjectTxRes.transactionHash, }, { @@ -123,3 +116,15 @@ console.log('objectName', objectName); }, ); })(); + +function createFile(path) { + const stats = fs.statSync(path); + const fileSize = stats.size; + + return { + name: path, + type: '', + size: fileSize, + content: fs.readFileSync(path), + }; +} diff --git a/examples/nodejs/cases/storage.js b/examples/nodejs/cases/storage.js index 45b85c21..e7bd4e56 100644 --- a/examples/nodejs/cases/storage.js +++ b/examples/nodejs/cases/storage.js @@ -2,10 +2,15 @@ require('dotenv').config(); const fs = require('fs'); const path = require('path'); const mimeTypes = require('mime-types'); -const { getCheckSums } = require('@bnb-chain/greenfiled-file-handle'); const { NodeAdapterReedSolomon } = require('@bnb-chain/reed-solomon/node.adapter'); const { client, selectSp, generateString } = require('../client'); const { ACCOUNT_ADDRESS, ACCOUNT_PRIVATEKEY } = require('../env'); +const { + VisibilityType, + RedundancyType, + Long, + bytesFromBase64, +} = require('@bnb-chain/greenfield-js-sdk'); const filePath = './CHANGELOG.md'; const bucketName = generateString(10); @@ -22,31 +27,20 @@ console.log('objectName', objectName); const spInfo = await selectSp(); // create bucket example: - const createBucketTx = await client.bucket.createBucket( - { - bucketName: bucketName, - creator: ACCOUNT_ADDRESS, - visibility: 'VISIBILITY_TYPE_PUBLIC_READ', - chargedReadQuota: '0', - spInfo: { - primarySpAddress: spInfo.primarySpAddress, - }, - paymentAddress: ACCOUNT_ADDRESS, - tags: { - tags: [], - }, - }, - { - type: 'ECDSA', - privateKey: ACCOUNT_PRIVATEKEY, - }, - ); + const createBucketTx = await client.bucket.createBucket({ + bucketName: bucketName, + creator: ACCOUNT_ADDRESS, + visibility: VisibilityType.VISIBILITY_TYPE_PUBLIC_READ, + chargedReadQuota: Long.fromString('0'), + paymentAddress: ACCOUNT_ADDRESS, + primarySpAddress: spInfo.primarySpAddress, + }); const createBucketTxSimulateInfo = await createBucketTx.simulate({ denom: 'BNB', }); - console.log('createBucketTxSimulateInfo', createBucketTxSimulateInfo); + // console.log('createBucketTxSimulateInfo', createBucketTxSimulateInfo); const createBucketTxRes = await createBucketTx.broadcast({ denom: 'BNB', @@ -57,27 +51,23 @@ console.log('objectName', objectName); privateKey: ACCOUNT_PRIVATEKEY, }); - console.log('create bucket success', createBucketTxRes); + if (createBucketTxRes.code === 0) { + console.log('create bucket success'); + } // create object example: const expectCheckSums = await rs.encodeInWorker(__filename, Uint8Array.from(fileBuffer)); - const createObjectTx = await client.object.createObject( - { - bucketName: bucketName, - objectName: objectName, - creator: ACCOUNT_ADDRESS, - visibility: 'VISIBILITY_TYPE_PRIVATE', - fileType: fileType, - redundancyType: 'REDUNDANCY_EC_TYPE', - contentLength: fileBuffer.length, - expectCheckSums, - }, - { - type: 'ECDSA', - privateKey: ACCOUNT_PRIVATEKEY, - }, - ); + const createObjectTx = await client.object.createObject({ + bucketName: bucketName, + objectName: objectName, + creator: ACCOUNT_ADDRESS, + visibility: VisibilityType.VISIBILITY_TYPE_PRIVATE, + contentType: fileType, + redundancyType: RedundancyType.REDUNDANCY_EC_TYPE, + payloadSize: Long.fromInt(fileBuffer.byteLength), + expectChecksums: expectCheckSums.map((x) => bytesFromBase64(x)), + }); const createObjectTxSimulateInfo = await createObjectTx.simulate({ denom: 'BNB', @@ -98,7 +88,7 @@ console.log('objectName', objectName); { bucketName: bucketName, objectName: objectName, - body: fileBuffer, + body: createFile(filePath), txnHash: createObjectTxRes.transactionHash, }, { @@ -112,17 +102,13 @@ console.log('objectName', objectName); } // create folder example: - const createFolderTx = await client.object.createFolder( - { - bucketName: bucketName, - objectName: objectName + '/', - creator: ACCOUNT_ADDRESS, - }, - { - type: 'ECDSA', - privateKey: ACCOUNT_PRIVATEKEY, - }, - ); + const createFolderTx = await client.object.createFolder({ + bucketName: bucketName, + objectName: objectName + '/', + creator: ACCOUNT_ADDRESS, + redundancyType: RedundancyType.REDUNDANCY_EC_TYPE, + visibility: VisibilityType.VISIBILITY_TYPE_PRIVATE, + }); const simulateInfo = await createFolderTx.simulate({ denom: 'BNB', }); @@ -140,3 +126,15 @@ console.log('objectName', objectName); console.log('create folder success', res); } })(); + +function createFile(path) { + const stats = fs.statSync(path); + const fileSize = stats.size; + + return { + name: path, + type: '', + size: fileSize, + content: fs.readFileSync(path), + }; +} diff --git a/packages/bsc-cross-sdk/CHANGELOG.md b/packages/bsc-cross-sdk/CHANGELOG.md new file mode 100644 index 00000000..def0600e --- /dev/null +++ b/packages/bsc-cross-sdk/CHANGELOG.md @@ -0,0 +1,17 @@ +# @bnb-chain/bsc-cross-greenfield-sdk + +## 0.0.2 + +### Patch Changes + +- [#522](https://github.com/bnb-chain/greenfield-js-sdk/pull/522) + [`6fb38a9cf4fdee012308a68cec4089d56117e905`](https://github.com/bnb-chain/greenfield-js-sdk/commit/6fb38a9cf4fdee012308a68cec4089d56117e905) + Thanks [@rrr523](https://github.com/rrr523)! - Release: BSC Cross Chain SDK + +## 0.0.2-alpha.0 + +### Patch Changes + +- [#522](https://github.com/bnb-chain/greenfield-js-sdk/pull/522) + [`6fb38a9cf4fdee012308a68cec4089d56117e905`](https://github.com/bnb-chain/greenfield-js-sdk/commit/6fb38a9cf4fdee012308a68cec4089d56117e905) + Thanks [@rrr523](https://github.com/rrr523)! - Release: BSC Cross Chain SDK diff --git a/packages/bsc-cross-sdk/README.md b/packages/bsc-cross-sdk/README.md new file mode 100644 index 00000000..1b099be4 --- /dev/null +++ b/packages/bsc-cross-sdk/README.md @@ -0,0 +1,163 @@ +# BSC Cross greenfield SDK + +## Install + +```bash +npm install @bnb-chain/bsc-cross-greenfield-sdk +``` + +## Usage Examples + +### Local Account + +> A Local Account performs signing of transactions & messages with a private key before executing a method over JSON-RPC. + +#### Executor + +```js +import {CrossChainClient, ExecutorClient, ExecutorMsg} from '@bnb-chain/bsc-cross-greenfield-sdk' +import {privateKeyToAccount} from 'viem' + +const privateKey = ... +const CrossChainAddress = ... +const ExecutorAddress = ... + +const account = privateKeyToAccount(privateKey); +const config = { + // 'testnet' | 'mainnet' + chainConfig: 'testnet', + accountConfig: { + privateKey: privateKey, + }, +}; + +const crossChainClient = new CrossChainClient(config, CrossChainAddress); +const executorClient = new ExecutorClient(config, ExecutorAddress); + +;(async => { + const { relayFee } = await crossChainClient.getRelayFee(); + const params = ExecutorMsg.getCreatePaymentAccountParams({ + creator: account.address, + }); + + const txHash = await executorClient.execute([params], { relayFee }); +})() +``` + +#### MultiMessage + +```js +import {CrossChainClient, MultiMessageClient} from '@bnb-chain/bsc-cross-greenfield-sdk' + +const privateKey = ... +const CrossChainAddress = ... +const MultiMessageAddress = ... + +const account = privateKeyToAccount(privateKey); + +const crossChainClient = new CrossChainClient(CrossChainAddress); +const multiMsgClient = new MultiMessageClient(ACCOUNT_PRIVATEKEY, MultiMessageAddress, { + bucketHubAddress: ..., + objectHubAddress: ..., + groupHubAddress: ..., + permissionHubAddress: ..., + tokenHubAddress: ..., +}); + +;(async => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = mutliMsgClient.createBucket( + { + name: 'testBucketName', + chargedReadQuota: BigInt(11), + creator: account.address, + visibility: 1, + paymentAddress: account.address, + primarySpAddress: '0xd142052d8c0881fc7485c1270c3510bc442e05dd', + primarySpApprovalExpiredHeight: BigInt(0), + globalVirtualGroupFamilyId: 1, + primarySpSignature: '0x', + extraData: '0x', + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + }, + ); + + const txHash = await mutliMsgClient.sendMessages([args]); +})() +``` + +### JSON-RPC Account + +> A JSON-RPC Account defers signing of transactions & messages to the target Wallet over JSON-RPC. An example could be sending a transaction via a Browser Extension Wallet (e.g. MetaMask) with the `window.ethereum` Provider. + +[Example](https://github.com/bnb-chain/greenfield-js-sdk/blob/60bdc913abd9bbcf1053d01259d006744b4da6d5/examples/nextjs/src/components/cross/index.tsx) + +#### Executor + +```js +import { CrossChainClient, ExecutorClient, ExecutorMsg} from '@bnb-chain/bsc-cross-greenfield-sdk'; + +const CROSSCHAIN_ADDRESS = ... + +const config = { + chainConfig: 'testnet', + accountConfig: { + address, + ethereumProvider: window.ethereum, + }, +}; + +const crossChainClient = new CrossChainClient(config, CROSSCHAIN_ADDRESS); +const executorClient = new ExecutorClient(config, EXECUTOR_ADDRESS); + +;(async () => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const params = ExecutorMsg.getCreatePaymentAccountParams({ + creator: address, + }); + + const txHash = await executorClient.execute([params], { relayFee }); +})() +``` + +#### MultiMessage + +```js +import { + CrossChainClient, + MultiMessageClient, +} from '@bnb-chain/bsc-cross-greenfield-sdk'; + +const crossChainClient = new CrossChainClient(config, CROSSCHAIN_ADDRESS); + +const mutliMsgClient = new MultiMessageClient(config, MULTIMESSAGE_ADDRESS, { + bucketHubAddress: ..., + objectHubAddress: ..., + groupHubAddress: ..., + permissionHubAddress: ..., + tokenHubAddress: ..., +}); + +const args = mutliMsgClient.deleteBucket( + { + id: BigInt(180013), + }, + { + sender: address, + minAckRelayFee, + relayFee, + }, +); + +;(async () => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const txHash = await mutliMsgClient.sendMessages([args]); +})() +``` diff --git a/packages/bsc-cross-sdk/config/tsconfig-cjs.json b/packages/bsc-cross-sdk/config/tsconfig-cjs.json new file mode 100644 index 00000000..cb04ce46 --- /dev/null +++ b/packages/bsc-cross-sdk/config/tsconfig-cjs.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "target": "ES2015", + "module": "ESNext", + "outDir": "../dist/cjs/", + "esModuleInterop": true, + "moduleResolution": "node" + } +} diff --git a/packages/bsc-cross-sdk/config/tsconfig-esm.json b/packages/bsc-cross-sdk/config/tsconfig-esm.json new file mode 100644 index 00000000..8aee7af3 --- /dev/null +++ b/packages/bsc-cross-sdk/config/tsconfig-esm.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "target": "es2020", + "module": "ES2020", + "outDir": "../dist/esm/", + "moduleResolution": "node" + } +} diff --git a/packages/bsc-cross-sdk/config/tsconfig-test.json b/packages/bsc-cross-sdk/config/tsconfig-test.json new file mode 100644 index 00000000..7a0229c2 --- /dev/null +++ b/packages/bsc-cross-sdk/config/tsconfig-test.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "target": "ES6", + "module": "CommonJS", + "outDir": "./dist/test", + "esModuleInterop": true, + "moduleResolution": "node" + } +} diff --git a/packages/bsc-cross-sdk/config/tsconfig.json b/packages/bsc-cross-sdk/config/tsconfig.json new file mode 100644 index 00000000..19053003 --- /dev/null +++ b/packages/bsc-cross-sdk/config/tsconfig.json @@ -0,0 +1,38 @@ +{ + "compilerOptions": { + "lib": [ + "es2021", + ], + "baseUrl": ".", + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "NodeNext", + "strict": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationDir": "../dist/types", + "outDir": "../dist", + "emitDeclarationOnly": false, + "allowUmdGlobalAccess": true, + "allowJs": true, + "resolveJsonModule": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "strictPropertyInitialization": false, + "paths": { + "@/*": [ + "../src/*" + ] + }, + }, + "include": [ + "../src", + "../types/*.d.ts" + ], + "exclude": [ + "../node_modules", + "../src/tests" + ] +} diff --git a/packages/file-handle/jest.config.mjs b/packages/bsc-cross-sdk/jest.config.mjs similarity index 93% rename from packages/file-handle/jest.config.mjs rename to packages/bsc-cross-sdk/jest.config.mjs index 58efe501..0ca73d79 100644 --- a/packages/file-handle/jest.config.mjs +++ b/packages/bsc-cross-sdk/jest.config.mjs @@ -20,4 +20,5 @@ export default { }, ], }, + setupFilesAfterEnv: ['/tests/env.ts'] }; diff --git a/packages/bsc-cross-sdk/package.json b/packages/bsc-cross-sdk/package.json new file mode 100644 index 00000000..01203884 --- /dev/null +++ b/packages/bsc-cross-sdk/package.json @@ -0,0 +1,81 @@ +{ + "name": "@bnb-chain/bsc-cross-greenfield-sdk", + "version": "0.0.2", + "description": "bsc cross greenfield sdk", + "main": "./dist/cjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/esm/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/esm/**.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/cjs/types/**.d.ts", + "default": "./dist/cjs/index.js" + } + } + }, + "browser": { + "./dist/cjs/index.js": "./dist/cjs/index.js", + "./dist/esm/index.js": "./dist/esm/index.js" + }, + "scripts": { + "predev": "rimraf ./dist", + "dev": "rollup -cw", + "prebuild": "rimraf ./dist", + "build": "rollup -c", + "test": "jest --runInBand", + "lint": "prettier --write './src/*.{ts,tsx,js,jsx}' && eslint ./src/ --ext .js,.jsx,.ts,.tsx --fix" + }, + "repository": { + "type": "git", + "url": "https://github.com/bnb-chain/greenfield-js-sdk", + "directory": "packages/bsc-cross-sdk" + }, + "homepage": "https://github.com/bnb-chain/greenfield-js-sdk/tree/alpha/packages/js-sdk#readme", + "bugs": "https://github.com/bnb-chain/greenfield-js-sdk/issues", + "keywords": [ + "bsc", + "greenfiled", + "js-sdk", + "cross-chain" + ], + "author": "", + "license": "GPLv3", + "files": [ + "dist", + "types" + ], + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, + "browserslist": { + "production": [ + "last 2 chrome version", + "last 2 firefox version", + "last 2 safari version", + "last 2 edge version" + ] + }, + "dependencies": { + "@bnb-chain/greenfield-cosmos-types": "0.4.0-alpha.32", + "long": "^5.2.1", + "viem": "^2.9.23" + }, + "devDependencies": { + "@jest/globals": "^29.5.0", + "@rollup/plugin-typescript": "^11.1.3", + "@types/jest": "^29.5.1", + "@types/mime": "^3.0.1", + "@types/xml2js": "^0.4.11", + "dotenv": "^16.0.3", + "jest": "^29.5.0", + "ts-jest": "^29.1.0", + "ts-node": "^10.9.1", + "tslib": "^2.5.0", + "typescript": "^5.4.5" + } +} diff --git a/packages/bsc-cross-sdk/rollup.config.js b/packages/bsc-cross-sdk/rollup.config.js new file mode 100644 index 00000000..1b52079d --- /dev/null +++ b/packages/bsc-cross-sdk/rollup.config.js @@ -0,0 +1,72 @@ +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import autoExternal from 'rollup-plugin-auto-external'; +import nodePolyfills from 'rollup-plugin-polyfill-node'; + +import pkg from './package.json'; +// const pathResolve = (p) => path.resolve(__dirname, p); + +function resolveExternal() { + return [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]; +} + +export default async () => { + return [ + // ESM + { + input: './src/index.ts', + output: { + dir: './dist/esm', + format: 'esm', + sourcemap: true, + // entryFileNames: '[name].esm.js', + }, + external: resolveExternal(), + context: 'window', + treeshake: true, + plugins: [ + commonjs({ + defaultIsModuleExports: false, + }), + resolve({ + exportConditions: ['default', 'module', 'import'], + mainFields: ['module', 'main'], + modulesOnly: true, + preferBuiltins: false, + }), + typescript({ + tsconfig: './config/tsconfig-esm.json', + declarationDir: './dist/esm', + }), + // terser() + ], + }, + + // CJS + { + input: './src/index.ts', + output: { + dir: './dist/cjs', + format: 'cjs', + sourcemap: true, + }, + external: resolveExternal(), + plugins: [ + autoExternal(), + nodePolyfills({ + include: 'node_modules/**', + }), + commonjs({ + ignoreDynamicRequires: true, + }), + typescript({ + tsconfig: './config/tsconfig-cjs.json', + declarationDir: './dist/cjs/types', + }), + // terser() + ], + }, + ]; +}; diff --git a/packages/bsc-cross-sdk/src/abi/BucketHub.abi.ts b/packages/bsc-cross-sdk/src/abi/BucketHub.abi.ts new file mode 100644 index 00000000..d404950c --- /dev/null +++ b/packages/bsc-cross-sdk/src/abi/BucketHub.abi.ts @@ -0,0 +1,1851 @@ +// https://github.com/bnb-chain/greenfield-contracts/blob/develop/contracts/interface/IBucketHub.sol +const BaseBucketHubAbi = [ + { + inputs: [], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + inputs: [], + name: 'Empty', + type: 'error', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes32', + name: 'pkgHash', + type: 'bytes32', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'AppHandleAckPkgFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes32', + name: 'pkgHash', + type: 'bytes32', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'AppHandleFailAckPkgFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'CreateFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: false, + internalType: 'string', + name: 'name', + type: 'string', + }, + ], + name: 'CreateSubmitted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'CreateSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteSubmitted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + indexed: false, + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'FailAckPkgReceived', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'uint8', + name: 'version', + type: 'uint8', + }, + ], + name: 'Initialized', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'MirrorFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + ], + name: 'MirrorSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'string', + name: 'key', + type: 'string', + }, + { + indexed: false, + internalType: 'bytes', + name: 'value', + type: 'bytes', + }, + ], + name: 'ParamChange', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'granter', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'expireTime', + type: 'uint256', + }, + ], + name: 'RoleGranted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'granter', + type: 'address', + }, + ], + name: 'RoleRevoked', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + indexed: false, + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'UnexpectedPackage', + type: 'event', + }, + { + inputs: [], + name: 'AUTH_CODE_CREATE', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'AUTH_CODE_DELETE', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'BUCKET_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'BUCKET_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'CROSS_CHAIN', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'EMERGENCY_OPERATOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'EMERGENCY_UPGRADE_OPERATOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ERC721Token', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GNFD_EXECUTOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GNFD_EXECUTOR_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GOV_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GOV_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GROUP_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GROUP_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'INIT_MAX_CALLBACK_DATA_LENGTH', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'LIGHT_CLIENT', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MAX_CALLBACK_GAS_LIMIT', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MULTI_MESSAGE', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MULTI_MESSAGE_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'OBJECT_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'OBJECT_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PERMISSION_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PERMISSION_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PROXY_ADMIN', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'RELAYER_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ROLE_CREATE', + outputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ROLE_DELETE', + outputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_FAILED', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_SUCCESS', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_UNEXPECTED', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TOKEN_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TRANSFER_IN_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TRANSFER_OUT_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_CREATE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_DELETE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_MIRROR', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_MULTI_MESSAGE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'additional', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'channelId', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + components: [ + { + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + internalType: 'string', + name: 'name', + type: 'string', + }, + { + internalType: 'enum BucketStorage.BucketVisibilityType', + name: 'visibility', + type: 'uint8', + }, + { + internalType: 'address', + name: 'paymentAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'primarySpAddress', + type: 'address', + }, + { + internalType: 'uint64', + name: 'primarySpApprovalExpiredHeight', + type: 'uint64', + }, + { + internalType: 'uint32', + name: 'globalVirtualGroupFamilyId', + type: 'uint32', + }, + { + internalType: 'bytes', + name: 'primarySpSignature', + type: 'bytes', + }, + { + internalType: 'uint64', + name: 'chargedReadQuota', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'extraData', + type: 'bytes', + }, + ], + internalType: 'struct BucketStorage.CreateBucketSynPackage', + name: '', + type: 'tuple', + }, + ], + name: 'createBucket', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + components: [ + { + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + internalType: 'string', + name: 'name', + type: 'string', + }, + { + internalType: 'enum BucketStorage.BucketVisibilityType', + name: 'visibility', + type: 'uint8', + }, + { + internalType: 'address', + name: 'paymentAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'primarySpAddress', + type: 'address', + }, + { + internalType: 'uint64', + name: 'primarySpApprovalExpiredHeight', + type: 'uint64', + }, + { + internalType: 'uint32', + name: 'globalVirtualGroupFamilyId', + type: 'uint32', + }, + { + internalType: 'bytes', + name: 'primarySpSignature', + type: 'bytes', + }, + { + internalType: 'uint64', + name: 'chargedReadQuota', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'extraData', + type: 'bytes', + }, + ], + internalType: 'struct BucketStorage.CreateBucketSynPackage', + name: '', + type: 'tuple', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'createBucket', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'deleteBucket', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'deleteBucket', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'grant', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'grantee', + type: 'address', + }, + { + internalType: 'uint256', + name: 'expireTime', + type: 'uint256', + }, + ], + name: 'grantRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'uint64', + name: 'sequence', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + { + internalType: 'uint256', + name: 'callbackGasLimit', + type: 'uint256', + }, + ], + name: 'handleAckPackage', + outputs: [ + { + internalType: 'uint256', + name: 'remainingGas', + type: 'uint256', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + internalType: 'uint64', + name: 'sequence', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + { + internalType: 'uint256', + name: 'callbackGasLimit', + type: 'uint256', + }, + ], + name: 'handleFailAckPackage', + outputs: [ + { + internalType: 'uint256', + name: 'remainingGas', + type: 'uint256', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'handleSynPackage', + outputs: [ + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'granter', + type: 'address', + }, + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'hasRole', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_ERC721_token', + type: 'address', + }, + { + internalType: 'address', + name: '_additional', + type: 'address', + }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'initializeV2', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'maxCallbackDataLength', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + name: 'packageMap', + outputs: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'uint32', + name: 'status', + type: 'uint32', + }, + { + internalType: 'uint8', + name: 'operationType', + type: 'uint8', + }, + { + internalType: 'uint256', + name: 'resourceId', + type: 'uint256', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + { + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + stateMutability: 'view', + type: 'function', + }, + + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'granter', + type: 'address', + }, + ], + name: 'renounceRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'retryPackage', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'retryQueue', + outputs: [ + { + internalType: 'int128', + name: '_begin', + type: 'int128', + }, + { + internalType: 'int128', + name: '_end', + type: 'int128', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + name: 'revoke', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'revokeRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'skipPackage', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'string', + name: 'key', + type: 'string', + }, + { + internalType: 'bytes', + name: 'value', + type: 'bytes', + }, + ], + name: 'updateParam', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'versionInfo', + outputs: [ + { + internalType: 'uint256', + name: 'version', + type: 'uint256', + }, + { + internalType: 'string', + name: 'name', + type: 'string', + }, + { + internalType: 'string', + name: 'description', + type: 'string', + }, + ], + stateMutability: 'pure', + type: 'function', + }, +] as const; + +export const PrepareCreateBucketHubAbi = [ + ...BaseBucketHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + components: [ + { + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + internalType: 'string', + name: 'name', + type: 'string', + }, + { + internalType: 'enum BucketStorage.BucketVisibilityType', + name: 'visibility', + type: 'uint8', + }, + { + internalType: 'address', + name: 'paymentAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'primarySpAddress', + type: 'address', + }, + { + internalType: 'uint64', + name: 'primarySpApprovalExpiredHeight', + type: 'uint64', + }, + { + internalType: 'uint32', + name: 'globalVirtualGroupFamilyId', + type: 'uint32', + }, + { + internalType: 'bytes', + name: 'primarySpSignature', + type: 'bytes', + }, + { + internalType: 'uint64', + name: 'chargedReadQuota', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'extraData', + type: 'bytes', + }, + ], + internalType: 'struct BucketStorage.CreateBucketSynPackage', + name: '', + type: 'tuple', + }, + ], + name: 'prepareCreateBucket', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareCreateBucketHubCallbackAbi = [ + ...BaseBucketHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + components: [ + { + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + internalType: 'string', + name: 'name', + type: 'string', + }, + { + internalType: 'enum BucketStorage.BucketVisibilityType', + name: 'visibility', + type: 'uint8', + }, + { + internalType: 'address', + name: 'paymentAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'primarySpAddress', + type: 'address', + }, + { + internalType: 'uint64', + name: 'primarySpApprovalExpiredHeight', + type: 'uint64', + }, + { + internalType: 'uint32', + name: 'globalVirtualGroupFamilyId', + type: 'uint32', + }, + { + internalType: 'bytes', + name: 'primarySpSignature', + type: 'bytes', + }, + { + internalType: 'uint64', + name: 'chargedReadQuota', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'extraData', + type: 'bytes', + }, + ], + internalType: 'struct BucketStorage.CreateBucketSynPackage', + name: '', + type: 'tuple', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'prepareCreateBucket', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareDeleteBucketHubAbi = [ + ...BaseBucketHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'prepareDeleteBucket', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareDeleteBucketHubCallbackAbi = [ + ...BaseBucketHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'prepareDeleteBucket', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; diff --git a/packages/bsc-cross-sdk/src/abi/CrossChain.abi.ts b/packages/bsc-cross-sdk/src/abi/CrossChain.abi.ts new file mode 100644 index 00000000..57cd9981 --- /dev/null +++ b/packages/bsc-cross-sdk/src/abi/CrossChain.abi.ts @@ -0,0 +1,6 @@ +// https://github.com/bnb-chain/greenfield-contracts/blob/develop/contracts/interface/ICrossChain.sol + +export const CrossChainABI = [ + 'function callbackGasPrice() external returns (uint256)', + 'function getRelayFees() view returns (uint256 relayFee, uint256 minAckRelayFee)', +]; diff --git a/packages/bsc-cross-sdk/src/abi/Executor.abi.ts b/packages/bsc-cross-sdk/src/abi/Executor.abi.ts new file mode 100644 index 00000000..52fc5c62 --- /dev/null +++ b/packages/bsc-cross-sdk/src/abi/Executor.abi.ts @@ -0,0 +1,4 @@ +// https://github.com/bnb-chain/greenfield-contracts/blob/develop/contracts/interface/IGreenfieldExecutor.sol +export const ExecutorABI = [ + 'function execute(uint8[] calldata _msgTypes, bytes[] calldata _msgBytes) external payable returns (bool)', +] as const; diff --git a/packages/bsc-cross-sdk/src/abi/GroupHub.abi.ts b/packages/bsc-cross-sdk/src/abi/GroupHub.abi.ts new file mode 100644 index 00000000..809ef0fa --- /dev/null +++ b/packages/bsc-cross-sdk/src/abi/GroupHub.abi.ts @@ -0,0 +1,2132 @@ +// https://github.com/bnb-chain/greenfield-contracts/blob/develop/contracts/interface/IGroupHub.sol +const GroupHubAbi = [ + { + inputs: [], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + inputs: [], + name: 'Empty', + type: 'error', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes32', + name: 'pkgHash', + type: 'bytes32', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'AppHandleAckPkgFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes32', + name: 'pkgHash', + type: 'bytes32', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'AppHandleFailAckPkgFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'CreateFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: false, + internalType: 'string', + name: 'name', + type: 'string', + }, + ], + name: 'CreateSubmitted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'CreateSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteSubmitted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + indexed: false, + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'FailAckPkgReceived', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'uint8', + name: 'version', + type: 'uint8', + }, + ], + name: 'Initialized', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'MirrorFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + ], + name: 'MirrorSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'string', + name: 'key', + type: 'string', + }, + { + indexed: false, + internalType: 'bytes', + name: 'value', + type: 'bytes', + }, + ], + name: 'ParamChange', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'granter', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'expireTime', + type: 'uint256', + }, + ], + name: 'RoleGranted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'granter', + type: 'address', + }, + ], + name: 'RoleRevoked', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + indexed: false, + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'UnexpectedPackage', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint8', + name: 'opType', + type: 'uint8', + }, + ], + name: 'UpdateFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: false, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint8', + name: 'opType', + type: 'uint8', + }, + { + indexed: false, + internalType: 'address[]', + name: 'members', + type: 'address[]', + }, + ], + name: 'UpdateSubmitted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint8', + name: 'opType', + type: 'uint8', + }, + ], + name: 'UpdateSuccess', + type: 'event', + }, + { + inputs: [], + name: 'AUTH_CODE_CREATE', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'AUTH_CODE_DELETE', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'AUTH_CODE_UPDATE', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'BUCKET_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'BUCKET_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'CROSS_CHAIN', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'EMERGENCY_OPERATOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'EMERGENCY_UPGRADE_OPERATOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ERC1155Token', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ERC721Token', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GNFD_EXECUTOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GNFD_EXECUTOR_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GOV_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GOV_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GROUP_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GROUP_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'INIT_MAX_CALLBACK_DATA_LENGTH', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'LIGHT_CLIENT', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MAX_CALLBACK_GAS_LIMIT', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MULTI_MESSAGE', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MULTI_MESSAGE_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'OBJECT_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'OBJECT_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PERMISSION_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PERMISSION_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PROXY_ADMIN', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'RELAYER_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ROLE_CREATE', + outputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ROLE_DELETE', + outputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ROLE_UPDATE', + outputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_FAILED', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_SUCCESS', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_UNEXPECTED', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TOKEN_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TRANSFER_IN_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TRANSFER_OUT_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_CREATE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_DELETE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_MIRROR', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_MULTI_MESSAGE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_UPDATE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'additional', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'channelId', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'string', + name: '', + type: 'string', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'createGroup', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + name: 'createGroup', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'deleteGroup', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'deleteGroup', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'grant', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'grantee', + type: 'address', + }, + { + internalType: 'uint256', + name: 'expireTime', + type: 'uint256', + }, + ], + name: 'grantRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'uint64', + name: 'sequence', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + { + internalType: 'uint256', + name: 'callbackGasLimit', + type: 'uint256', + }, + ], + name: 'handleAckPackage', + outputs: [ + { + internalType: 'uint256', + name: 'remainingGas', + type: 'uint256', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + internalType: 'uint64', + name: 'sequence', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + { + internalType: 'uint256', + name: 'callbackGasLimit', + type: 'uint256', + }, + ], + name: 'handleFailAckPackage', + outputs: [ + { + internalType: 'uint256', + name: 'remainingGas', + type: 'uint256', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'handleSynPackage', + outputs: [ + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'granter', + type: 'address', + }, + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'hasRole', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_ERC721_token', + type: 'address', + }, + { + internalType: 'address', + name: '_ERC1155_token', + type: 'address', + }, + { + internalType: 'address', + name: '_additional', + type: 'address', + }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'initializeV2', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'maxCallbackDataLength', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + name: 'packageMap', + outputs: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'uint32', + name: 'status', + type: 'uint32', + }, + { + internalType: 'uint8', + name: 'operationType', + type: 'uint8', + }, + { + internalType: 'uint256', + name: 'resourceId', + type: 'uint256', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + { + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'granter', + type: 'address', + }, + ], + name: 'renounceRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'retryPackage', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'retryQueue', + outputs: [ + { + internalType: 'int128', + name: '_begin', + type: 'int128', + }, + { + internalType: 'int128', + name: '_end', + type: 'int128', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + name: 'revoke', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'revokeRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'skipPackage', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + components: [ + { + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + internalType: 'enum GroupStorage.UpdateGroupOpType', + name: 'opType', + type: 'uint8', + }, + { + internalType: 'address[]', + name: 'members', + type: 'address[]', + }, + { + internalType: 'bytes', + name: 'extraData', + type: 'bytes', + }, + { + internalType: 'uint64[]', + name: 'memberExpiration', + type: 'uint64[]', + }, + ], + internalType: 'struct GroupStorage.UpdateGroupSynPackage', + name: '', + type: 'tuple', + }, + ], + name: 'updateGroup', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + components: [ + { + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + internalType: 'enum GroupStorage.UpdateGroupOpType', + name: 'opType', + type: 'uint8', + }, + { + internalType: 'address[]', + name: 'members', + type: 'address[]', + }, + { + internalType: 'bytes', + name: 'extraData', + type: 'bytes', + }, + { + internalType: 'uint64[]', + name: 'memberExpiration', + type: 'uint64[]', + }, + ], + internalType: 'struct GroupStorage.UpdateGroupSynPackage', + name: '', + type: 'tuple', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'updateGroup', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'string', + name: 'key', + type: 'string', + }, + { + internalType: 'bytes', + name: 'value', + type: 'bytes', + }, + ], + name: 'updateParam', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'versionInfo', + outputs: [ + { + internalType: 'uint256', + name: 'version', + type: 'uint256', + }, + { + internalType: 'string', + name: 'name', + type: 'string', + }, + { + internalType: 'string', + name: 'description', + type: 'string', + }, + ], + stateMutability: 'pure', + type: 'function', + }, +] as const; + +export const PrepareUpdateGroupHubAbi = [ + ...GroupHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + components: [ + { + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + internalType: 'enum GroupStorage.UpdateGroupOpType', + name: 'opType', + type: 'uint8', + }, + { + internalType: 'address[]', + name: 'members', + type: 'address[]', + }, + { + internalType: 'bytes', + name: 'extraData', + type: 'bytes', + }, + { + internalType: 'uint64[]', + name: 'memberExpiration', + type: 'uint64[]', + }, + ], + internalType: 'struct GroupStorage.UpdateGroupSynPackage', + name: '', + type: 'tuple', + }, + ], + name: 'prepareUpdateGroup', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareUpdateGroupHubCallbackAbi = [ + ...GroupHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + components: [ + { + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + internalType: 'enum GroupStorage.UpdateGroupOpType', + name: 'opType', + type: 'uint8', + }, + { + internalType: 'address[]', + name: 'members', + type: 'address[]', + }, + { + internalType: 'bytes', + name: 'extraData', + type: 'bytes', + }, + { + internalType: 'uint64[]', + name: 'memberExpiration', + type: 'uint64[]', + }, + ], + internalType: 'struct GroupStorage.UpdateGroupSynPackage', + name: '', + type: 'tuple', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'prepareUpdateGroup', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareCreateGroupAbi = [ + ...GroupHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + name: 'prepareCreateGroup', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareCreateGroupHubCallbackAbi = [ + ...GroupHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'string', + name: '', + type: 'string', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'prepareCreateGroup', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareDeleteGroupHubAbi = [ + ...GroupHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'prepareDeleteGroup', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareDeleteGroupHubCallbackAbi = [ + ...GroupHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'prepareDeleteGroup', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; diff --git a/packages/bsc-cross-sdk/src/abi/MultiMessage.abi.ts b/packages/bsc-cross-sdk/src/abi/MultiMessage.abi.ts new file mode 100644 index 00000000..5cba6d8f --- /dev/null +++ b/packages/bsc-cross-sdk/src/abi/MultiMessage.abi.ts @@ -0,0 +1,4 @@ +// https://github.com/bnb-chain/greenfield-contracts/blob/develop/contracts/interface/IMultiMessage.sol +export const MultiMessageAbi = [ + 'function sendMessages(address[] calldata _targets, bytes[] calldata _data,uint256[] calldata _values) external payable returns (bool)', +] as const; diff --git a/packages/bsc-cross-sdk/src/abi/ObjectHub.abi.ts b/packages/bsc-cross-sdk/src/abi/ObjectHub.abi.ts new file mode 100644 index 00000000..ee1f99ad --- /dev/null +++ b/packages/bsc-cross-sdk/src/abi/ObjectHub.abi.ts @@ -0,0 +1,1444 @@ +// https://github.com/bnb-chain/greenfield-contracts/blob/develop/contracts/interface/IObjectHub.sol +const ObjectHubAbi = [ + { + inputs: [], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + inputs: [], + name: 'Empty', + type: 'error', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes32', + name: 'pkgHash', + type: 'bytes32', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'AppHandleAckPkgFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes32', + name: 'pkgHash', + type: 'bytes32', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'AppHandleFailAckPkgFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'CreateFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: false, + internalType: 'string', + name: 'name', + type: 'string', + }, + ], + name: 'CreateSubmitted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'CreateSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteSubmitted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + indexed: false, + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'FailAckPkgReceived', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'uint8', + name: 'version', + type: 'uint8', + }, + ], + name: 'Initialized', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'MirrorFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + ], + name: 'MirrorSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'string', + name: 'key', + type: 'string', + }, + { + indexed: false, + internalType: 'bytes', + name: 'value', + type: 'bytes', + }, + ], + name: 'ParamChange', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'granter', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'expireTime', + type: 'uint256', + }, + ], + name: 'RoleGranted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'granter', + type: 'address', + }, + ], + name: 'RoleRevoked', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + indexed: false, + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'UnexpectedPackage', + type: 'event', + }, + { + inputs: [], + name: 'AUTH_CODE_CREATE', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'AUTH_CODE_DELETE', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'BUCKET_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'BUCKET_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'CROSS_CHAIN', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'EMERGENCY_OPERATOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'EMERGENCY_UPGRADE_OPERATOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ERC721Token', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GNFD_EXECUTOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GNFD_EXECUTOR_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GOV_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GOV_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GROUP_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GROUP_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'INIT_MAX_CALLBACK_DATA_LENGTH', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'LIGHT_CLIENT', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MAX_CALLBACK_GAS_LIMIT', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MULTI_MESSAGE', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MULTI_MESSAGE_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'OBJECT_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'OBJECT_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PERMISSION_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PERMISSION_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PROXY_ADMIN', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'RELAYER_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ROLE_CREATE', + outputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ROLE_DELETE', + outputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_FAILED', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_SUCCESS', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_UNEXPECTED', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TOKEN_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TRANSFER_IN_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TRANSFER_OUT_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_CREATE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_DELETE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_MIRROR', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_MULTI_MESSAGE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'additional', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'channelId', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'deleteObject', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'deleteObject', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'grant', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'grantee', + type: 'address', + }, + { + internalType: 'uint256', + name: 'expireTime', + type: 'uint256', + }, + ], + name: 'grantRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'uint64', + name: 'sequence', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + { + internalType: 'uint256', + name: 'callbackGasLimit', + type: 'uint256', + }, + ], + name: 'handleAckPackage', + outputs: [ + { + internalType: 'uint256', + name: 'remainingGas', + type: 'uint256', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + internalType: 'uint64', + name: 'sequence', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + { + internalType: 'uint256', + name: 'callbackGasLimit', + type: 'uint256', + }, + ], + name: 'handleFailAckPackage', + outputs: [ + { + internalType: 'uint256', + name: 'remainingGas', + type: 'uint256', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'handleSynPackage', + outputs: [ + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'granter', + type: 'address', + }, + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'hasRole', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_ERC721_token', + type: 'address', + }, + { + internalType: 'address', + name: '_additional', + type: 'address', + }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'initializeV2', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'maxCallbackDataLength', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + name: 'packageMap', + outputs: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'uint32', + name: 'status', + type: 'uint32', + }, + { + internalType: 'uint8', + name: 'operationType', + type: 'uint8', + }, + { + internalType: 'uint256', + name: 'resourceId', + type: 'uint256', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + { + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'granter', + type: 'address', + }, + ], + name: 'renounceRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'retryPackage', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'retryQueue', + outputs: [ + { + internalType: 'int128', + name: '_begin', + type: 'int128', + }, + { + internalType: 'int128', + name: '_end', + type: 'int128', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + name: 'revoke', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'revokeRole', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'skipPackage', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'string', + name: 'key', + type: 'string', + }, + { + internalType: 'bytes', + name: 'value', + type: 'bytes', + }, + ], + name: 'updateParam', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'versionInfo', + outputs: [ + { + internalType: 'uint256', + name: 'version', + type: 'uint256', + }, + { + internalType: 'string', + name: 'name', + type: 'string', + }, + { + internalType: 'string', + name: 'description', + type: 'string', + }, + ], + stateMutability: 'pure', + type: 'function', + }, +] as const; + +export const PrepareDeleteObjectAbi = [ + ...ObjectHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'prepareDeleteObject', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareDeleteObjectCallbackAbi = [ + ...ObjectHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'prepareDeleteObject', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; diff --git a/packages/bsc-cross-sdk/src/abi/PermissionHub.abi.ts b/packages/bsc-cross-sdk/src/abi/PermissionHub.abi.ts new file mode 100644 index 00000000..70f383c9 --- /dev/null +++ b/packages/bsc-cross-sdk/src/abi/PermissionHub.abi.ts @@ -0,0 +1,1478 @@ +// https://github.com/bnb-chain/greenfield-contracts/blob/develop/contracts/interface/IPermissionHub.sol +const PermissionHubAbi = [ + { + inputs: [], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + inputs: [], + name: 'Empty', + type: 'error', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes32', + name: 'pkgHash', + type: 'bytes32', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'AppHandleAckPkgFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes32', + name: 'pkgHash', + type: 'bytes32', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'AppHandleFailAckPkgFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'CreateFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: false, + internalType: 'string', + name: 'name', + type: 'string', + }, + ], + name: 'CreateSubmitted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'creator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'CreateSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteSubmitted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'DeleteSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + indexed: false, + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'FailAckPkgReceived', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'uint8', + name: 'version', + type: 'uint8', + }, + ], + name: 'Initialized', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: false, + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + name: 'MirrorFailed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + ], + name: 'MirrorSuccess', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'string', + name: 'key', + type: 'string', + }, + { + indexed: false, + internalType: 'bytes', + name: 'value', + type: 'bytes', + }, + ], + name: 'ParamChange', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + indexed: false, + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + ], + name: 'UnexpectedPackage', + type: 'event', + }, + { + inputs: [], + name: 'AUTH_CODE_CREATE', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'AUTH_CODE_DELETE', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'BUCKET_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'BUCKET_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'CROSS_CHAIN', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'EMERGENCY_OPERATOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'EMERGENCY_UPGRADE_OPERATOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ERC721Token', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GNFD_EXECUTOR', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GNFD_EXECUTOR_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GOV_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GOV_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GROUP_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'GROUP_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'INIT_MAX_CALLBACK_DATA_LENGTH', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'LIGHT_CLIENT', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MAX_CALLBACK_GAS_LIMIT', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MULTI_MESSAGE', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'MULTI_MESSAGE_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'OBJECT_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'OBJECT_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PERMISSION_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PERMISSION_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'PROXY_ADMIN', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'RELAYER_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ROLE_CREATE', + outputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'ROLE_DELETE', + outputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_FAILED', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_SUCCESS', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'STATUS_UNEXPECTED', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TOKEN_HUB', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TRANSFER_IN_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TRANSFER_OUT_CHANNEL_ID', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_CREATE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_DELETE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_MIRROR', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TYPE_MULTI_MESSAGE', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'additional', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'channelId', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + ], + name: 'createPolicy', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'createPolicy', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'deletePolicy', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'deletePolicy', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'grant', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'uint64', + name: 'sequence', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + { + internalType: 'uint256', + name: 'callbackGasLimit', + type: 'uint256', + }, + ], + name: 'handleAckPackage', + outputs: [ + { + internalType: 'uint256', + name: 'remainingGas', + type: 'uint256', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: 'channelId', + type: 'uint8', + }, + { + internalType: 'uint64', + name: 'sequence', + type: 'uint64', + }, + { + internalType: 'bytes', + name: 'msgBytes', + type: 'bytes', + }, + { + internalType: 'uint256', + name: 'callbackGasLimit', + type: 'uint256', + }, + ], + name: 'handleFailAckPackage', + outputs: [ + { + internalType: 'uint256', + name: 'remainingGas', + type: 'uint256', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + ], + name: 'handleSynPackage', + outputs: [ + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_ERC721_token', + type: 'address', + }, + { + internalType: 'address', + name: '_additional', + type: 'address', + }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'initializeV2', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'maxCallbackDataLength', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes32', + name: '', + type: 'bytes32', + }, + ], + name: 'packageMap', + outputs: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'uint32', + name: 'status', + type: 'uint32', + }, + { + internalType: 'uint8', + name: 'operationType', + type: 'uint8', + }, + { + internalType: 'uint256', + name: 'resourceId', + type: 'uint256', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + { + internalType: 'bytes', + name: 'failReason', + type: 'bytes', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'retryPackage', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'retryQueue', + outputs: [ + { + internalType: 'int128', + name: '_begin', + type: 'int128', + }, + { + internalType: 'int128', + name: '_end', + type: 'int128', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + name: 'revoke', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'skipPackage', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'string', + name: 'key', + type: 'string', + }, + { + internalType: 'bytes', + name: 'value', + type: 'bytes', + }, + ], + name: 'updateParam', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'versionInfo', + outputs: [ + { + internalType: 'uint256', + name: 'version', + type: 'uint256', + }, + { + internalType: 'string', + name: 'name', + type: 'string', + }, + { + internalType: 'string', + name: 'description', + type: 'string', + }, + ], + stateMutability: 'pure', + type: 'function', + }, +] as const; + +export const PrepareCreatePolicyAbi = [ + ...PermissionHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + ], + name: 'prepareCreatePolicy', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareCreatePolicyCallbackAbi = [ + ...PermissionHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'prepareCreatePolicy', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareDeletePolicyAbi = [ + ...PermissionHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'prepareDeletePolicy', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; + +export const PrepareDeletePolicyCallbackAbi = [ + ...PermissionHubAbi, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + components: [ + { + internalType: 'address', + name: 'appAddress', + type: 'address', + }, + { + internalType: 'address', + name: 'refundAddress', + type: 'address', + }, + { + internalType: 'enum PackageQueue.FailureHandleStrategy', + name: 'failureHandleStrategy', + type: 'uint8', + }, + { + internalType: 'bytes', + name: 'callbackData', + type: 'bytes', + }, + ], + internalType: 'struct CmnStorage.ExtraData', + name: '', + type: 'tuple', + }, + ], + name: 'prepareDeletePolicy', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + { + internalType: 'bytes', + name: '', + type: 'bytes', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'payable', + type: 'function', + }, +] as const; diff --git a/packages/bsc-cross-sdk/src/abi/TokenHub.abi.ts b/packages/bsc-cross-sdk/src/abi/TokenHub.abi.ts new file mode 100644 index 00000000..ea0b3e12 --- /dev/null +++ b/packages/bsc-cross-sdk/src/abi/TokenHub.abi.ts @@ -0,0 +1,4 @@ +// https://github.com/bnb-chain/greenfield-contracts/blob/develop/contracts/interface/ITokenHub.sol +export const TokenHubAbi = [ + 'function prepareTransferOut(address sender, address recipient,uint256 amount) external payable returns (uint8, bytes memory, uint256, uint256, address)', +]; diff --git a/packages/bsc-cross-sdk/src/account/index.ts b/packages/bsc-cross-sdk/src/account/index.ts new file mode 100644 index 00000000..6acc4291 --- /dev/null +++ b/packages/bsc-cross-sdk/src/account/index.ts @@ -0,0 +1,37 @@ +import { createPublicClient, createWalletClient, custom, http } from 'viem'; +import { assertAddress } from '../asserts'; +import { ChainConfig, JSONRpcAccountConfig, PrivateKeyAccountConfig } from '../types'; +import { getChain } from '../utils'; + +export const getPrivateKeyAccount = ( + { privateKey }: PrivateKeyAccountConfig, + chainConfig: ChainConfig, +) => { + assertAddress(privateKey); + + return createWalletClient({ + // account: privateKeyToAccount(privateKey), + chain: getChain(chainConfig), + transport: http(), + }); +}; + +export const getJSONRpcAccount = ( + { address, ethereumProvider }: JSONRpcAccountConfig, + chainConfig: ChainConfig, +) => { + assertAddress(address); + + return createWalletClient({ + account: address, + chain: getChain(chainConfig), + transport: custom(ethereumProvider), + }); +}; + +export const getPublicClient = (chainConfig: ChainConfig) => { + return createPublicClient({ + chain: getChain(chainConfig), + transport: http(), + }); +}; diff --git a/packages/bsc-cross-sdk/src/asserts.ts b/packages/bsc-cross-sdk/src/asserts.ts new file mode 100644 index 00000000..c1e8ecad --- /dev/null +++ b/packages/bsc-cross-sdk/src/asserts.ts @@ -0,0 +1,29 @@ +import { isAddress } from 'viem'; +import { AccountConfig, JSONRpcAccountConfig, PrivateKeyAccountConfig } from './types'; + +export function assertHubAddress( + errMsg: string, + address?: `0x${string}`, +): asserts address is `0x${string}` { + if (!address || !isAddress(address)) { + throw new Error(errMsg); + } +} + +export function assertAddress(address: string): asserts address is `0x${string}` { + if (address && !address.startsWith('0x')) { + throw new Error('address should start with 0x'); + } +} + +export function isJSONRpcAccount( + accountConfig: AccountConfig, +): accountConfig is JSONRpcAccountConfig { + return 'address' in accountConfig; +} + +export function isPrivateKeyAccount( + accountConfig: AccountConfig, +): accountConfig is PrivateKeyAccountConfig { + return 'privateKey' in accountConfig; +} diff --git a/packages/bsc-cross-sdk/src/client/basic/client.ts b/packages/bsc-cross-sdk/src/client/basic/client.ts new file mode 100644 index 00000000..c7f93e7f --- /dev/null +++ b/packages/bsc-cross-sdk/src/client/basic/client.ts @@ -0,0 +1,26 @@ +import { Account, Address, WalletClient } from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; +import { getJSONRpcAccount, getPrivateKeyAccount, getPublicClient } from '../../account'; +import { isJSONRpcAccount, isPrivateKeyAccount } from '../../asserts'; +import { BasicClientParams } from '../../types'; + +export class BasicClient { + protected publicClient: any; + protected walletClient: WalletClient; + protected account: Account | Address; + + constructor(initParams: BasicClientParams) { + const { chainConfig, accountConfig } = initParams; + + if (isJSONRpcAccount(accountConfig)) { + this.walletClient = getJSONRpcAccount(accountConfig, chainConfig); + this.account = accountConfig.address; + } + if (isPrivateKeyAccount(accountConfig)) { + this.walletClient = getPrivateKeyAccount(accountConfig, chainConfig); + this.account = privateKeyToAccount(accountConfig.privateKey); + } + + this.publicClient = getPublicClient(chainConfig); + } +} diff --git a/packages/bsc-cross-sdk/src/client/basic/index.ts b/packages/bsc-cross-sdk/src/client/basic/index.ts new file mode 100644 index 00000000..4f1cce44 --- /dev/null +++ b/packages/bsc-cross-sdk/src/client/basic/index.ts @@ -0,0 +1 @@ +export * from './client'; diff --git a/packages/bsc-cross-sdk/src/client/cross-chain/client.ts b/packages/bsc-cross-sdk/src/client/cross-chain/client.ts new file mode 100644 index 00000000..91e041d3 --- /dev/null +++ b/packages/bsc-cross-sdk/src/client/cross-chain/client.ts @@ -0,0 +1,42 @@ +import { parseAbi } from 'viem'; +import { CrossChainABI } from '../../abi/CrossChain.abi'; +import { BasicClientParams } from '../../types'; +import { BasicClient } from '../basic'; + +interface ICrossChainClient { + getRelayFee(): Promise<{ + relayFee: bigint; + minAckRelayFee: bigint; + }>; + + getCallbackGasPrice(): Promise; +} + +export class CrossChainClient extends BasicClient implements ICrossChainClient { + constructor(initParams: BasicClientParams, public crossChainAddress: `0x${string}`) { + super(initParams); + } + + async getRelayFee() { + const data = await this.publicClient.readContract({ + address: this.crossChainAddress, + abi: parseAbi(CrossChainABI), + functionName: 'getRelayFees', + }); + + return { + relayFee: data[0], + minAckRelayFee: data[1], + }; + } + + async getCallbackGasPrice() { + const data = await this.publicClient.readContract({ + address: this.crossChainAddress, + abi: parseAbi(CrossChainABI), + functionName: 'callbackGasPrice', + }); + + return data as bigint; + } +} diff --git a/packages/bsc-cross-sdk/src/client/cross-chain/index.ts b/packages/bsc-cross-sdk/src/client/cross-chain/index.ts new file mode 100644 index 00000000..4f1cce44 --- /dev/null +++ b/packages/bsc-cross-sdk/src/client/cross-chain/index.ts @@ -0,0 +1 @@ +export * from './client'; diff --git a/packages/bsc-cross-sdk/src/client/executor/client.ts b/packages/bsc-cross-sdk/src/client/executor/client.ts new file mode 100644 index 00000000..7d1167b8 --- /dev/null +++ b/packages/bsc-cross-sdk/src/client/executor/client.ts @@ -0,0 +1,45 @@ +import { Address, parseAbi } from 'viem'; +import { ExecutorABI } from '../../abi/Executor.abi'; +import { BasicClient } from '../basic'; +import { BasicClientParams, ExecuteParams } from '../../types'; +import { splitExecutorParams } from '../../utils'; + +interface IExecutorClient { + execute( + params: ExecuteParams[], + opts: { + relayFee: bigint; + }, + ): Promise
    ; +} + +export class ExecutorClient extends BasicClient implements IExecutorClient { + constructor(initParams: BasicClientParams, public executorAddress: `0x${string}`) { + super(initParams); + this.executorAddress = executorAddress; + } + + async execute( + params: ExecuteParams[], + opts: { + relayFee: bigint; + }, + ) { + if (params.length === 0) throw new Error('execute params is empty'); + + const { types, bytes } = splitExecutorParams(params); + const { relayFee } = opts; + + const { request } = await this.publicClient.simulateContract({ + account: this.account, + address: this.executorAddress, + abi: parseAbi(ExecutorABI), + functionName: 'execute', + args: [types, bytes], + value: relayFee, + }); + + const txHash = await this.walletClient.writeContract(request); + return txHash; + } +} diff --git a/packages/bsc-cross-sdk/src/client/executor/index.ts b/packages/bsc-cross-sdk/src/client/executor/index.ts new file mode 100644 index 00000000..870ee625 --- /dev/null +++ b/packages/bsc-cross-sdk/src/client/executor/index.ts @@ -0,0 +1,2 @@ +export * from './client'; +export * from './message'; diff --git a/packages/bsc-cross-sdk/src/client/executor/message.ts b/packages/bsc-cross-sdk/src/client/executor/message.ts new file mode 100644 index 00000000..ece97948 --- /dev/null +++ b/packages/bsc-cross-sdk/src/client/executor/message.ts @@ -0,0 +1,88 @@ +import { + MsgCreatePaymentAccount, + MsgDeposit, + MsgDisableRefund, + MsgWithdraw, +} from '@bnb-chain/greenfield-cosmos-types/greenfield/payment/tx'; +import { + MsgCancelMigrateBucket, + MsgCopyObject, + MsgMigrateBucket, + MsgSetBucketFlowRateLimit, + MsgSetTag, + MsgToggleSPAsDelegatedAgent, + MsgUpdateBucketInfo, + MsgUpdateGroupExtra, + MsgUpdateObjectInfo, +} from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/tx'; +import { toHex } from 'viem'; +import { ExecuteParams } from '../../types'; + +// https://github.com/bnb-chain/greenfield-contracts/blob/develop/contracts/middle-layer/GreenfieldExecutor.sol + +export class ExecutorMsg { + static getCreatePaymentAccountParams = (msg: MsgCreatePaymentAccount): ExecuteParams => [ + 1, + toHex(MsgCreatePaymentAccount.encode(msg).finish()), + ]; + + static getDepositParams = (msg: MsgDeposit): ExecuteParams => [ + 2, + toHex(MsgDeposit.encode(msg).finish()), + ]; + + static getDisableRefundParams = (msg: MsgDisableRefund): ExecuteParams => [ + 3, + toHex(MsgDisableRefund.encode(msg).finish()), + ]; + + static getWithdrawParams = (msg: MsgWithdraw): ExecuteParams => [ + 4, + toHex(MsgWithdraw.encode(msg).finish()), + ]; + + static getMigrateBucketParams = (msg: MsgMigrateBucket): ExecuteParams => [ + 5, + toHex(MsgMigrateBucket.encode(msg).finish()), + ]; + + static getCancelMigrateBucketParams = (msg: MsgCancelMigrateBucket): ExecuteParams => [ + 6, + toHex(MsgCancelMigrateBucket.encode(msg).finish()), + ]; + + static getUpdateBucketInfoParams = (msg: MsgUpdateBucketInfo): ExecuteParams => [ + 7, + toHex(MsgUpdateBucketInfo.encode(msg).finish()), + ]; + + static getToggleSPAsDelegatedAgentParams = (msg: MsgToggleSPAsDelegatedAgent): ExecuteParams => [ + 8, + toHex(MsgToggleSPAsDelegatedAgent.encode(msg).finish()), + ]; + + static getSetBucketFlowRateLimitParams = (msg: MsgSetBucketFlowRateLimit): ExecuteParams => [ + 9, + toHex(MsgSetBucketFlowRateLimit.encode(msg).finish()), + ]; + + static getCopyObjectParams = (msg: MsgCopyObject): ExecuteParams => [ + 10, + toHex(MsgCopyObject.encode(msg).finish()), + ]; + + static getUpdateObjectInfoParams = (msg: MsgUpdateObjectInfo): ExecuteParams => [ + 11, + toHex(MsgUpdateObjectInfo.encode(msg).finish()), + ]; + + static getUpdateGroupExtraParams = (msg: MsgUpdateGroupExtra): ExecuteParams => [ + 12, + toHex(MsgUpdateGroupExtra.encode(msg).finish()), + ]; + + static getSetTagParams = (msg: MsgSetTag): ExecuteParams => [ + 13, + toHex(MsgSetTag.encode(msg).finish()), + ]; +} diff --git a/packages/bsc-cross-sdk/src/client/multi-message/client.ts b/packages/bsc-cross-sdk/src/client/multi-message/client.ts new file mode 100644 index 00000000..213d93c0 --- /dev/null +++ b/packages/bsc-cross-sdk/src/client/multi-message/client.ts @@ -0,0 +1,293 @@ +import { Policy } from '@bnb-chain/greenfield-cosmos-types/greenfield/permission/types'; +import { Address, encodeFunctionData, parseAbi, toHex } from 'viem'; +import { + PrepareCreateBucketHubAbi, + PrepareCreateBucketHubCallbackAbi, + PrepareDeleteBucketHubAbi, + PrepareDeleteBucketHubCallbackAbi, +} from '../../abi/BucketHub.abi'; +import { + PrepareCreateGroupAbi, + PrepareCreateGroupHubCallbackAbi, + PrepareDeleteGroupHubAbi, + PrepareDeleteGroupHubCallbackAbi, + PrepareUpdateGroupHubAbi, + PrepareUpdateGroupHubCallbackAbi, +} from '../../abi/GroupHub.abi'; +import { MultiMessageAbi } from '../../abi/MultiMessage.abi'; +import { PrepareDeleteObjectAbi, PrepareDeleteObjectCallbackAbi } from '../../abi/ObjectHub.abi'; +import { + PrepareCreatePolicyAbi, + PrepareCreatePolicyCallbackAbi, + PrepareDeletePolicyAbi, + PrepareDeletePolicyCallbackAbi, +} from '../../abi/PermissionHub.abi'; +import { TokenHubAbi } from '../../abi/TokenHub.abi'; +import { assertAddress, assertHubAddress } from '../../asserts'; +import { + BasicClientParams, + CreateBucketSynPackage, + CreateGroupSynPackage, + DeleteBucketSynPackage, + DeleteGroupSynPackage, + DeleteObjectSynPackage, + DeletePolicySynPackage, + HubAddresses, + MultiMessageParamOptions, + SendMessagesParams, + TransferOutSynPackage, + UpdateGroupSynPackage, +} from '../../types'; +import { splitMultiMessageParams } from '../../utils'; +import { BasicClient } from '../basic'; + +interface IMultiMessageClient { + createBucket(synPkg: CreateBucketSynPackage, opts: MultiMessageParamOptions): SendMessagesParams; + + deleteBucket(synPkg: DeleteBucketSynPackage, opts: MultiMessageParamOptions): SendMessagesParams; + + deleteObject(synPkg: DeleteObjectSynPackage, opts: MultiMessageParamOptions): SendMessagesParams; + + createGroup(synPkg: CreateGroupSynPackage, opts: MultiMessageParamOptions): SendMessagesParams; + + deleteGroup(synPkg: DeleteGroupSynPackage, opts: MultiMessageParamOptions): SendMessagesParams; + + updateGroup(synPkg: UpdateGroupSynPackage, opts: MultiMessageParamOptions): SendMessagesParams; + + /** + * `createPolicy` is special function, need pass Greenfield protobuf message not synPackage message + */ + createPolicy(msg: Policy, opts: MultiMessageParamOptions): SendMessagesParams; + + deletePolicy(synPkg: DeletePolicySynPackage, opts: MultiMessageParamOptions): SendMessagesParams; + + transferOut(synPkg: TransferOutSynPackage, opts: MultiMessageParamOptions): SendMessagesParams; + + sendMessages(params: SendMessagesParams[]): Promise
    ; +} + +export class MultiMessageClient extends BasicClient implements IMultiMessageClient { + constructor( + initParams: BasicClientParams, + public multiMsgAddress: `0x${string}`, + public hubAddress: HubAddresses, + ) { + super(initParams); + this.multiMsgAddress = multiMsgAddress; + this.hubAddress = hubAddress; + } + + transferOut(synPkg: TransferOutSynPackage, opts: MultiMessageParamOptions): SendMessagesParams { + assertHubAddress( + 'token hub address is required in init params', + this.hubAddress.tokenHubAddress, + ); + + if (opts.cb) throw new Error('callback is not supported in transferOut'); + + let fee = this.calculateFee(opts); + fee += synPkg.amount; + + return { + target: this.hubAddress.tokenHubAddress, + msgBytes: encodeFunctionData({ + abi: parseAbi(TokenHubAbi), + functionName: 'prepareTransferOut', + args: [opts.sender, synPkg.recipient, synPkg.amount], + }), + values: fee, + }; + } + + updateGroup(synPkg: UpdateGroupSynPackage, opts: MultiMessageParamOptions): SendMessagesParams { + assertHubAddress( + 'group hub address is required in init params', + this.hubAddress.groupHubAddress, + ); + + const fee = this.calculateFee(opts); + return { + target: this.hubAddress.groupHubAddress, + msgBytes: encodeFunctionData({ + abi: opts.cb ? PrepareUpdateGroupHubCallbackAbi : PrepareUpdateGroupHubAbi, + functionName: 'prepareUpdateGroup', + args: !opts.cb + ? [opts.sender, synPkg] + : [opts.sender, synPkg, opts.cb.gasLimit, opts.cb.extraData], + }), + values: fee, + }; + } + + createGroup(synPkg: CreateGroupSynPackage, opts: MultiMessageParamOptions): SendMessagesParams { + assertHubAddress( + 'group hub address is required in init params', + this.hubAddress.groupHubAddress, + ); + + const fee = this.calculateFee(opts); + return { + target: this.hubAddress.groupHubAddress, + msgBytes: encodeFunctionData({ + abi: opts.cb ? PrepareCreateGroupHubCallbackAbi : PrepareCreateGroupAbi, + functionName: 'prepareCreateGroup', + args: !opts.cb + ? [opts.sender, synPkg.owner, synPkg.name] + : [opts.sender, synPkg.owner, synPkg.name, opts.cb.gasLimit, opts.cb.extraData], + }), + values: fee, + }; + } + + deleteGroup(synPkg: DeleteGroupSynPackage, opts: MultiMessageParamOptions): SendMessagesParams { + assertHubAddress( + 'group hub address is required in init params', + this.hubAddress.groupHubAddress, + ); + + const fee = this.calculateFee(opts); + return { + target: this.hubAddress.groupHubAddress, + msgBytes: encodeFunctionData({ + abi: opts.cb ? PrepareDeleteGroupHubCallbackAbi : PrepareDeleteGroupHubAbi, + functionName: 'prepareDeleteGroup', + args: !opts.cb + ? [opts.sender, synPkg.id] + : [opts.sender, synPkg.id, opts.cb.gasLimit, opts.cb.extraData], + }), + values: fee, + }; + } + + createBucket(synPkg: CreateBucketSynPackage, opts: MultiMessageParamOptions): SendMessagesParams { + assertHubAddress( + 'bucket hub address is required in init params', + this.hubAddress.bucketHubAddress, + ); + assertAddress(synPkg.creator); + assertAddress(synPkg.primarySpAddress); + + const fee = this.calculateFee(opts); + return { + target: this.hubAddress.bucketHubAddress, + msgBytes: encodeFunctionData({ + abi: opts.cb ? PrepareCreateBucketHubCallbackAbi : PrepareCreateBucketHubAbi, + functionName: 'prepareCreateBucket', + args: !opts.cb + ? [opts.sender, synPkg] + : [opts.sender, synPkg, opts.cb.gasLimit, opts.cb.extraData], + }), + values: fee, + }; + } + + deleteBucket(synPkg: DeleteBucketSynPackage, opts: MultiMessageParamOptions): SendMessagesParams { + assertHubAddress( + 'bucket hub address is required in init params', + this.hubAddress.bucketHubAddress, + ); + + const fee = this.calculateFee(opts); + return { + target: this.hubAddress.bucketHubAddress, + msgBytes: encodeFunctionData({ + abi: opts.cb ? PrepareDeleteBucketHubCallbackAbi : PrepareDeleteBucketHubAbi, + functionName: 'prepareDeleteBucket', + args: !opts.cb + ? [opts.sender, synPkg.id] + : [opts.sender, synPkg.id, opts.cb.gasLimit, opts.cb.extraData], + }), + values: fee, + }; + } + + deleteObject(synPkg: DeleteObjectSynPackage, opts: MultiMessageParamOptions): SendMessagesParams { + assertHubAddress( + 'object hub address is required in init params', + this.hubAddress.objectHubAddress, + ); + + const fee = this.calculateFee(opts); + return { + target: this.hubAddress.objectHubAddress, + msgBytes: encodeFunctionData({ + abi: opts.cb ? PrepareDeleteObjectCallbackAbi : PrepareDeleteObjectAbi, + functionName: 'prepareDeleteObject', + args: !opts.cb + ? [opts.sender, synPkg.id] + : [opts.sender, synPkg.id, opts.cb.gasLimit, opts.cb.extraData], + }), + values: fee, + }; + } + + createPolicy(msg: Policy, opts: MultiMessageParamOptions) { + assertHubAddress( + 'permission hub address is required in init params', + this.hubAddress.permissionHubAddress, + ); + + const data = toHex(Policy.encode(msg).finish()); + + const fee = this.calculateFee(opts); + return { + target: this.hubAddress.permissionHubAddress, + msgBytes: encodeFunctionData({ + abi: opts.cb ? PrepareCreatePolicyCallbackAbi : PrepareCreatePolicyAbi, + functionName: 'prepareCreatePolicy', + args: !opts.cb ? [opts.sender, data] : [opts.sender, data, opts.cb.extraData], + }), + values: fee, + }; + } + + deletePolicy(synPkg: DeletePolicySynPackage, opts: MultiMessageParamOptions): SendMessagesParams { + assertHubAddress( + 'permission hub address is required in init params', + this.hubAddress.permissionHubAddress, + ); + + const fee = this.calculateFee(opts); + return { + target: this.hubAddress.permissionHubAddress, + msgBytes: encodeFunctionData({ + abi: opts.cb ? PrepareDeletePolicyCallbackAbi : PrepareDeletePolicyAbi, + functionName: 'prepareDeletePolicy', + args: !opts.cb ? [opts.sender, synPkg.id] : [opts.sender, synPkg.id, opts.cb.extraData], + }), + values: fee, + }; + } + + async sendMessages(params: SendMessagesParams[]) { + if (params.length === 0) throw new Error('execute params is empty'); + + const { targets, msgBytes, values } = splitMultiMessageParams(params); + + const sumValue = values.reduce((a, b) => a + b, BigInt(0)); + + const { request } = await this.publicClient.simulateContract({ + account: this.account, + address: this.multiMsgAddress, + abi: parseAbi(MultiMessageAbi), + functionName: 'sendMessages', + args: [targets, msgBytes, values], + value: sumValue, + }); + + const txHash = await this.walletClient.writeContract(request); + + return txHash; + } + + private calculateFee(opts: MultiMessageParamOptions) { + let fee = opts.relayFee + opts.minAckRelayFee; + + if (opts.cb) { + const callbackGasCost = opts.cb.gasLimit * opts.cb.gasPrice; + fee += callbackGasCost; + } + + return fee; + } +} diff --git a/packages/bsc-cross-sdk/src/client/multi-message/index.ts b/packages/bsc-cross-sdk/src/client/multi-message/index.ts new file mode 100644 index 00000000..4f1cce44 --- /dev/null +++ b/packages/bsc-cross-sdk/src/client/multi-message/index.ts @@ -0,0 +1 @@ +export * from './client'; diff --git a/packages/bsc-cross-sdk/src/index.ts b/packages/bsc-cross-sdk/src/index.ts new file mode 100644 index 00000000..98e128c1 --- /dev/null +++ b/packages/bsc-cross-sdk/src/index.ts @@ -0,0 +1,6 @@ +export * from './account'; +export * from './client/basic'; +export * from './client/executor'; +export * from './client/cross-chain'; +export * from './client/multi-message'; +export * from './types'; diff --git a/packages/bsc-cross-sdk/src/types/index.ts b/packages/bsc-cross-sdk/src/types/index.ts new file mode 100644 index 00000000..a803c500 --- /dev/null +++ b/packages/bsc-cross-sdk/src/types/index.ts @@ -0,0 +1,114 @@ +import { Address, EIP1193Provider, Hex } from 'viem'; + +export type ChainConfig = 'testnet' | 'mainnet'; +export type AccountConfig = PrivateKeyAccountConfig | JSONRpcAccountConfig; +export type PrivateKeyAccountConfig = { + privateKey: Address; +}; +export type JSONRpcAccountConfig = { + address: Address; + ethereumProvider: EIP1193Provider; +}; +export type BasicClientParams = { + chainConfig: ChainConfig; + accountConfig: AccountConfig; +}; + +export type ExecuteParams = [number, `0x${string}`]; + +export type SendMessagesParams = { + target: `0x${string}`; + msgBytes: `0x${string}`; + values: bigint; +}; + +export type HubAddresses = { + bucketHubAddress?: Address; + objectHubAddress?: Address; + tokenHubAddress?: Address; + permissionHubAddress?: Address; + groupHubAddress?: Address; +}; + +export type MultiMessageParamOptions = { + sender: Address; + relayFee: bigint; + minAckRelayFee: bigint; + cb?: { + gasLimit: bigint; + gasPrice: bigint; + extraData: { + appAddress: Address; + refundAddress: Address; + failureHandleStrategy: FailureHandleStrategy; + callbackData: Hex; + }; + }; +}; + +export enum FailureHandleStrategy { + BlockOnFail = 0, + CacheOnFail, + SkipOnFail, +} + +export enum BucketVisibilityType { + Unspecified = 0, + PublicRead, + Private, + Inherit, +} + +export enum UpdateGroupOpType { + AddMembers = 0, + RemoveMembers, + RenewMembers, +} + +export type CreateBucketSynPackage = { + creator: Address; + name: string; + visibility: BucketVisibilityType; + paymentAddress: Address; + primarySpAddress: Address; + primarySpApprovalExpiredHeight: bigint; + globalVirtualGroupFamilyId: number; + primarySpSignature: Address; + chargedReadQuota: bigint; + extraData: `0x${string}`; +}; + +export type DeleteBucketSynPackage = { + id: bigint; +}; + +export type DeleteObjectSynPackage = { + id: bigint; +}; + +export type CreateGroupSynPackage = { + owner: Address; + name: string; +}; + +export type DeleteGroupSynPackage = { + id: bigint; +}; + +export type UpdateGroupSynPackage = { + operator: Address; + id: bigint; + opType: UpdateGroupOpType; + members: Address[]; + extraData: `0x${string}`; + memberExpiration: bigint[]; +}; + +export type DeletePolicySynPackage = { + id: bigint; +}; + +export type TransferOutSynPackage = { + recipient: Address; + amount: bigint; +}; diff --git a/packages/bsc-cross-sdk/src/utils.ts b/packages/bsc-cross-sdk/src/utils.ts new file mode 100644 index 00000000..1a98af2c --- /dev/null +++ b/packages/bsc-cross-sdk/src/utils.ts @@ -0,0 +1,40 @@ +import { Address } from 'viem'; +import { ChainConfig, ExecuteParams, SendMessagesParams } from './types'; +import { bsc, bscTestnet } from 'viem/chains'; + +export const getChain = (chainConfig: ChainConfig) => { + return chainConfig === 'testnet' ? bscTestnet : bsc; +}; + +export const splitExecutorParams = (params: ExecuteParams[]) => { + const types: number[] = []; + const bytes: `0x${string}`[] = []; + + params.forEach((p) => { + types.push(p[0]); + bytes.push(p[1]); + }); + + return { + types, + bytes, + }; +}; + +export const splitMultiMessageParams = (params: SendMessagesParams[]) => { + const targets: Address[] = []; + const msgBytes: Address[] = []; + const values: bigint[] = []; + + params.forEach((p) => { + targets.push(p.target); + msgBytes.push(p.msgBytes); + values.push(p.values); + }); + + return { + targets, + msgBytes, + values, + }; +}; diff --git a/packages/bsc-cross-sdk/tests/.env.simple b/packages/bsc-cross-sdk/tests/.env.simple new file mode 100644 index 00000000..1082cb76 --- /dev/null +++ b/packages/bsc-cross-sdk/tests/.env.simple @@ -0,0 +1,9 @@ +ACCOUNT_PRIVATEKEY= +EXECUTOR_ADDRESS= +CROSSCHAIN_ADDRESS= +MULTIMESSAGE_ADDRESS= +BUCKETHUB_ADDRESS= +OBJECTHUB_ADDRESS= +TOKENHUB_ADDRESS= +PERMISSIONHUB_ADDRESS= +GROUPHUB_ADDRESS= diff --git a/packages/bsc-cross-sdk/tests/cross.spec.ts b/packages/bsc-cross-sdk/tests/cross.spec.ts new file mode 100644 index 00000000..7869c6e7 --- /dev/null +++ b/packages/bsc-cross-sdk/tests/cross.spec.ts @@ -0,0 +1,37 @@ +import { expect } from '@jest/globals'; +import { CrossChainClient } from '../src/client/cross-chain'; +import { BasicClientParams } from '../src/types'; +import { ACCOUNT_PRIVATEKEY, CrossChainAddress } from './env'; + +describe('base', () => { + let crossChainClient: CrossChainClient; + + beforeEach(() => { + const config: BasicClientParams = { + chainConfig: 'testnet', + accountConfig: { + privateKey: ACCOUNT_PRIVATEKEY, + }, + }; + + crossChainClient = new CrossChainClient(config, CrossChainAddress); + }); + + test('getCallbackGasPrice', async () => { + const gasPrice = await crossChainClient.getCallbackGasPrice(); + + // eslint-disable-next-line no-console + console.log('gasPrice', gasPrice); + + expect(gasPrice).toBeDefined(); + }); + + test('getCallbackGasPrice', async () => { + const realyFee = await crossChainClient.getRelayFee(); + + // eslint-disable-next-line no-console + console.log('realyFee', realyFee); + + expect(realyFee).toBeDefined(); + }); +}); diff --git a/packages/bsc-cross-sdk/tests/env.ts b/packages/bsc-cross-sdk/tests/env.ts new file mode 100644 index 00000000..ca8df023 --- /dev/null +++ b/packages/bsc-cross-sdk/tests/env.ts @@ -0,0 +1,14 @@ +import * as dotenv from 'dotenv'; +dotenv.config({ + path: process.cwd() + '/tests/.env', +}); + +export const ACCOUNT_PRIVATEKEY = (process.env.ACCOUNT_PRIVATEKEY as `0x${string}`) || '0x'; +export const ExecutorAddress = (process.env.EXECUTOR_ADDRESS as `0x${string}`) || '0x'; +export const CrossChainAddress = (process.env.CROSSCHAIN_ADDRESS as `0x${string}`) || '0x'; +export const MultiMessageAddress = (process.env.MULTIMESSAGE_ADDRESS as `0x${string}`) || '0x'; +export const BucketHubAddress = (process.env.BUCKETHUB_ADDRESS as `0x${string}`) || '0x'; +export const ObjectHubAddress = (process.env.OBJECTHUB_ADDRESS as `0x${string}`) || '0x'; +export const TokenHubAddress = (process.env.TOKENHUB_ADDRESS as `0x${string}`) || '0x'; +export const PermissionHubAddress = (process.env.PERMISSIONHUB_ADDRESS as `0x${string}`) || '0x'; +export const GroupHubAddress = (process.env.GROUPHUB_ADDRESS as `0x${string}`) || '0x'; diff --git a/packages/bsc-cross-sdk/tests/executor.spec.ts b/packages/bsc-cross-sdk/tests/executor.spec.ts new file mode 100644 index 00000000..78cc4f06 --- /dev/null +++ b/packages/bsc-cross-sdk/tests/executor.spec.ts @@ -0,0 +1,101 @@ +import { UInt64Value } from '@bnb-chain/greenfield-cosmos-types/greenfield/common/wrapper'; +import { VisibilityType } from '@bnb-chain/greenfield-cosmos-types/greenfield/storage/common'; +import { Long } from '@bnb-chain/greenfield-cosmos-types/helpers'; +import { describe, expect, test } from '@jest/globals'; +import { Account, privateKeyToAccount } from 'viem/accounts'; +import { ACCOUNT_PRIVATEKEY, CrossChainAddress, ExecutorAddress } from './env'; +import { CrossChainClient } from '../src/client/cross-chain'; +import { BasicClientParams } from '../src/types'; +import { ExecutorClient } from '../src'; +import { ExecutorMsg } from '../src/client/executor/message'; + +describe('executor', () => { + let account: Account; + let crossChainClient: CrossChainClient; + let executorClient: ExecutorClient; + + beforeEach(() => { + account = privateKeyToAccount(ACCOUNT_PRIVATEKEY); + + const config: BasicClientParams = { + chainConfig: 'testnet', + accountConfig: { + privateKey: ACCOUNT_PRIVATEKEY, + }, + }; + + crossChainClient = new CrossChainClient(config, CrossChainAddress); + + executorClient = new ExecutorClient(config, ExecutorAddress); + }); + + test('deposit', async () => { + const { relayFee } = await crossChainClient.getRelayFee(); + + const params = ExecutorMsg.getDepositParams({ + creator: account.address, + to: '0x00000000000000000000', + amount: '0.001', + }); + + const txHash = await executorClient.execute([params], { relayFee }); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + expect(txHash).toBeDefined(); + }); + + test('createPayment', async () => { + const { relayFee } = await crossChainClient.getRelayFee(); + + const params = ExecutorMsg.getCreatePaymentAccountParams({ + creator: account.address, + }); + + const txHash = await executorClient.execute([params], { relayFee }); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + + expect(txHash).toBeDefined(); + }); + + test('updateBucketInfo', async () => { + const { relayFee } = await crossChainClient.getRelayFee(); + + const params = ExecutorMsg.getUpdateBucketInfoParams({ + bucketName: 'stplfiijom', + operator: account.address, + paymentAddress: account.address, + visibility: VisibilityType.VISIBILITY_TYPE_PRIVATE, + chargedReadQuota: UInt64Value.fromPartial({ + value: Long.fromString('10'), + }), + }); + + const txHash = await executorClient.execute([params], { relayFee }); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + + expect(txHash).toBeDefined(); + }); + + test('multiTx', async () => { + const { relayFee } = await crossChainClient.getRelayFee(); + + const params1 = ExecutorMsg.getDepositParams({ + creator: account.address, + to: '0x00000000000000000000', + amount: '0.001', + }); + + const params2 = ExecutorMsg.getCreatePaymentAccountParams({ + creator: account.address, + }); + + const txHash = await executorClient.execute([params1, params2], { relayFee }); + // console.log('txHash', txHash); + expect(txHash).toBeDefined(); + }); +}); diff --git a/packages/bsc-cross-sdk/tests/multiMessage.spec.ts b/packages/bsc-cross-sdk/tests/multiMessage.spec.ts new file mode 100644 index 00000000..23d47bd0 --- /dev/null +++ b/packages/bsc-cross-sdk/tests/multiMessage.spec.ts @@ -0,0 +1,397 @@ +import { beforeEach, describe, expect, test } from '@jest/globals'; +import { Account, privateKeyToAccount } from 'viem/accounts'; +import { + ACCOUNT_PRIVATEKEY, + BucketHubAddress, + CrossChainAddress, + GroupHubAddress, + MultiMessageAddress, + ObjectHubAddress, + PermissionHubAddress, + TokenHubAddress, +} from './env'; +import { generateString } from './utils'; +import { parseEther, toHex, zeroAddress } from 'viem'; +import { ResourceType } from '@bnb-chain/greenfield-cosmos-types/greenfield/resource/types'; +import { + ActionType, + Effect, + PrincipalType, +} from '@bnb-chain/greenfield-cosmos-types/greenfield/permission/common'; +import { CrossChainClient } from '../src/client/cross-chain'; +import { MultiMessageClient } from '../src/client/multi-message'; +import { BasicClientParams } from '../src/types'; + +describe('base', () => { + let account: Account; + let crossChainClient: CrossChainClient; + let multiMsgClient: MultiMessageClient; + + beforeEach(() => { + account = privateKeyToAccount(ACCOUNT_PRIVATEKEY); + + const config: BasicClientParams = { + chainConfig: 'testnet', + accountConfig: { + privateKey: ACCOUNT_PRIVATEKEY, + }, + }; + + crossChainClient = new CrossChainClient(config, CrossChainAddress); + + multiMsgClient = new MultiMessageClient(config, MultiMessageAddress, { + bucketHubAddress: BucketHubAddress, + objectHubAddress: ObjectHubAddress, + groupHubAddress: GroupHubAddress, + permissionHubAddress: PermissionHubAddress, + tokenHubAddress: TokenHubAddress, + }); + }); + + test('createBucket', async () => { + // const gasPrice = crossChainClient.getCallbackGasPrice(); + const bucketName = generateString(10); + + // eslint-disable-next-line no-console + console.log('bucketName', bucketName); + + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = multiMsgClient.createBucket( + { + name: bucketName, + chargedReadQuota: BigInt(0), + creator: account.address, + visibility: 1, + paymentAddress: account.address, + primarySpAddress: '0xd142052d8c0881fc7485c1270c3510bc442e05dd', + primarySpApprovalExpiredHeight: BigInt(0), + globalVirtualGroupFamilyId: 1, + primarySpSignature: '0x', + extraData: '0x', + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + + expect(txHash).toBeDefined(); + }); + + test('createBucketCb', async () => { + const gasPrice = await crossChainClient.getCallbackGasPrice(); + const bucketName = generateString(10); + + // eslint-disable-next-line no-console + console.log('bucketName', bucketName); + + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = multiMsgClient.createBucket( + { + name: bucketName, + chargedReadQuota: BigInt(0), + creator: account.address, + visibility: 1, + paymentAddress: account.address, + primarySpAddress: '0xd142052d8c0881fc7485c1270c3510bc442e05dd', + primarySpApprovalExpiredHeight: BigInt(0), + globalVirtualGroupFamilyId: 1, + primarySpSignature: '0x', + extraData: '0x', + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + cb: { + gasPrice, + gasLimit: BigInt(1000000), + extraData: { + appAddress: account.address, + refundAddress: account.address, + failureHandleStrategy: 0, + callbackData: toHex(''), + }, + }, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + + expect(txHash).toBeDefined(); + }); + + test('deleteBucket', async () => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = multiMsgClient.deleteBucket( + { + id: BigInt(180005), + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + + expect(txHash).toBeDefined(); + }); + + test('deleteBucketCb', async () => { + const gasPrice = await crossChainClient.getCallbackGasPrice(); + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = multiMsgClient.deleteBucket( + { + id: BigInt(180006), + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + cb: { + gasPrice, + gasLimit: BigInt(100000), + extraData: { + appAddress: account.address, + refundAddress: account.address, + failureHandleStrategy: 0, + callbackData: toHex(''), + }, + }, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + + expect(txHash).toBeDefined(); + }); + + test('deleteObject', async () => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = multiMsgClient.deleteObject( + { + id: BigInt(423155), + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + expect(txHash).toBeDefined(); + }); + + test('createGroup', async () => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const groupName = generateString(5); + // eslint-disable-next-line no-console + console.log('groupName', groupName); + + const args = multiMsgClient.createGroup( + { + name: groupName, + owner: account.address, + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + expect(txHash).toBeDefined(); + }); + + test('createGroupCb', async () => { + const gasPrice = await crossChainClient.getCallbackGasPrice(); + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const groupName = generateString(5); + // eslint-disable-next-line no-console + console.log('groupName', groupName); + + const args = multiMsgClient.createGroup( + { + name: groupName, + owner: account.address, + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + cb: { + gasPrice, + gasLimit: BigInt(100000), + extraData: { + appAddress: account.address, + refundAddress: account.address, + failureHandleStrategy: 0, + callbackData: toHex(''), + }, + }, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + expect(txHash).toBeDefined(); + }); + + test('updateGroup', async () => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = multiMsgClient.updateGroup( + { + id: BigInt(546), + operator: account.address, + opType: 0, + extraData: '0x31', + memberExpiration: [BigInt(1734276997)], + members: ['0xe0523429ea945ced7bd3b170fd8dbe797778049b'], + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + expect(txHash).toBeDefined(); + }); + + test('deleteGroup', async () => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = multiMsgClient.deleteGroup( + { + id: BigInt(545), + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + expect(txHash).toBeDefined(); + }); + + test('createPolicy', async () => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = multiMsgClient.createPolicy( + { + id: '0', + resourceId: '234011', + resourceType: ResourceType.RESOURCE_TYPE_BUCKET, + statements: [ + { + effect: Effect.EFFECT_ALLOW, + actions: [ActionType.ACTION_DELETE_BUCKET], + resources: [], + }, + ], + principal: { + type: PrincipalType.PRINCIPAL_TYPE_GNFD_ACCOUNT, + value: '0x0C02787e83948e7aD29abE3a99b29c480f9F0096', + }, + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + expect(txHash).toBeDefined(); + }); + + test('deletePolicy', async () => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = multiMsgClient.deletePolicy( + { + id: BigInt(646), + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + expect(txHash).toBeDefined(); + }); + + test('transferOut', async () => { + const { relayFee, minAckRelayFee } = await crossChainClient.getRelayFee(); + + const args = multiMsgClient.transferOut( + { + recipient: zeroAddress, + amount: parseEther('0.0001'), + }, + { + sender: account.address, + minAckRelayFee, + relayFee, + }, + ); + + const txHash = await multiMsgClient.sendMessages([args]); + + // eslint-disable-next-line no-console + console.log('txHash', txHash); + expect(txHash).toBeDefined(); + }); +}); diff --git a/packages/bsc-cross-sdk/tests/utils.ts b/packages/bsc-cross-sdk/tests/utils.ts new file mode 100644 index 00000000..e0a6aca9 --- /dev/null +++ b/packages/bsc-cross-sdk/tests/utils.ts @@ -0,0 +1,11 @@ +export function generateString(length: number) { + const characters = 'abcdefghijklmnopqrstuvwxyz'; + + let result = ''; + const charactersLength = characters.length; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + + return result; +} diff --git a/packages/file-handle/CHANGELOG.md b/packages/file-handle/CHANGELOG.md deleted file mode 100644 index a768e541..00000000 --- a/packages/file-handle/CHANGELOG.md +++ /dev/null @@ -1,129 +0,0 @@ -# @bnb-chain/greenfiled-file-handle - -## 1.0.2 - -### Patch Changes - -- [#409](https://github.com/bnb-chain/greenfield-js-sdk/pull/409) - [`b97b305`](https://github.com/bnb-chain/greenfield-js-sdk/commit/b97b305ced1af7b9642f873be71167f673b84728) - Thanks [@rrr523](https://github.com/rrr523)! - fix: Multi cal hash - -## 1.0.1 - -### Patch Changes - -- [#407](https://github.com/bnb-chain/greenfield-js-sdk/pull/407) - [`5330912`](https://github.com/bnb-chain/greenfield-js-sdk/commit/5330912ee04935f7733e2453f75eca30f9cc7544) - Thanks [@rrr523](https://github.com/rrr523)! - feat: support multi thread hash cal. - -## 1.0.0 - -### Major Changes - -- [#365](https://github.com/bnb-chain/greenfield-js-sdk/pull/365) - [`57082ea`](https://github.com/bnb-chain/greenfield-js-sdk/commit/57082eace1beff17c2ab9b21d099ba6563fe94bf) - Thanks [@rrr523](https://github.com/rrr523)! - release 1.0.0 version - -## 1.0.0-alpha.0 - -### Major Changes - -- [#365](https://github.com/bnb-chain/greenfield-js-sdk/pull/365) - [`57082ea`](https://github.com/bnb-chain/greenfield-js-sdk/commit/57082eace1beff17c2ab9b21d099ba6563fe94bf) - Thanks [@rrr523](https://github.com/rrr523)! - release 1.0.0 version - -## 0.2.2 - -### Patch Changes - -- [#346](https://github.com/bnb-chain/greenfield-js-sdk/pull/346) - [`00a2cdd`](https://github.com/bnb-chain/greenfield-js-sdk/commit/00a2cddf98623c59780b6f8a8892674124d910c9) - Thanks [@rrr523](https://github.com/rrr523)! - chore: Update package.json - -- [#347](https://github.com/bnb-chain/greenfield-js-sdk/pull/347) - [`10c5723`](https://github.com/bnb-chain/greenfield-js-sdk/commit/10c572370abfa76c30c5f2f4b288cbc76efed6b1) - Thanks [@rrr523](https://github.com/rrr523)! - chore: Update deps - -## 0.2.2-alpha.0 - -### Patch Changes - -- [#346](https://github.com/bnb-chain/greenfield-js-sdk/pull/346) - [`00a2cdd`](https://github.com/bnb-chain/greenfield-js-sdk/commit/00a2cddf98623c59780b6f8a8892674124d910c9) - Thanks [@rrr523](https://github.com/rrr523)! - chore: Update package.json - -- [#347](https://github.com/bnb-chain/greenfield-js-sdk/pull/347) - [`10c5723`](https://github.com/bnb-chain/greenfield-js-sdk/commit/10c572370abfa76c30c5f2f4b288cbc76efed6b1) - Thanks [@rrr523](https://github.com/rrr523)! - chore: Update deps - -## 0.2.1 - -### Patch Changes - -- [#212](https://github.com/bnb-chain/greenfield-js-sdk/pull/212) - [`ab9d200`](https://github.com/bnb-chain/greenfield-js-sdk/commit/ab9d20036dda8e972db029025a6140e43c19464d) - Thanks [@rrr523](https://github.com/rrr523)! - feat: Using tinygo reduce size - -## 0.2.1-alpha.0 - -### Patch Changes - -- [#212](https://github.com/bnb-chain/greenfield-js-sdk/pull/212) - [`ab9d200`](https://github.com/bnb-chain/greenfield-js-sdk/commit/ab9d20036dda8e972db029025a6140e43c19464d) - Thanks [@rrr523](https://github.com/rrr523)! - feat: Using tinygo reduce size - -## 0.2.0 - -### Minor Changes - -- [#38](https://github.com/bnb-chain/greenfield-js-sdk/pull/38) - [`cee97f8`](https://github.com/bnb-chain/greenfield-js-sdk/commit/cee97f8e373175392da33943863b81555f6d2255) - Thanks [@rrr523](https://github.com/rrr523)! - New Client - -### Patch Changes - -- [#38](https://github.com/bnb-chain/greenfield-js-sdk/pull/38) - [`cee97f8`](https://github.com/bnb-chain/greenfield-js-sdk/commit/cee97f8e373175392da33943863b81555f6d2255) - Thanks [@rrr523](https://github.com/rrr523)! - support commonjs export - -- [#38](https://github.com/bnb-chain/greenfield-js-sdk/pull/38) - [`cee97f8`](https://github.com/bnb-chain/greenfield-js-sdk/commit/cee97f8e373175392da33943863b81555f6d2255) - Thanks [@rrr523](https://github.com/rrr523)! - Query support nodejs and browser - -## 0.1.0 - -### Minor Changes - -- [#33](https://github.com/bnb-chain/greenfield-js-sdk/pull/33) - [`b8c0ba0`](https://github.com/bnb-chain/greenfield-js-sdk/commit/b8c0ba0f7a5ebae8e1c682bc9c6c0959d5ede8c5) - Thanks [@rrr523](https://github.com/rrr523)! - New Client - -### Patch Changes - -- [#33](https://github.com/bnb-chain/greenfield-js-sdk/pull/33) - [`b8c0ba0`](https://github.com/bnb-chain/greenfield-js-sdk/commit/b8c0ba0f7a5ebae8e1c682bc9c6c0959d5ede8c5) - Thanks [@rrr523](https://github.com/rrr523)! - support commonjs export - -- [#33](https://github.com/bnb-chain/greenfield-js-sdk/pull/33) - [`b8c0ba0`](https://github.com/bnb-chain/greenfield-js-sdk/commit/b8c0ba0f7a5ebae8e1c682bc9c6c0959d5ede8c5) - Thanks [@rrr523](https://github.com/rrr523)! - Query support nodejs and browser - -## 0.1.0-alpha.1 - -### Patch Changes - -- [#28](https://github.com/bnb-chain/greenfield-js-sdk/pull/28) - [`884b824`](https://github.com/bnb-chain/greenfield-js-sdk/commit/884b8243c75544cee079b49ccb27b227be554b01) - Thanks [@ybgbob](https://github.com/ybgbob)! - support commonjs export - -- [#28](https://github.com/bnb-chain/greenfield-js-sdk/pull/28) - [`884b824`](https://github.com/bnb-chain/greenfield-js-sdk/commit/884b8243c75544cee079b49ccb27b227be554b01) - Thanks [@ybgbob](https://github.com/ybgbob)! - Query support nodejs and browser - -## 0.1.0-alpha.0 - -### Minor Changes - -- [#20](https://github.com/bnb-chain/greenfield-js-sdk/pull/20) - [`2a22a57`](https://github.com/bnb-chain/greenfield-js-sdk/commit/2a22a57b4a266d3ff28918b4c8ca47a42a6edd1d) - Thanks [@rrr523](https://github.com/rrr523)! - New Client diff --git a/packages/file-handle/README.md b/packages/file-handle/README.md deleted file mode 100644 index 636f20b9..00000000 --- a/packages/file-handle/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# Greenfield Files JS SDK (Deprecated!) - -> Move to [reed-solomon](../reed-solomon/README.md) - -WASM module that handle file, such as `checksums` method. - -## Usage on Nodejs - -```javascript -const fs = require('fs') -const { getCheckSums } = require('@bnb-chain/greenfiled-file-handle'); -const fileBuffer = fs.readFileSync('./CHANGELOG.md'); - -(async () => { - const { contentLength, expectCheckSums } = await getCheckSums(fileBuffer); -})() -``` - -Full Code: https://github.com/bnb-chain/greenfield-js-sdk/blob/main/examples/nodejs/storage.js - -## Usage on Browser - -load wasm: - -```html - - -``` - -execute wasm: - -```javascript -(async () => { - // file is from input element - const fileBytes = await file.arrayBuffer(); - const hashResult = await (window as any).FileHandle.getCheckSums( - new Uint8Array(fileBytes), - ); - const { contentLength, expectCheckSums } = hashResult; -})() -``` - -Full Code: https://github.com/bnb-chain/greenfield-js-sdk/blob/main/examples/nextjs/src/components/object/create/index.tsx#L63 diff --git a/packages/file-handle/package.json b/packages/file-handle/package.json deleted file mode 100644 index a67f7c34..00000000 --- a/packages/file-handle/package.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "name": "@bnb-chain/greenfiled-file-handle", - "version": "1.0.2", - "description": "checksums wasm package", - "module": "./dist/browser/esm/index.js", - "main": "./dist/node/index.js", - "types": "./types/index.d.ts", - "exports": { - ".": { - "import": "./dist/browser/esm/index.js", - "main": "./dist/node/index.js", - "default": "./dist/node/index.js", - "types": "./types/index.d.ts" - }, - "./file-handle.wasm": "./dist/node/file-handle.wasm" - }, - "scripts": { - "predev": "rimraf ./dist", - "dev": "weboack -w", - "prebuild": "rimraf ./dist", - "build": "webpack", - "test": "" - }, - "repository": { - "type": "git", - "url": "https://github.com/bnb-chain/greenfield-js-sdk", - "directory": "packages/file-handle" - }, - "homepage": "https://github.com/bnb-chain/greenfield-js-sdk/tree/alpha/packages/file-handle#readme", - "bugs": "https://github.com/bnb-chain/greenfield-js-sdk/issues", - "keywords": [ - "greenfiled", - "checksums" - ], - "author": "", - "license": "GPLv3", - "engines": { - "yarn": "please use pnpm", - "npm": "please use pnpm" - }, - "files": [ - "dist", - "types" - ], - "publishConfig": { - "registry": "https://registry.npmjs.org/", - "access": "public" - }, - "browserslist": { - "production": [ - "last 2 chrome version", - "last 2 firefox version", - "last 2 safari version", - "last 2 edge version" - ] - }, - "devDependencies": { - "clean-webpack-plugin": "^4.0.0", - "copy-webpack-plugin": "^11.0.0", - "rimraf": "^3.0.2", - "typescript": "^5.1.6", - "webpack": "^5.88.1", - "webpack-cli": "^5.1.4" - }, - "dependencies": { - "buffer": "^6.0.3", - "hash-wasm": "^4.11.0", - "lodash-es": "^4.17.21" - } -} diff --git a/packages/file-handle/src/browser/index.js b/packages/file-handle/src/browser/index.js deleted file mode 100644 index 32a30dbc..00000000 --- a/packages/file-handle/src/browser/index.js +++ /dev/null @@ -1,32 +0,0 @@ -import { ensureServiceIsRunning, initialize, instantiateWASM } from './init'; -import { DEFAULT_DATA_BLOCKS, DEFAULT_PARITY_BLOCKS, DEFAULT_SEGMENT_SIZE } from '../constants'; -import { getChecksumApi } from './worker/index'; - -// 1. modify method of `exports` and `globalThis` export. -export const startRunningService = async (wasmURL) => { - const module = await instantiateWASM(wasmURL); - module.instance.exports; - - // `exports` is a map to `//export` way of TinyGo way. - // const { add } = exports; - - // `globalThis` is a map to complex way of `syscall/js` way. - const { getCheckSums } = globalThis; - - return { - getCheckSums, - }; -}; - -export const getCheckSums = async ( - bytes, - segmentSize = DEFAULT_SEGMENT_SIZE, - dataBlocks = DEFAULT_DATA_BLOCKS, - parityBlocks = DEFAULT_PARITY_BLOCKS, -) => { - await initialize(); - return ensureServiceIsRunning().getCheckSums(bytes, segmentSize, dataBlocks, parityBlocks); -}; - -// please keep singleton -export const getCheckSumsWorker = getChecksumApi; diff --git a/packages/file-handle/src/browser/init.js b/packages/file-handle/src/browser/init.js deleted file mode 100644 index c753ec0f..00000000 --- a/packages/file-handle/src/browser/init.js +++ /dev/null @@ -1,47 +0,0 @@ -import { startRunningService } from '.'; -import Go from './wasm_exec.js'; - -export const initialize = async () => { - if (!initializePromise) { - const input = window.__PUBLIC_FILE_HANDLE_WASM_PATH__; - initializePromise = startRunningService(input).catch((err) => { - // Let the caller try again if this fails. - initializePromise = void 0; - // But still, throw the error back up the caller. - throw err; - }); - } - longLivedService = longLivedService || (await initializePromise); -}; - -export const instantiateWASM = async (wasmURL) => { - let module = undefined; - const go = new Go(); - - if (!WebAssembly.instantiateStreaming) { - WebAssembly.instantiateStreaming = async (resp, importObject) => { - const source = await (await resp).arrayBuffer(); - return await WebAssembly.instantiate(source, importObject); - }; - } - - const fetchAndInstantiateTask = async () => { - return WebAssembly.instantiateStreaming(fetch(wasmURL), go.importObject); - }; - module = await fetchAndInstantiateTask(); - go.run(module.instance); - - return module; -}; - -let initializePromise; -let longLivedService; - -export const ensureServiceIsRunning = () => { - if (!initializePromise) throw new Error('You need to call "initialize" before calling this'); - if (!longLivedService) - throw new Error( - 'You need to wait for the promise returned from "initialize" to be resolved before calling this', - ); - return longLivedService; -}; diff --git a/packages/file-handle/src/browser/wasm_exec.js b/packages/file-handle/src/browser/wasm_exec.js deleted file mode 100644 index 56d7352b..00000000 --- a/packages/file-handle/src/browser/wasm_exec.js +++ /dev/null @@ -1,608 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// This file has been modified for use by the TinyGo compiler. - -// Map multiple JavaScript environments to a single common API, -// preferring web standards over Node.js API. -// -// Environments considered: -// - Browsers -// - Node.js -// - Electron -// - Parcel - -if (typeof global !== 'undefined') { - // global already exists -} else if (typeof window !== 'undefined') { - window.global = window; -} else if (typeof self !== 'undefined') { - self.global = self; -} else { - throw new Error('cannot export Go (neither global, window nor self is defined)'); -} - -if (!global.require && typeof require !== 'undefined') { - global.require = require; -} - -if (!global.fs && global.require) { - global.fs = require('fs'); -} - -const enosys = () => { - const err = new Error('not implemented'); - err.code = 'ENOSYS'; - return err; -}; - -if (!global.fs) { - let outputBuf = ''; - global.fs = { - constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused - writeSync(fd, buf) { - outputBuf += decoder.decode(buf); - const nl = outputBuf.lastIndexOf('\n'); - if (nl != -1) { - console.log(outputBuf.substr(0, nl)); - outputBuf = outputBuf.substr(nl + 1); - } - return buf.length; - }, - write(fd, buf, offset, length, position, callback) { - if (offset !== 0 || length !== buf.length || position !== null) { - callback(enosys()); - return; - } - const n = this.writeSync(fd, buf); - callback(null, n); - }, - chmod(path, mode, callback) { - callback(enosys()); - }, - chown(path, uid, gid, callback) { - callback(enosys()); - }, - close(fd, callback) { - callback(enosys()); - }, - fchmod(fd, mode, callback) { - callback(enosys()); - }, - fchown(fd, uid, gid, callback) { - callback(enosys()); - }, - fstat(fd, callback) { - callback(enosys()); - }, - fsync(fd, callback) { - callback(null); - }, - ftruncate(fd, length, callback) { - callback(enosys()); - }, - lchown(path, uid, gid, callback) { - callback(enosys()); - }, - link(path, link, callback) { - callback(enosys()); - }, - lstat(path, callback) { - callback(enosys()); - }, - mkdir(path, perm, callback) { - callback(enosys()); - }, - open(path, flags, mode, callback) { - callback(enosys()); - }, - read(fd, buffer, offset, length, position, callback) { - callback(enosys()); - }, - readdir(path, callback) { - callback(enosys()); - }, - readlink(path, callback) { - callback(enosys()); - }, - rename(from, to, callback) { - callback(enosys()); - }, - rmdir(path, callback) { - callback(enosys()); - }, - stat(path, callback) { - callback(enosys()); - }, - symlink(path, link, callback) { - callback(enosys()); - }, - truncate(path, length, callback) { - callback(enosys()); - }, - unlink(path, callback) { - callback(enosys()); - }, - utimes(path, atime, mtime, callback) { - callback(enosys()); - }, - }; -} - -if (!global.process) { - global.process = { - getuid() { - return -1; - }, - getgid() { - return -1; - }, - geteuid() { - return -1; - }, - getegid() { - return -1; - }, - getgroups() { - throw enosys(); - }, - pid: -1, - ppid: -1, - umask() { - throw enosys(); - }, - cwd() { - throw enosys(); - }, - chdir() { - throw enosys(); - }, - }; -} - -if (!global.crypto) { - const nodeCrypto = require('crypto'); - global.crypto = { - getRandomValues(b) { - nodeCrypto.randomFillSync(b); - }, - }; -} - -if (!global.performance) { - global.performance = { - now() { - const [sec, nsec] = process.hrtime(); - return sec * 1000 + nsec / 1000000; - }, - }; -} - -if (!global.TextEncoder) { - global.TextEncoder = require('util').TextEncoder; -} - -if (!global.TextDecoder) { - global.TextDecoder = require('util').TextDecoder; -} - -// End of polyfills for common API. - -const encoder = new TextEncoder('utf-8'); -const decoder = new TextDecoder('utf-8'); -var logLine = []; - -export default class Go { - importObject; - constructor() { - this._callbackTimeouts = new Map(); - this._nextCallbackTimeoutID = 1; - - const mem = () => { - // The buffer may change when requesting more memory. - return new DataView(this._inst.exports.memory.buffer); - }; - - const setInt64 = (addr, v) => { - mem().setUint32(addr + 0, v, true); - mem().setUint32(addr + 4, Math.floor(v / 4294967296), true); - }; - - const getInt64 = (addr) => { - const low = mem().getUint32(addr + 0, true); - const high = mem().getInt32(addr + 4, true); - return low + high * 4294967296; - }; - - const loadValue = (addr) => { - const f = mem().getFloat64(addr, true); - if (f === 0) { - return undefined; - } - if (!isNaN(f)) { - return f; - } - - const id = mem().getUint32(addr, true); - return this._values[id]; - }; - - const storeValue = (addr, v) => { - const nanHead = 0x7ff80000; - - if (typeof v === 'number') { - if (isNaN(v)) { - mem().setUint32(addr + 4, nanHead, true); - mem().setUint32(addr, 0, true); - return; - } - if (v === 0) { - mem().setUint32(addr + 4, nanHead, true); - mem().setUint32(addr, 1, true); - return; - } - mem().setFloat64(addr, v, true); - return; - } - - switch (v) { - case undefined: - mem().setFloat64(addr, 0, true); - return; - case null: - mem().setUint32(addr + 4, nanHead, true); - mem().setUint32(addr, 2, true); - return; - case true: - mem().setUint32(addr + 4, nanHead, true); - mem().setUint32(addr, 3, true); - return; - case false: - mem().setUint32(addr + 4, nanHead, true); - mem().setUint32(addr, 4, true); - return; - } - - let id = this._ids.get(v); - if (id === undefined) { - id = this._idPool.pop(); - if (id === undefined) { - id = this._values.length; - } - this._values[id] = v; - this._goRefCounts[id] = 0; - this._ids.set(v, id); - } - this._goRefCounts[id]++; - let typeFlag = 1; - switch (typeof v) { - case 'string': - typeFlag = 2; - break; - case 'symbol': - typeFlag = 3; - break; - case 'function': - typeFlag = 4; - break; - } - mem().setUint32(addr + 4, nanHead | typeFlag, true); - mem().setUint32(addr, id, true); - }; - - const loadSlice = (array, len, cap) => { - return new Uint8Array(this._inst.exports.memory.buffer, array, len); - }; - - const loadSliceOfValues = (array, len, cap) => { - const a = new Array(len); - for (let i = 0; i < len; i++) { - a[i] = loadValue(array + i * 8); - } - return a; - }; - - const loadString = (ptr, len) => { - return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len)); - }; - - const timeOrigin = Date.now() - performance.now(); - this.importObject = { - wasi_snapshot_preview1: { - // https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write - fd_write: function (fd, iovs_ptr, iovs_len, nwritten_ptr) { - let nwritten = 0; - if (fd == 1) { - for (let iovs_i = 0; iovs_i < iovs_len; iovs_i++) { - let iov_ptr = iovs_ptr + iovs_i * 8; // assuming wasm32 - let ptr = mem().getUint32(iov_ptr + 0, true); - let len = mem().getUint32(iov_ptr + 4, true); - nwritten += len; - for (let i = 0; i < len; i++) { - let c = mem().getUint8(ptr + i); - if (c == 13) { - // CR - // ignore - } else if (c == 10) { - // LF - // write line - let line = decoder.decode(new Uint8Array(logLine)); - logLine = []; - console.log(line); - } else { - logLine.push(c); - } - } - } - } else { - console.error('invalid file descriptor:', fd); - } - mem().setUint32(nwritten_ptr, nwritten, true); - return 0; - }, - fd_close: () => 0, // dummy - fd_fdstat_get: () => 0, // dummy - fd_seek: () => 0, // dummy - proc_exit: (code) => { - if (global.process) { - // Node.js - process.exit(code); - } else { - // Can't exit in a browser. - throw 'trying to exit with code ' + code; - } - }, - random_get: (bufPtr, bufLen) => { - crypto.getRandomValues(loadSlice(bufPtr, bufLen)); - return 0; - }, - }, - env: { - // func ticks() float64 - 'runtime.ticks': () => { - return timeOrigin + performance.now(); - }, - - // func sleepTicks(timeout float64) - 'runtime.sleepTicks': (timeout) => { - // Do not sleep, only reactivate scheduler after the given timeout. - setTimeout(this._inst.exports.go_scheduler, timeout); - }, - - // func finalizeRef(v ref) - 'syscall/js.finalizeRef': (v_addr) => { - // Note: TinyGo does not support finalizers so this is only called - // for one specific case, by js.go:jsString. - const id = mem().getUint32(v_addr, true); - this._goRefCounts[id]--; - if (this._goRefCounts[id] === 0) { - const v = this._values[id]; - this._values[id] = null; - this._ids.delete(v); - this._idPool.push(id); - } - }, - - // func stringVal(value string) ref - 'syscall/js.stringVal': (ret_ptr, value_ptr, value_len) => { - const s = loadString(value_ptr, value_len); - storeValue(ret_ptr, s); - }, - - // func valueGet(v ref, p string) ref - 'syscall/js.valueGet': (retval, v_addr, p_ptr, p_len) => { - let prop = loadString(p_ptr, p_len); - let value = loadValue(v_addr); - let result = Reflect.get(value, prop); - storeValue(retval, result); - }, - - // func valueSet(v ref, p string, x ref) - 'syscall/js.valueSet': (v_addr, p_ptr, p_len, x_addr) => { - const v = loadValue(v_addr); - const p = loadString(p_ptr, p_len); - const x = loadValue(x_addr); - Reflect.set(v, p, x); - }, - - // func valueDelete(v ref, p string) - 'syscall/js.valueDelete': (v_addr, p_ptr, p_len) => { - const v = loadValue(v_addr); - const p = loadString(p_ptr, p_len); - Reflect.deleteProperty(v, p); - }, - - // func valueIndex(v ref, i int) ref - 'syscall/js.valueIndex': (ret_addr, v_addr, i) => { - storeValue(ret_addr, Reflect.get(loadValue(v_addr), i)); - }, - - // valueSetIndex(v ref, i int, x ref) - 'syscall/js.valueSetIndex': (v_addr, i, x_addr) => { - Reflect.set(loadValue(v_addr), i, loadValue(x_addr)); - }, - - // func valueCall(v ref, m string, args []ref) (ref, bool) - 'syscall/js.valueCall': (ret_addr, v_addr, m_ptr, m_len, args_ptr, args_len, args_cap) => { - const v = loadValue(v_addr); - const name = loadString(m_ptr, m_len); - const args = loadSliceOfValues(args_ptr, args_len, args_cap); - try { - const m = Reflect.get(v, name); - storeValue(ret_addr, Reflect.apply(m, v, args)); - mem().setUint8(ret_addr + 8, 1); - } catch (err) { - storeValue(ret_addr, err); - mem().setUint8(ret_addr + 8, 0); - } - }, - - // func valueInvoke(v ref, args []ref) (ref, bool) - 'syscall/js.valueInvoke': (ret_addr, v_addr, args_ptr, args_len, args_cap) => { - try { - const v = loadValue(v_addr); - const args = loadSliceOfValues(args_ptr, args_len, args_cap); - storeValue(ret_addr, Reflect.apply(v, undefined, args)); - mem().setUint8(ret_addr + 8, 1); - } catch (err) { - storeValue(ret_addr, err); - mem().setUint8(ret_addr + 8, 0); - } - }, - - // func valueNew(v ref, args []ref) (ref, bool) - 'syscall/js.valueNew': (ret_addr, v_addr, args_ptr, args_len, args_cap) => { - const v = loadValue(v_addr); - const args = loadSliceOfValues(args_ptr, args_len, args_cap); - try { - storeValue(ret_addr, Reflect.construct(v, args)); - mem().setUint8(ret_addr + 8, 1); - } catch (err) { - storeValue(ret_addr, err); - mem().setUint8(ret_addr + 8, 0); - } - }, - - // func valueLength(v ref) int - 'syscall/js.valueLength': (v_addr) => { - return loadValue(v_addr).length; - }, - - // valuePrepareString(v ref) (ref, int) - 'syscall/js.valuePrepareString': (ret_addr, v_addr) => { - const s = String(loadValue(v_addr)); - const str = encoder.encode(s); - storeValue(ret_addr, str); - setInt64(ret_addr + 8, str.length); - }, - - // valueLoadString(v ref, b []byte) - 'syscall/js.valueLoadString': (v_addr, slice_ptr, slice_len, slice_cap) => { - const str = loadValue(v_addr); - loadSlice(slice_ptr, slice_len, slice_cap).set(str); - }, - - // func valueInstanceOf(v ref, t ref) bool - 'syscall/js.valueInstanceOf': (v_addr, t_addr) => { - return loadValue(v_addr) instanceof loadValue(t_addr); - }, - - // func copyBytesToGo(dst []byte, src ref) (int, bool) - 'syscall/js.copyBytesToGo': (ret_addr, dest_addr, dest_len, dest_cap, source_addr) => { - let num_bytes_copied_addr = ret_addr; - let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable - - const dst = loadSlice(dest_addr, dest_len); - const src = loadValue(source_addr); - if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) { - mem().setUint8(returned_status_addr, 0); // Return "not ok" status - return; - } - const toCopy = src.subarray(0, dst.length); - dst.set(toCopy); - setInt64(num_bytes_copied_addr, toCopy.length); - mem().setUint8(returned_status_addr, 1); // Return "ok" status - }, - - // copyBytesToJS(dst ref, src []byte) (int, bool) - // Originally copied from upstream Go project, then modified: - // https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416 - 'syscall/js.copyBytesToJS': (ret_addr, dest_addr, source_addr, source_len, source_cap) => { - let num_bytes_copied_addr = ret_addr; - let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable - - const dst = loadValue(dest_addr); - const src = loadSlice(source_addr, source_len); - if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) { - mem().setUint8(returned_status_addr, 0); // Return "not ok" status - return; - } - const toCopy = src.subarray(0, dst.length); - dst.set(toCopy); - setInt64(num_bytes_copied_addr, toCopy.length); - mem().setUint8(returned_status_addr, 1); // Return "ok" status - }, - }, - }; - } - - async run(instance) { - this._inst = instance; - this._values = [ - // JS values that Go currently has references to, indexed by reference id - NaN, - 0, - null, - true, - false, - global, - this, - ]; - this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id - this._ids = new Map(); // mapping from JS values to reference ids - this._idPool = []; // unused ids that have been garbage collected - this.exited = false; // whether the Go program has exited - - const mem = new DataView(this._inst.exports.memory.buffer); - - while (true) { - const callbackPromise = new Promise((resolve) => { - this._resolveCallbackPromise = () => { - if (this.exited) { - throw new Error('bad callback: Go program has already exited'); - } - setTimeout(resolve, 0); // make sure it is asynchronous - }; - }); - this._inst.exports._start(); - if (this.exited) { - break; - } - await callbackPromise; - } - } - - _resume() { - if (this.exited) { - throw new Error('Go program has already exited'); - } - this._inst.exports.resume(); - if (this.exited) { - this._resolveExitPromise(); - } - } - - _makeFuncWrapper(id) { - const go = this; - return function () { - const event = { id: id, this: this, args: arguments }; - go._pendingEvent = event; - go._resume(); - return event.result; - }; - } -} - -// if ( -// global.require && -// global.require.main === module && -// global.process && -// global.process.versions && -// !global.process.versions.electron -// ) { -// if (process.argv.length != 3) { -// console.error("usage: go_js_wasm_exec [wasm binary] [arguments]"); -// process.exit(1); -// } - -// const go = new Go(); -// WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => { -// return go.run(result.instance); -// }).catch((err) => { -// console.error(err); -// process.exit(1); -// }); -// } diff --git a/packages/file-handle/src/browser/worker/index.js b/packages/file-handle/src/browser/worker/index.js deleted file mode 100644 index 170885cc..00000000 --- a/packages/file-handle/src/browser/worker/index.js +++ /dev/null @@ -1,291 +0,0 @@ -import { Buffer } from 'buffer'; -import { sha256 } from 'hash-wasm'; -import { values } from 'lodash-es'; -import { encodeBase64 } from '../../utils'; - -export function getChecksumApi() { - const segmentSize = 16 * 1024 * 1024; - const dataBlocks = 4; - const parityBlocks = 2; - const WORKER_POOL_SIZE = 6; - - const _createFileChunks = (file) => { - if (!file.size) return [{ file }]; - const SIZE = segmentSize; - const fileChunkList = []; - let cur = 0; - while (cur < file.size) { - fileChunkList.push({ file: file.slice(cur, cur + SIZE) }); - cur += SIZE; - } - return fileChunkList; - }; - - const _generateIntegrityHash = async (list) => { - const hex = await sha256(Buffer.from(list.join(''), 'hex')); - return encodeBase64(Uint8Array.from(Buffer.from(hex, 'hex'))); - }; - - const primaryWorkerScript = ` - importScripts('https://unpkg.com/hash-wasm@4.11.0/dist/sha256.umd.min.js') - const encodePrimary = async (chunkId, buffer) => { - const primary = await hashwasm.sha256(new Uint8Array(buffer)); - return [chunkId, primary]; - }; - - onmessage = async (e) => { - const { chunkId, buffer, taskId } = e.data; - const result = await encodePrimary(chunkId, buffer); - - postMessage({ - result, - taskId, - }); - }; - - `; - const _initPrimaryWorkers = ({ consumers }) => { - const workers = new Array(WORKER_POOL_SIZE).fill(1).map(() => { - // return new Worker(new URL('./calcPrimaryWorker', import.meta.url)); - return new Worker( - URL.createObjectURL(new Blob([primaryWorkerScript], { type: 'text/javascript' })), - ); - }); - workers.forEach((it) => { - it.onmessage = (e) => { - const { result, taskId } = e.data; - const id = result[0]; - if (!consumers[id]) return; - const { resolve, data, taskId: _taskId } = consumers[id]; - if (taskId !== _taskId) return; - data[result[0]] = result[1]; - resolve(); - }; - }); - - return workers; - }; - - const workerScript = ` - importScripts('https://unpkg.com/hash-wasm@4.11.0/dist/sha256.umd.min.js') - importScripts('https://unpkg.com/@bnb-chain/greenfiled-file-handle/dist/browser/esm/wasm_exec-worker.js'); - function getDecodeBase64Length(data) { - let bufferLength = Math.floor(data.length * 0.75); - const len = data.length; - - if (data[len - 1] === '=') { - bufferLength -= 1; - if (data[len - 2] === '=') { - bufferLength -= 1; - } - } - - return bufferLength; - } - const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - const base64Lookup = new Uint8Array(256); - for (let i = 0; i < base64Chars.length; i++) { - base64Lookup[base64Chars.charCodeAt(i)] = i; - } - - function decodeBase64(data) { - const bufferLength = getDecodeBase64Length(data); - const len = data.length; - - const bytes = new Uint8Array(bufferLength); - - let p = 0; - for (let i = 0; i < len; i += 4) { - const encoded1 = base64Lookup[data.charCodeAt(i)]; - const encoded2 = base64Lookup[data.charCodeAt(i + 1)]; - const encoded3 = base64Lookup[data.charCodeAt(i + 2)]; - const encoded4 = base64Lookup[data.charCodeAt(i + 3)]; - - bytes[p] = (encoded1 << 2) | (encoded2 >> 4); - p += 1; - bytes[p] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - p += 1; - bytes[p] = ((encoded3 & 3) << 6) | (encoded4 & 63); - p += 1; - } - - return bytes; - } - const init = async () => { - const go = new Go(); - const result = await WebAssembly.instantiateStreaming( - fetch('https://unpkg.com/@bnb-chain/greenfiled-file-handle/dist/node/file-handle-worker.wasm'), - go.importObject, - ); - if (result) { - go.run(result.instance); - // Ensure hash-wasm initial success, - // Otherwise, after the browser finishes loading the page, - // the user immediately uploads a large object, - // and hash-wasm has a certain probability of initialization failure due to memory problems in chrome. - await hashwasm.sha256(''); - } - }; - - init(); - - const encodeSegment = async ( - chunkId, - buffer, - dataBlocks, - parityBlocks, - ) => { - const results = []; - const bytes = new Uint8Array(buffer); - - if (typeof encodeRawSegment === 'undefined') { - await init(); - } - const result = encodeRawSegment(bytes, dataBlocks, parityBlocks); - const shards = JSON.parse(result.result); - - // Empty chunks should also return digest arrays of the corresponding length. - await Promise.all( - shards.map(async (shard, idx) => { - if (!results[idx]) { - results[idx] = []; - } - const hex = await hashwasm.sha256(decodeBase64(shard || '')); - results[idx].unshift(hex); - }), - ); - - return [chunkId, results]; - }; - - onmessage = async (e) => { - const { chunkId, buffer, dataBlocks, parityBlocks, taskId } = e.data; - - const result = await encodeSegment(chunkId, buffer, dataBlocks, parityBlocks); - - postMessage({ - result, - taskId, - }); - }; - `; - - const _initSecondWorkers = ({ consumers }) => { - const workers = new Array(WORKER_POOL_SIZE).fill(1).map(() => { - // return new Worker(new URL('./calcSecondWorker', import.meta.url)); - return new Worker(URL.createObjectURL(new Blob([workerScript], { type: 'text/javascript' }))); - }); - workers.forEach((it) => { - it.onmessage = (e) => { - const { result, taskId } = e.data; - const id = result[0]; - if (!consumers[id]) return; - const { resolve, data, taskId: _taskId } = consumers[id]; - if (taskId !== _taskId) return; - data[result[0]] = result[1]; - resolve(); - }; - }); - - return workers; - }; - - // js vm instance memory will not release immediately. try reuse worker thread. - let primaryWorkers = []; - let secondWorkers = []; - - const primaryWorkerConsumers = {}; - primaryWorkers = _initPrimaryWorkers({ - consumers: primaryWorkerConsumers, - }); - - const secondWorkerConsumers = {}; - secondWorkers = _initSecondWorkers({ - consumers: secondWorkerConsumers, - }); - - const generateCheckSumV2 = async (file) => { - if (!file) return {}; - - const taskId = Date.now(); - let checkSumRes; - - values(primaryWorkerConsumers).forEach((r) => r.resolve()); - values(secondWorkerConsumers).forEach((r) => r.resolve()); - - try { - const fileChunks = _createFileChunks(file); - const secondResults = []; - const primaryResults = []; - - const segments = fileChunks.map(async (fileItem, chunkId) => { - const buffer = await fileItem.file.arrayBuffer(); - - const primaryPromise = new Promise((resolve) => { - primaryWorkerConsumers[chunkId] = { - resolve, - data: primaryResults, - taskId, - }; - - const workerIdx = chunkId % WORKER_POOL_SIZE; - primaryWorkers[workerIdx].postMessage({ chunkId, buffer, taskId }); - }); - - // shards - const shardsPromise = new Promise((resolve) => { - secondWorkerConsumers[chunkId] = { - resolve, - data: secondResults, - taskId, - }; - - const workerIdx = chunkId % WORKER_POOL_SIZE; - secondWorkers[workerIdx].postMessage({ - chunkId, - buffer, - dataBlocks, - parityBlocks, - taskId, - }); - }); - - return Promise.all([shardsPromise, primaryPromise]); - }); - - await Promise.all(segments); - - const combinedShards = []; - secondResults.forEach((items, idx) => { - items.forEach((child, childIdx) => { - if (!combinedShards[childIdx]) { - combinedShards[childIdx] = []; - } else if (!combinedShards[childIdx][idx]) { - combinedShards[childIdx][idx] = []; - } - combinedShards[childIdx][idx] = child[0]; - }); - }); - - const primaryCheckSum = await _generateIntegrityHash(primaryResults); - const secondsCheckSum = await Promise.all( - combinedShards.map((it) => _generateIntegrityHash(it)), - ); - const value = [primaryCheckSum].concat(secondsCheckSum); - checkSumRes = { - fileChunks: fileChunks.length, - contentLength: file.size, - expectCheckSums: value, - }; - } catch (e) { - // eslint-disable-next-line no-console - console.log('check sum error', e); - } - - return checkSumRes; - }; - - return { - generateCheckSumV2, - }; -} diff --git a/packages/file-handle/src/browser/worker/wasm_exec-worker.js b/packages/file-handle/src/browser/worker/wasm_exec-worker.js deleted file mode 100644 index b793fc0e..00000000 --- a/packages/file-handle/src/browser/worker/wasm_exec-worker.js +++ /dev/null @@ -1,634 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -'use strict'; - -(() => { - const enosys = () => { - const err = new Error('not implemented'); - err.code = 'ENOSYS'; - return err; - }; - - if (!globalThis.fs) { - let outputBuf = ''; - globalThis.fs = { - constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused - writeSync(fd, buf) { - outputBuf += decoder.decode(buf); - const nl = outputBuf.lastIndexOf('\n'); - if (nl != -1) { - // eslint-disable-next-line no-console - console.log(outputBuf.substring(0, nl)); - outputBuf = outputBuf.substring(nl + 1); - } - return buf.length; - }, - write(fd, buf, offset, length, position, callback) { - if (offset !== 0 || length !== buf.length || position !== null) { - callback(enosys()); - return; - } - const n = this.writeSync(fd, buf); - callback(null, n); - }, - chmod(path, mode, callback) { - callback(enosys()); - }, - chown(path, uid, gid, callback) { - callback(enosys()); - }, - close(fd, callback) { - callback(enosys()); - }, - fchmod(fd, mode, callback) { - callback(enosys()); - }, - fchown(fd, uid, gid, callback) { - callback(enosys()); - }, - fstat(fd, callback) { - callback(enosys()); - }, - fsync(fd, callback) { - callback(null); - }, - ftruncate(fd, length, callback) { - callback(enosys()); - }, - lchown(path, uid, gid, callback) { - callback(enosys()); - }, - link(path, link, callback) { - callback(enosys()); - }, - lstat(path, callback) { - callback(enosys()); - }, - mkdir(path, perm, callback) { - callback(enosys()); - }, - open(path, flags, mode, callback) { - callback(enosys()); - }, - read(fd, buffer, offset, length, position, callback) { - callback(enosys()); - }, - readdir(path, callback) { - callback(enosys()); - }, - readlink(path, callback) { - callback(enosys()); - }, - rename(from, to, callback) { - callback(enosys()); - }, - rmdir(path, callback) { - callback(enosys()); - }, - stat(path, callback) { - callback(enosys()); - }, - symlink(path, link, callback) { - callback(enosys()); - }, - truncate(path, length, callback) { - callback(enosys()); - }, - unlink(path, callback) { - callback(enosys()); - }, - utimes(path, atime, mtime, callback) { - callback(enosys()); - }, - }; - } - - if (!globalThis.process) { - globalThis.process = { - getuid() { - return -1; - }, - getgid() { - return -1; - }, - geteuid() { - return -1; - }, - getegid() { - return -1; - }, - getgroups() { - throw enosys(); - }, - pid: -1, - ppid: -1, - umask() { - throw enosys(); - }, - cwd() { - throw enosys(); - }, - chdir() { - throw enosys(); - }, - }; - } - - if (!globalThis.crypto) { - throw new Error( - 'globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)', - ); - } - - if (!globalThis.performance) { - throw new Error( - 'globalThis.performance is not available, polyfill required (performance.now only)', - ); - } - - if (!globalThis.TextEncoder) { - throw new Error('globalThis.TextEncoder is not available, polyfill required'); - } - - if (!globalThis.TextDecoder) { - throw new Error('globalThis.TextDecoder is not available, polyfill required'); - } - - const encoder = new TextEncoder('utf-8'); - const decoder = new TextDecoder('utf-8'); - - globalThis.Go = class { - constructor() { - this.argv = ['js']; - this.env = {}; - this.exit = (code) => { - if (code !== 0) { - // eslint-disable-next-line no-console - console.warn('exit code:', code); - } - }; - this._exitPromise = new Promise((resolve) => { - this._resolveExitPromise = resolve; - }); - this._pendingEvent = null; - this._scheduledTimeouts = new Map(); - this._nextCallbackTimeoutID = 1; - - const setInt64 = (addr, v) => { - this.mem.setUint32(addr + 0, v, true); - this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true); - }; - - const setInt32 = (addr, v) => { - this.mem.setUint32(addr + 0, v, true); - }; - - const getInt64 = (addr) => { - const low = this.mem.getUint32(addr + 0, true); - const high = this.mem.getInt32(addr + 4, true); - return low + high * 4294967296; - }; - - const loadValue = (addr) => { - const f = this.mem.getFloat64(addr, true); - if (f === 0) { - return undefined; - } - if (!isNaN(f)) { - return f; - } - - const id = this.mem.getUint32(addr, true); - return this._values[id]; - }; - - const storeValue = (addr, v) => { - const nanHead = 0x7ff80000; - - if (typeof v === 'number' && v !== 0) { - if (isNaN(v)) { - this.mem.setUint32(addr + 4, nanHead, true); - this.mem.setUint32(addr, 0, true); - return; - } - this.mem.setFloat64(addr, v, true); - return; - } - - if (v === undefined) { - this.mem.setFloat64(addr, 0, true); - return; - } - - let id = this._ids.get(v); - if (id === undefined) { - id = this._idPool.pop(); - if (id === undefined) { - id = this._values.length; - } - this._values[id] = v; - this._goRefCounts[id] = 0; - this._ids.set(v, id); - } - this._goRefCounts[id]++; - let typeFlag = 0; - switch (typeof v) { - case 'object': - if (v !== null) { - typeFlag = 1; - } - break; - case 'string': - typeFlag = 2; - break; - case 'symbol': - typeFlag = 3; - break; - case 'function': - typeFlag = 4; - break; - } - this.mem.setUint32(addr + 4, nanHead | typeFlag, true); - this.mem.setUint32(addr, id, true); - }; - - const loadSlice = (addr) => { - const array = getInt64(addr + 0); - const len = getInt64(addr + 8); - return new Uint8Array(this._inst.exports.mem.buffer, array, len); - }; - - const loadSliceOfValues = (addr) => { - const array = getInt64(addr + 0); - const len = getInt64(addr + 8); - const a = new Array(len); - for (let i = 0; i < len; i++) { - a[i] = loadValue(array + i * 8); - } - return a; - }; - - const loadString = (addr) => { - const saddr = getInt64(addr + 0); - const len = getInt64(addr + 8); - return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len)); - }; - - const timeOrigin = Date.now() - performance.now(); - this.importObject = { - _gotest: { - add: (a, b) => a + b, - }, - gojs: { - // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters) - // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported - // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function). - // This changes the SP, thus we have to update the SP used by the imported function. - - // func wasmExit(code int32) - 'runtime.wasmExit': (sp) => { - sp >>>= 0; - const code = this.mem.getInt32(sp + 8, true); - this.exited = true; - delete this._inst; - delete this._values; - delete this._goRefCounts; - delete this._ids; - delete this._idPool; - this.exit(code); - }, - - // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) - 'runtime.wasmWrite': (sp) => { - sp >>>= 0; - const fd = getInt64(sp + 8); - const p = getInt64(sp + 16); - const n = this.mem.getInt32(sp + 24, true); - fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n)); - }, - - // func resetMemoryDataView() - 'runtime.resetMemoryDataView': (sp) => { - sp >>>= 0; - this.mem = new DataView(this._inst.exports.mem.buffer); - }, - - // func nanotime1() int64 - 'runtime.nanotime1': (sp) => { - sp >>>= 0; - setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); - }, - - // func walltime() (sec int64, nsec int32) - 'runtime.walltime': (sp) => { - sp >>>= 0; - const msec = new Date().getTime(); - setInt64(sp + 8, msec / 1000); - this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true); - }, - - // func scheduleTimeoutEvent(delay int64) int32 - 'runtime.scheduleTimeoutEvent': (sp) => { - sp >>>= 0; - const id = this._nextCallbackTimeoutID; - this._nextCallbackTimeoutID++; - this._scheduledTimeouts.set( - id, - setTimeout(() => { - this._resume(); - while (this._scheduledTimeouts.has(id)) { - // for some reason Go failed to register the timeout event, log and try again - // (temporary workaround for https://github.com/golang/go/issues/28975) - // eslint-disable-next-line no-console - console.warn('scheduleTimeoutEvent: missed timeout event'); - this._resume(); - } - }, getInt64(sp + 8)), - ); - this.mem.setInt32(sp + 16, id, true); - }, - - // func clearTimeoutEvent(id int32) - 'runtime.clearTimeoutEvent': (sp) => { - sp >>>= 0; - const id = this.mem.getInt32(sp + 8, true); - clearTimeout(this._scheduledTimeouts.get(id)); - this._scheduledTimeouts.delete(id); - }, - - // func getRandomData(r []byte) - 'runtime.getRandomData': (sp) => { - sp >>>= 0; - crypto.getRandomValues(loadSlice(sp + 8)); - }, - - // func finalizeRef(v ref) - 'syscall/js.finalizeRef': (sp) => { - sp >>>= 0; - const id = this.mem.getUint32(sp + 8, true); - this._goRefCounts[id]--; - if (this._goRefCounts[id] === 0) { - const v = this._values[id]; - this._values[id] = null; - this._ids.delete(v); - this._idPool.push(id); - } - }, - - // func stringVal(value string) ref - 'syscall/js.stringVal': (sp) => { - sp >>>= 0; - storeValue(sp + 24, loadString(sp + 8)); - }, - - // func valueGet(v ref, p string) ref - 'syscall/js.valueGet': (sp) => { - sp >>>= 0; - const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16)); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 32, result); - }, - - // func valueSet(v ref, p string, x ref) - 'syscall/js.valueSet': (sp) => { - sp >>>= 0; - Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32)); - }, - - // func valueDelete(v ref, p string) - 'syscall/js.valueDelete': (sp) => { - sp >>>= 0; - Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16)); - }, - - // func valueIndex(v ref, i int) ref - 'syscall/js.valueIndex': (sp) => { - sp >>>= 0; - storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16))); - }, - - // valueSetIndex(v ref, i int, x ref) - 'syscall/js.valueSetIndex': (sp) => { - sp >>>= 0; - Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24)); - }, - - // func valueCall(v ref, m string, args []ref) (ref, bool) - 'syscall/js.valueCall': (sp) => { - sp >>>= 0; - try { - const v = loadValue(sp + 8); - const m = Reflect.get(v, loadString(sp + 16)); - const args = loadSliceOfValues(sp + 32); - const result = Reflect.apply(m, v, args); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 56, result); - this.mem.setUint8(sp + 64, 1); - } catch (err) { - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 56, err); - this.mem.setUint8(sp + 64, 0); - } - }, - - // func valueInvoke(v ref, args []ref) (ref, bool) - 'syscall/js.valueInvoke': (sp) => { - sp >>>= 0; - try { - const v = loadValue(sp + 8); - const args = loadSliceOfValues(sp + 16); - const result = Reflect.apply(v, undefined, args); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, result); - this.mem.setUint8(sp + 48, 1); - } catch (err) { - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, err); - this.mem.setUint8(sp + 48, 0); - } - }, - - // func valueNew(v ref, args []ref) (ref, bool) - 'syscall/js.valueNew': (sp) => { - sp >>>= 0; - try { - const v = loadValue(sp + 8); - const args = loadSliceOfValues(sp + 16); - const result = Reflect.construct(v, args); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, result); - this.mem.setUint8(sp + 48, 1); - } catch (err) { - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, err); - this.mem.setUint8(sp + 48, 0); - } - }, - - // func valueLength(v ref) int - 'syscall/js.valueLength': (sp) => { - sp >>>= 0; - setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); - }, - - // valuePrepareString(v ref) (ref, int) - 'syscall/js.valuePrepareString': (sp) => { - sp >>>= 0; - const str = encoder.encode(String(loadValue(sp + 8))); - storeValue(sp + 16, str); - setInt64(sp + 24, str.length); - }, - - // valueLoadString(v ref, b []byte) - 'syscall/js.valueLoadString': (sp) => { - sp >>>= 0; - const str = loadValue(sp + 8); - loadSlice(sp + 16).set(str); - }, - - // func valueInstanceOf(v ref, t ref) bool - 'syscall/js.valueInstanceOf': (sp) => { - sp >>>= 0; - this.mem.setUint8(sp + 24, loadValue(sp + 8) instanceof loadValue(sp + 16) ? 1 : 0); - }, - - // func copyBytesToGo(dst []byte, src ref) (int, bool) - 'syscall/js.copyBytesToGo': (sp) => { - sp >>>= 0; - const dst = loadSlice(sp + 8); - const src = loadValue(sp + 32); - if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) { - this.mem.setUint8(sp + 48, 0); - return; - } - const toCopy = src.subarray(0, dst.length); - dst.set(toCopy); - setInt64(sp + 40, toCopy.length); - this.mem.setUint8(sp + 48, 1); - }, - - // func copyBytesToJS(dst ref, src []byte) (int, bool) - 'syscall/js.copyBytesToJS': (sp) => { - sp >>>= 0; - const dst = loadValue(sp + 8); - const src = loadSlice(sp + 16); - if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) { - this.mem.setUint8(sp + 48, 0); - return; - } - const toCopy = src.subarray(0, dst.length); - dst.set(toCopy); - setInt64(sp + 40, toCopy.length); - this.mem.setUint8(sp + 48, 1); - }, - - debug: (value) => { - // eslint-disable-next-line no-console - console.log(value); - }, - }, - }; - } - - async run(instance) { - if (!(instance instanceof WebAssembly.Instance)) { - throw new Error('Go.run: WebAssembly.Instance expected'); - } - this._inst = instance; - this.mem = new DataView(this._inst.exports.mem.buffer); - this._values = [ - // JS values that Go currently has references to, indexed by reference id - NaN, - 0, - null, - true, - false, - globalThis, - this, - ]; - this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id - this._ids = new Map([ - // mapping from JS values to reference ids - [0, 1], - [null, 2], - [true, 3], - [false, 4], - [globalThis, 5], - [this, 6], - ]); - this._idPool = []; // unused ids that have been garbage collected - this.exited = false; // whether the Go program has exited - - // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. - let offset = 4096; - - const strPtr = (str) => { - const ptr = offset; - const bytes = encoder.encode(str + '\0'); - new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes); - offset += bytes.length; - if (offset % 8 !== 0) { - offset += 8 - (offset % 8); - } - return ptr; - }; - - const argc = this.argv.length; - - const argvPtrs = []; - this.argv.forEach((arg) => { - argvPtrs.push(strPtr(arg)); - }); - argvPtrs.push(0); - - const keys = Object.keys(this.env).sort(); - keys.forEach((key) => { - argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); - }); - argvPtrs.push(0); - - const argv = offset; - argvPtrs.forEach((ptr) => { - this.mem.setUint32(offset, ptr, true); - this.mem.setUint32(offset + 4, 0, true); - offset += 8; - }); - - // The linker guarantees global data starts from at least wasmMinDataAddr. - // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. - const wasmMinDataAddr = 4096 + 8192; - if (offset >= wasmMinDataAddr) { - throw new Error('total length of command line and environment variables exceeds limit'); - } - - this._inst.exports.run(argc, argv); - if (this.exited) { - this._resolveExitPromise(); - } - await this._exitPromise; - } - - _resume() { - if (this.exited) { - throw new Error('Go program has already exited'); - } - this._inst.exports.resume(); - if (this.exited) { - this._resolveExitPromise(); - } - } - - _makeFuncWrapper(id) { - // eslint-disable-next-line @typescript-eslint/no-this-alias - const go = this; - return function () { - const event = { id: id, this: this, args: arguments }; - go._pendingEvent = event; - go._resume(); - return event.result; - }; - } - }; -})(); diff --git a/packages/file-handle/src/constants.js b/packages/file-handle/src/constants.js deleted file mode 100644 index 93d69989..00000000 --- a/packages/file-handle/src/constants.js +++ /dev/null @@ -1,3 +0,0 @@ -export const DEFAULT_SEGMENT_SIZE = 16 * 1024 * 1024; -export const DEFAULT_DATA_BLOCKS = 4; -export const DEFAULT_PARITY_BLOCKS = 2; diff --git a/packages/file-handle/src/go-wasm/README.md b/packages/file-handle/src/go-wasm/README.md deleted file mode 100644 index 8ecd1896..00000000 --- a/packages/file-handle/src/go-wasm/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Wasm part - -This folder contains methods that needed to be transformed from Golang to WebAssembly in `greenfield-go-common` repository. - -## How to update wasm - -Navigate to `wasm` directory in root dir, and execute `GOOS=js GOARCH=wasm go build -o ../files-handle-wasm/main.wasm` to generate new wasm file. diff --git a/packages/file-handle/src/go-wasm/go.mod b/packages/file-handle/src/go-wasm/go.mod deleted file mode 100644 index 13491197..00000000 --- a/packages/file-handle/src/go-wasm/go.mod +++ /dev/null @@ -1,15 +0,0 @@ -module wasm - -go 1.20 - -require github.com/bnb-chain/greenfield-common/go v0.0.0-20230310033112-2d379fdc2987 - -require ( - github.com/klauspost/cpuid/v2 v2.2.4 // indirect - github.com/klauspost/reedsolomon v1.11.6 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect - github.com/rs/zerolog v1.29.0 // indirect - github.com/stretchr/testify v1.8.1 // indirect - golang.org/x/sys v0.5.0 // indirect -) diff --git a/packages/file-handle/src/go-wasm/go.sum b/packages/file-handle/src/go-wasm/go.sum deleted file mode 100644 index 27c519dd..00000000 --- a/packages/file-handle/src/go-wasm/go.sum +++ /dev/null @@ -1,41 +0,0 @@ -github.com/bnb-chain/greenfield-common/go v0.0.0-20230310033112-2d379fdc2987 h1:+SOlI4dfp5y/2srTBdAEOujoJboMx+m22zvj5xuBLgU= -github.com/bnb-chain/greenfield-common/go v0.0.0-20230310033112-2d379fdc2987/go.mod h1:Nzpqn+BK8P1Ub3Tgn300bHmWMUk9R6cBwvmasVY25J8= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/klauspost/reedsolomon v1.11.6 h1:h0MUpEzmretucmlelC3EefQHKgk6vWpKz/ctB/tmaEs= -github.com/klauspost/reedsolomon v1.11.6/go.mod h1:cuXqklb3LNaurR5MVjy7WLXAEUqGz4I0Uc+rnQ7POUg= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= -github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/packages/file-handle/src/go-wasm/main.go b/packages/file-handle/src/go-wasm/main.go deleted file mode 100644 index 26a63e45..00000000 --- a/packages/file-handle/src/go-wasm/main.go +++ /dev/null @@ -1,64 +0,0 @@ -package main - -import ( - "bytes" - "encoding/json" - "syscall/js" - - lib "github.com/bnb-chain/greenfield-common/go/hash" - redundancy "github.com/bnb-chain/greenfield-common/go/redundancy" -) - -func hashFunc(this js.Value, args []js.Value) interface{} { - if len(args) != 4 { - return "invalid ComputerHashFromFile params amount" - } - array := args[0] - byteLength := array.Get("byteLength").Int() - var buffer []uint8 = make([]uint8, byteLength) - js.CopyBytesToGo(buffer, array) - segmentSize := args[1].Int() - dataBlocks := args[2].Int() - parityBlocks := args[3].Int() - reader := bytes.NewReader(buffer) - pieceHashRoots, contentLen, err := lib.ComputeIntegrityHash(reader, int64(segmentSize), dataBlocks, parityBlocks) - if err != nil { - return err.Error() - } - expectCheckSumsJson, err := json.Marshal(pieceHashRoots) - if err != nil { - return err.Error() - } - - return map[string]interface{}{ - "expectCheckSums": string(expectCheckSumsJson), - "contentLength": contentLen, - "redundancyVal": 0, - } -} - -func encodeRawSegment(this js.Value, args []js.Value) interface{} { - array := args[0] - dataBlocks := args[1].Int() - parityBlocks := args[2].Int() - - byteLength := array.Get("byteLength").Int() - data := make([]byte, byteLength) - var buffer []uint8 = make([]uint8, byteLength) - js.CopyBytesToGo(buffer, array) - reader := bytes.NewReader(buffer) - reader.Read(data) - - encodeShards, _ := redundancy.EncodeRawSegment(data, dataBlocks, parityBlocks) - shardsJson, _ := json.Marshal(encodeShards) - return map[string]interface{}{ - "result": string(shardsJson), - } -} - -func main() { - done := make(chan int, 0) - js.Global().Set("getCheckSums", js.FuncOf(hashFunc)) - js.Global().Set("encodeRawSegment", js.FuncOf(encodeRawSegment)) - <-done -} diff --git a/packages/file-handle/src/node/index.js b/packages/file-handle/src/node/index.js deleted file mode 100644 index 1c9c361a..00000000 --- a/packages/file-handle/src/node/index.js +++ /dev/null @@ -1,33 +0,0 @@ -import path from 'path'; -import * as wasm from '../wasm/file-handle.wasm'; -import { getService, instantiateWASM } from './init'; -import { DEFAULT_DATA_BLOCKS, DEFAULT_PARITY_BLOCKS, DEFAULT_SEGMENT_SIZE } from '../constants'; - -// 1. modify method of `exports` and `globalThis` export. -export const startRunningService = async () => { - // `wasm.default` is `cross-wasm.wasm` - const wasmPath = path.resolve(__dirname, wasm.default); - await instantiateWASM(wasmPath); - // const exports = module.instance.exports; - - // `exports` is a map to `//export` way of TinyGo way. - // const { add } = exports; - - // `globalThis` is a map to complex way of `syscall/js` way. - const { getCheckSums } = globalThis; - - return { - getCheckSums, - }; -}; - -// 2. wasm export function: -export const getCheckSums = async ( - bytes, - segmentSize = DEFAULT_SEGMENT_SIZE, - dataBlocks = DEFAULT_DATA_BLOCKS, - parityBlocks = DEFAULT_PARITY_BLOCKS, -) => { - const service = await getService(); - return service.getCheckSums(bytes, segmentSize, dataBlocks, parityBlocks); -}; diff --git a/packages/file-handle/src/node/init.js b/packages/file-handle/src/node/init.js deleted file mode 100644 index 4bbe150d..00000000 --- a/packages/file-handle/src/node/init.js +++ /dev/null @@ -1,32 +0,0 @@ -import fs from 'node:fs'; -import { startRunningService } from '.'; -import Go from './wasm_exec'; -let longLivedService; - -export const getService = () => { - if (!longLivedService) { - longLivedService = startRunningService().catch((err) => { - // Let the caller try again if this fails. - longLivedService = void 0; - // But still, throw the error back up the caller. - throw err; - }); - } - return longLivedService; -}; - -export const instantiateWASM = async (wasmPath) => { - let response = undefined; - - const fetchAndInstantiateTask = async () => { - const buf = fs.readFileSync(wasmPath); - const go = new Go(); - const module = await WebAssembly.instantiate(new Uint8Array(buf), go.importObject); - - go.run(module.instance); - return module; - }; - response = await fetchAndInstantiateTask(); - - return response; -}; diff --git a/packages/file-handle/src/node/wasm_exec.js b/packages/file-handle/src/node/wasm_exec.js deleted file mode 100644 index d53f3291..00000000 --- a/packages/file-handle/src/node/wasm_exec.js +++ /dev/null @@ -1,608 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// This file has been modified for use by the TinyGo compiler. - -// Map multiple JavaScript environments to a single common API, -// preferring web standards over Node.js API. -// -// Environments considered: -// - Browsers -// - Node.js -// - Electron -// - Parcel - -if (typeof global !== 'undefined') { - // global already exists -} else if (typeof window !== 'undefined') { - window.global = window; -} else if (typeof self !== 'undefined') { - self.global = self; -} else { - throw new Error('cannot export Go (neither global, window nor self is defined)'); -} - -if (!global.require && typeof require !== 'undefined') { - global.require = require; -} - -if (!global.fs && global.require) { - global.fs = require('fs'); -} - -const enosys = () => { - const err = new Error('not implemented'); - err.code = 'ENOSYS'; - return err; -}; - -if (!global.fs) { - let outputBuf = ''; - global.fs = { - constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused - writeSync(fd, buf) { - outputBuf += decoder.decode(buf); - const nl = outputBuf.lastIndexOf('\n'); - if (nl != -1) { - console.log(outputBuf.substr(0, nl)); - outputBuf = outputBuf.substr(nl + 1); - } - return buf.length; - }, - write(fd, buf, offset, length, position, callback) { - if (offset !== 0 || length !== buf.length || position !== null) { - callback(enosys()); - return; - } - const n = this.writeSync(fd, buf); - callback(null, n); - }, - chmod(path, mode, callback) { - callback(enosys()); - }, - chown(path, uid, gid, callback) { - callback(enosys()); - }, - close(fd, callback) { - callback(enosys()); - }, - fchmod(fd, mode, callback) { - callback(enosys()); - }, - fchown(fd, uid, gid, callback) { - callback(enosys()); - }, - fstat(fd, callback) { - callback(enosys()); - }, - fsync(fd, callback) { - callback(null); - }, - ftruncate(fd, length, callback) { - callback(enosys()); - }, - lchown(path, uid, gid, callback) { - callback(enosys()); - }, - link(path, link, callback) { - callback(enosys()); - }, - lstat(path, callback) { - callback(enosys()); - }, - mkdir(path, perm, callback) { - callback(enosys()); - }, - open(path, flags, mode, callback) { - callback(enosys()); - }, - read(fd, buffer, offset, length, position, callback) { - callback(enosys()); - }, - readdir(path, callback) { - callback(enosys()); - }, - readlink(path, callback) { - callback(enosys()); - }, - rename(from, to, callback) { - callback(enosys()); - }, - rmdir(path, callback) { - callback(enosys()); - }, - stat(path, callback) { - callback(enosys()); - }, - symlink(path, link, callback) { - callback(enosys()); - }, - truncate(path, length, callback) { - callback(enosys()); - }, - unlink(path, callback) { - callback(enosys()); - }, - utimes(path, atime, mtime, callback) { - callback(enosys()); - }, - }; -} - -if (!global.process) { - global.process = { - getuid() { - return -1; - }, - getgid() { - return -1; - }, - geteuid() { - return -1; - }, - getegid() { - return -1; - }, - getgroups() { - throw enosys(); - }, - pid: -1, - ppid: -1, - umask() { - throw enosys(); - }, - cwd() { - throw enosys(); - }, - chdir() { - throw enosys(); - }, - }; -} - -if (!global.crypto) { - const nodeCrypto = require('crypto'); - global.crypto = { - getRandomValues(b) { - nodeCrypto.randomFillSync(b); - }, - }; -} - -if (!global.performance) { - global.performance = { - now() { - const [sec, nsec] = process.hrtime(); - return sec * 1000 + nsec / 1000000; - }, - }; -} - -if (!global.TextEncoder) { - global.TextEncoder = require('util').TextEncoder; -} - -if (!global.TextDecoder) { - global.TextDecoder = require('util').TextDecoder; -} - -// End of polyfills for common API. - -const encoder = new TextEncoder('utf-8'); -const decoder = new TextDecoder('utf-8'); -var logLine = []; - -module.exports = class Go { - importObject; - constructor() { - this._callbackTimeouts = new Map(); - this._nextCallbackTimeoutID = 1; - - const mem = () => { - // The buffer may change when requesting more memory. - return new DataView(this._inst.exports.memory.buffer); - }; - - const setInt64 = (addr, v) => { - mem().setUint32(addr + 0, v, true); - mem().setUint32(addr + 4, Math.floor(v / 4294967296), true); - }; - - const getInt64 = (addr) => { - const low = mem().getUint32(addr + 0, true); - const high = mem().getInt32(addr + 4, true); - return low + high * 4294967296; - }; - - const loadValue = (addr) => { - const f = mem().getFloat64(addr, true); - if (f === 0) { - return undefined; - } - if (!isNaN(f)) { - return f; - } - - const id = mem().getUint32(addr, true); - return this._values[id]; - }; - - const storeValue = (addr, v) => { - const nanHead = 0x7ff80000; - - if (typeof v === 'number') { - if (isNaN(v)) { - mem().setUint32(addr + 4, nanHead, true); - mem().setUint32(addr, 0, true); - return; - } - if (v === 0) { - mem().setUint32(addr + 4, nanHead, true); - mem().setUint32(addr, 1, true); - return; - } - mem().setFloat64(addr, v, true); - return; - } - - switch (v) { - case undefined: - mem().setFloat64(addr, 0, true); - return; - case null: - mem().setUint32(addr + 4, nanHead, true); - mem().setUint32(addr, 2, true); - return; - case true: - mem().setUint32(addr + 4, nanHead, true); - mem().setUint32(addr, 3, true); - return; - case false: - mem().setUint32(addr + 4, nanHead, true); - mem().setUint32(addr, 4, true); - return; - } - - let id = this._ids.get(v); - if (id === undefined) { - id = this._idPool.pop(); - if (id === undefined) { - id = this._values.length; - } - this._values[id] = v; - this._goRefCounts[id] = 0; - this._ids.set(v, id); - } - this._goRefCounts[id]++; - let typeFlag = 1; - switch (typeof v) { - case 'string': - typeFlag = 2; - break; - case 'symbol': - typeFlag = 3; - break; - case 'function': - typeFlag = 4; - break; - } - mem().setUint32(addr + 4, nanHead | typeFlag, true); - mem().setUint32(addr, id, true); - }; - - const loadSlice = (array, len, cap) => { - return new Uint8Array(this._inst.exports.memory.buffer, array, len); - }; - - const loadSliceOfValues = (array, len, cap) => { - const a = new Array(len); - for (let i = 0; i < len; i++) { - a[i] = loadValue(array + i * 8); - } - return a; - }; - - const loadString = (ptr, len) => { - return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len)); - }; - - const timeOrigin = Date.now() - performance.now(); - this.importObject = { - wasi_snapshot_preview1: { - // https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write - fd_write: function (fd, iovs_ptr, iovs_len, nwritten_ptr) { - let nwritten = 0; - if (fd == 1) { - for (let iovs_i = 0; iovs_i < iovs_len; iovs_i++) { - let iov_ptr = iovs_ptr + iovs_i * 8; // assuming wasm32 - let ptr = mem().getUint32(iov_ptr + 0, true); - let len = mem().getUint32(iov_ptr + 4, true); - nwritten += len; - for (let i = 0; i < len; i++) { - let c = mem().getUint8(ptr + i); - if (c == 13) { - // CR - // ignore - } else if (c == 10) { - // LF - // write line - let line = decoder.decode(new Uint8Array(logLine)); - logLine = []; - console.log(line); - } else { - logLine.push(c); - } - } - } - } else { - console.error('invalid file descriptor:', fd); - } - mem().setUint32(nwritten_ptr, nwritten, true); - return 0; - }, - fd_close: () => 0, // dummy - fd_fdstat_get: () => 0, // dummy - fd_seek: () => 0, // dummy - proc_exit: (code) => { - if (global.process) { - // Node.js - process.exit(code); - } else { - // Can't exit in a browser. - throw 'trying to exit with code ' + code; - } - }, - random_get: (bufPtr, bufLen) => { - crypto.getRandomValues(loadSlice(bufPtr, bufLen)); - return 0; - }, - }, - env: { - // func ticks() float64 - 'runtime.ticks': () => { - return timeOrigin + performance.now(); - }, - - // func sleepTicks(timeout float64) - 'runtime.sleepTicks': (timeout) => { - // Do not sleep, only reactivate scheduler after the given timeout. - setTimeout(this._inst.exports.go_scheduler, timeout); - }, - - // func finalizeRef(v ref) - 'syscall/js.finalizeRef': (v_addr) => { - // Note: TinyGo does not support finalizers so this is only called - // for one specific case, by js.go:jsString. - const id = mem().getUint32(v_addr, true); - this._goRefCounts[id]--; - if (this._goRefCounts[id] === 0) { - const v = this._values[id]; - this._values[id] = null; - this._ids.delete(v); - this._idPool.push(id); - } - }, - - // func stringVal(value string) ref - 'syscall/js.stringVal': (ret_ptr, value_ptr, value_len) => { - const s = loadString(value_ptr, value_len); - storeValue(ret_ptr, s); - }, - - // func valueGet(v ref, p string) ref - 'syscall/js.valueGet': (retval, v_addr, p_ptr, p_len) => { - let prop = loadString(p_ptr, p_len); - let value = loadValue(v_addr); - let result = Reflect.get(value, prop); - storeValue(retval, result); - }, - - // func valueSet(v ref, p string, x ref) - 'syscall/js.valueSet': (v_addr, p_ptr, p_len, x_addr) => { - const v = loadValue(v_addr); - const p = loadString(p_ptr, p_len); - const x = loadValue(x_addr); - Reflect.set(v, p, x); - }, - - // func valueDelete(v ref, p string) - 'syscall/js.valueDelete': (v_addr, p_ptr, p_len) => { - const v = loadValue(v_addr); - const p = loadString(p_ptr, p_len); - Reflect.deleteProperty(v, p); - }, - - // func valueIndex(v ref, i int) ref - 'syscall/js.valueIndex': (ret_addr, v_addr, i) => { - storeValue(ret_addr, Reflect.get(loadValue(v_addr), i)); - }, - - // valueSetIndex(v ref, i int, x ref) - 'syscall/js.valueSetIndex': (v_addr, i, x_addr) => { - Reflect.set(loadValue(v_addr), i, loadValue(x_addr)); - }, - - // func valueCall(v ref, m string, args []ref) (ref, bool) - 'syscall/js.valueCall': (ret_addr, v_addr, m_ptr, m_len, args_ptr, args_len, args_cap) => { - const v = loadValue(v_addr); - const name = loadString(m_ptr, m_len); - const args = loadSliceOfValues(args_ptr, args_len, args_cap); - try { - const m = Reflect.get(v, name); - storeValue(ret_addr, Reflect.apply(m, v, args)); - mem().setUint8(ret_addr + 8, 1); - } catch (err) { - storeValue(ret_addr, err); - mem().setUint8(ret_addr + 8, 0); - } - }, - - // func valueInvoke(v ref, args []ref) (ref, bool) - 'syscall/js.valueInvoke': (ret_addr, v_addr, args_ptr, args_len, args_cap) => { - try { - const v = loadValue(v_addr); - const args = loadSliceOfValues(args_ptr, args_len, args_cap); - storeValue(ret_addr, Reflect.apply(v, undefined, args)); - mem().setUint8(ret_addr + 8, 1); - } catch (err) { - storeValue(ret_addr, err); - mem().setUint8(ret_addr + 8, 0); - } - }, - - // func valueNew(v ref, args []ref) (ref, bool) - 'syscall/js.valueNew': (ret_addr, v_addr, args_ptr, args_len, args_cap) => { - const v = loadValue(v_addr); - const args = loadSliceOfValues(args_ptr, args_len, args_cap); - try { - storeValue(ret_addr, Reflect.construct(v, args)); - mem().setUint8(ret_addr + 8, 1); - } catch (err) { - storeValue(ret_addr, err); - mem().setUint8(ret_addr + 8, 0); - } - }, - - // func valueLength(v ref) int - 'syscall/js.valueLength': (v_addr) => { - return loadValue(v_addr).length; - }, - - // valuePrepareString(v ref) (ref, int) - 'syscall/js.valuePrepareString': (ret_addr, v_addr) => { - const s = String(loadValue(v_addr)); - const str = encoder.encode(s); - storeValue(ret_addr, str); - setInt64(ret_addr + 8, str.length); - }, - - // valueLoadString(v ref, b []byte) - 'syscall/js.valueLoadString': (v_addr, slice_ptr, slice_len, slice_cap) => { - const str = loadValue(v_addr); - loadSlice(slice_ptr, slice_len, slice_cap).set(str); - }, - - // func valueInstanceOf(v ref, t ref) bool - 'syscall/js.valueInstanceOf': (v_addr, t_addr) => { - return loadValue(v_addr) instanceof loadValue(t_addr); - }, - - // func copyBytesToGo(dst []byte, src ref) (int, bool) - 'syscall/js.copyBytesToGo': (ret_addr, dest_addr, dest_len, dest_cap, source_addr) => { - let num_bytes_copied_addr = ret_addr; - let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable - - const dst = loadSlice(dest_addr, dest_len); - const src = loadValue(source_addr); - if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) { - mem().setUint8(returned_status_addr, 0); // Return "not ok" status - return; - } - const toCopy = src.subarray(0, dst.length); - dst.set(toCopy); - setInt64(num_bytes_copied_addr, toCopy.length); - mem().setUint8(returned_status_addr, 1); // Return "ok" status - }, - - // copyBytesToJS(dst ref, src []byte) (int, bool) - // Originally copied from upstream Go project, then modified: - // https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416 - 'syscall/js.copyBytesToJS': (ret_addr, dest_addr, source_addr, source_len, source_cap) => { - let num_bytes_copied_addr = ret_addr; - let returned_status_addr = ret_addr + 4; // Address of returned boolean status variable - - const dst = loadValue(dest_addr); - const src = loadSlice(source_addr, source_len); - if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) { - mem().setUint8(returned_status_addr, 0); // Return "not ok" status - return; - } - const toCopy = src.subarray(0, dst.length); - dst.set(toCopy); - setInt64(num_bytes_copied_addr, toCopy.length); - mem().setUint8(returned_status_addr, 1); // Return "ok" status - }, - }, - }; - } - - async run(instance) { - this._inst = instance; - this._values = [ - // JS values that Go currently has references to, indexed by reference id - NaN, - 0, - null, - true, - false, - global, - this, - ]; - this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id - this._ids = new Map(); // mapping from JS values to reference ids - this._idPool = []; // unused ids that have been garbage collected - this.exited = false; // whether the Go program has exited - - const mem = new DataView(this._inst.exports.memory.buffer); - - while (true) { - const callbackPromise = new Promise((resolve) => { - this._resolveCallbackPromise = () => { - if (this.exited) { - throw new Error('bad callback: Go program has already exited'); - } - setTimeout(resolve, 0); // make sure it is asynchronous - }; - }); - this._inst.exports._start(); - if (this.exited) { - break; - } - await callbackPromise; - } - } - - _resume() { - if (this.exited) { - throw new Error('Go program has already exited'); - } - this._inst.exports.resume(); - if (this.exited) { - this._resolveExitPromise(); - } - } - - _makeFuncWrapper(id) { - const go = this; - return function () { - const event = { id: id, this: this, args: arguments }; - go._pendingEvent = event; - go._resume(); - return event.result; - }; - } -}; - -// if ( -// global.require && -// global.require.main === module && -// global.process && -// global.process.versions && -// !global.process.versions.electron -// ) { -// if (process.argv.length != 3) { -// console.error("usage: go_js_wasm_exec [wasm binary] [arguments]"); -// process.exit(1); -// } - -// const go = new Go(); -// WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => { -// return go.run(result.instance); -// }).catch((err) => { -// console.error(err); -// process.exit(1); -// }); -// } diff --git a/packages/file-handle/src/utils.js b/packages/file-handle/src/utils.js deleted file mode 100644 index 19b3cbf9..00000000 --- a/packages/file-handle/src/utils.js +++ /dev/null @@ -1,42 +0,0 @@ -const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - -export function encodeBase64(data, pad = true) { - const len = data.length; - const extraBytes = len % 3; - const parts = []; - - const len2 = len - extraBytes; - for (let i = 0; i < len2; i += 3) { - const tmp = ((data[i] << 16) & 0xff0000) + ((data[i + 1] << 8) & 0xff00) + (data[i + 2] & 0xff); - - const triplet = - base64Chars.charAt((tmp >> 18) & 0x3f) + - base64Chars.charAt((tmp >> 12) & 0x3f) + - base64Chars.charAt((tmp >> 6) & 0x3f) + - base64Chars.charAt(tmp & 0x3f); - - parts.push(triplet); - } - - if (extraBytes === 1) { - const tmp = data[len - 1]; - const a = base64Chars.charAt(tmp >> 2); - const b = base64Chars.charAt((tmp << 4) & 0x3f); - - parts.push(`${a}${b}`); - if (pad) { - parts.push('=='); - } - } else if (extraBytes === 2) { - const tmp = (data[len - 2] << 8) + data[len - 1]; - const a = base64Chars.charAt(tmp >> 10); - const b = base64Chars.charAt((tmp >> 4) & 0x3f); - const c = base64Chars.charAt((tmp << 2) & 0x3f); - parts.push(`${a}${b}${c}`); - if (pad) { - parts.push('='); - } - } - - return parts.join(''); -} diff --git a/packages/file-handle/src/wasm/file-handle-worker.wasm b/packages/file-handle/src/wasm/file-handle-worker.wasm deleted file mode 100755 index 2826fa5c9385b0e85835332e36095d878ab69251..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3122432 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%0DTOlTo_8RrXk`+F}dvKbkmd)L#8z$lQm5) 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