├── .changeset ├── README.md └── config.json ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── feature_request.yml ├── scripts │ └── prevent-major-bumps.js └── workflows │ ├── add-pitches-to-project.yml │ ├── integrate.yml │ └── release.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── SECURITY.md ├── assets └── build-resolve-send-decode.png ├── docs ├── flow-docs.json ├── images │ ├── discovery.png │ └── wc-discovery.png ├── index.md ├── index.mdx ├── reference │ ├── api.md │ ├── authentication.mdx │ ├── configure-fcl.mdx │ ├── discovery.mdx │ ├── installation.mdx │ ├── interaction-templates.mdx │ ├── proving-authentication.mdx │ ├── scripts.mdx │ ├── sdk-guidelines.mdx │ ├── transactions.mdx │ ├── user-signatures.mdx │ └── wallet-connect.mdx └── tutorials │ └── flow-app-quickstart.mdx ├── jest.config.js ├── lerna.json ├── package-lock.json ├── package.json ├── packages ├── config │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ ├── README.md │ │ ├── config.test.ts │ │ ├── config.ts │ │ └── utils │ │ │ ├── utils.test.ts │ │ │ └── utils.ts │ └── tsconfig.json ├── fcl-bundle │ ├── .babelrc │ ├── .browserslistrc │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ └── src │ │ ├── build │ │ ├── build-watch.js │ │ ├── build.js │ │ ├── get-input-options.js │ │ ├── get-output-options.js │ │ └── watcher-pool.js │ │ ├── cli.js │ │ ├── get-package-json.js │ │ ├── package-config.js │ │ ├── plugins │ │ ├── banner.js │ │ └── preserve-dynamic-imports.js │ │ ├── program.js │ │ └── util.js ├── fcl-core │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── TRANSITIONS.md │ ├── WARNINGS.md │ ├── assets │ │ └── service-method-diagrams │ │ │ ├── ext-rpc.png │ │ │ ├── http-post.excalidraw │ │ │ ├── http-post.png │ │ │ ├── iframe-rpc.excalidraw │ │ │ ├── iframe-rpc.png │ │ │ ├── pop-rpc.excalidraw │ │ │ ├── pop-rpc.png │ │ │ ├── tab-rpc.excalidraw │ │ │ └── tab-rpc.png │ ├── package.json │ ├── src │ │ ├── VERSION.js │ │ ├── app-utils │ │ │ ├── __tests__ │ │ │ │ └── verify-user-sig.test.js │ │ │ ├── index.js │ │ │ └── verify-signatures.js │ │ ├── current-user │ │ │ ├── build-user.js │ │ │ ├── exec-service │ │ │ │ ├── index.js │ │ │ │ ├── plugins.ts │ │ │ │ ├── strategies │ │ │ │ │ ├── http-post.js │ │ │ │ │ └── utils │ │ │ │ │ │ ├── buildMessageHandler.js │ │ │ │ │ │ ├── fetch-service.js │ │ │ │ │ │ ├── poll.js │ │ │ │ │ │ └── service-endpoint.js │ │ │ │ └── wc-check.ts │ │ │ ├── fetch-services.js │ │ │ ├── index.js │ │ │ ├── merge-services.js │ │ │ ├── service-of-type.js │ │ │ ├── service-of-type.test.js │ │ │ └── url-from-service.js │ │ ├── default-config.js │ │ ├── discovery │ │ │ ├── index.js │ │ │ ├── services.js │ │ │ ├── services.test.js │ │ │ ├── services │ │ │ │ └── authn.js │ │ │ └── utils.js │ │ ├── document │ │ │ ├── document.js │ │ │ └── document.test.js │ │ ├── events │ │ │ ├── index.test.ts │ │ │ ├── index.ts │ │ │ └── legacy-events.js │ │ ├── exec │ │ │ ├── args.ts │ │ │ ├── mutate.js │ │ │ ├── mutate.md │ │ │ ├── query.js │ │ │ ├── query.md │ │ │ ├── utils │ │ │ │ ├── normalize-args.js │ │ │ │ ├── pre.js │ │ │ │ ├── prep-template-opts.js │ │ │ │ └── prep-template-opts.test.js │ │ │ └── verify.js │ │ ├── fcl-core.ts │ │ ├── fcl.test.js │ │ ├── interaction-template-utils │ │ │ ├── derive-cadence-by-network │ │ │ │ ├── derive-cadence-by-network-1.0.0.js │ │ │ │ ├── derive-cadence-by-network-1.1.0.js │ │ │ │ ├── derive-cadence-by-network.js │ │ │ │ └── derive-cadence-by-network.test.js │ │ │ ├── generate-dependency-pin │ │ │ │ ├── generate-dependency-pin-1.0.0.js │ │ │ │ ├── generate-dependency-pin-1.1.0.js │ │ │ │ ├── generate-dependency-pin.js │ │ │ │ └── generate-dependency-pin.test.js │ │ │ ├── generate-template-id │ │ │ │ ├── generate-template-id-1.0.0.js │ │ │ │ ├── generate-template-id-1.1.0.js │ │ │ │ ├── generate-template-id-1.1.0.test.js │ │ │ │ └── generate-template-id.js │ │ │ ├── get-interaction-template-audits.js │ │ │ ├── get-template-argument-message.js │ │ │ ├── get-template-argument-message.test.js │ │ │ ├── get-template-message.js │ │ │ ├── get-template-message.test.js │ │ │ ├── index.js │ │ │ ├── utils │ │ │ │ ├── find-imports.js │ │ │ │ ├── find-imports.test.js │ │ │ │ ├── generate-import.js │ │ │ │ ├── hash.js │ │ │ │ ├── replace-string-imports.js │ │ │ │ └── replace-string-imports.test.js │ │ │ ├── verify-dependency-pin-same-at-block.js │ │ │ └── verify-dependency-pin-same-at-block.test.js │ │ ├── normalizers │ │ │ └── service │ │ │ │ ├── __vsn.js │ │ │ │ ├── account-proof.js │ │ │ │ ├── authn-refresh.js │ │ │ │ ├── authn.js │ │ │ │ ├── authz.js │ │ │ │ ├── back-channel-rpc.js │ │ │ │ ├── composite-signature.js │ │ │ │ ├── frame.js │ │ │ │ ├── local-view.js │ │ │ │ ├── open-id.js │ │ │ │ ├── polling-response.js │ │ │ │ ├── pre-authz.js │ │ │ │ ├── service.js │ │ │ │ └── user-signature.js │ │ ├── serialize │ │ │ └── index.js │ │ ├── transaction │ │ │ ├── constants.ts │ │ │ ├── index.ts │ │ │ ├── legacy-polling.js │ │ │ ├── legacy-polling.test.js │ │ │ ├── transaction-error.test.ts │ │ │ ├── transaction-error.ts │ │ │ ├── transaction.test.ts │ │ │ ├── transaction.ts │ │ │ ├── types.ts │ │ │ └── utils.ts │ │ ├── utils │ │ │ ├── chain-id │ │ │ │ ├── chain-id-watcher.js │ │ │ │ ├── chain-id-watcher.test.js │ │ │ │ ├── fetch-chain-id.js │ │ │ │ ├── get-chain-id.js │ │ │ │ └── get-chain-id.test.js │ │ │ ├── constants.js │ │ │ ├── index.js │ │ │ ├── is-react-native.js │ │ │ ├── is.js │ │ │ ├── storage.ts │ │ │ └── url.js │ │ ├── wallet-provider-spec │ │ │ ├── README.md │ │ │ ├── assets │ │ │ │ ├── fcl-ars-auth-v1.excalidraw │ │ │ │ ├── fcl-ars-auth-v1.png │ │ │ │ ├── fcl-ars-auth-v2.excalidraw │ │ │ │ ├── fcl-ars-auth-v2.png │ │ │ │ ├── fcl-ars-auth-v3.1.excalidraw │ │ │ │ ├── fcl-ars-auth-v3.1.png │ │ │ │ ├── fcl-ars-auth-v3.2.excalidraw │ │ │ │ ├── fcl-ars-auth-v3.2.png │ │ │ │ ├── fcl-ars-auth-v3.excalidraw │ │ │ │ └── fcl-ars-auth-v3.png │ │ │ ├── authorization-function.md │ │ │ ├── custodial.md │ │ │ ├── draft-v2.md │ │ │ ├── draft-v3.md │ │ │ ├── draft-v4.md │ │ │ ├── draft.md │ │ │ ├── non-custodial.md │ │ │ ├── provable-authn.md │ │ │ ├── user-signature.md │ │ │ └── wallet-discover.md │ │ └── wallet-utils │ │ │ ├── CompositeSignature.js │ │ │ ├── encode-account-proof.js │ │ │ ├── encode-account-proof.test.js │ │ │ ├── index.js │ │ │ ├── inject-ext-service.js │ │ │ ├── on-message-from-fcl.js │ │ │ ├── send-msg-to-fcl.js │ │ │ └── wallet-utils.test.js │ └── tsconfig.json ├── fcl-ethereum-provider │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __mocks__ │ │ │ └── fcl.ts │ │ ├── accounts │ │ │ ├── account-manager.test.ts │ │ │ ├── account-manager.ts │ │ │ └── sign-message.test.ts │ │ ├── cadence.ts │ │ ├── constants.ts │ │ ├── create-provider.ts │ │ ├── events │ │ │ ├── event-dispatcher.test.ts │ │ │ └── event-dispatcher.ts │ │ ├── gateway │ │ │ ├── gateway.test.ts │ │ │ └── gateway.ts │ │ ├── hash-utils.test.ts │ │ ├── hash-utils.ts │ │ ├── index.ts │ │ ├── network │ │ │ ├── network-manager.test.ts │ │ │ └── network-manager.ts │ │ ├── notifications.ts │ │ ├── provider.test.ts │ │ ├── provider.ts │ │ ├── rpc │ │ │ ├── handlers │ │ │ │ ├── eth-accounts.test.ts │ │ │ │ ├── eth-accounts.ts │ │ │ │ ├── eth-chain-id.test.ts │ │ │ │ ├── eth-chain-id.ts │ │ │ │ ├── eth-send-transaction.test.ts │ │ │ │ ├── eth-send-transaction.ts │ │ │ │ ├── eth-signtypeddata.ts │ │ │ │ └── personal-sign.ts │ │ │ ├── rpc-processor.test.ts │ │ │ ├── rpc-processor.ts │ │ │ └── types.ts │ │ ├── types │ │ │ ├── account.ts │ │ │ ├── eth.ts │ │ │ ├── events.ts │ │ │ └── provider.ts │ │ ├── util │ │ │ ├── chain.ts │ │ │ ├── errors.ts │ │ │ ├── eth.ts │ │ │ ├── observable.ts │ │ │ └── transaction.ts │ │ └── wc-provider.ts │ └── tsconfig.json ├── fcl-rainbowkit-adapter │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── create-connector.ts │ │ ├── fcl-rainbowkit-adapter.test.ts │ │ ├── get-wc-connector.ts │ │ ├── index.ts │ │ ├── use-is-cadence-wallet-connected.ts │ │ └── wallets │ │ │ ├── flow-wallet.ts │ │ │ └── wc-wallet.ts │ └── tsconfig.json ├── fcl-react-native │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── VERSION.js │ │ ├── fcl-react-native.ts │ │ └── utils │ │ │ └── react-native │ │ │ ├── ServiceDiscovery.js │ │ │ ├── __tests__ │ │ │ └── default-config.test.js │ │ │ ├── coreStrategies.js │ │ │ ├── default-config.js │ │ │ ├── exec-local.js │ │ │ ├── index.js │ │ │ ├── render-browser.js │ │ │ ├── render-deeplink.js │ │ │ ├── storage.ts │ │ │ └── strategies │ │ │ ├── deeplink-rpc.js │ │ │ └── utils │ │ │ ├── browser.js │ │ │ └── service-endpoint.js │ └── tsconfig.json ├── fcl-wagmi-adapter │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── fcl-connector.ts │ │ ├── fcl-wagmi-adapter.test.ts │ │ ├── index.ts │ │ └── wc-connector.ts │ └── tsconfig.json ├── fcl-wc │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── jest.config.js │ ├── jest.setup.ts │ ├── package.json │ ├── postcss.config.js │ ├── src │ │ ├── constants.ts │ │ ├── fcl-wc.test.ts │ │ ├── fcl-wc.ts │ │ ├── index.ts │ │ ├── mocks │ │ │ └── file-mock.ts │ │ ├── service.ts │ │ ├── session.ts │ │ ├── store.ts │ │ ├── types │ │ │ ├── declarations.d.ts │ │ │ └── types.ts │ │ ├── ui │ │ │ ├── assets │ │ │ │ └── mobile.svg │ │ │ ├── components │ │ │ │ └── Notification.tsx │ │ │ ├── notifications.tsx │ │ │ └── styles.css │ │ └── utils.ts │ ├── tailwind.config.js │ └── tsconfig.json ├── fcl │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── TRANSITIONS.md │ ├── package.json │ ├── src │ │ ├── VERSION.js │ │ ├── discovery │ │ │ ├── exec-discovery.ts │ │ │ ├── exec-hook.ts │ │ │ └── rpc │ │ │ │ ├── client.ts │ │ │ │ ├── handlers │ │ │ │ ├── exec-service.ts │ │ │ │ └── request-wc-qr.ts │ │ │ │ └── requests.ts │ │ ├── fcl.ts │ │ └── utils │ │ │ ├── async.ts │ │ │ ├── walletconnect │ │ │ └── loader.ts │ │ │ └── web │ │ │ ├── __tests__ │ │ │ └── default-config.test.js │ │ │ ├── coreStrategies.js │ │ │ ├── default-config.js │ │ │ ├── exec-local.js │ │ │ ├── index.js │ │ │ ├── render-frame.js │ │ │ ├── render-pop.js │ │ │ ├── render-tab.js │ │ │ ├── storage.ts │ │ │ └── strategies │ │ │ ├── ext-rpc.js │ │ │ ├── iframe-rpc.js │ │ │ ├── pop-rpc.js │ │ │ ├── tab-rpc.js │ │ │ └── utils │ │ │ ├── extension.js │ │ │ ├── frame.js │ │ │ ├── pop.js │ │ │ └── tab.js │ └── tsconfig.json ├── kit │ ├── .babelrc │ ├── .browserslistrc │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── __mocks__ │ │ │ ├── fcl.ts │ │ │ ├── noop.ts │ │ │ ├── tx.ts │ │ │ └── user.ts │ │ ├── components │ │ │ └── index.ts │ │ ├── constants.ts │ │ ├── core │ │ │ ├── context.ts │ │ │ └── types.ts │ │ ├── hooks │ │ │ ├── index.ts │ │ │ ├── useCrossVmBatchTransaction.test.ts │ │ │ ├── useCrossVmBatchTransaction.ts │ │ │ ├── useCrossVmTokenBalance.test.ts │ │ │ ├── useCrossVmTokenBalance.ts │ │ │ ├── useCurrentFlowUser.ts │ │ │ ├── useCurrentUser.test.ts │ │ │ ├── useFlowAccount.test.ts │ │ │ ├── useFlowAccount.ts │ │ │ ├── useFlowBlock.test.ts │ │ │ ├── useFlowBlock.ts │ │ │ ├── useFlowChainId.test.ts │ │ │ ├── useFlowChainId.ts │ │ │ ├── useFlowConfig.ts │ │ │ ├── useFlowEvents.test.ts │ │ │ ├── useFlowEvents.ts │ │ │ ├── useFlowMutate.test.ts │ │ │ ├── useFlowMutate.ts │ │ │ ├── useFlowQuery.test.ts │ │ │ ├── useFlowQuery.ts │ │ │ ├── useFlowRevertibleRandom.test.tsx │ │ │ ├── useFlowRevertibleRandom.ts │ │ │ ├── useFlowTransactionStatus.test.ts │ │ │ └── useFlowTransactionStatus.ts │ │ ├── index.ts │ │ ├── jest-setup.ts │ │ ├── provider │ │ │ ├── FlowProvider.tsx │ │ │ ├── FlowQueryClient.tsx │ │ │ └── index.ts │ │ └── utils │ │ │ └── deepEqual.ts │ └── tsconfig.json ├── protobuf │ ├── .babelrc │ ├── .browserslistrc │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── generated │ │ │ └── flow │ │ │ │ ├── access │ │ │ │ ├── access_pb.d.ts │ │ │ │ ├── access_pb.js │ │ │ │ ├── access_pb_service.d.ts │ │ │ │ └── access_pb_service.js │ │ │ │ ├── entities │ │ │ │ ├── account_pb.d.ts │ │ │ │ ├── account_pb.js │ │ │ │ ├── account_pb_service.d.ts │ │ │ │ ├── account_pb_service.js │ │ │ │ ├── block_execution_data_pb.d.ts │ │ │ │ ├── block_execution_data_pb.js │ │ │ │ ├── block_execution_data_pb_service.d.ts │ │ │ │ ├── block_execution_data_pb_service.js │ │ │ │ ├── block_header_pb.d.ts │ │ │ │ ├── block_header_pb.js │ │ │ │ ├── block_header_pb_service.d.ts │ │ │ │ ├── block_header_pb_service.js │ │ │ │ ├── block_pb.d.ts │ │ │ │ ├── block_pb.js │ │ │ │ ├── block_pb_service.d.ts │ │ │ │ ├── block_pb_service.js │ │ │ │ ├── block_seal_pb.d.ts │ │ │ │ ├── block_seal_pb.js │ │ │ │ ├── block_seal_pb_service.d.ts │ │ │ │ ├── block_seal_pb_service.js │ │ │ │ ├── collection_pb.d.ts │ │ │ │ ├── collection_pb.js │ │ │ │ ├── collection_pb_service.d.ts │ │ │ │ ├── collection_pb_service.js │ │ │ │ ├── event_pb.d.ts │ │ │ │ ├── event_pb.js │ │ │ │ ├── event_pb_service.d.ts │ │ │ │ ├── event_pb_service.js │ │ │ │ ├── execution_result_pb.d.ts │ │ │ │ ├── execution_result_pb.js │ │ │ │ ├── execution_result_pb_service.d.ts │ │ │ │ ├── execution_result_pb_service.js │ │ │ │ ├── metadata_pb.d.ts │ │ │ │ ├── metadata_pb.js │ │ │ │ ├── metadata_pb_service.d.ts │ │ │ │ ├── metadata_pb_service.js │ │ │ │ ├── node_version_info_pb.d.ts │ │ │ │ ├── node_version_info_pb.js │ │ │ │ ├── node_version_info_pb_service.d.ts │ │ │ │ ├── node_version_info_pb_service.js │ │ │ │ ├── register_pb.d.ts │ │ │ │ ├── register_pb.js │ │ │ │ ├── register_pb_service.d.ts │ │ │ │ ├── register_pb_service.js │ │ │ │ ├── transaction_pb.d.ts │ │ │ │ ├── transaction_pb.js │ │ │ │ ├── transaction_pb_service.d.ts │ │ │ │ └── transaction_pb_service.js │ │ │ │ ├── execution │ │ │ │ ├── execution_pb.d.ts │ │ │ │ ├── execution_pb.js │ │ │ │ ├── execution_pb_service.d.ts │ │ │ │ └── execution_pb_service.js │ │ │ │ └── executiondata │ │ │ │ ├── executiondata_pb.d.ts │ │ │ │ ├── executiondata_pb.js │ │ │ │ ├── executiondata_pb_service.d.ts │ │ │ │ └── executiondata_pb_service.js │ │ ├── index.js │ │ ├── index.test.js │ │ └── proto │ │ │ └── flow │ │ │ ├── access │ │ │ └── access.proto │ │ │ ├── entities │ │ │ ├── account.proto │ │ │ ├── block.proto │ │ │ ├── block_execution_data.proto │ │ │ ├── block_header.proto │ │ │ ├── block_seal.proto │ │ │ ├── collection.proto │ │ │ ├── event.proto │ │ │ ├── execution_result.proto │ │ │ ├── metadata.proto │ │ │ ├── node_version_info.proto │ │ │ ├── register.proto │ │ │ └── transaction.proto │ │ │ ├── execution │ │ │ └── execution.proto │ │ │ ├── executiondata │ │ │ └── executiondata.proto │ │ │ └── legacy │ │ │ ├── access │ │ │ └── access.proto │ │ │ ├── entities │ │ │ ├── account.proto │ │ │ ├── block.proto │ │ │ ├── block_header.proto │ │ │ ├── block_seal.proto │ │ │ ├── collection.proto │ │ │ ├── event.proto │ │ │ └── transaction.proto │ │ │ └── execution │ │ │ └── execution.proto │ └── webpack.config.js ├── rlp │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ └── index.ts │ └── tsconfig.json ├── sdk │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── TRANSITIONS.md │ ├── package.json │ ├── readme.md │ ├── src │ │ ├── VERSION.ts │ │ ├── account │ │ │ ├── account.test.ts │ │ │ └── account.ts │ │ ├── block │ │ │ ├── block.test.ts │ │ │ └── block.ts │ │ ├── build │ │ │ ├── build-arguments.test.ts │ │ │ ├── build-arguments.ts │ │ │ ├── build-at-block-height.test.ts │ │ │ ├── build-at-block-height.ts │ │ │ ├── build-at-block-id.test.ts │ │ │ ├── build-at-block-id.ts │ │ │ ├── build-at-latest-block.test.ts │ │ │ ├── build-at-latest-block.ts │ │ │ ├── build-authorizations.test.ts │ │ │ ├── build-authorizations.ts │ │ │ ├── build-get-account.test.ts │ │ │ ├── build-get-account.ts │ │ │ ├── build-get-block-header.test.ts │ │ │ ├── build-get-block-header.ts │ │ │ ├── build-get-block.test.ts │ │ │ ├── build-get-block.ts │ │ │ ├── build-get-collection.test.ts │ │ │ ├── build-get-collection.ts │ │ │ ├── build-get-events-at-block-height-range.test.ts │ │ │ ├── build-get-events-at-block-height-range.ts │ │ │ ├── build-get-events-at-block-ids.test.ts │ │ │ ├── build-get-events-at-block-ids.ts │ │ │ ├── build-get-events.test.ts │ │ │ ├── build-get-events.ts │ │ │ ├── build-get-latest-block.test.ts │ │ │ ├── build-get-latest-block.ts │ │ │ ├── build-get-network-parameters.test.ts │ │ │ ├── build-get-network-parameters.ts │ │ │ ├── build-get-node-version-info.test.ts │ │ │ ├── build-get-node-version-info.ts │ │ │ ├── build-get-transaction-status.test.ts │ │ │ ├── build-get-transaction-status.ts │ │ │ ├── build-get-transaction.test.ts │ │ │ ├── build-get-transaction.ts │ │ │ ├── build-invariant.js │ │ │ ├── build-invariant.test.js │ │ │ ├── build-limit.test.ts │ │ │ ├── build-limit.ts │ │ │ ├── build-payer.test.ts │ │ │ ├── build-payer.ts │ │ │ ├── build-ping.test.ts │ │ │ ├── build-ping.ts │ │ │ ├── build-proposer.test.ts │ │ │ ├── build-proposer.ts │ │ │ ├── build-ref.test.ts │ │ │ ├── build-ref.ts │ │ │ ├── build-script.test.ts │ │ │ ├── build-script.ts │ │ │ ├── build-subscribe-events.test.ts │ │ │ ├── build-subscribe-events.ts │ │ │ ├── build-transaction.test.ts │ │ │ ├── build-transaction.ts │ │ │ ├── build-validator.test.ts │ │ │ ├── build-validator.ts │ │ │ ├── build-voucher-intercept.test.ts │ │ │ ├── build-voucher-intercept.ts │ │ │ ├── build.test.ts │ │ │ └── build.ts │ │ ├── constants.ts │ │ ├── contract.test.ts │ │ ├── decode │ │ │ ├── README.md │ │ │ ├── decode-stream.test.ts │ │ │ ├── decode-stream.ts │ │ │ ├── decode.test.js │ │ │ ├── decode.ts │ │ │ └── sdk-decode.ts │ │ ├── encode │ │ │ ├── README.md │ │ │ ├── encode.test.ts │ │ │ └── encode.ts │ │ ├── interaction │ │ │ ├── interaction.test.ts │ │ │ └── interaction.ts │ │ ├── node-version-info │ │ │ └── node-version-info.ts │ │ ├── resolve │ │ │ ├── __snapshots__ │ │ │ │ └── resolve-signatures.test.ts.snap │ │ │ ├── __tests__ │ │ │ │ └── resolve-accounts.test.js │ │ │ ├── resolve-accounts.test.js │ │ │ ├── resolve-accounts.ts │ │ │ ├── resolve-arguments.test.ts │ │ │ ├── resolve-arguments.ts │ │ │ ├── resolve-cadence.test.ts │ │ │ ├── resolve-cadence.ts │ │ │ ├── resolve-compute-limit.test.ts │ │ │ ├── resolve-compute-limit.ts │ │ │ ├── resolve-final-normalization.test.ts │ │ │ ├── resolve-final-normalization.ts │ │ │ ├── resolve-proposer-sequence-number.test.ts │ │ │ ├── resolve-proposer-sequence-number.ts │ │ │ ├── resolve-ref-block-id.test.ts │ │ │ ├── resolve-ref-block-id.ts │ │ │ ├── resolve-signatures.test.ts │ │ │ ├── resolve-signatures.ts │ │ │ ├── resolve-validators.test.ts │ │ │ ├── resolve-validators.ts │ │ │ ├── resolve-voucher-intercept.test.ts │ │ │ ├── resolve-voucher-intercept.ts │ │ │ ├── resolve.ts │ │ │ └── voucher.ts │ │ ├── response │ │ │ ├── README.md │ │ │ ├── __snapshots__ │ │ │ │ └── response.test.ts.snap │ │ │ ├── response.test.ts │ │ │ └── response.ts │ │ ├── sdk.test.js │ │ ├── sdk.ts │ │ ├── test-utils │ │ │ ├── authz-fn.ts │ │ │ ├── index.ts │ │ │ ├── mock-send.js │ │ │ └── run.ts │ │ ├── transport │ │ │ ├── get-transport.test.ts │ │ │ ├── get-transport.ts │ │ │ ├── index.ts │ │ │ ├── send │ │ │ │ ├── send.test.ts │ │ │ │ └── send.ts │ │ │ └── subscribe │ │ │ │ ├── errors.ts │ │ │ │ ├── subscribe-raw.test.ts │ │ │ │ ├── subscribe-raw.ts │ │ │ │ ├── subscribe.test.ts │ │ │ │ ├── subscribe.ts │ │ │ │ └── types.ts │ │ └── wallet-utils │ │ │ ├── encode-signable.test.ts │ │ │ ├── encode-signable.ts │ │ │ ├── index.ts │ │ │ ├── validate-tx.test.ts │ │ │ └── validate-tx.ts │ └── tsconfig.json ├── transport-grpc │ ├── .babelrc │ ├── .browserslistrc │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── sdk-send-grpc.js │ │ ├── send-execute-script.js │ │ ├── send-execute-script.test.js │ │ ├── send-get-account.js │ │ ├── send-get-account.test.js │ │ ├── send-get-block-header.js │ │ ├── send-get-block-header.test.js │ │ ├── send-get-block.js │ │ ├── send-get-block.test.js │ │ ├── send-get-collection.js │ │ ├── send-get-collection.test.js │ │ ├── send-get-events.js │ │ ├── send-get-events.test.js │ │ ├── send-get-network-parameters.js │ │ ├── send-get-network-parameters.test.js │ │ ├── send-get-node-version-info.js │ │ ├── send-get-node-version-info.test.js │ │ ├── send-get-transaction-status.js │ │ ├── send-get-transaction-status.test.js │ │ ├── send-get-transaction.js │ │ ├── send-get-transaction.test.js │ │ ├── send-grpc.js │ │ ├── send-ping.js │ │ ├── send-ping.test.js │ │ ├── send-transaction.js │ │ ├── send-transaction.test.js │ │ └── unary.js │ └── tsconfig.json ├── transport-http │ ├── .babelrc │ ├── .browserslistrc │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── send │ │ │ ├── connect-subscribe-events.test.ts │ │ │ ├── connect-subscribe-events.ts │ │ │ ├── connect-ws.test.ts │ │ │ ├── connect-ws.ts │ │ │ ├── http-request.js │ │ │ ├── http-request.test.js │ │ │ ├── send-execute-script.js │ │ │ ├── send-execute-script.test.js │ │ │ ├── send-get-account.js │ │ │ ├── send-get-account.test.js │ │ │ ├── send-get-block-header.js │ │ │ ├── send-get-block-header.test.js │ │ │ ├── send-get-block.js │ │ │ ├── send-get-block.test.js │ │ │ ├── send-get-collection.js │ │ │ ├── send-get-collection.test.js │ │ │ ├── send-get-events.js │ │ │ ├── send-get-events.test.js │ │ │ ├── send-get-network-parameters.js │ │ │ ├── send-get-network-parameters.test.js │ │ │ ├── send-get-node-version-info.test.ts │ │ │ ├── send-get-node-version-info.ts │ │ │ ├── send-get-transaction-status.js │ │ │ ├── send-get-transaction-status.test.js │ │ │ ├── send-get-transaction.js │ │ │ ├── send-get-transaction.test.js │ │ │ ├── send-http.ts │ │ │ ├── send-ping.test.ts │ │ │ ├── send-ping.ts │ │ │ ├── send-transaction.js │ │ │ ├── send-transaction.test.js │ │ │ └── utils.js │ │ ├── subscribe │ │ │ ├── handlers │ │ │ │ ├── account-statuses.ts │ │ │ │ ├── block-digests.ts │ │ │ │ ├── block-headers.ts │ │ │ │ ├── blocks.ts │ │ │ │ ├── events.ts │ │ │ │ ├── transaction-statuses.ts │ │ │ │ └── types.ts │ │ │ ├── models.ts │ │ │ ├── subscribe.test.ts │ │ │ ├── subscribe.ts │ │ │ ├── subscription-manager.test.ts │ │ │ ├── subscription-manager.ts │ │ │ └── websocket.ts │ │ ├── transport.ts │ │ └── utils │ │ │ ├── combine-urls.test.ts │ │ │ └── combine-urls.ts │ └── tsconfig.json ├── typedefs │ ├── .babelrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── fvm-errors.ts │ │ ├── index.test.js │ │ ├── index.ts │ │ ├── interaction.ts │ │ ├── subscriptions.ts │ │ └── transport.ts │ └── tsconfig.json ├── types │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── WARNINGS.md │ ├── package.json │ ├── src │ │ ├── types.test.ts │ │ └── types.ts │ └── tsconfig.json ├── util-actor │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ ├── index.ts │ │ └── mailbox │ │ │ ├── README.md │ │ │ ├── index.test.ts │ │ │ └── index.ts │ └── tsconfig.json ├── util-address │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ └── index.ts │ └── tsconfig.json ├── util-encode-key │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __snapshots__ │ │ │ └── index.test.ts.snap │ │ ├── index.test.ts │ │ └── index.ts │ └── tsconfig.json ├── util-invariant │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ └── index.ts │ └── tsconfig.json ├── util-logger │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── util-logger.test.ts │ │ └── util-logger.ts │ └── tsconfig.json ├── util-rpc │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── messages.ts │ │ ├── rpc-client.test.ts │ │ ├── rpc-client.ts │ │ └── rpc-error.ts │ └── tsconfig.json ├── util-semver │ ├── .babelrc │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ ├── compare-identifiers.js │ │ ├── compare.js │ │ ├── compare.test.js │ │ └── index.ts │ └── tsconfig.json ├── util-template │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __snapshots__ │ │ │ └── template.test.ts.snap │ │ ├── template.test.ts │ │ └── template.ts │ └── tsconfig.json └── util-uid │ ├── .babelrc │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ ├── util-uid.test.ts │ └── util-uid.ts │ └── tsconfig.json └── tsconfig.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.7.0/schema.json", 3 | "changelog": ["@changesets/changelog-github", {"repo": "onflow/fcl-js"}], 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "ignore": ["@onflow/transport-grpc"] 11 | } 12 | -------------------------------------------------------------------------------- /.github/workflows/add-pitches-to-project.yml: -------------------------------------------------------------------------------- 1 | name: Adds all issues to the project board. 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@v0.4.1 14 | with: 15 | project-url: https://github.com/orgs/onflow/projects/85 16 | github-token: ${{ secrets.GH_ACTION_FOR_PROJECTS }} 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # folders 2 | node_modules/ 3 | dist/ 4 | .parcel-cache/ 5 | flowdb/ 6 | 7 | .exrc 8 | .DS_Store 9 | 10 | # file types 11 | dev-wallet/db/*.db 12 | todo.md 13 | **/debug.log 14 | *.log 15 | .vscode/* 16 | 17 | # type declarations 18 | packages/*/types/ -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | README.md 2 | *.md 3 | *.mdx 4 | packages/protobuf/src/generated/ -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "trailingComma": "es5", 4 | "bracketSpacing": false, 5 | "arrowParens": "avoid", 6 | "plugins": ["prettier-plugin-tailwindcss", "prettier-plugin-classnames"] 7 | } 8 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @onflow/fcl 2 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Flow 2 | Copyright 2019-2020 Dapper Labs, Inc. 3 | 4 | This product includes software developed at Dapper Labs, Inc. (https://www.dapperlabs.com/). 5 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | # Responsible Disclosure Policy 3 | 4 | Flow was built from the ground up with security in mind. Our code, infrastructure, and development methodology helps us keep our users safe. 5 | 6 | We really appreciate the community's help. Responsible disclosure of vulnerabilities helps to maintain the security and privacy of everyone. 7 | 8 | If you care about making a difference, please follow the guidelines below. 9 | 10 | # **Guidelines For Responsible Disclosure** 11 | 12 | We ask that all researchers adhere to these guidelines [here](https://flow.com/flow-responsible-disclosure). 13 | -------------------------------------------------------------------------------- /assets/build-resolve-send-decode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/assets/build-resolve-send-decode.png -------------------------------------------------------------------------------- /docs/images/discovery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/docs/images/discovery.png -------------------------------------------------------------------------------- /docs/images/wc-discovery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/docs/images/wc-discovery.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/index.md 4 | -------------------------------------------------------------------------------- /docs/index.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/index.mdx.txt 4 | -------------------------------------------------------------------------------- /docs/reference/api.md: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/api.md 4 | -------------------------------------------------------------------------------- /docs/reference/authentication.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/authentication.mdx 4 | -------------------------------------------------------------------------------- /docs/reference/configure-fcl.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/configure-fcl.mdx 4 | -------------------------------------------------------------------------------- /docs/reference/discovery.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/discovery.mdx 4 | -------------------------------------------------------------------------------- /docs/reference/installation.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/installation.mdx 4 | -------------------------------------------------------------------------------- /docs/reference/interaction-templates.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/interaction-templates.mdx 4 | -------------------------------------------------------------------------------- /docs/reference/proving-authentication.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/proving-authentication.mdx 4 | -------------------------------------------------------------------------------- /docs/reference/scripts.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/scripts.mdx 4 | -------------------------------------------------------------------------------- /docs/reference/sdk-guidelines.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/sdk-guidelines.mdx 4 | -------------------------------------------------------------------------------- /docs/reference/transactions.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/transactions.mdx 4 | -------------------------------------------------------------------------------- /docs/reference/user-signatures.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/user-signatures.mdx 4 | -------------------------------------------------------------------------------- /docs/reference/wallet-connect.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/fcl-js/wallet-connect.mdx 4 | -------------------------------------------------------------------------------- /docs/tutorials/flow-app-quickstart.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tutorials/flow-app-quickstart.mdx 4 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | projects: ["/packages/*"], 3 | } 4 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": ["packages/*"], 3 | "version": "independent" 4 | } 5 | -------------------------------------------------------------------------------- /packages/config/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/config/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/config/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"], 20 | "rules": { 21 | "@typescript-eslint/no-explicit-any": "off" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/config/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/config/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/fcl-bundle/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"]] 3 | } 4 | -------------------------------------------------------------------------------- /packages/fcl-bundle/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/fcl-bundle/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/fcl-bundle/src/build/build.js: -------------------------------------------------------------------------------- 1 | const {rollup} = require("rollup") 2 | 3 | const getInputOptions = require("./get-input-options") 4 | const getOutputOptions = require("./get-output-options") 5 | 6 | module.exports = async function buildModules(builds, package) { 7 | console.log(`Building ${package.name}...`) 8 | await Promise.all(builds.map(build => buildModule(build, package))) 9 | console.log("Build Success!") 10 | } 11 | 12 | async function buildModule(build, package) { 13 | const inputOptions = getInputOptions(package, build) 14 | const outputOptions = getOutputOptions(package, build) 15 | 16 | let bundle, buildError 17 | try { 18 | bundle = await rollup(inputOptions) 19 | await generateOutput(bundle, outputOptions) 20 | } catch (error) { 21 | buildError = error 22 | } 23 | if (bundle) await bundle.close() 24 | 25 | if (buildError) { 26 | throw new Error(buildError) 27 | } 28 | } 29 | 30 | async function generateOutput(bundle, outputOptions) { 31 | const {output} = await bundle.write(outputOptions) 32 | } 33 | -------------------------------------------------------------------------------- /packages/fcl-bundle/src/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const program = require("./program") 3 | const getPackageJSON = require("./get-package-json") 4 | const parsePackageJSON = require("./package-config") 5 | 6 | const package = getPackageJSON() 7 | const config = parsePackageJSON(package) 8 | 9 | program(config)(package) 10 | -------------------------------------------------------------------------------- /packages/fcl-bundle/src/get-package-json.js: -------------------------------------------------------------------------------- 1 | const {existsSync, readFileSync} = require("fs") 2 | const {resolve} = require("path") 3 | const {getPackageRoot} = require("./util") 4 | 5 | module.exports = function getPackageJSON() { 6 | const pathPackageJSON = resolve(getPackageRoot(), "package.json") 7 | if (existsSync(pathPackageJSON)) { 8 | return JSON.parse(readFileSync(pathPackageJSON)) 9 | } else { 10 | throw new Error("Package.json was not found! Aborting!") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/fcl-bundle/src/plugins/banner.js: -------------------------------------------------------------------------------- 1 | module.exports = function banner({banner, raw}) { 2 | return { 3 | name: "banner", 4 | outputOptions(options) { 5 | if (!raw) { 6 | banner = [ 7 | "/**", 8 | ...banner.split(/\r?\n/).map(l => ` * ${l}`), 9 | "*/", 10 | ].reduce((acc, l) => (acc += `${l}\n`), "") 11 | } 12 | return { 13 | ...options, 14 | banner, 15 | } 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/fcl-bundle/src/plugins/preserve-dynamic-imports.js: -------------------------------------------------------------------------------- 1 | module.exports = function preserveDynamicImports() { 2 | return { 3 | name: "preserve-dynamic-imports", 4 | renderDynamicImport() { 5 | return { 6 | left: "import(", 7 | right: ")", 8 | } 9 | }, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/fcl-bundle/src/program.js: -------------------------------------------------------------------------------- 1 | const {program} = require("commander") 2 | const buildModule = require("./build/build") 3 | const watchModule = require("./build/build-watch") 4 | const assert = require("assert") 5 | const getPackageJson = require("./get-package-json") 6 | const {resolve} = require("path") 7 | 8 | module.exports = packageConfig => package => { 9 | let bundlerPackageJson = getPackageJson(resolve(__dirname, "..")) 10 | 11 | program 12 | .name("FCL Build Tool") 13 | .description("Zero-configuration CLI to build FCL packages") 14 | .version(bundlerPackageJson.version) 15 | .option("-w, --watch", "Run the build in watch mode") 16 | .parse() 17 | 18 | program.action(async () => { 19 | assert( 20 | packageConfig.builds, 21 | "Module entry point(s) (package.build) must be defined" 22 | ) 23 | 24 | const buildAction = program.getOptionValue("watch") 25 | ? watchModule 26 | : buildModule 27 | 28 | await buildAction(packageConfig.builds, package) 29 | }) 30 | 31 | program.parse() 32 | } 33 | -------------------------------------------------------------------------------- /packages/fcl-bundle/src/util.js: -------------------------------------------------------------------------------- 1 | function isArray(obj) { 2 | return Object.prototype.toString.call(obj) === "[object Array]" 3 | } 4 | 5 | function isObject(obj) { 6 | return Object.prototype.toString.call(obj) === "[object Object]" 7 | } 8 | 9 | function isString(obj) { 10 | return typeof obj === "string" || obj instanceof String 11 | } 12 | 13 | // Get the root path of the package that the bundle is being built for 14 | function getPackageRoot() { 15 | return process.cwd() 16 | } 17 | 18 | module.exports = { 19 | isArray, 20 | isObject, 21 | isString, 22 | getPackageRoot, 23 | } 24 | -------------------------------------------------------------------------------- /packages/fcl-core/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "useBuiltIns": false 7 | } 8 | ], 9 | "@babel/preset-typescript" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /packages/fcl-core/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/fcl-core/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": ["plugin:jsdoc/recommended"], 9 | "plugins": ["jsdoc"], 10 | "parserOptions": { 11 | "ecmaVersion": "latest", 12 | "sourceType": "module" 13 | }, 14 | "globals": { 15 | "JSX": "readonly" 16 | }, 17 | "ignorePatterns": ["**/dist/"], 18 | 19 | "rules": { 20 | "jsdoc/require-jsdoc": 0, 21 | "jsdoc/tag-lines": 0, 22 | "jsdoc/require-param-description": 0, 23 | "jsdoc/valid-types": 0, 24 | "jsdoc/require-returns-description": 0, 25 | "no-undef": 1 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/fcl-core/.gitignore: -------------------------------------------------------------------------------- 1 | types/ -------------------------------------------------------------------------------- /packages/fcl-core/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | assets/ -------------------------------------------------------------------------------- /packages/fcl-core/WARNINGS.md: -------------------------------------------------------------------------------- 1 | # Warnings 2 | 3 | ## 0001 Current User Data 4 | 5 | - **Date:** July 22nd 2020 6 | - **Issue:** [#180](https://github.com/onflow/fcl-js/issues/180) 7 | - **Type:** Deprecation of Certain Fields on Object 8 | 9 | In the case of `userData` in the following:`fcl.currentUser().subscribe(userData)` and `var userData = await fcl.currentUser().snapshot()`, most fields will cease to exist. 10 | 11 | Please limit your use of the data within `userData` to `cid` and `loggedIn`. 12 | -------------------------------------------------------------------------------- /packages/fcl-core/assets/service-method-diagrams/ext-rpc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/packages/fcl-core/assets/service-method-diagrams/ext-rpc.png -------------------------------------------------------------------------------- /packages/fcl-core/assets/service-method-diagrams/http-post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/packages/fcl-core/assets/service-method-diagrams/http-post.png -------------------------------------------------------------------------------- /packages/fcl-core/assets/service-method-diagrams/iframe-rpc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/packages/fcl-core/assets/service-method-diagrams/iframe-rpc.png -------------------------------------------------------------------------------- /packages/fcl-core/assets/service-method-diagrams/pop-rpc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/packages/fcl-core/assets/service-method-diagrams/pop-rpc.png -------------------------------------------------------------------------------- /packages/fcl-core/assets/service-method-diagrams/tab-rpc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/packages/fcl-core/assets/service-method-diagrams/tab-rpc.png -------------------------------------------------------------------------------- /packages/fcl-core/src/VERSION.js: -------------------------------------------------------------------------------- 1 | export const VERSION = PACKAGE_CURRENT_VERSION || "TESTVERSION" 2 | -------------------------------------------------------------------------------- /packages/fcl-core/src/app-utils/index.js: -------------------------------------------------------------------------------- 1 | export {verifyAccountProof, verifyUserSignatures} from "./verify-signatures.js" 2 | -------------------------------------------------------------------------------- /packages/fcl-core/src/current-user/exec-service/strategies/utils/fetch-service.js: -------------------------------------------------------------------------------- 1 | import {serviceEndpoint} from "./service-endpoint" 2 | 3 | export function fetchService(service, opts = {}) { 4 | const method = opts.method || "POST" 5 | const body = 6 | method === "GET" 7 | ? undefined 8 | : JSON.stringify(opts.data || service.data || {}) 9 | 10 | return fetch(serviceEndpoint(service), { 11 | method: method, 12 | headers: { 13 | ...(service.headers || {}), 14 | ...(opts.headers || {}), 15 | "Content-Type": "application/json", 16 | }, 17 | body: body, 18 | }).then(d => d.json()) 19 | } 20 | -------------------------------------------------------------------------------- /packages/fcl-core/src/current-user/exec-service/strategies/utils/service-endpoint.js: -------------------------------------------------------------------------------- 1 | import {URL} from "../../../../utils/url" 2 | 3 | export function serviceEndpoint(service) { 4 | const url = new URL(service.endpoint) 5 | if (window?.location?.origin) { 6 | url.searchParams.append("l6n", window.location.origin) 7 | } 8 | if (service.params != null) { 9 | for (let [key, value] of Object.entries(service.params || {})) { 10 | url.searchParams.append(key, value) 11 | } 12 | } 13 | return url 14 | } 15 | -------------------------------------------------------------------------------- /packages/fcl-core/src/current-user/exec-service/wc-check.ts: -------------------------------------------------------------------------------- 1 | import * as logger from "@onflow/util-logger" 2 | import {getServiceRegistry} from "./plugins" 3 | 4 | const FCL_WC_SERVICE_METHOD = "WC/RPC" 5 | 6 | const isServerSide = typeof window === "undefined" 7 | 8 | // Utility to notify the user if the Walletconnect service plugin has not been loaded 9 | export function checkWalletConnectEnabled() { 10 | if (isServerSide) return 11 | 12 | const serviceRegistry = getServiceRegistry() 13 | const strategies = serviceRegistry.getStrategies() 14 | 15 | if (!strategies.includes(FCL_WC_SERVICE_METHOD)) { 16 | logger.log({ 17 | title: "FCL WalletConnect Service Plugin", 18 | level: logger.LEVELS.error, 19 | message: 20 | "All dApps are expected to register for a WalletConnect projectId & add this to their FCL configuration. If you do not do so, users will be unable to use certain wallets to interact with your dApp. See https://developers.flow.com/tools/clients/fcl-js/configure-fcl for more information.", 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/fcl-core/src/current-user/merge-services.js: -------------------------------------------------------------------------------- 1 | export function mergeServices(sx1 = [], sx2 = []) { 2 | // TODO: Make this smarter 3 | return [...sx1, ...sx2] 4 | } 5 | -------------------------------------------------------------------------------- /packages/fcl-core/src/current-user/service-of-type.js: -------------------------------------------------------------------------------- 1 | import * as semver from "@onflow/util-semver" 2 | 3 | export function serviceOfType(services = [], type) { 4 | // Find the greatest version of the service type 5 | return services.reduce( 6 | (mostRecent, service) => 7 | service.type === type 8 | ? !mostRecent || semver.compare(service.f_vsn, mostRecent.f_vsn) > 0 9 | ? service 10 | : mostRecent 11 | : mostRecent, 12 | null 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /packages/fcl-core/src/current-user/service-of-type.test.js: -------------------------------------------------------------------------------- 1 | import {serviceOfType} from "./service-of-type" 2 | 3 | describe("service-of-type", () => { 4 | it("should choose the most recent version of a service", () => { 5 | const services = [ 6 | { 7 | type: "authn", 8 | f_vsn: "1.0.0", 9 | }, 10 | { 11 | type: "authn", 12 | f_vsn: "2.0.0", 13 | }, 14 | ] 15 | 16 | const service = serviceOfType(services, "authn") 17 | 18 | expect(service).toEqual({ 19 | type: "authn", 20 | f_vsn: "2.0.0", 21 | }) 22 | }) 23 | 24 | it("should return null if no service of type exists", () => { 25 | const services = [ 26 | { 27 | type: "authn", 28 | f_vsn: "1.0.0", 29 | }, 30 | { 31 | type: "authn", 32 | f_vsn: "2.0.0", 33 | }, 34 | ] 35 | 36 | const service = serviceOfType(services, "non-existent") 37 | 38 | expect(service).toBe(null) 39 | }) 40 | }) 41 | -------------------------------------------------------------------------------- /packages/fcl-core/src/current-user/url-from-service.js: -------------------------------------------------------------------------------- 1 | import {URL} from "../utils/url" 2 | 3 | export function urlFromService(service, includeParams = true) { 4 | const url = new URL(service.endpoint) 5 | if (includeParams) { 6 | for (let [key, value] of Object.entries(service.params || {})) { 7 | url.searchParams.append(key, value) 8 | } 9 | } 10 | return url 11 | } 12 | -------------------------------------------------------------------------------- /packages/fcl-core/src/default-config.js: -------------------------------------------------------------------------------- 1 | import {config} from "@onflow/config" 2 | 3 | export async function configLens(regex) { 4 | return Object.fromEntries( 5 | Object.entries(await config().where(regex)).map(([key, value]) => [ 6 | key.replace(regex, ""), 7 | value, 8 | ]) 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /packages/fcl-core/src/discovery/index.js: -------------------------------------------------------------------------------- 1 | import authn from "./services/authn" 2 | export {getDiscoveryService, makeDiscoveryServices} from "./utils" 3 | 4 | const discovery = { 5 | authn, 6 | } 7 | 8 | export {discovery} 9 | -------------------------------------------------------------------------------- /packages/fcl-core/src/document/document.test.js: -------------------------------------------------------------------------------- 1 | import {retrieve} from "./document.js" 2 | import {config} from "@onflow/config" 3 | 4 | describe("resolveArguments", () => { 5 | test("Should invoke resolver", async () => { 6 | const templateResolver = jest.fn() 7 | 8 | const ret = await config.overload( 9 | { 10 | "document.resolver.testprotocol": templateResolver, 11 | }, 12 | async d => { 13 | await retrieve({url: "testprotocol://example.test"}) 14 | 15 | expect(templateResolver.mock.calls.length).toEqual(1) 16 | } 17 | ) 18 | }) 19 | }) 20 | -------------------------------------------------------------------------------- /packages/fcl-core/src/exec/args.ts: -------------------------------------------------------------------------------- 1 | import {arg} from "@onflow/sdk" 2 | import * as t from "@onflow/types" 3 | 4 | type ArgFn = typeof arg 5 | type Types = typeof t 6 | /** 7 | * @param arg - Argument function to define a single argument 8 | * @param t - Cadence Types object used to define the type 9 | * @returns {any[]} 10 | */ 11 | export type ArgsFn = (arg: ArgFn, t: Types) => any[] 12 | -------------------------------------------------------------------------------- /packages/fcl-core/src/exec/utils/normalize-args.js: -------------------------------------------------------------------------------- 1 | import {isFunc} from "../../utils/is" 2 | import * as sdk from "@onflow/sdk" 3 | import * as t from "@onflow/types" 4 | 5 | export function normalizeArgs(ax) { 6 | if (isFunc(ax)) return ax(sdk.arg, t) 7 | return [] 8 | } 9 | -------------------------------------------------------------------------------- /packages/fcl-core/src/exec/utils/prep-template-opts.js: -------------------------------------------------------------------------------- 1 | import {retrieve} from "../../document/document.js" 2 | import {deriveCadenceByNetwork} from "../../interaction-template-utils/derive-cadence-by-network/derive-cadence-by-network.js" 3 | import {isString} from "../../utils/is" 4 | import {getChainId} from "../../utils" 5 | 6 | export async function prepTemplateOpts(opts) { 7 | if (isString(opts?.template)) { 8 | opts.template = await retrieve({url: opts?.template}) 9 | } 10 | 11 | const cadence = 12 | opts.cadence || 13 | (await deriveCadenceByNetwork({ 14 | template: opts.template, 15 | network: await getChainId(opts), 16 | })) 17 | 18 | opts.cadence = cadence 19 | 20 | return opts 21 | } 22 | -------------------------------------------------------------------------------- /packages/fcl-core/src/exec/verify.js: -------------------------------------------------------------------------------- 1 | import {log} from "@onflow/util-logger" 2 | import {verifyUserSignatures as verify} from "../app-utils" 3 | 4 | /** 5 | * Verify a valid signature/s for an account on Flow. 6 | * 7 | * @deprecated since version '1.0.0-alpha.0', use AppUtils.verifyUserSignatures instead 8 | * 9 | */ 10 | export const verifyUserSignatures = log.deprecate({ 11 | pkg: "FCL", 12 | subject: "fcl.verifyUserSignatures()", 13 | message: "Please use fcl.AppUtils.verifyUserSignatures()", 14 | callback: function verifyUserSignatures(message, compSigs) { 15 | return verify(message, compSigs) 16 | }, 17 | }) 18 | -------------------------------------------------------------------------------- /packages/fcl-core/src/interaction-template-utils/index.js: -------------------------------------------------------------------------------- 1 | export {getInteractionTemplateAudits} from "./get-interaction-template-audits.js" 2 | export { 3 | generateDependencyPin, 4 | generateDependencyPinAtLatestSealedBlock, 5 | } from "./generate-dependency-pin/generate-dependency-pin.js" 6 | export { 7 | generateTemplateId, 8 | verifyGeneratedTemplateId, 9 | } from "./generate-template-id/generate-template-id.js" 10 | export { 11 | verifyDependencyPinsSame, 12 | verifyDependencyPinsSameAtLatestSealedBlock, 13 | } from "./verify-dependency-pin-same-at-block.js" 14 | export {deriveCadenceByNetwork} from "./derive-cadence-by-network/derive-cadence-by-network.js" 15 | export {getTemplateMessage} from "./get-template-message.js" 16 | export {getTemplateArgumentMessage} from "./get-template-argument-message.js" 17 | -------------------------------------------------------------------------------- /packages/fcl-core/src/interaction-template-utils/utils/find-imports.js: -------------------------------------------------------------------------------- 1 | import {generateImport} from "./generate-import.js" 2 | 3 | export function findImports(cadence) { 4 | const imports = [] 5 | 6 | const importsReg = /import ((\w|,| )+)* from 0x\w+/g 7 | const fileImports = cadence.match(importsReg) || [] 8 | 9 | for (const fileImport of fileImports) { 10 | const importLineReg = /import ((\w+|, |)*) from (0x\w+)/g 11 | const importLine = importLineReg.exec(fileImport) 12 | 13 | const contractsReg = /((?:\w+)+),?/g 14 | const contracts = importLine[1].match(contractsReg) || [] 15 | 16 | for (const contract of contracts) { 17 | imports.push( 18 | generateImport({ 19 | address: importLine[3], 20 | contractName: contract.replace(/,/g, ""), 21 | }) 22 | ) 23 | } 24 | } 25 | 26 | return imports 27 | } 28 | -------------------------------------------------------------------------------- /packages/fcl-core/src/interaction-template-utils/utils/generate-import.js: -------------------------------------------------------------------------------- 1 | export function generateImport({contractName, address}) { 2 | return {contractName, address, contract: ""} 3 | } 4 | -------------------------------------------------------------------------------- /packages/fcl-core/src/interaction-template-utils/utils/hash.js: -------------------------------------------------------------------------------- 1 | import {SHA3} from "sha3" 2 | import {Buffer} from "@onflow/rlp" 3 | 4 | export function genHash(utf8String) { 5 | const sha = new SHA3(256) 6 | sha.update(Buffer.from(utf8String, "utf8")) 7 | return sha.digest("hex") 8 | } 9 | -------------------------------------------------------------------------------- /packages/fcl-core/src/interaction-template-utils/utils/replace-string-imports.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description - Replaces string imports with the actual contract address 3 | * 4 | * @param {object} param 5 | * @param {string} param.cadence 6 | * @param {object} param.networkDependencies 7 | * @returns {string} - Cadence 8 | */ 9 | export function replaceStringImports({cadence, networkDependencies}) { 10 | return Object.keys(networkDependencies).reduce((c, contractName) => { 11 | const address = networkDependencies[contractName] 12 | const regex = new RegExp(`import "\\b${contractName}\\b"`, "g") 13 | return c.replace(regex, `import ${contractName} from ${address}`) 14 | }, cadence) 15 | } 16 | -------------------------------------------------------------------------------- /packages/fcl-core/src/interaction-template-utils/utils/replace-string-imports.test.js: -------------------------------------------------------------------------------- 1 | import {replaceStringImports} from "./replace-string-imports" 2 | 3 | describe("Verify replace imports works ", () => { 4 | test("replace single import", async () => { 5 | const cadence = await replaceStringImports({ 6 | cadence: 'import "FungibleToken"\n\n', 7 | networkDependencies: { 8 | FungibleToken: "0xf233dcee88fe0abe", 9 | }, 10 | }) 11 | expect(cadence).toEqual("import FungibleToken from 0xf233dcee88fe0abe\n\n") 12 | }) 13 | 14 | test("replace multiple import", async () => { 15 | const cadence = await replaceStringImports({ 16 | cadence: 'import "FungibleToken"\nimport "NonFungibleToken"\n\n', 17 | networkDependencies: { 18 | FungibleToken: "0xf233dcee88fe0abe", 19 | NonFungibleToken: "0x1d7e57aa55817448", 20 | }, 21 | }) 22 | 23 | expect(cadence).toEqual( 24 | "import FungibleToken from 0xf233dcee88fe0abe\nimport NonFungibleToken from 0x1d7e57aa55817448\n\n" 25 | ) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /packages/fcl-core/src/normalizers/service/__vsn.js: -------------------------------------------------------------------------------- 1 | export const SERVICE_PRAGMA = { 2 | f_type: "Service", 3 | f_vsn: "1.0.0", 4 | } 5 | 6 | export const IDENTITY_PRAGMA = { 7 | f_type: "Identity", 8 | f_vsn: "1.0.0", 9 | } 10 | 11 | export const PROVIDER_PRAGMA = { 12 | f_type: "Provider", 13 | f_vsn: "1.0.0", 14 | } 15 | 16 | export const USER_PRAGMA = { 17 | f_type: "USER", 18 | f_vsn: "1.0.0", 19 | } 20 | 21 | export const POLLING_RESPONSE_PRAGMA = { 22 | f_type: "PollingResponse", 23 | f_vsn: "1.0.0", 24 | } 25 | 26 | export const COMPOSITE_SIGNATURE_PRAGMA = { 27 | f_type: "CompositeSignature", 28 | f_vsn: "1.0.0", 29 | } 30 | 31 | export const OPEN_ID_PRAGMA = { 32 | f_type: "OpenId", 33 | f_vsn: "1.0.0", 34 | } 35 | -------------------------------------------------------------------------------- /packages/fcl-core/src/normalizers/service/authn-refresh.js: -------------------------------------------------------------------------------- 1 | // { 2 | // "f_type": "Service", 3 | // "f_vsn": "1.0.0", 4 | // "type": "authn-refresh", 5 | // "uid": "uniqueDedupeKey", 6 | // "endpoint": "https://rawr", 7 | // "method": "HTTP/POST", // "HTTP/POST", // HTTP/POST | IFRAME/RPC | HTTP/RPC 8 | // "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // wallets internal id for the user 9 | // "data": {}, // included in body of request 10 | // "params": {}, // included as query params on endpoint url 11 | // } 12 | export function normalizeAuthnRefresh(service) { 13 | if (service == null) return null 14 | 15 | if (!service["f_vsn"]) { 16 | throw new Error("Invalid authn-refresh service") 17 | } 18 | 19 | switch (service["f_vsn"]) { 20 | case "1.0.0": 21 | return service 22 | 23 | default: 24 | return null 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/fcl-core/src/normalizers/service/back-channel-rpc.js: -------------------------------------------------------------------------------- 1 | import {SERVICE_PRAGMA} from "./__vsn" 2 | 3 | // { 4 | // "f_type": "Service", 5 | // "f_vsn": "1.0.0", 6 | // "type": "back-channel-rpc", 7 | // "endpoint": "https://rawr", 8 | // "method": "HTTP/GET", // HTTP/GET | HTTP/POST 9 | // "data": {}, // included in body of rpc 10 | // "params": {}, // included as query params on endpoint url 11 | // } 12 | export function normalizeBackChannelRpc(service) { 13 | if (service == null) return null 14 | 15 | if (!service["f_vsn"]) { 16 | return { 17 | ...SERVICE_PRAGMA, 18 | type: "back-channel-rpc", 19 | endpoint: service.endpoint, 20 | method: service.method, 21 | params: service.params || {}, 22 | data: service.data || {}, 23 | } 24 | } 25 | 26 | switch (service["f_vsn"]) { 27 | case "1.0.0": 28 | return service 29 | 30 | default: 31 | return null 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/fcl-core/src/normalizers/service/composite-signature.js: -------------------------------------------------------------------------------- 1 | import {COMPOSITE_SIGNATURE_PRAGMA} from "./__vsn" 2 | import {sansPrefix} from "@onflow/util-address" 3 | 4 | // { 5 | // "f_type": "CompositeSignature", 6 | // "f_vsn": "1.0.0", 7 | // "addr": "_____", // sans-prefix 8 | // "signature": "adfe1234", // hex 9 | // "keyId": 3, 10 | // } 11 | export function normalizeCompositeSignature(resp) { 12 | if (resp == null) return null 13 | 14 | if (!resp["f_vsn"]) { 15 | return { 16 | ...COMPOSITE_SIGNATURE_PRAGMA, 17 | addr: sansPrefix(resp.addr || resp.address), 18 | signature: resp.signature || resp.sig, 19 | keyId: resp.keyId, 20 | } 21 | } 22 | 23 | switch (resp["f_vsn"]) { 24 | case "1.0.0": 25 | return resp 26 | 27 | default: 28 | return null 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/fcl-core/src/normalizers/service/frame.js: -------------------------------------------------------------------------------- 1 | import {SERVICE_PRAGMA} from "./__vsn" 2 | 3 | // { 4 | // "f_type": "Service", 5 | // "f_vsn": "1.0.0", 6 | // "type": "frame", 7 | // "endpoint": "https://rawr", 8 | // "data": {}, // Sent to frame when ready 9 | // "params": {}, // include in query params on frame 10 | // } 11 | export function normalizeFrame(service) { 12 | if (service == null) return null 13 | 14 | if (!service["f_vsn"]) { 15 | return { 16 | old: service, 17 | ...SERVICE_PRAGMA, 18 | type: "frame", 19 | endpoint: service.endpoint, 20 | params: service.params || {}, 21 | data: service.data || {}, 22 | } 23 | } 24 | 25 | switch (service["f_vsn"]) { 26 | case "1.0.0": 27 | return service 28 | 29 | default: 30 | return null 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/fcl-core/src/normalizers/service/local-view.js: -------------------------------------------------------------------------------- 1 | import {SERVICE_PRAGMA} from "./__vsn" 2 | 3 | // { 4 | // "f_type": "Service", 5 | // "f_vsn": "1.0.0", 6 | // type: "local-view", 7 | // method: "VIEW/IFRAME", 8 | // endpoint: "https://woot.org/authz/local", 9 | // data: {}, 10 | // params: {}, 11 | // } 12 | export function normalizeLocalView(resp) { 13 | if (resp == null) return null 14 | if (resp.method == null) { 15 | resp = {...resp, type: "local-view", method: "VIEW/IFRAME"} 16 | } 17 | 18 | if (!resp["f_vsn"]) { 19 | return { 20 | ...SERVICE_PRAGMA, 21 | type: resp.type || "local-view", 22 | method: resp.method, 23 | endpoint: resp.endpoint, 24 | data: resp.data || {}, 25 | params: resp.params || {}, 26 | } 27 | } 28 | 29 | switch (resp["f_vsn"]) { 30 | case "1.0.0": 31 | return resp 32 | 33 | default: 34 | return null 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/fcl-core/src/normalizers/service/user-signature.js: -------------------------------------------------------------------------------- 1 | // { 2 | // "f_type": "Service", 3 | // "f_vsn": "1.0.0", 4 | // "type": "user-signature", 5 | // "uid": "uniqueDedupeKey", 6 | // "endpoint": "https://rawr", 7 | // "method": "IFRAME/RPC", // HTTP/POST | IFRAME/RPC | HTTP/RPC 8 | // "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // wallets internal id for the user 9 | // "data": {}, // included in body of user-signature request 10 | // "params": {}, // included as query params on endpoint url 11 | // } 12 | export function normalizeUserSignature(service) { 13 | if (service == null) return null 14 | 15 | if (!service["f_vsn"]) { 16 | throw new Error("Invalid user-signature service") 17 | } 18 | 19 | switch (service["f_vsn"]) { 20 | case "1.0.0": 21 | return service 22 | 23 | default: 24 | return null 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/fcl-core/src/serialize/index.js: -------------------------------------------------------------------------------- 1 | import {interaction, pipe} from "@onflow/sdk" 2 | import {resolve as defaultResolve} from "@onflow/sdk" 3 | import {config, createSignableVoucher} from "@onflow/sdk" 4 | 5 | export const serialize = async (args = [], opts = {}) => { 6 | const resolveFunction = await config.first( 7 | ["sdk.resolve"], 8 | opts.resolve || defaultResolve 9 | ) 10 | 11 | if (Array.isArray(args)) args = await pipe(interaction(), args) 12 | 13 | return JSON.stringify( 14 | createSignableVoucher(await resolveFunction(args)), 15 | null, 16 | 2 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /packages/fcl-core/src/transaction/constants.ts: -------------------------------------------------------------------------------- 1 | export const TXID_REGEXP = /^[0-9a-fA-F]{64}$/ 2 | -------------------------------------------------------------------------------- /packages/fcl-core/src/transaction/index.ts: -------------------------------------------------------------------------------- 1 | export {TransactionError} from "./transaction-error" 2 | export {transaction} from "./transaction" 3 | -------------------------------------------------------------------------------- /packages/fcl-core/src/transaction/transaction-error.ts: -------------------------------------------------------------------------------- 1 | import {FvmErrorCode} from "@onflow/typedefs" 2 | 3 | const ERROR_CODE_REGEX = /\[Error Code: (\d+)\]/ 4 | 5 | export class TransactionError extends Error { 6 | public code: FvmErrorCode 7 | public type: string 8 | 9 | private constructor(message: string, code: FvmErrorCode) { 10 | super(message) 11 | this.code = code 12 | this.type = FvmErrorCode[code] 13 | } 14 | 15 | static fromErrorMessage(errorMessage: string): TransactionError { 16 | const match = errorMessage.match(ERROR_CODE_REGEX) 17 | const code = match ? parseInt(match[1], 10) : undefined 18 | 19 | return new TransactionError( 20 | errorMessage, 21 | code || FvmErrorCode.UNKNOWN_ERROR 22 | ) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/fcl-core/src/transaction/types.ts: -------------------------------------------------------------------------------- 1 | import {TransactionStatus} from "@onflow/typedefs" 2 | -------------------------------------------------------------------------------- /packages/fcl-core/src/utils/chain-id/chain-id-watcher.js: -------------------------------------------------------------------------------- 1 | import {config} from "@onflow/config" 2 | import {getChainId} from "./get-chain-id" 3 | 4 | /** 5 | * @description 6 | * Watches the config for changes to access node and updates the chain id accordingly 7 | * 8 | * @returns {Function} A function that unsubscribes the listener 9 | * 10 | */ 11 | export function watchForChainIdChanges() { 12 | return config.subscribe(() => { 13 | // Call getChainId to update the chainId cache if access node has changed 14 | getChainId({ 15 | enableRequestLogging: false, 16 | }).catch(() => {}) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /packages/fcl-core/src/utils/chain-id/fetch-chain-id.js: -------------------------------------------------------------------------------- 1 | import * as sdk from "@onflow/sdk" 2 | 3 | export async function fetchChainId(opts = {}) { 4 | const response = await sdk 5 | .send([sdk.getNetworkParameters()], opts) 6 | .then(sdk.decode) 7 | return response.chainId 8 | } 9 | -------------------------------------------------------------------------------- /packages/fcl-core/src/utils/constants.js: -------------------------------------------------------------------------------- 1 | export const FCL_REDIRECT_URL_PARAM_NAME = "fcl_redirect_url" 2 | export const FCL_RESPONSE_PARAM_NAME = "fclResponseJson" 3 | 4 | export const CORE_STRATEGIES = { 5 | "HTTP/RPC": "HTTP/RPC", 6 | "HTTP/POST": "HTTP/POST", 7 | "IFRAME/RPC": "IFRAME/RPC", 8 | "POP/RPC": "POP/RPC", 9 | "TAB/RPC": "TAB/RPC", 10 | "EXT/RPC": "EXT/RPC", 11 | "DEEPLINK/RPC": "DEEPLINK/RPC", 12 | } 13 | -------------------------------------------------------------------------------- /packages/fcl-core/src/utils/index.js: -------------------------------------------------------------------------------- 1 | export {getChainId} from "./chain-id/get-chain-id" 2 | export {watchForChainIdChanges} from "./chain-id/chain-id-watcher" 3 | 4 | export function isAndroid() { 5 | return ( 6 | typeof navigator !== "undefined" && /android/i.test(navigator.userAgent) 7 | ) 8 | } 9 | 10 | export function isSmallIOS() { 11 | return ( 12 | typeof navigator !== "undefined" && /iPhone|iPod/.test(navigator.userAgent) 13 | ) 14 | } 15 | 16 | export function isLargeIOS() { 17 | return typeof navigator !== "undefined" && /iPad/.test(navigator.userAgent) 18 | } 19 | 20 | export function isIOS() { 21 | return isSmallIOS() || isLargeIOS() 22 | } 23 | 24 | export function isMobile() { 25 | return isAndroid() || isIOS() 26 | } 27 | -------------------------------------------------------------------------------- /packages/fcl-core/src/utils/is-react-native.js: -------------------------------------------------------------------------------- 1 | let _isReactNative = false 2 | 3 | export function isReactNative() { 4 | return _isReactNative 5 | } 6 | 7 | export function setIsReactNative(value) { 8 | _isReactNative = value 9 | } 10 | -------------------------------------------------------------------------------- /packages/fcl-core/src/utils/is.js: -------------------------------------------------------------------------------- 1 | const is = type => d => typeof d === type 2 | 3 | export const isRequired = d => d != null 4 | export const isObject = is("object") 5 | export const isString = is("string") 6 | export const isFunc = is("function") 7 | export const isNumber = is("number") 8 | -------------------------------------------------------------------------------- /packages/fcl-core/src/utils/storage.ts: -------------------------------------------------------------------------------- 1 | export type StorageProvider = { 2 | can: boolean 3 | get: (key: string) => Promise 4 | put: (key: string, value: any) => Promise 5 | } 6 | -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-provider-spec/README.md: -------------------------------------------------------------------------------- 1 | Sorry, We will be adding these docs ASAP. 2 | If you are interested in this, reach out to us on [Discord](https://discord.gg/k6cZ7QC). 3 | -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-provider-spec/assets/fcl-ars-auth-v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/packages/fcl-core/src/wallet-provider-spec/assets/fcl-ars-auth-v1.png -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-provider-spec/assets/fcl-ars-auth-v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/packages/fcl-core/src/wallet-provider-spec/assets/fcl-ars-auth-v2.png -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-provider-spec/assets/fcl-ars-auth-v3.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/packages/fcl-core/src/wallet-provider-spec/assets/fcl-ars-auth-v3.1.png -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-provider-spec/assets/fcl-ars-auth-v3.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/packages/fcl-core/src/wallet-provider-spec/assets/fcl-ars-auth-v3.2.png -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-provider-spec/assets/fcl-ars-auth-v3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onflow/fcl-js/ad50c627b31e38fdb39ec3a5c4bb4cbf392347f4/packages/fcl-core/src/wallet-provider-spec/assets/fcl-ars-auth-v3.png -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-provider-spec/non-custodial.md: -------------------------------------------------------------------------------- 1 | Sorry, We will be adding these docs ASAP. 2 | If you are interested in this, reach out to us on [Discord](https://discord.gg/k6cZ7QC). 3 | -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-provider-spec/wallet-discover.md: -------------------------------------------------------------------------------- 1 | Sorry, We will be adding these docs ASAP. 2 | If you are interested in this, reach out to us on [Discord](https://discord.gg/k6cZ7QC). 3 | -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-utils/CompositeSignature.js: -------------------------------------------------------------------------------- 1 | import {withPrefix} from "@onflow/util-address" 2 | import {COMPOSITE_SIGNATURE_PRAGMA} from "../normalizers/service/__vsn" 3 | 4 | /** 5 | * @description 6 | * Constructs a new CompositeSignature instance. 7 | * 8 | * @param {string} addr - Flow Address 9 | * @param {number} keyId - Key ID 10 | * @param {string} signature - Signature as a hex string 11 | */ 12 | export function CompositeSignature(addr, keyId, signature) { 13 | this.f_type = COMPOSITE_SIGNATURE_PRAGMA.f_type 14 | this.f_vsn = COMPOSITE_SIGNATURE_PRAGMA.f_vsn 15 | this.addr = withPrefix(addr) 16 | this.keyId = Number(keyId) 17 | this.signature = signature 18 | } 19 | -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-utils/index.js: -------------------------------------------------------------------------------- 1 | export { 2 | sendMsgToFCL, 3 | ready, 4 | close, 5 | approve, 6 | decline, 7 | redirect, 8 | } from "./send-msg-to-fcl.js" 9 | export {onMessageFromFCL} from "./on-message-from-fcl.js" 10 | export {encodeMessageFromSignable} from "@onflow/sdk" 11 | export {CompositeSignature} from "./CompositeSignature.js" 12 | export {encodeAccountProof} from "./encode-account-proof.js" 13 | export {injectExtService} from "./inject-ext-service.js" 14 | -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-utils/inject-ext-service.js: -------------------------------------------------------------------------------- 1 | export function injectExtService(service) { 2 | if (service.type === "authn" && service.endpoint != null) { 3 | if (!Array.isArray(window.fcl_extensions)) { 4 | window.fcl_extensions = [] 5 | } 6 | window.fcl_extensions.push(service) 7 | } else { 8 | console.warn("Authn service is required") 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-utils/on-message-from-fcl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 3 | * Listens for messages from FCL 4 | * 5 | * @param {string} messageType - Message type 6 | * @param {Function} cb - Callback function 7 | * @returns {Function} - Function to remove event listener 8 | */ 9 | export const onMessageFromFCL = (messageType, cb = () => {}) => { 10 | const buildData = data => { 11 | if (data.deprecated) 12 | console.warn("DEPRECATION NOTICE", data.deprecated.message) 13 | delete data?.body?.interaction 14 | 15 | return data 16 | } 17 | 18 | const internal = e => { 19 | const {data, origin} = e 20 | if (typeof data !== "object") return 21 | if (typeof data == null) return 22 | if (data.type !== messageType) return 23 | 24 | cb(buildData(data), {origin}) 25 | } 26 | 27 | window.addEventListener("message", internal) 28 | return () => window.removeEventListener("message", internal) 29 | } 30 | -------------------------------------------------------------------------------- /packages/fcl-core/src/wallet-utils/wallet-utils.test.js: -------------------------------------------------------------------------------- 1 | import {CompositeSignature} from "./CompositeSignature" 2 | 3 | describe("wallet utils", () => { 4 | test("returns composite signature", () => { 5 | const COMPOSITE_SIGNATURE = { 6 | f_type: "CompositeSignature", 7 | f_vsn: "1.0.0", 8 | addr: "0x1", 9 | keyId: 0, 10 | signature: "foo", 11 | } 12 | const compSig = new CompositeSignature("1", 0, "foo") 13 | expect(compSig).toEqual(COMPOSITE_SIGNATURE) 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /packages/fcl-core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/README.md: -------------------------------------------------------------------------------- 1 | # @onflow/fcl-ethereum-provider 2 | 3 | This package exposes a client-side [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) compatible Ethereum provider that leverages an FCL-authenticated Cadence Owned Account (COA) under the hood. It enables wallets without native EVM capabilities to emulate Ethereum JSON-RPC by delegating signing and COA interactions to FCL. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm install --save @onflow/fcl-ethereum-provider 9 | ``` 10 | 11 | ## Usage 12 | 13 | Check out the [documentation](https://developers.flow.com/tools/clients/fcl-js/cross-vm/ethereum-provider) for guides and examples on how to integrate and use this provider in your project. 14 | 15 | ## License 16 | 17 | Apache-2.0 -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/index.ts: -------------------------------------------------------------------------------- 1 | export {createProvider} from "./create-provider" 2 | export {WalletConnectEthereumProvider} from "./wc-provider" 3 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/provider.test.ts: -------------------------------------------------------------------------------- 1 | describe("provider", () => { 2 | test("should be tested", () => { 3 | expect(true).toBe(true) 4 | }) 5 | }) 6 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/rpc/handlers/eth-accounts.ts: -------------------------------------------------------------------------------- 1 | import {withPrefix} from "@onflow/fcl" 2 | import {AccountManager} from "../../accounts/account-manager" 3 | 4 | export async function ethAccounts( 5 | accountManager: AccountManager 6 | ): Promise { 7 | const accounts = await accountManager.getAccounts() 8 | return accounts.map(x => withPrefix(x)) 9 | } 10 | 11 | export async function ethRequestAccounts( 12 | accountManager: AccountManager, 13 | chainId: number 14 | ): Promise { 15 | await accountManager.authenticate() 16 | const accounts = await accountManager.getAndCreateAccounts(chainId) 17 | return accounts.map(x => withPrefix(x)) 18 | } 19 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/rpc/handlers/eth-chain-id.ts: -------------------------------------------------------------------------------- 1 | import {NetworkManager} from "../../network/network-manager" 2 | import {formatChainId} from "../../util/eth" 3 | 4 | export async function ethChainId(networkManager: NetworkManager) { 5 | const chainId = await networkManager.getChainId() 6 | if (!chainId) { 7 | throw new Error("No active chain") 8 | } 9 | return formatChainId(chainId) 10 | } 11 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/rpc/handlers/eth-send-transaction.ts: -------------------------------------------------------------------------------- 1 | import {AccountManager} from "../../accounts/account-manager" 2 | import {NetworkManager} from "../../network/network-manager" 3 | 4 | export async function ethSendTransaction( 5 | accountManager: AccountManager, 6 | networkManager: NetworkManager, 7 | params: any 8 | ) { 9 | return await accountManager.sendTransaction({ 10 | ...params[0], 11 | // We pass the chainId to avoid race conditions where the chainId changes 12 | chainId: await networkManager.getChainId(), 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/rpc/handlers/eth-signtypeddata.ts: -------------------------------------------------------------------------------- 1 | import {AccountManager} from "../../accounts/account-manager" 2 | import {SignTypedDataParams} from "../../types/eth" 3 | import { 4 | hashTypedDataLegacy, 5 | hashTypedDataV3, 6 | hashTypedDataV4, 7 | } from "../../hash-utils" 8 | 9 | export async function signTypedData( 10 | accountManager: AccountManager, 11 | params: SignTypedDataParams, 12 | version: "eth_signTypedData" | "eth_signTypedData_v3" | "eth_signTypedData_v4" 13 | ) { 14 | const {address, data} = params 15 | 16 | if (!address || !data) { 17 | throw new Error("Missing signer address or typed data") 18 | } 19 | 20 | let hashedMessage: string 21 | if (version === "eth_signTypedData_v3") { 22 | hashedMessage = hashTypedDataV3(data) 23 | } else if (version === "eth_signTypedData_v4") { 24 | hashedMessage = hashTypedDataV4(data) 25 | } else { 26 | hashedMessage = hashTypedDataLegacy(data) 27 | } 28 | 29 | return await accountManager.signMessage(hashedMessage, address) 30 | } 31 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/rpc/handlers/personal-sign.ts: -------------------------------------------------------------------------------- 1 | import {AccountManager} from "../../accounts/account-manager" 2 | import {PersonalSignParams} from "../../types/eth" 3 | 4 | export async function personalSign( 5 | accountManager: AccountManager, 6 | params: PersonalSignParams 7 | ) { 8 | const [message, from] = params 9 | 10 | return await accountManager.signMessage(message, from) 11 | } 12 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/rpc/types.ts: -------------------------------------------------------------------------------- 1 | export type RpcHandler = (params: any) => Promise 2 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/types/account.ts: -------------------------------------------------------------------------------- 1 | export interface AddressStoreState { 2 | isLoading: boolean 3 | address: string | null 4 | error: Error | null 5 | } 6 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/types/events.ts: -------------------------------------------------------------------------------- 1 | export type TransactionExecutedEvent = { 2 | hash: string[] 3 | index: string 4 | type: string 5 | payload: string[] 6 | errorCode: string 7 | errorMessage: string 8 | gasConsumed: string 9 | contractAddress: string 10 | logs: string[] 11 | blockHeight: string 12 | returnedData: string[] 13 | precompiledCalls: string[] 14 | stateUpdateChecksum: string 15 | } 16 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/types/provider.ts: -------------------------------------------------------------------------------- 1 | // Types for RPC request and events 2 | import {ProviderError} from "../util/errors" 3 | 4 | export type ProviderRequest = { 5 | method: string 6 | params?: unknown[] | Record 7 | } 8 | 9 | export type ProviderResponse = T 10 | 11 | // Event types for the provider 12 | export type ProviderEvents = { 13 | connect: {chainId: string} 14 | disconnect: ProviderError 15 | chainChanged: string 16 | accountsChanged: string[] 17 | } 18 | 19 | // Event callback 20 | export type EventCallback = (event: T) => void 21 | 22 | // Base EIP-1193 Provider Interface 23 | export interface Eip1193Provider { 24 | request(args: ProviderRequest): Promise> 25 | on( 26 | event: E, 27 | listener: EventCallback 28 | ): void 29 | removeListener( 30 | event: E, 31 | listener: EventCallback 32 | ): void 33 | disconnect(): Promise 34 | } 35 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/util/chain.ts: -------------------------------------------------------------------------------- 1 | import {FLOW_CHAINS, FlowNetwork} from "../constants" 2 | 3 | export function getFlowNetwork(chainId: number): FlowNetwork | undefined { 4 | return Object.entries(FLOW_CHAINS).find( 5 | ([, chain]) => chain.eip155ChainId === chainId 6 | )?.[0] as FlowNetwork | undefined 7 | } 8 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/src/util/eth.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ContractType, 3 | FLOW_CHAINS, 4 | FLOW_CONTRACTS, 5 | FlowNetwork, 6 | } from "../constants" 7 | import * as fcl from "@onflow/fcl" 8 | 9 | export function formatChainId(chainId: string | number): `0x${string}` { 10 | const numericChainId = 11 | typeof chainId === "string" ? parseInt(chainId) : chainId 12 | return `0x${numericChainId.toString(16)}` 13 | } 14 | 15 | export function getContractAddress( 16 | contractType: ContractType, 17 | chainId: number 18 | ) { 19 | // Find the Flow network based on the chain ID 20 | const flowNetwork = Object.entries(FLOW_CHAINS).find( 21 | ([, chain]) => chain.eip155ChainId === chainId 22 | )?.[0] as FlowNetwork | undefined 23 | 24 | if (!flowNetwork) { 25 | throw new Error("Flow network not found for chain ID") 26 | } 27 | 28 | const evmContractAddress = fcl.withPrefix( 29 | FLOW_CONTRACTS[contractType][flowNetwork] 30 | ) 31 | return evmContractAddress 32 | } 33 | -------------------------------------------------------------------------------- /packages/fcl-ethereum-provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/fcl-rainbowkit-adapter/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/fcl-rainbowkit-adapter/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/fcl-rainbowkit-adapter/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/fcl-rainbowkit-adapter/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/fcl-rainbowkit-adapter/README.md: -------------------------------------------------------------------------------- 1 | # @onflow/fcl-rainbowkit-adapter 2 | 3 | RainbowKit adapter used to enable cross-VM wallet connections across both FCL & Wagmi. This package exposes RainbowKit connectors which can be used to establish these hybrid-style wallet connections. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm install --save @onflow/fcl-rainbowkit-adapter 9 | ``` 10 | 11 | ## Usage 12 | 13 | Check out the [documentation](https://developers.flow.com/tools/clients/fcl-js/cross-vm/rainbowkit-adapter) for guides and examples on how to integrate and use this adapter in your project. 14 | 15 | ## License 16 | 17 | Apache-2.0 -------------------------------------------------------------------------------- /packages/fcl-rainbowkit-adapter/src/fcl-rainbowkit-adapter.test.ts: -------------------------------------------------------------------------------- 1 | describe("fcl rainbowkit adapter", () => { 2 | it("should be tested", () => { 3 | expect(true).toBe(true) 4 | }) 5 | }) 6 | -------------------------------------------------------------------------------- /packages/fcl-rainbowkit-adapter/src/index.ts: -------------------------------------------------------------------------------- 1 | export {flowWallet} from "./wallets/flow-wallet" 2 | export {createFclConnector} from "./create-connector" 3 | export { 4 | type WalletConnectWalletOptions, 5 | walletConnectWallet, 6 | } from "./wallets/wc-wallet" 7 | -------------------------------------------------------------------------------- /packages/fcl-rainbowkit-adapter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/fcl-react-native/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"]] 3 | } 4 | -------------------------------------------------------------------------------- /packages/fcl-react-native/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/fcl-react-native/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": ["plugin:jsdoc/recommended"], 9 | "plugins": ["jsdoc"], 10 | "parserOptions": { 11 | "ecmaVersion": "latest", 12 | "sourceType": "module" 13 | }, 14 | "globals": { 15 | "JSX": "readonly" 16 | }, 17 | "ignorePatterns": ["**/dist/"], 18 | 19 | "rules": { 20 | "jsdoc/require-jsdoc": 0, 21 | "jsdoc/tag-lines": 0, 22 | "jsdoc/require-param-description": 0, 23 | "jsdoc/valid-types": 0, 24 | "jsdoc/require-returns-description": 0, 25 | "no-undef": 1 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/fcl-react-native/.gitignore: -------------------------------------------------------------------------------- 1 | types/ -------------------------------------------------------------------------------- /packages/fcl-react-native/.npmignore: -------------------------------------------------------------------------------- 1 | src/ -------------------------------------------------------------------------------- /packages/fcl-react-native/src/VERSION.js: -------------------------------------------------------------------------------- 1 | export const VERSION = PACKAGE_CURRENT_VERSION || "TESTVERSION" 2 | -------------------------------------------------------------------------------- /packages/fcl-react-native/src/utils/react-native/__tests__/default-config.test.js: -------------------------------------------------------------------------------- 1 | import {getDefaultConfig} from "../default-config" 2 | 3 | describe("getDefaultConfig tests", () => { 4 | it("should return default config", () => { 5 | const defaultConfig = getDefaultConfig() 6 | expect(defaultConfig["discovery.wallet.method.default"]).toBe( 7 | "DEEPLINK/RPC" 8 | ) 9 | }) 10 | }) 11 | -------------------------------------------------------------------------------- /packages/fcl-react-native/src/utils/react-native/coreStrategies.js: -------------------------------------------------------------------------------- 1 | import {CORE_STRATEGIES, getExecHttpPost} from "@onflow/fcl-core" 2 | import {execLocal} from "./exec-local" 3 | import {execDeeplinkRPC} from "./strategies/deeplink-rpc" 4 | 5 | export const coreStrategies = { 6 | [CORE_STRATEGIES["HTTP/RPC"]]: getExecHttpPost(execLocal), 7 | [CORE_STRATEGIES["HTTP/POST"]]: getExecHttpPost(execLocal), 8 | [CORE_STRATEGIES["DEEPLINK/RPC"]]: execDeeplinkRPC, 9 | } 10 | -------------------------------------------------------------------------------- /packages/fcl-react-native/src/utils/react-native/default-config.js: -------------------------------------------------------------------------------- 1 | export const getDefaultConfig = () => { 2 | return { 3 | "discovery.wallet.method.default": "DEEPLINK/RPC", 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/fcl-react-native/src/utils/react-native/exec-local.js: -------------------------------------------------------------------------------- 1 | import {renderBrowser} from "./render-browser" 2 | import {renderDeeplink} from "./render-deeplink" 3 | 4 | const NOT_IMPLEMENTED = strategy => () => { 5 | throw new Error( 6 | `${strategy} Strategy util has not been implemented on this platform` 7 | ) 8 | } 9 | 10 | const VIEWS = { 11 | "VIEW/IFRAME": NOT_IMPLEMENTED("VIEW/IFRAME"), 12 | "VIEW/POP": NOT_IMPLEMENTED("VIEW/IFRAME"), 13 | "VIEW/TAB": NOT_IMPLEMENTED("VIEW/TAB"), 14 | "VIEW/MOBILE_BROWSER": renderBrowser, 15 | "VIEW/DEEPLINK": renderDeeplink, 16 | } 17 | 18 | export async function execLocal( 19 | service, 20 | opts = {serviceEndpoint: () => {}, onClose: () => {}} 21 | ) { 22 | const {serviceEndpoint} = opts 23 | try { 24 | return VIEWS[service.method](serviceEndpoint(service), opts) 25 | } catch (error) { 26 | console.error("execLocal({service, opts = {}})", error, {service, opts}) 27 | throw error 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/fcl-react-native/src/utils/react-native/index.js: -------------------------------------------------------------------------------- 1 | export {ServiceDiscovery, useServiceDiscovery} from "./ServiceDiscovery" 2 | export {getDefaultConfig} from "./default-config" 3 | export {coreStrategies} from "./coreStrategies" 4 | -------------------------------------------------------------------------------- /packages/fcl-react-native/src/utils/react-native/render-browser.js: -------------------------------------------------------------------------------- 1 | import * as WebBrowser from "expo-web-browser" 2 | import * as Linking from "expo-linking" 3 | import {FCL_REDIRECT_URL_PARAM_NAME, URL} from "@onflow/fcl-core" 4 | 5 | /** 6 | * 7 | * @param {URL} src 8 | * @param {object} opts 9 | * @returns {[object, () => void]} 10 | */ 11 | export function renderBrowser(src, opts = {}) { 12 | const redirectUrl = Linking.createURL("$$fcl_auth_callback$$", { 13 | queryParams: {}, 14 | }) 15 | const url = new URL(src.toString()) 16 | url.searchParams.append(FCL_REDIRECT_URL_PARAM_NAME, redirectUrl) 17 | const webbrowser = WebBrowser.openAuthSessionAsync(url.toString()) 18 | 19 | const unmount = () => { 20 | try { 21 | WebBrowser.dismissAuthSession() 22 | } catch (error) { 23 | console.log(error) 24 | } 25 | } 26 | 27 | // Call onClose when the webbrowser is closed 28 | webbrowser.then(() => { 29 | if (opts?.onClose) { 30 | opts.onClose() 31 | } 32 | }) 33 | 34 | return [webbrowser, unmount] 35 | } 36 | -------------------------------------------------------------------------------- /packages/fcl-react-native/src/utils/react-native/storage.ts: -------------------------------------------------------------------------------- 1 | import AsyncStorage from "@react-native-async-storage/async-storage" 2 | 3 | const safeParseJSON = (str?: string | null) => { 4 | if (str == null) return null 5 | try { 6 | return JSON.parse(str) 7 | } catch (error) { 8 | return null 9 | } 10 | } 11 | 12 | export const getAsyncStorage = () => { 13 | try { 14 | const ASYNC_STORAGE = { 15 | can: true, 16 | get: async (key: string) => 17 | safeParseJSON(await AsyncStorage.getItem(key)), 18 | put: async (key: string, value: any) => 19 | await AsyncStorage.setItem(key, JSON.stringify(value)), 20 | } 21 | return ASYNC_STORAGE 22 | } catch (error) { 23 | return null 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/fcl-react-native/src/utils/react-native/strategies/utils/service-endpoint.js: -------------------------------------------------------------------------------- 1 | import {URL} from "@onflow/fcl-core" 2 | 3 | const isBodyEmpty = body => { 4 | return ( 5 | !body || 6 | (body?.data !== undefined && 7 | Object.keys(body).filter(key => key !== "data").length === 0) 8 | ) 9 | } 10 | 11 | export function serviceEndpoint(service, config, body) { 12 | const url = new URL(service.endpoint) 13 | if (!isBodyEmpty(body)) { 14 | url.searchParams.append("fclMessageJson", JSON.stringify({...body, config})) 15 | } else { 16 | url.searchParams.append("fclMessageJson", JSON.stringify({config})) 17 | } 18 | 19 | if (service.params != null) { 20 | for (let [key, value] of Object.entries(service.params || {})) { 21 | url.searchParams.append(key, value) 22 | } 23 | } 24 | return url 25 | } 26 | -------------------------------------------------------------------------------- /packages/fcl-react-native/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/fcl-wagmi-adapter/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/fcl-wagmi-adapter/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/fcl-wagmi-adapter/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/fcl-wagmi-adapter/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/fcl-wagmi-adapter/README.md: -------------------------------------------------------------------------------- 1 | # @onflow/fcl-wagmi-adapter 2 | 3 | Provides a Wagmi connector that uses @onflow/fcl-ethereum-provider under the hood, allowing you to integrate Flow-based Cadence-Owned Accounts (COAs) seamlessly into Wagmi applications. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm install --save @onflow/fcl-wagmi-adapter 9 | ``` 10 | 11 | ## Usage 12 | 13 | Check out the [documentation](https://developers.flow.com/tools/clients/fcl-js/cross-vm/wagmi-adapter) for guides and examples on how to integrate and use this adapter in your project. 14 | 15 | ## License 16 | 17 | Apache-2.0 -------------------------------------------------------------------------------- /packages/fcl-wagmi-adapter/src/fcl-wagmi-adapter.test.ts: -------------------------------------------------------------------------------- 1 | describe("fcl wagmi adapter", () => { 2 | it("should be tested", () => { 3 | expect(true).toBe(true) 4 | }) 5 | }) 6 | -------------------------------------------------------------------------------- /packages/fcl-wagmi-adapter/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./wc-connector" 2 | export * from "./fcl-connector" 3 | -------------------------------------------------------------------------------- /packages/fcl-wagmi-adapter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/fcl-wc/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env"], 4 | [ 5 | "@babel/preset-typescript", 6 | { 7 | "allowDeclareFields": true 8 | } 9 | ] 10 | ], 11 | "plugins": [ 12 | [ 13 | "@babel/plugin-transform-react-jsx", 14 | { 15 | "importSource": "preact", 16 | "runtime": "automatic" 17 | } 18 | ] 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/fcl-wc/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/fcl-wc/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": ["plugin:jsdoc/recommended"], 9 | "plugins": ["jsdoc"], 10 | "parserOptions": { 11 | "ecmaVersion": "latest", 12 | "sourceType": "module" 13 | }, 14 | "globals": { 15 | "JSX": "readonly" 16 | }, 17 | "ignorePatterns": ["**/dist/"], 18 | 19 | "rules": { 20 | "jsdoc/require-jsdoc": 0, 21 | "jsdoc/tag-lines": 0, 22 | "jsdoc/require-param-description": 0, 23 | "jsdoc/valid-types": 0, 24 | "jsdoc/require-returns-description": 0, 25 | "no-undef": 1 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/fcl-wc/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/fcl-wc/jest.config.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | preset: "jest-preset-preact", 3 | moduleNameMapper: { 4 | "\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": 5 | "/src/mocks/file-mock.ts", 6 | "\\.(css|less)$": "/src/mocks/file-mock.ts", 7 | }, 8 | setupFilesAfterEnv: ["/jest.setup.ts"], 9 | } 10 | 11 | module.exports = config 12 | -------------------------------------------------------------------------------- /packages/fcl-wc/jest.setup.ts: -------------------------------------------------------------------------------- 1 | // Polyfill TextEncoder / TextDecoder for Jest 2 | import {TextEncoder, TextDecoder} from "util" 3 | 4 | global.TextEncoder = TextEncoder 5 | global.TextDecoder = TextDecoder as any 6 | -------------------------------------------------------------------------------- /packages/fcl-wc/postcss.config.js: -------------------------------------------------------------------------------- 1 | const tailwindcss = require("tailwindcss") 2 | const tailwindConfig = require("./tailwind.config.js") 3 | const autoprefixer = require("autoprefixer") 4 | 5 | module.exports = { 6 | plugins: [tailwindcss(tailwindConfig), autoprefixer], 7 | } 8 | -------------------------------------------------------------------------------- /packages/fcl-wc/src/constants.ts: -------------------------------------------------------------------------------- 1 | export enum FLOW_METHODS { 2 | FLOW_AUTHN = "flow_authn", 3 | FLOW_PRE_AUTHZ = "flow_pre_authz", 4 | FLOW_AUTHZ = "flow_authz", 5 | FLOW_USER_SIGN = "flow_user_sign", 6 | } 7 | 8 | export enum REQUEST_TYPES { 9 | SESSION_REQUEST = "session_proposal", 10 | SIGNING_REQUEST = "signing_request", 11 | } 12 | 13 | export const SERVICE_PLUGIN_NAME = "fcl-plugin-service-walletconnect" 14 | export const WC_SERVICE_METHOD = "WC/RPC" 15 | -------------------------------------------------------------------------------- /packages/fcl-wc/src/fcl-wc.test.ts: -------------------------------------------------------------------------------- 1 | import {init} from "./fcl-wc" 2 | import * as fcl from "@onflow/fcl" 3 | 4 | jest.mock("@walletconnect/modal", () => {}) 5 | jest.mock("@walletconnect/utils", () => {}) 6 | 7 | jest.mock("@onflow/fcl", () => { 8 | return { 9 | __esModule: true, 10 | ...jest.requireActual("@onflow/fcl"), 11 | } 12 | }) 13 | 14 | describe("Init Client", () => { 15 | let chainIdSpy 16 | beforeEach(() => { 17 | chainIdSpy = jest.spyOn(fcl, "getChainId") 18 | chainIdSpy.mockImplementation(async () => "testnet") 19 | }) 20 | 21 | afterEach(() => { 22 | chainIdSpy.mockRestore() 23 | }) 24 | 25 | it("should throw without projectId", async () => { 26 | expect.assertions(1) 27 | await expect(init).rejects.toThrow(Error) 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /packages/fcl-wc/src/index.ts: -------------------------------------------------------------------------------- 1 | export {init, initLazy, getProvider} from "./fcl-wc" 2 | export {createSessionProposal, request} from "./session" 3 | export {FLOW_METHODS, SERVICE_PLUGIN_NAME, WC_SERVICE_METHOD} from "./constants" 4 | -------------------------------------------------------------------------------- /packages/fcl-wc/src/mocks/file-mock.ts: -------------------------------------------------------------------------------- 1 | export default "mocked-file" 2 | -------------------------------------------------------------------------------- /packages/fcl-wc/src/store.ts: -------------------------------------------------------------------------------- 1 | export function createStore(initialState: T) { 2 | const subscribers = new Set<(state: T) => void>() 3 | let state = initialState 4 | 5 | const subscribe = (subscriber: (state: T) => void) => { 6 | subscribers.add(subscriber) 7 | return () => { 8 | subscribers.delete(subscriber) 9 | } 10 | } 11 | 12 | const setState = (newState: T) => { 13 | state = newState 14 | subscribers.forEach(subscriber => subscriber(state)) 15 | } 16 | 17 | const getState = () => state 18 | 19 | return { 20 | subscribe, 21 | setState, 22 | getState, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/fcl-wc/src/types/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.svg" { 2 | const value: string 3 | export default value 4 | } 5 | 6 | declare module "*.css" { 7 | const value: string 8 | export default value 9 | } 10 | -------------------------------------------------------------------------------- /packages/fcl-wc/src/types/types.ts: -------------------------------------------------------------------------------- 1 | export type NotificationInfo = { 2 | title: string 3 | message: string 4 | icon?: string 5 | onClick?: () => void 6 | onDismiss?: () => void 7 | } 8 | -------------------------------------------------------------------------------- /packages/fcl-wc/src/ui/assets/mobile.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/fcl-wc/src/ui/styles.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss/base"; 2 | @import "tailwindcss/components"; 3 | @import "tailwindcss/utilities"; 4 | -------------------------------------------------------------------------------- /packages/fcl-wc/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{js,jsx,ts,tsx}"], 4 | theme: { 5 | extend: { 6 | keyframes: { 7 | slideUp: { 8 | "0%": { 9 | transform: "translateY(100%)", 10 | }, 11 | "100%": { 12 | transform: "translateY(0)", 13 | }, 14 | }, 15 | }, 16 | animation: { 17 | slideUp: "slideUp 0.2s ease-out forwards", 18 | }, 19 | }, 20 | }, 21 | darkMode: "class", 22 | plugins: [], 23 | } 24 | -------------------------------------------------------------------------------- /packages/fcl-wc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "jsx": "react-jsx", 8 | "jsxImportSource": "preact" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/fcl/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "useBuiltIns": false 7 | } 8 | ], 9 | "@babel/preset-typescript" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /packages/fcl/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/fcl/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": ["plugin:jsdoc/recommended"], 9 | "plugins": ["jsdoc"], 10 | "parserOptions": { 11 | "ecmaVersion": "latest", 12 | "sourceType": "module" 13 | }, 14 | "globals": { 15 | "JSX": "readonly" 16 | }, 17 | "ignorePatterns": ["**/dist/"], 18 | 19 | "rules": { 20 | "jsdoc/require-jsdoc": 0, 21 | "jsdoc/tag-lines": 0, 22 | "jsdoc/require-param-description": 0, 23 | "jsdoc/valid-types": 0, 24 | "jsdoc/require-returns-description": 0, 25 | "no-undef": 1 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/fcl/.npmignore: -------------------------------------------------------------------------------- 1 | src/ -------------------------------------------------------------------------------- /packages/fcl/TRANSITIONS.md: -------------------------------------------------------------------------------- 1 | # Transitions 2 | 3 | ## 0001 Deprecate `env` config key 4 | - **Date:** May 26th 2022 5 | - **Type:** Deprecation of `env` in config 6 | 7 | When specifying which flow network for FCL to use, use the `flow.network` config key instead of `env` (e.g. `fcl.config.put("flow.network", "testnet")`). Permitted values are currently `local`, `canarynet`, `testnet`, `mainnet`. 8 | 9 | FCL currently falls back to `env` for the `flow.network` field but this will be removed in a future update. 10 | 11 | ## 0002 Deprecate `flow.network` config key 12 | - **Date:** September 26th 2022 13 | - **Type:** Deprecation of `flow.network` in config 14 | 15 | FCL now has a built-in utility to get which flow network to use. Manual specification in config is no longer required 16 | 17 | FCL currently falls back to `flow.network` in case of failure but this will be removed in a future update. -------------------------------------------------------------------------------- /packages/fcl/src/VERSION.js: -------------------------------------------------------------------------------- 1 | export const VERSION = PACKAGE_CURRENT_VERSION || "TESTVERSION" 2 | -------------------------------------------------------------------------------- /packages/fcl/src/discovery/exec-discovery.ts: -------------------------------------------------------------------------------- 1 | import {execStrategy} from "@onflow/fcl-core" 2 | 3 | export async function execDiscovery({ 4 | customRpc, 5 | opts, 6 | args, 7 | abortSignal, 8 | }: { 9 | customRpc: any 10 | opts: any 11 | args: any 12 | abortSignal: any 13 | }) { 14 | // Update the discovery config to enable RPC support 15 | const discoveryConfig = { 16 | ...opts.config, 17 | client: { 18 | ...opts.config.client, 19 | discoveryRpcEnabled: true, 20 | }, 21 | } 22 | 23 | // Execute base discovery request 24 | return execStrategy( 25 | { 26 | ...opts, 27 | config: discoveryConfig, 28 | customRpc, 29 | abortSignal, 30 | }, 31 | // @ts-ignore - Pass the rest of the arguments (protect against future changes) 32 | ...args.slice(1) 33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /packages/fcl/src/discovery/rpc/requests.ts: -------------------------------------------------------------------------------- 1 | import {RpcClient, RpcNotification} from "@onflow/util-rpc" 2 | 3 | export type DiscoveryRpc = RpcClient<{}, DiscoveryNotifications> 4 | 5 | export enum DiscoveryNotification { 6 | NOTIFY_QRCODE_CONNECTING = "notifyQrCodeConnecting", 7 | NOTIFY_QRCODE_CONNECTED = "notifyQrCodeConnected", 8 | NOTIFY_QRCODE_ERROR = "notifyQrCodeError", 9 | } 10 | 11 | export enum FclRequest { 12 | REQUEST_WALLETCONNECT_QRCODE = "requestWalletConnectQrCode", 13 | EXEC_SERVICE = "execService", 14 | } 15 | 16 | export type DiscoveryNotifications = { 17 | [DiscoveryNotification.NOTIFY_QRCODE_CONNECTING]: RpcNotification<{ 18 | uri: string 19 | }> 20 | [DiscoveryNotification.NOTIFY_QRCODE_CONNECTED]: RpcNotification<{ 21 | uri: string 22 | }> 23 | [DiscoveryNotification.NOTIFY_QRCODE_ERROR]: RpcNotification<{ 24 | uri: string 25 | error: string 26 | }> 27 | } 28 | -------------------------------------------------------------------------------- /packages/fcl/src/utils/async.ts: -------------------------------------------------------------------------------- 1 | const AbortController = 2 | globalThis.AbortController || require("abort-controller") 3 | 4 | export function wrapAbortSignal(signal?: AbortSignal) { 5 | const controller = new AbortController() 6 | if (signal?.aborted) controller.abort() 7 | signal?.addEventListener("abort", () => controller.abort()) 8 | return controller 9 | } 10 | -------------------------------------------------------------------------------- /packages/fcl/src/utils/web/__tests__/default-config.test.js: -------------------------------------------------------------------------------- 1 | import {getDefaultConfig} from "../default-config" 2 | 3 | describe("getDefaultConfig tests", () => { 4 | it("should return default config", () => { 5 | const defaultConfig = getDefaultConfig() 6 | expect(defaultConfig["discovery.wallet.method.default"]).toBe("IFRAME/RPC") 7 | }) 8 | }) 9 | -------------------------------------------------------------------------------- /packages/fcl/src/utils/web/coreStrategies.js: -------------------------------------------------------------------------------- 1 | import {CORE_STRATEGIES, getExecHttpPost} from "@onflow/fcl-core" 2 | import {execIframeRPC} from "./strategies/iframe-rpc" 3 | import {execPopRPC} from "./strategies/pop-rpc" 4 | import {execTabRPC} from "./strategies/tab-rpc" 5 | import {execExtRPC} from "./strategies/ext-rpc" 6 | import {execLocal} from "./exec-local" 7 | 8 | export const coreStrategies = { 9 | [CORE_STRATEGIES["HTTP/RPC"]]: getExecHttpPost(execLocal), 10 | [CORE_STRATEGIES["HTTP/POST"]]: getExecHttpPost(execLocal), 11 | [CORE_STRATEGIES["IFRAME/RPC"]]: execIframeRPC, 12 | [CORE_STRATEGIES["POP/RPC"]]: execPopRPC, 13 | [CORE_STRATEGIES["TAB/RPC"]]: execTabRPC, 14 | [CORE_STRATEGIES["EXT/RPC"]]: execExtRPC, 15 | } 16 | -------------------------------------------------------------------------------- /packages/fcl/src/utils/web/default-config.js: -------------------------------------------------------------------------------- 1 | export const getDefaultConfig = () => { 2 | return { 3 | "discovery.wallet.method.default": "IFRAME/RPC", 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/fcl/src/utils/web/exec-local.js: -------------------------------------------------------------------------------- 1 | import {renderFrame} from "./render-frame" 2 | import {renderPop} from "./render-pop" 3 | import {renderTab} from "./render-tab" 4 | 5 | const NOT_IMPLEMENTED = () => { 6 | throw new Error("Strategy util has not been implemented on this platform") 7 | } 8 | 9 | const VIEWS = { 10 | "VIEW/IFRAME": renderFrame, 11 | "VIEW/POP": renderPop, 12 | "VIEW/TAB": renderTab, 13 | "VIEW/MOBILE_BROWSER": NOT_IMPLEMENTED, 14 | "VIEW/DEEPLINK": NOT_IMPLEMENTED, 15 | } 16 | 17 | export async function execLocal(service, opts = {serviceEndpoint: () => {}}) { 18 | const {serviceEndpoint} = opts 19 | try { 20 | return VIEWS[service.method](serviceEndpoint(service), opts) 21 | } catch (error) { 22 | console.error("execLocal({service, opts = {}})", error, {service, opts}) 23 | throw error 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/fcl/src/utils/web/index.js: -------------------------------------------------------------------------------- 1 | export {renderFrame} from "./render-frame" 2 | export {renderPop} from "./render-pop" 3 | export {renderTab} from "./render-tab" 4 | export {getDefaultConfig} from "./default-config" 5 | export {coreStrategies} from "./coreStrategies" 6 | export {LOCAL_STORAGE, SESSION_STORAGE} from "./storage" 7 | -------------------------------------------------------------------------------- /packages/fcl/src/utils/web/render-tab.js: -------------------------------------------------------------------------------- 1 | const TAB = "FCL_TAB" 2 | 3 | let tab = null 4 | let previousUrl = null 5 | 6 | export function renderTab(src) { 7 | if (tab == null || tab?.closed) { 8 | tab = window.open(src, "_blank") 9 | if (!tab) 10 | throw new Error("Tab failed to open (was it blocked by the browser?)") 11 | } else if (previousUrl !== src) { 12 | tab.location.replace(src) 13 | tab.focus() 14 | } else { 15 | tab.focus() 16 | } 17 | 18 | previousUrl = src 19 | 20 | const unmount = () => { 21 | if (tab && !tab.closed) { 22 | tab.close() 23 | } 24 | tab = null 25 | } 26 | 27 | return [tab, unmount] 28 | } 29 | -------------------------------------------------------------------------------- /packages/fcl/src/utils/web/storage.ts: -------------------------------------------------------------------------------- 1 | import {StorageProvider} from "@onflow/fcl-core" 2 | 3 | const isServerSide = () => typeof window === "undefined" 4 | const safeParseJSON = (str?: string | null) => { 5 | if (str == null) return null 6 | try { 7 | return JSON.parse(str) 8 | } catch (error) { 9 | return null 10 | } 11 | } 12 | 13 | export const SESSION_STORAGE = { 14 | can: !isServerSide() && !!window.sessionStorage, 15 | get: async (key: string) => safeParseJSON(sessionStorage.getItem(key)), 16 | put: async (key: string, value: any) => 17 | sessionStorage.setItem(key, JSON.stringify(value)), 18 | } as StorageProvider 19 | 20 | export const LOCAL_STORAGE = { 21 | can: !isServerSide() && !!window.localStorage, 22 | get: async (key: string) => safeParseJSON(localStorage.getItem(key)), 23 | put: async (key: string, value: any) => 24 | localStorage.setItem(key, JSON.stringify(value)), 25 | } as StorageProvider 26 | -------------------------------------------------------------------------------- /packages/fcl/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/kit/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-typescript", 4 | "@babel/preset-env", 5 | ["@babel/preset-react", {"runtime": "automatic"}] 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/kit/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/kit/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/kit/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: "jsdom", 3 | moduleNameMapper: { 4 | "^@walletconnect": "/src/__mocks__/noop.ts", 5 | "^preact": "/src/__mocks__/noop.ts", 6 | }, 7 | // This is a workaround with Jest v29 issues related to BigInt serialization 8 | // It can be removed once Jest v30 is released and upgraded 9 | // https://github.com/jestjs/jest/issues/11617 10 | workerThreads: true, 11 | setupFiles: ["/src/jest-setup.ts"], 12 | } 13 | -------------------------------------------------------------------------------- /packages/kit/src/__mocks__/noop.ts: -------------------------------------------------------------------------------- 1 | // This file is meant to stub out the @walletconnect/relay package which has an issue where it tries 2 | // to `require` an ESM package (uint8arrays) which causes the test to fail. This is a temporary 3 | // workaround until the issue is resolved. 4 | -------------------------------------------------------------------------------- /packages/kit/src/__mocks__/tx.ts: -------------------------------------------------------------------------------- 1 | import {TransactionStatus} from "@onflow/typedefs" 2 | 3 | export const defaultTxStatus: TransactionStatus = { 4 | blockId: "", 5 | status: 0, 6 | statusString: "UNKNOWN", 7 | statusCode: 0, 8 | errorMessage: "", 9 | events: [], 10 | } 11 | 12 | export const errorTxStatus: TransactionStatus = { 13 | blockId: "block123", 14 | status: 2, 15 | statusString: "ERROR", 16 | statusCode: 1, 17 | errorMessage: "Test error occurred", 18 | events: [], 19 | } 20 | -------------------------------------------------------------------------------- /packages/kit/src/__mocks__/user.ts: -------------------------------------------------------------------------------- 1 | import {CurrentUser} from "@onflow/typedefs" 2 | 3 | export const defaultUser: CurrentUser = { 4 | f_type: "USER", 5 | f_vsn: "1.0.0", 6 | loggedIn: false, 7 | services: [], 8 | } 9 | 10 | export const authenticatedUser: CurrentUser = { 11 | f_type: "USER", 12 | f_vsn: "1.0.0", 13 | loggedIn: true, 14 | addr: "0x1234", 15 | services: [], 16 | } 17 | -------------------------------------------------------------------------------- /packages/kit/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export {} 2 | -------------------------------------------------------------------------------- /packages/kit/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const CONTRACT_ADDRESSES = { 2 | testnet: { 3 | EVM: "0x8c5303eaa26202d6", 4 | FungibleToken: "0x9a0766d93b6608b7", 5 | FlowToken: "0x7e60df042a9c0868", 6 | FlowEVMBridgeUtils: "0xdfc20aee650fcbdf", 7 | FlowEVMBridgeConfig: "0xdfc20aee650fcbdf", 8 | FungibleTokenMetadataViews: "0x9a0766d93b6608b7", 9 | }, 10 | mainnet: { 11 | EVM: "0xe467b9dd11fa00df", 12 | FungibleToken: "0xf233dcee88fe0abe", 13 | FlowToken: "0x1654653399040a61", 14 | FlowEVMBridgeUtils: "0x1e4aa0b87d10b141", 15 | FlowEVMBridgeConfig: "0x1e4aa0b87d10b141", 16 | FungibleTokenMetadataViews: "0xf233dcee88fe0abe", 17 | }, 18 | } 19 | 20 | export const CADENCE_UFIX64_PRECISION = 8 21 | -------------------------------------------------------------------------------- /packages/kit/src/core/context.ts: -------------------------------------------------------------------------------- 1 | import {createContext} from "react" 2 | import {FlowNetwork} from "./types" 3 | 4 | export type FlowConfig = { 5 | accessNodeUrl?: string 6 | appDetailTitle?: string 7 | appDetailIcon?: string 8 | appDetailDescription?: string 9 | appDetailUrl?: string 10 | discoveryWallet?: string 11 | discoveryWalletMethod?: string 12 | fclLimit?: number 13 | flowNetwork?: FlowNetwork 14 | serviceOpenIdScopes?: string[] 15 | walletconnectProjectId?: string 16 | walletconnectDisableNotifications?: boolean 17 | } 18 | 19 | export const FlowConfigContext = createContext({}) 20 | -------------------------------------------------------------------------------- /packages/kit/src/core/types.ts: -------------------------------------------------------------------------------- 1 | export type FlowNetwork = "emulator" | "testnet" | "mainnet" 2 | -------------------------------------------------------------------------------- /packages/kit/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export {useCurrentFlowUser} from "./useCurrentFlowUser" 2 | export {useFlowAccount} from "./useFlowAccount" 3 | export {useFlowBlock} from "./useFlowBlock" 4 | export {useFlowConfig} from "./useFlowConfig" 5 | export {useFlowEvents} from "./useFlowEvents" 6 | export {useFlowMutate} from "./useFlowMutate" 7 | export {useFlowQuery} from "./useFlowQuery" 8 | export {useFlowRevertibleRandom} from "./useFlowRevertibleRandom" 9 | export {useCrossVmBatchTransaction} from "./useCrossVmBatchTransaction" 10 | export {useCrossVmTokenBalance} from "./useCrossVmTokenBalance" 11 | export {useFlowTransactionStatus} from "./useFlowTransactionStatus" 12 | -------------------------------------------------------------------------------- /packages/kit/src/hooks/useCurrentFlowUser.ts: -------------------------------------------------------------------------------- 1 | import {useState, useEffect} from "react" 2 | import * as fcl from "@onflow/fcl" 3 | import {CurrentUser} from "@onflow/typedefs" 4 | 5 | interface UseCurrentFlowUserResult { 6 | user: CurrentUser | null 7 | authenticate: () => Promise 8 | unauthenticate: () => void 9 | } 10 | 11 | export function useCurrentFlowUser(): UseCurrentFlowUserResult { 12 | const [user, setUser] = useState(null) 13 | 14 | useEffect(() => { 15 | const unsubscribe = fcl.currentUser.subscribe(setUser) 16 | return () => unsubscribe() 17 | }, []) 18 | 19 | const authenticate = async (): Promise => { 20 | try { 21 | return await fcl.authenticate() 22 | } catch (error) { 23 | throw error 24 | } 25 | } 26 | 27 | const unauthenticate = (): void => { 28 | fcl.unauthenticate() 29 | } 30 | 31 | return { 32 | user, 33 | authenticate, 34 | unauthenticate, 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/kit/src/hooks/useFlowChainId.ts: -------------------------------------------------------------------------------- 1 | import * as fcl from "@onflow/fcl" 2 | import {useQuery, UseQueryOptions, UseQueryResult} from "@tanstack/react-query" 3 | import {useFlowQueryClient} from "../provider/FlowQueryClient" 4 | import {useCallback} from "react" 5 | import {useFlowConfig} from "./useFlowConfig" 6 | 7 | /** 8 | * Gets the Flow chain ID. 9 | */ 10 | export function useFlowChainId( 11 | queryOptions: Omit< 12 | UseQueryOptions, 13 | "queryKey" | "queryFn" 14 | > = {} 15 | ): UseQueryResult { 16 | const queryClient = useFlowQueryClient() 17 | const config = useFlowConfig() 18 | 19 | const fetchChainId = useCallback(async () => { 20 | return await fcl.getChainId() 21 | }, [config]) 22 | 23 | return useQuery( 24 | { 25 | queryKey: ["flowChainId"], 26 | queryFn: fetchChainId, 27 | initialData: null, 28 | ...queryOptions, 29 | }, 30 | queryClient 31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /packages/kit/src/hooks/useFlowConfig.ts: -------------------------------------------------------------------------------- 1 | import {useContext} from "react" 2 | import {FlowConfigContext, FlowConfig} from "../core/context" 3 | 4 | export function useFlowConfig(): FlowConfig { 5 | return useContext(FlowConfigContext) 6 | } 7 | -------------------------------------------------------------------------------- /packages/kit/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./core/types" 2 | export * from "./hooks" 3 | export * from "./components" 4 | export * from "./provider" 5 | -------------------------------------------------------------------------------- /packages/kit/src/jest-setup.ts: -------------------------------------------------------------------------------- 1 | import {TextEncoder, TextDecoder} from "util" 2 | 3 | Object.assign(global, {TextDecoder, TextEncoder}) 4 | -------------------------------------------------------------------------------- /packages/kit/src/provider/FlowQueryClient.tsx: -------------------------------------------------------------------------------- 1 | import React, {createContext, useContext, FC, PropsWithChildren} from "react" 2 | import {QueryClient} from "@tanstack/react-query" 3 | 4 | const FlowQueryClientContext = createContext(undefined) 5 | 6 | export function FlowQueryClientProvider({ 7 | queryClient, 8 | children, 9 | }: PropsWithChildren<{queryClient: QueryClient}>) { 10 | return ( 11 | 12 | ) 13 | } 14 | 15 | export function useFlowQueryClient() { 16 | const queryClient = useContext(FlowQueryClientContext) 17 | if (!queryClient) { 18 | throw new Error( 19 | "useFlowQueryClient must be used within a FlowQueryClientProvider" 20 | ) 21 | } 22 | return queryClient 23 | } 24 | -------------------------------------------------------------------------------- /packages/kit/src/provider/index.ts: -------------------------------------------------------------------------------- 1 | export {FlowProvider} from "./FlowProvider" 2 | -------------------------------------------------------------------------------- /packages/kit/src/utils/deepEqual.ts: -------------------------------------------------------------------------------- 1 | export function deepEqual(a: any, b: any): boolean { 2 | if (a === b) return true 3 | 4 | if ( 5 | typeof a !== "object" || 6 | a === null || 7 | typeof b !== "object" || 8 | b === null 9 | ) { 10 | return false 11 | } 12 | 13 | if (Array.isArray(a) !== Array.isArray(b)) return false 14 | 15 | const keysA = Object.keys(a) 16 | const keysB = Object.keys(b) 17 | if (keysA.length !== keysB.length) return false 18 | 19 | for (const key of keysA) { 20 | if (!Object.prototype.hasOwnProperty.call(b, key)) return false 21 | if (!deepEqual(a[key], b[key])) return false 22 | } 23 | 24 | return true 25 | } 26 | -------------------------------------------------------------------------------- /packages/kit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "include": ["src/**/*"], 4 | "compilerOptions": { 5 | "declarationDir": "types", 6 | "rootDir": "src", 7 | "paths": { 8 | "react": ["../../node_modules/@types/react/index"] 9 | }, 10 | "jsx": "react" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/protobuf/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"]] 3 | } 4 | -------------------------------------------------------------------------------- /packages/protobuf/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/protobuf/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/account_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/account.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/account_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/account.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/block_execution_data_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/block_execution_data.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/block_execution_data_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/block_execution_data.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/block_header_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/block_header.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/block_header_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/block_header.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/block_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/block.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/block_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/block.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/block_seal_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/block_seal.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/block_seal_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/block_seal.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/collection_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/collection.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/collection_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/collection.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/event_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/event.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/event_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/event.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/execution_result_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/execution_result.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/execution_result_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/execution_result.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/metadata_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/metadata.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/metadata_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/metadata.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/node_version_info_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/node_version_info.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/node_version_info_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/node_version_info.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/register_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/register.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/register_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/register.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/transaction_pb_service.d.ts: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/transaction.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/generated/flow/entities/transaction_pb_service.js: -------------------------------------------------------------------------------- 1 | // package: flow.entities 2 | // file: flow/entities/transaction.proto 3 | 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/index.test.js: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(1).toBe(1) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/entities/account.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package flow.entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/entities"; 6 | option java_package = "org.onflow.protobuf.entities"; 7 | 8 | message Account { 9 | bytes address = 1; 10 | uint64 balance = 2; 11 | bytes code = 3; 12 | repeated AccountKey keys = 4; 13 | map contracts = 5; 14 | } 15 | 16 | message AccountKey { 17 | uint32 index = 1; 18 | bytes public_key = 2; 19 | uint32 sign_algo = 3; 20 | uint32 hash_algo = 4; 21 | uint32 weight = 5; 22 | uint32 sequence_number = 6; 23 | bool revoked = 7; 24 | } 25 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/entities/block_seal.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package flow.entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/entities"; 6 | option java_package = "org.onflow.protobuf.entities"; 7 | 8 | message BlockSeal { 9 | bytes block_id = 1; 10 | bytes execution_receipt_id = 2; 11 | repeated bytes execution_receipt_signatures = 3; 12 | repeated bytes result_approval_signatures = 4; 13 | bytes final_state = 5; 14 | bytes result_id = 6; 15 | repeated AggregatedSignature aggregated_approval_sigs = 7; 16 | } 17 | 18 | message AggregatedSignature { 19 | repeated bytes verifier_signatures = 1; 20 | repeated bytes signer_ids = 2; 21 | } -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/entities/collection.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package flow.entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/entities"; 6 | option java_package = "org.onflow.protobuf.entities"; 7 | 8 | message Collection { 9 | bytes id = 1; 10 | repeated bytes transaction_ids = 2; 11 | } 12 | 13 | message CollectionGuarantee { 14 | bytes collection_id = 1; 15 | repeated bytes signatures = 2; 16 | bytes reference_block_id = 3; 17 | bytes signature = 4; 18 | repeated bytes signer_ids = 5; // deprecated!! value will be empty. replaced by signer_indices 19 | bytes signer_indices = 6; 20 | } 21 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/entities/event.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package flow.entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/entities"; 6 | option java_package = "org.onflow.protobuf.entities"; 7 | 8 | enum EventEncodingVersion { 9 | JSON_CDC_V0 = 0; 10 | CCF_V0 = 1; 11 | } 12 | 13 | message Event { 14 | string type = 1; 15 | bytes transaction_id = 2; 16 | uint32 transaction_index = 3; 17 | uint32 event_index = 4; 18 | bytes payload = 5; 19 | } 20 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/entities/metadata.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package flow.entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/entities"; 6 | option java_package = "org.onflow.protobuf.entities"; 7 | 8 | message Metadata { 9 | bytes latest_finalized_block_id = 1; 10 | uint64 latest_finalized_height = 2; 11 | bytes node_id = 3; 12 | } -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/entities/register.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package flow.entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/entities"; 6 | option java_package = "org.onflow.protobuf.entities"; 7 | 8 | message RegisterID { 9 | bytes owner = 1; 10 | bytes key = 2; 11 | } 12 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/entities/transaction.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package flow.entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/entities"; 6 | option java_package = "org.onflow.protobuf.entities"; 7 | 8 | import "flow/entities/event.proto"; 9 | 10 | enum TransactionStatus { 11 | UNKNOWN = 0; 12 | PENDING = 1; 13 | FINALIZED = 2; 14 | EXECUTED = 3; 15 | SEALED = 4; 16 | EXPIRED = 5; 17 | } 18 | 19 | message Transaction { 20 | message ProposalKey { 21 | bytes address = 1; 22 | uint32 key_id = 2; 23 | uint64 sequence_number = 3; 24 | } 25 | 26 | message Signature { 27 | bytes address = 1; 28 | uint32 key_id = 2; 29 | bytes signature = 3; 30 | } 31 | 32 | bytes script = 1; 33 | repeated bytes arguments = 2; 34 | bytes reference_block_id = 3; 35 | uint64 gas_limit = 4; 36 | ProposalKey proposal_key = 5; 37 | bytes payer = 6; 38 | repeated bytes authorizers = 7; 39 | repeated Signature payload_signatures = 8; 40 | repeated Signature envelope_signatures = 9; 41 | } 42 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/legacy/entities/account.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/legacy/entities"; 6 | option java_package = "org.onflow.protobuf.legacy.entities"; 7 | 8 | message Account { 9 | bytes address = 1; 10 | uint64 balance = 2; 11 | bytes code = 3; 12 | repeated AccountKey keys = 4; 13 | } 14 | 15 | message AccountKey { 16 | uint32 index = 1; 17 | bytes public_key = 2; 18 | uint32 sign_algo = 3; 19 | uint32 hash_algo = 4; 20 | uint32 weight = 5; 21 | uint32 sequence_number = 6; 22 | } 23 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/legacy/entities/block.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/legacy/entities"; 6 | option java_package = "org.onflow.protobuf.legacy.entities"; 7 | 8 | import "google/protobuf/timestamp.proto"; 9 | 10 | import "flow/legacy/entities/collection.proto"; 11 | import "flow/legacy/entities/block_seal.proto"; 12 | 13 | message Block { 14 | bytes id = 1; 15 | bytes parent_id = 2; 16 | uint64 height = 3; 17 | google.protobuf.Timestamp timestamp = 4; 18 | repeated CollectionGuarantee collection_guarantees = 5; 19 | repeated BlockSeal block_seals = 6; 20 | repeated bytes signatures = 7; 21 | } 22 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/legacy/entities/block_header.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/legacy/entities"; 6 | option java_package = "org.onflow.protobuf.legacy.entities"; 7 | 8 | import "google/protobuf/timestamp.proto"; 9 | 10 | message BlockHeader { 11 | bytes id = 1; 12 | bytes parent_id = 2; 13 | uint64 height = 3; 14 | google.protobuf.Timestamp timestamp = 4; 15 | } 16 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/legacy/entities/block_seal.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/legacy/entities"; 6 | option java_package = "org.onflow.protobuf.legacy.entities"; 7 | 8 | message BlockSeal { 9 | bytes block_id = 1; 10 | bytes execution_receipt_id = 2; 11 | repeated bytes execution_receipt_signatures = 3; 12 | repeated bytes result_approval_signatures = 4; 13 | } 14 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/legacy/entities/collection.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/legacy/entities"; 6 | option java_package = "org.onflow.protobuf.legacy.entities"; 7 | 8 | message Collection { 9 | bytes id = 1; 10 | repeated bytes transaction_ids = 2; 11 | } 12 | 13 | message CollectionGuarantee { 14 | bytes collection_id = 1; 15 | repeated bytes signatures = 2; 16 | } -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/legacy/entities/event.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/legacy/entities"; 6 | option java_package = "org.onflow.protobuf.legacy.entities"; 7 | 8 | message Event { 9 | string type = 1; 10 | bytes transaction_id = 2; 11 | uint32 transaction_index = 3; 12 | uint32 event_index = 4; 13 | bytes payload = 5; 14 | } 15 | -------------------------------------------------------------------------------- /packages/protobuf/src/proto/flow/legacy/entities/transaction.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package entities; 4 | 5 | option go_package = "github.com/onflow/flow/protobuf/go/flow/legacy/entities"; 6 | option java_package = "org.onflow.protobuf.legacy.entities"; 7 | 8 | enum TransactionStatus { 9 | UNKNOWN = 0; 10 | PENDING = 1; 11 | FINALIZED = 2; 12 | EXECUTED = 3; 13 | SEALED = 4; 14 | EXPIRED = 5; 15 | } 16 | 17 | message Transaction { 18 | message ProposalKey { 19 | bytes address = 1; 20 | uint32 key_id = 2; 21 | uint64 sequence_number = 3; 22 | } 23 | 24 | message Signature { 25 | bytes address = 1; 26 | uint32 key_id = 2; 27 | bytes signature = 3; 28 | } 29 | 30 | bytes script = 1; 31 | repeated bytes arguments = 2; 32 | bytes reference_block_id = 3; 33 | uint64 gas_limit = 4; 34 | ProposalKey proposal_key = 5; 35 | bytes payer = 6; 36 | repeated bytes authorizers = 7; 37 | repeated Signature payload_signatures = 8; 38 | repeated Signature envelope_signatures = 9; 39 | } 40 | -------------------------------------------------------------------------------- /packages/protobuf/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | 3 | module.exports = { 4 | entry: "./src/index.js", 5 | target: "node", 6 | devtool: "source-map", 7 | output: { 8 | path: path.resolve(__dirname, "dist"), 9 | filename: "index.js", 10 | libraryTarget: "commonjs-module", 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /packages/rlp/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/rlp/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/rlp/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "rules": { 20 | "jsdoc/require-jsdoc": 0, 21 | "jsdoc/tag-lines": 0, 22 | "jsdoc/require-param-description": 0, 23 | "jsdoc/require-param": 0, 24 | "jsdoc/valid-types": 0, 25 | "jsdoc/require-returns-description": 0, 26 | "jsdoc/require-returns": 0, 27 | "@typescript-eslint/no-explicit-any": "off" 28 | }, 29 | "ignorePatterns": ["**/dist/"] 30 | } 31 | -------------------------------------------------------------------------------- /packages/rlp/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/rlp/README.md: -------------------------------------------------------------------------------- 1 | Port of [ethereumjs/rlp][https://github.com/ethereumjs/rlp] sans BN support/dependency. 2 | -------------------------------------------------------------------------------- /packages/rlp/src/index.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(1).toBe(1) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/rlp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/sdk/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "useBuiltIns": false 7 | } 8 | ], 9 | "@babel/preset-typescript" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /packages/sdk/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/sdk/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": ["plugin:jsdoc/recommended"], 9 | "plugins": ["jsdoc"], 10 | "parserOptions": { 11 | "ecmaVersion": "latest", 12 | "sourceType": "module" 13 | }, 14 | "ignorePatterns": ["**/dist/"], 15 | "rules": { 16 | "jsdoc/require-jsdoc": 0, 17 | "jsdoc/valid-types": 0 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/sdk/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/sdk/src/VERSION.ts: -------------------------------------------------------------------------------- 1 | declare const PACKAGE_CURRENT_VERSION: string | undefined 2 | 3 | export const VERSION: string = PACKAGE_CURRENT_VERSION || "TESTVERSION" 4 | -------------------------------------------------------------------------------- /packages/sdk/src/account/account.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/block/block.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-arguments.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-arguments.ts: -------------------------------------------------------------------------------- 1 | import {pipe, makeArgument, CadenceArgument} from "../interaction/interaction" 2 | import {TypeDescriptorInput, TypeDescriptor} from "@onflow/types" 3 | 4 | /** 5 | * @description A utility builder to be used with other builders to pass in arguments with a value and supported type 6 | * @param ax An array of arguments 7 | * @returns An interaction object 8 | */ 9 | export function args(ax: CadenceArgument[]) { 10 | return pipe(ax.map(makeArgument)) 11 | } 12 | 13 | /** 14 | * @description A utility builder to be used with fcl.args[...] to create FCL supported arguments for interactions 15 | * @param value The value of the argument 16 | * @param xform A function to transform the value 17 | * @returns An argument object 18 | */ 19 | export function arg>( 20 | value: TypeDescriptorInput, 21 | xform: T 22 | ) { 23 | return {value, xform} as CadenceArgument 24 | } 25 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-at-block-height.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction} from "../interaction/interaction" 2 | import {atBlockHeight} from "./build-at-block-height" 3 | 4 | describe("Build At Block Height", () => { 5 | test("At Block Height", async () => { 6 | const blockHeight = 123 7 | 8 | const ix = await atBlockHeight(blockHeight)(initInteraction()) 9 | 10 | expect(ix.block.height).toBe(blockHeight) 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-at-block-height.ts: -------------------------------------------------------------------------------- 1 | import {pipe, InteractionBuilderFn} from "../interaction/interaction" 2 | import {Interaction} from "@onflow/typedefs" 3 | import {validator} from "./build-validator" 4 | 5 | /** 6 | * @description A builder function that returns a partial interaction to a block at a specific height 7 | * @param height The height of the block to get 8 | * @returns A function that processes a partial interaction object 9 | */ 10 | export function atBlockHeight(height: number): InteractionBuilderFn { 11 | return pipe([ 12 | (ix: Interaction) => { 13 | ix.block.height = height 14 | return ix 15 | }, 16 | validator((ix: Interaction) => { 17 | if (typeof ix.block.isSealed === "boolean") 18 | throw new Error("Unable to specify both block height and isSealed.") 19 | if (ix.block.id) 20 | throw new Error("Unable to specify both block height and block id.") 21 | return ix 22 | }), 23 | ]) 24 | } 25 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-at-block-id.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction} from "../interaction/interaction" 2 | import {atBlockId} from "./build-at-block-id" 3 | 4 | describe("Build At Block ID", () => { 5 | test("At Block ID", async () => { 6 | const blockId = "abc123" 7 | 8 | const ix = await atBlockId(blockId)(initInteraction()) 9 | 10 | expect(ix.block.id).toBe(blockId) 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-at-block-id.ts: -------------------------------------------------------------------------------- 1 | import { 2 | isGetAccount, 3 | pipe, 4 | Ok as OkFn, 5 | Bad as BadFn, 6 | InteractionBuilderFn, 7 | } from "../interaction/interaction" 8 | import {validator} from "./build-validator" 9 | import {Interaction} from "@onflow/typedefs" 10 | 11 | export function atBlockId(id: string): InteractionBuilderFn { 12 | return pipe([ 13 | (ix: Interaction) => { 14 | ix.block.id = id 15 | return OkFn(ix) 16 | }, 17 | validator( 18 | (ix: Interaction, {Ok, Bad}: {Ok: typeof OkFn; Bad: typeof BadFn}) => { 19 | if (isGetAccount(ix)) 20 | return Bad( 21 | ix, 22 | "Unable to specify a block id with a Get Account interaction." 23 | ) 24 | if (typeof ix.block.isSealed === "boolean") 25 | return Bad(ix, "Unable to specify both block id and isSealed.") 26 | if (ix.block.height) 27 | return Bad(ix, "Unable to specify both block id and block height.") 28 | return Ok(ix) 29 | } 30 | ), 31 | ]) 32 | } 33 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-at-latest-block.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction} from "../interaction/interaction" 2 | import {atLatestBlock} from "./build-at-latest-block" 3 | 4 | describe("Build At Latest Block", () => { 5 | test("At Latest Sealed Block", async () => { 6 | const ix = await atLatestBlock(true)(initInteraction()) 7 | 8 | expect(ix.block.isSealed).toBe(true) 9 | }) 10 | 11 | test("At Latest Executed Block", async () => { 12 | const ix = await atLatestBlock(false)(initInteraction()) 13 | 14 | expect(ix.block.isSealed).toBe(false) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-authorizations.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction} from "../interaction/interaction" 2 | import {authorizations, authorization} from "./build-authorizations" 3 | 4 | describe("Build Authorizations", () => { 5 | test("build authorizer", async () => { 6 | let ix = await ( 7 | await authorizations([ 8 | authorization("0xabc123", () => ({signature: "123"}), 1, 123), 9 | ]) 10 | )(initInteraction()) 11 | 12 | const authorizerAccount = 13 | ix.accounts[ix.authorizations as unknown as string] 14 | 15 | expect(authorizerAccount.addr).toEqual("0xabc123") 16 | expect(authorizerAccount.role).toEqual({ 17 | authorizer: true, 18 | payer: false, 19 | proposer: false, 20 | param: false, 21 | }) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-account.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction} from "../interaction/interaction" 2 | import {sansPrefix, withPrefix} from "@onflow/util-address" 3 | import {getAccount} from "./build-get-account" 4 | 5 | const ADDRESS = "0xf117a8efa34ffd58" 6 | 7 | describe("address as input", () => { 8 | test("sansPrefix", async () => { 9 | const addr = sansPrefix(ADDRESS) 10 | const result = await getAccount(addr)(initInteraction()) 11 | 12 | expect(result.account.addr).toBe(sansPrefix(ADDRESS)) 13 | }) 14 | 15 | test("withPrefix", async () => { 16 | const addr = withPrefix(ADDRESS) 17 | const result = await getAccount(addr)(initInteraction()) 18 | 19 | expect(result.account.addr).toBe(sansPrefix(ADDRESS)) 20 | }) 21 | }) 22 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-account.ts: -------------------------------------------------------------------------------- 1 | import {sansPrefix} from "@onflow/util-address" 2 | import { 3 | InteractionBuilderFn, 4 | makeGetAccount, 5 | Ok, 6 | pipe, 7 | } from "../interaction/interaction" 8 | 9 | /** 10 | * @description A builder function that returns the interaction to get an account by address 11 | * @param addr The address of the account to get 12 | * @returns A function that processes an interaction object 13 | */ 14 | export function getAccount(addr: string): InteractionBuilderFn { 15 | return pipe([ 16 | makeGetAccount, 17 | ix => { 18 | ix.account.addr = sansPrefix(addr) 19 | return Ok(ix) 20 | }, 21 | ]) 22 | } 23 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-block-header.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction, isGetBlockHeader} from "../interaction/interaction" 2 | import {getBlockHeader} from "./build-get-block-header" 3 | 4 | describe("Build Get Block Header", () => { 5 | test("Get Block Header, isSealed = false", async () => { 6 | const isSealed = false 7 | 8 | const ix = await getBlockHeader(isSealed)(initInteraction()) 9 | 10 | expect(isGetBlockHeader(ix)).toBe(true) 11 | expect(ix.block.isSealed).toEqual(isSealed) 12 | }) 13 | 14 | test("Get Block Header, isSealed = true", async () => { 15 | const isSealed = true 16 | 17 | const ix = await getBlockHeader(isSealed)(initInteraction()) 18 | 19 | expect(isGetBlockHeader(ix)).toBe(true) 20 | expect(ix.block.isSealed).toEqual(isSealed) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-block-header.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | Ok, 4 | makeGetBlockHeader, 5 | InteractionBuilderFn, 6 | } from "../interaction/interaction" 7 | 8 | /** 9 | * @description A builder function that returns the interaction to get a block header 10 | * @param isSealed Whether or not the block should be sealed 11 | * @returns A function that processes an interaction object 12 | */ 13 | export function getBlockHeader( 14 | isSealed: boolean | null = null 15 | ): InteractionBuilderFn { 16 | return pipe([ 17 | makeGetBlockHeader, 18 | ix => { 19 | ix.block.isSealed = isSealed 20 | return Ok(ix) 21 | }, 22 | ]) 23 | } 24 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-block.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction, isGetBlock} from "../interaction/interaction" 2 | import {getBlock} from "./build-get-block" 3 | 4 | describe("Build Get Block", () => { 5 | test("Get Block - isSealed = false", async () => { 6 | const isSealed = false 7 | 8 | const ix = await getBlock(isSealed)(initInteraction()) 9 | 10 | expect(isGetBlock(ix)).toBe(true) 11 | expect(ix.block.isSealed).toBe(false) 12 | }) 13 | 14 | test("Get Block - isSealed = false", async () => { 15 | const isSealed = true 16 | 17 | const ix = await getBlock(isSealed)(initInteraction()) 18 | 19 | expect(isGetBlock(ix)).toBe(true) 20 | expect(ix.block.isSealed).toBe(true) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-block.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | Ok, 4 | makeGetBlock, 5 | InteractionBuilderFn, 6 | } from "../interaction/interaction" 7 | 8 | /** 9 | * @description A builder function that returns the interaction to get the latest block 10 | * @param isSealed Whether or not the block should be sealed 11 | * @returns A function that processes an interaction object 12 | */ 13 | export function getBlock( 14 | isSealed: boolean | null = null 15 | ): InteractionBuilderFn { 16 | return pipe([ 17 | makeGetBlock, 18 | ix => { 19 | ix.block.isSealed = isSealed 20 | return Ok(ix) 21 | }, 22 | ]) 23 | } 24 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-collection.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction, isGetCollection} from "../interaction/interaction" 2 | import {getCollection} from "./build-get-collection" 3 | 4 | describe("Build Get Collection", () => { 5 | test("Get Collection", async () => { 6 | const collectionId = "my-collection-id" 7 | 8 | const ix = await getCollection(collectionId)(initInteraction()) 9 | 10 | expect(isGetCollection(ix)).toBe(true) 11 | expect(ix.collection.id).toBe(collectionId) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-collection.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | makeGetCollection, 4 | InteractionBuilderFn, 5 | } from "../interaction/interaction" 6 | 7 | /** 8 | * @description A builder function that returns the interaction to get a collection by ID 9 | * @param id The ID of the collection to get 10 | * @returns A function that processes an interaction object 11 | */ 12 | export function getCollection(id: string | null = null): InteractionBuilderFn { 13 | return pipe([ 14 | makeGetCollection, 15 | ix => { 16 | ix.collection.id = id 17 | return ix 18 | }, 19 | ]) 20 | } 21 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-events-at-block-height-range.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction, isGetEvents} from "../interaction/interaction" 2 | import {getEventsAtBlockHeightRange} from "./build-get-events-at-block-height-range" 3 | 4 | describe("Build Get Events At Block Height Range", () => { 5 | test("Get Events At Block Height Range", async () => { 6 | const eventName = "MyEvent" 7 | const start = 123 8 | const end = 456 9 | 10 | let ix = await getEventsAtBlockHeightRange( 11 | eventName, 12 | start, 13 | end 14 | )(initInteraction()) 15 | 16 | expect(isGetEvents(ix)).toBe(true) 17 | expect(ix.events.eventType).toBe(eventName) 18 | expect(ix.events.start).toBe(start) 19 | expect(ix.events.end).toBe(end) 20 | }) 21 | }) 22 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-events-at-block-height-range.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | Ok, 4 | makeGetEvents, 5 | InteractionBuilderFn, 6 | } from "../interaction/interaction" 7 | 8 | /** 9 | * @description A builder function that returns the interaction to get events at a block height range 10 | * @param eventType The type of event to get 11 | * @param startHeight The start height of the block range 12 | * @param endHeight The end height of the block range 13 | * @returns A function that processes an interaction object 14 | */ 15 | export function getEventsAtBlockHeightRange( 16 | eventType: string, 17 | startHeight: number, 18 | endHeight: number 19 | ): InteractionBuilderFn { 20 | return pipe([ 21 | makeGetEvents, 22 | ix => { 23 | ix.events.eventType = eventType 24 | ix.events.start = startHeight 25 | ix.events.end = endHeight 26 | return Ok(ix) 27 | }, 28 | ]) 29 | } 30 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-events-at-block-ids.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction, isGetEvents} from "../interaction/interaction" 2 | import {getEventsAtBlockIds} from "./build-get-events-at-block-ids" 3 | 4 | describe("Build Get Events At Block Ids", () => { 5 | test("Get Events At Block Ids", async () => { 6 | const eventName = "MyEvent" 7 | const blockIds = ["abc", "123"] 8 | 9 | let ix = await getEventsAtBlockIds(eventName, blockIds)(initInteraction()) 10 | 11 | expect(isGetEvents(ix)).toBe(true) 12 | expect(ix.events.eventType).toBe(eventName) 13 | expect(ix.events.blockIds).toBe(blockIds) 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-events-at-block-ids.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | Ok, 4 | makeGetEvents, 5 | InteractionBuilderFn, 6 | } from "../interaction/interaction" 7 | 8 | /** 9 | * @description A builder function that returns the interaction to get events at specific block IDs 10 | * @param eventType The type of event to get 11 | * @param blockIds The block IDs to get events from 12 | * @returns A function that processes an interaction object 13 | */ 14 | export function getEventsAtBlockIds( 15 | eventType: string, 16 | blockIds: string[] 17 | ): InteractionBuilderFn { 18 | return pipe([ 19 | makeGetEvents, 20 | ix => { 21 | ix.events.eventType = eventType 22 | ix.events.blockIds = blockIds 23 | return Ok(ix) 24 | }, 25 | ]) 26 | } 27 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-events.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-events.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | Ok, 4 | makeGetEvents, 5 | InteractionBuilderFn, 6 | } from "../interaction/interaction" 7 | 8 | /** 9 | * @description A builder function that returns the interaction to get events 10 | * @param eventType The type of event to get 11 | * @param start The start block ID or height 12 | * @param end The end block ID or height 13 | * @returns A function that processes an interaction object 14 | */ 15 | export function getEvents( 16 | eventType: string, 17 | start: number, 18 | end: number 19 | ): InteractionBuilderFn { 20 | return pipe([ 21 | makeGetEvents, 22 | ix => { 23 | ix.events.eventType = eventType 24 | ix.events.start = start 25 | ix.events.end = end 26 | return Ok(ix) 27 | }, 28 | ]) 29 | } 30 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-latest-block.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-latest-block.ts: -------------------------------------------------------------------------------- 1 | import {log} from "@onflow/util-logger" 2 | import { 3 | pipe, 4 | Ok, 5 | makeGetBlock, 6 | InteractionBuilderFn, 7 | } from "../interaction/interaction" 8 | 9 | /** 10 | * @description A builder function that returns the interaction to get the latest block 11 | * @param isSealed Whether or not the block should be sealed 12 | * @returns A function that processes an interaction object 13 | */ 14 | export function getLatestBlock( 15 | isSealed: boolean = false 16 | ): InteractionBuilderFn { 17 | log.deprecate({ 18 | pkg: "FCL/SDK", 19 | subject: "The getLatestBlock builder", 20 | transition: 21 | "https://github.com/onflow/flow-js-sdk/blob/master/packages/sdk/TRANSITIONS.md#0006-deprecate-get-latest-block-builder", 22 | }) 23 | 24 | return pipe([ 25 | makeGetBlock, 26 | ix => { 27 | ix.block.isSealed = isSealed 28 | return Ok(ix) 29 | }, 30 | ]) 31 | } 32 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-network-parameters.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | initInteraction, 3 | isGetNetworkParameters, 4 | } from "../interaction/interaction" 5 | import {getNetworkParameters} from "./build-get-network-parameters" 6 | 7 | describe("Build Get Network Parameters", () => { 8 | test("Get Network Parameters", async () => { 9 | let ix = await getNetworkParameters()(initInteraction()) 10 | 11 | expect(isGetNetworkParameters(ix)).toBe(true) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-network-parameters.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | makeGetNetworkParameters, 4 | Ok, 5 | InteractionBuilderFn, 6 | } from "../interaction/interaction" 7 | 8 | /** 9 | * @description A builder function that returns the interaction to get network parameters 10 | * @returns A function that processes an interaction object 11 | */ 12 | export function getNetworkParameters(): InteractionBuilderFn { 13 | return pipe([ 14 | makeGetNetworkParameters, 15 | ix => { 16 | return Ok(ix) 17 | }, 18 | ]) 19 | } 20 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-node-version-info.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction, isGetNodeVersionInfo} from "../interaction/interaction" 2 | import {getNodeVersionInfo} from "./build-get-node-version-info" 3 | 4 | describe("Build Get Node Version Info", () => { 5 | test("Get Node Version Info", async () => { 6 | let ix = await getNodeVersionInfo()(initInteraction()) 7 | 8 | expect(isGetNodeVersionInfo(ix)).toBe(true) 9 | }) 10 | }) 11 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-node-version-info.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Ok, 3 | makeGetNodeVerionInfo, 4 | pipe, 5 | InteractionBuilderFn, 6 | } from "../interaction/interaction" 7 | 8 | /** 9 | * @description A builder function for the Get Node Version Info interaction 10 | * @returns An interaction object 11 | */ 12 | export function getNodeVersionInfo(): InteractionBuilderFn { 13 | return pipe([ 14 | makeGetNodeVerionInfo, 15 | ix => { 16 | return Ok(ix) 17 | }, 18 | ]) 19 | } 20 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-transaction-status.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | initInteraction, 3 | isGetTransactionStatus, 4 | } from "../interaction/interaction" 5 | import {getTransactionStatus} from "./build-get-transaction-status" 6 | 7 | describe("Build Get Transaction Status", () => { 8 | test("Get Transaction Status", async () => { 9 | const transactionId = "abc123" 10 | 11 | let ix = await getTransactionStatus(transactionId)(initInteraction()) 12 | 13 | expect(isGetTransactionStatus(ix)).toBe(true) 14 | expect(ix.transaction.id).toBe(transactionId) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-transaction-status.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | Ok, 4 | makeGetTransactionStatus, 5 | InteractionBuilderFn, 6 | } from "../interaction/interaction" 7 | 8 | /** 9 | * @description A builder function that returns the status of transaction 10 | * NOTE: The transactionID provided must be from the current spork. 11 | * @param transactionId The id of the transaction to get status 12 | * @returns An interaction object 13 | */ 14 | export function getTransactionStatus( 15 | transactionId: string 16 | ): InteractionBuilderFn { 17 | return pipe([ 18 | makeGetTransactionStatus, 19 | ix => { 20 | ix.transaction.id = transactionId 21 | return Ok(ix) 22 | }, 23 | ]) 24 | } 25 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-transaction.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction, isGetTransaction} from "../interaction/interaction" 2 | import {getTransaction} from "./build-get-transaction" 3 | 4 | describe("Build Get Transaction", () => { 5 | test("Get Transaction", async () => { 6 | const transactionId = "abc123" 7 | 8 | let ix = await getTransaction(transactionId)(initInteraction()) 9 | 10 | expect(isGetTransaction(ix)).toBe(true) 11 | expect(ix.transaction.id).toBe(transactionId) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-get-transaction.ts: -------------------------------------------------------------------------------- 1 | import { 2 | InteractionBuilderFn, 3 | Ok, 4 | makeGetTransaction, 5 | pipe, 6 | } from "../interaction/interaction" 7 | 8 | /** 9 | * @description A builder function that returns the interaction to get a transaction by ID 10 | * @param id The ID of the transaction to get 11 | * @returns A function that processes an interaction object 12 | */ 13 | export function getTransaction(id: string): InteractionBuilderFn { 14 | return pipe([ 15 | makeGetTransaction, 16 | ix => { 17 | ix.transaction.id = id 18 | return Ok(ix) 19 | }, 20 | ]) 21 | } 22 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-invariant.js: -------------------------------------------------------------------------------- 1 | import {Ok, Bad} from "../interaction/interaction" 2 | 3 | export function invariant(...args) { 4 | if (args.length > 1) { 5 | const [predicate, message] = args 6 | return invariant((ix, {Ok, Bad}) => { 7 | return predicate ? Ok(ix) : Bad(ix, message) 8 | }) 9 | } 10 | const [fn] = args 11 | return ix => fn(ix, {Ok, Bad}) 12 | } 13 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-invariant.test.js: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-limit.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction} from "../interaction/interaction" 2 | import {limit} from "./build-limit" 3 | 4 | describe("Build Limit", () => { 5 | test("Build Limit", async () => { 6 | const txLimit = 100 7 | 8 | let ix = await limit(txLimit)(initInteraction()) 9 | 10 | expect(ix.message.computeLimit).toEqual(txLimit) 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-limit.ts: -------------------------------------------------------------------------------- 1 | import {InteractionBuilderFn} from "../interaction/interaction" 2 | 3 | /** 4 | * @description A builder function that sets the compute limit for a transaction 5 | * @param limit The compute limit to set 6 | * @returns A function that processes an interaction object 7 | */ 8 | export function limit(limit: number): InteractionBuilderFn { 9 | return ix => { 10 | ix.message.computeLimit = limit 11 | return ix 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-payer.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction} from "../interaction/interaction" 2 | import {payer} from "./build-payer" 3 | 4 | describe("Build Payer", () => { 5 | test("Build Payer", async () => { 6 | const authz = {addr: "0xabc123"} 7 | 8 | let ix = await (await payer(authz))(initInteraction()) 9 | 10 | const payerAccount = ix.accounts[ix.payer[0]] 11 | 12 | expect(payerAccount.addr).toEqual(authz.addr) 13 | expect(payerAccount.role).toEqual({ 14 | authorizer: false, 15 | param: false, 16 | payer: true, 17 | proposer: false, 18 | }) 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-payer.ts: -------------------------------------------------------------------------------- 1 | import {TransactionRole} from "@onflow/typedefs" 2 | import { 3 | AccountAuthorization, 4 | pipe, 5 | prepAccount, 6 | } from "../interaction/interaction" 7 | 8 | /** 9 | * @description A builder function that adds payer account(s) to a transaction 10 | * @param ax An account address or array of account addresses 11 | * @returns A function that takes an interaction and returns a new interaction with the payer(s) added 12 | */ 13 | export function payer(ax: AccountAuthorization[] = []) { 14 | if (!Array.isArray(ax)) ax = [ax] 15 | return pipe( 16 | ax.map(authz => { 17 | return prepAccount(authz, { 18 | role: TransactionRole.PAYER, 19 | }) 20 | }) 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-ping.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction, isPing} from "../interaction/interaction" 2 | import {ping} from "./build-ping" 3 | 4 | describe("Build Ping", () => { 5 | test("Build Ping", async () => { 6 | let ix = await ping()(initInteraction()) 7 | 8 | expect(isPing(ix)).toBe(true) 9 | }) 10 | }) 11 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-ping.ts: -------------------------------------------------------------------------------- 1 | import {makePing, InteractionBuilderFn} from "../interaction/interaction" 2 | 3 | /** 4 | * @description A builder function that creates a ping interaction 5 | * @returns A function that processes an interaction object 6 | */ 7 | export function ping(): InteractionBuilderFn { 8 | return makePing 9 | } 10 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-proposer.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction} from "../interaction/interaction" 2 | import {proposer} from "./build-proposer" 3 | 4 | describe("Build Proposer", () => { 5 | test("Build Proposer", async () => { 6 | const authz = {addr: "0xabc123"} 7 | 8 | let ix = await (await proposer(authz))(initInteraction()) 9 | 10 | const proposerAccount = ix.accounts[ix.proposer!] 11 | 12 | expect(proposerAccount.addr).toEqual(authz.addr) 13 | expect(proposerAccount.role).toEqual({ 14 | authorizer: false, 15 | param: false, 16 | payer: false, 17 | proposer: true, 18 | }) 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-proposer.ts: -------------------------------------------------------------------------------- 1 | import {TransactionRole} from "@onflow/typedefs" 2 | import {AccountAuthorization, prepAccount} from "../interaction/interaction" 3 | 4 | export function proposer(authz: AccountAuthorization) { 5 | return prepAccount(authz, { 6 | role: TransactionRole.PROPOSER, 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-ref.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction} from "../interaction/interaction" 2 | import {ref} from "./build-ref" 3 | 4 | describe("Build Ref", () => { 5 | test("Build Ref", async () => { 6 | const refBlockId = "abc123" 7 | 8 | let ix = await ref(refBlockId)(initInteraction()) 9 | 10 | expect(ix.message.refBlock).toEqual(refBlockId) 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-ref.ts: -------------------------------------------------------------------------------- 1 | import {pipe, Ok, InteractionBuilderFn} from "../interaction/interaction" 2 | 3 | /** 4 | * @description A builder function that sets the reference block for a transaction 5 | * @param refBlock The reference block ID 6 | * @returns A function that processes an interaction object 7 | */ 8 | export function ref(refBlock: string): InteractionBuilderFn { 9 | return pipe([ 10 | ix => { 11 | ix.message.refBlock = refBlock 12 | return Ok(ix) 13 | }, 14 | ]) 15 | } 16 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-script.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction, isScript} from "../interaction/interaction" 2 | import {script} from "./build-script" 3 | 4 | describe("Build Script", () => { 5 | test("Build Script", async () => { 6 | const cadence = "access(all) fun main(): Int { return 123 }" 7 | 8 | let ix = await script(cadence)(initInteraction()) 9 | 10 | expect(isScript(ix)).toBe(true) 11 | expect(ix.assigns["ix.cadence"]).not.toBeUndefined() 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-script.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | put, 4 | makeScript, 5 | InteractionBuilderFn, 6 | } from "../interaction/interaction" 7 | import {template} from "@onflow/util-template" 8 | 9 | /** 10 | * @description A builder function that creates a script interaction 11 | * @returns A function that processes an interaction object 12 | */ 13 | export function script( 14 | ...args: [ 15 | string | TemplateStringsArray | ((x?: unknown) => string), 16 | ...unknown[], 17 | ] 18 | ): InteractionBuilderFn { 19 | return pipe([makeScript, put("ix.cadence", template(...args))]) 20 | } 21 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-transaction.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction, isTransaction} from "../interaction/interaction" 2 | import {transaction} from "./build-transaction" 3 | 4 | describe("Build Transaction", () => { 5 | test("Build Transaction", async () => { 6 | const cadence = "transaction { increaseMyBallerStatus() }" 7 | 8 | let ix = await transaction(cadence)(initInteraction()) 9 | 10 | expect(isTransaction(ix)).toBe(true) 11 | expect(ix.assigns["ix.cadence"]).not.toBeUndefined() 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-transaction.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | put, 4 | Ok, 5 | makeTransaction, 6 | InteractionBuilderFn, 7 | } from "../interaction/interaction" 8 | import {template} from "@onflow/util-template" 9 | 10 | const DEFAULT_SCRIPT_ACCOUNTS: string[] = [] 11 | const DEFAULT_REF: any = null 12 | 13 | /** 14 | * @description A template builder to use a Cadence transaction for an interaction 15 | * @param args The arguments to pass 16 | * @returns A function that processes an interaction object 17 | */ 18 | export function transaction( 19 | ...args: [string | TemplateStringsArray, ...any[]] 20 | ): InteractionBuilderFn { 21 | return pipe([ 22 | makeTransaction, 23 | put("ix.cadence", template(...args)), 24 | ix => { 25 | ix.message.refBlock = ix.message.refBlock || DEFAULT_REF 26 | ix.authorizations = ix.authorizations || DEFAULT_SCRIPT_ACCOUNTS 27 | return Ok(ix) 28 | }, 29 | ]) 30 | } 31 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-validator.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-validator.ts: -------------------------------------------------------------------------------- 1 | import {update, InteractionBuilderFn} from "../interaction/interaction" 2 | 3 | /** 4 | * @description A builder function that adds a validator to a transaction 5 | * @param cb The validator function 6 | * @returns A function that processes an interaction object 7 | */ 8 | export function validator(cb: Function): InteractionBuilderFn { 9 | return update("ix.validators", (validators: Function | Function[]) => 10 | Array.isArray(validators) ? [...validators, cb] : [cb] 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-voucher-intercept.test.ts: -------------------------------------------------------------------------------- 1 | import {initInteraction} from "../interaction/interaction" 2 | import {voucherIntercept} from "./build-voucher-intercept" 3 | 4 | describe("Build voucherIntercept", () => { 5 | test("Build voucherIntercept", async () => { 6 | const checkFunc = async () => "test func" 7 | 8 | const ix = await voucherIntercept(checkFunc)(initInteraction()) 9 | 10 | expect(ix.assigns["ix.voucher-intercept"]).toEqual(checkFunc) 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build-voucher-intercept.ts: -------------------------------------------------------------------------------- 1 | import {put, InteractionBuilderFn} from "../interaction/interaction" 2 | import {Voucher} from "../encode/encode" 3 | 4 | type VoucherInterceptFn = (voucher: Voucher) => any | Promise 5 | 6 | /** 7 | * @description A builder function that intercepts and modifies a voucher 8 | * @param fn The function to intercept and modify the voucher 9 | * @returns A function that processes an interaction object 10 | */ 11 | export function voucherIntercept(fn: VoucherInterceptFn): InteractionBuilderFn { 12 | return put("ix.voucher-intercept", fn) 13 | } 14 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/build/build.ts: -------------------------------------------------------------------------------- 1 | import { 2 | pipe, 3 | initInteraction, 4 | InteractionBuilderFn, 5 | } from "../interaction/interaction" 6 | import {Interaction} from "@onflow/typedefs" 7 | 8 | /** 9 | * @description A builder function that creates an interaction 10 | * @param fns The functions to apply to the interaction 11 | * @returns A promise of an interaction 12 | */ 13 | export function build( 14 | fns: (InteractionBuilderFn | false)[] = [] 15 | ): Promise { 16 | return pipe(initInteraction(), fns) 17 | } 18 | -------------------------------------------------------------------------------- /packages/sdk/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const flowMainnet: Record = { 2 | "flow.network": "mainnet", 3 | "accessNode.api": "https://rest-mainnet.onflow.org", 4 | "discovery.wallet": "https://fcl-discovery.onflow.org/authn", 5 | } 6 | 7 | export const flowTestnet: Record = { 8 | "flow.network": "testnet", 9 | "accessNode.api": "https://rest-testnet.onflow.org", 10 | "discovery.wallet": "https://fcl-discovery.onflow.org/testnet/authn", 11 | } 12 | 13 | export const flowEmulator: Record = { 14 | "flow.network": "local", 15 | "accessNode.api": "http://127.0.0.1:8888", 16 | "discovery.wallet": "http://localhost:8701/fcl/authn", 17 | } 18 | -------------------------------------------------------------------------------- /packages/sdk/src/decode/sdk-decode.ts: -------------------------------------------------------------------------------- 1 | import {config} from "@onflow/config" 2 | import {decodeResponse} from "./decode" 3 | 4 | export async function decode(response: any): Promise { 5 | const decodersFromConfig = await config().where(/^decoder\./) 6 | const decoders = Object.entries(decodersFromConfig).map( 7 | ([pattern, xform]) => { 8 | pattern = `/${pattern.replace(/^decoder\./, "")}$/` 9 | return [pattern, xform] 10 | } 11 | ) 12 | 13 | return decodeResponse(response, Object.fromEntries(decoders)) 14 | } 15 | -------------------------------------------------------------------------------- /packages/sdk/src/node-version-info/node-version-info.ts: -------------------------------------------------------------------------------- 1 | import {NodeVersionInfo} from "@onflow/typedefs" 2 | import {getNodeVersionInfo} from "../build/build-get-node-version-info" 3 | import {decodeResponse as decode} from "../decode/decode" 4 | import {send} from "../transport" 5 | 6 | /** 7 | * @description Returns the version information from to connected node 8 | * @returns A promise that resolves to a block response 9 | */ 10 | export async function nodeVersionInfo( 11 | opts: any = {} 12 | ): Promise { 13 | return await send([getNodeVersionInfo()], opts).then(decode) 14 | } 15 | -------------------------------------------------------------------------------- /packages/sdk/src/resolve/resolve-compute-limit.ts: -------------------------------------------------------------------------------- 1 | import {isTransaction} from "../interaction/interaction" 2 | import {config} from "@onflow/config" 3 | import * as logger from "@onflow/util-logger" 4 | import {Interaction} from "@onflow/typedefs" 5 | 6 | const DEFAULT_COMPUTE_LIMIT = 100 7 | 8 | export async function resolveComputeLimit( 9 | ix: Interaction 10 | ): Promise { 11 | if (isTransaction(ix)) { 12 | ix.message.computeLimit = 13 | ix.message.computeLimit || (await config.get("fcl.limit")) 14 | 15 | if (!ix.message.computeLimit) { 16 | logger.log.deprecate({ 17 | pkg: "FCL/SDK", 18 | subject: 19 | "The built-in default compute limit (DEFAULT_COMPUTE_LIMIT=10)", 20 | transition: 21 | "https://github.com/onflow/flow-js-sdk/blob/master/packages/sdk/TRANSITIONS.md#0009-deprecate-default-compute-limit", 22 | }) 23 | ix.message.computeLimit = DEFAULT_COMPUTE_LIMIT 24 | } 25 | } 26 | return ix 27 | } 28 | -------------------------------------------------------------------------------- /packages/sdk/src/resolve/resolve-final-normalization.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/resolve/resolve-final-normalization.ts: -------------------------------------------------------------------------------- 1 | import {sansPrefix} from "@onflow/util-address" 2 | import {Interaction} from "@onflow/typedefs" 3 | 4 | export async function resolveFinalNormalization( 5 | ix: Interaction 6 | ): Promise { 7 | for (let key of Object.keys(ix.accounts)) { 8 | ix.accounts[key].addr = sansPrefix(ix.accounts[key].addr) 9 | } 10 | return ix 11 | } 12 | -------------------------------------------------------------------------------- /packages/sdk/src/resolve/resolve-proposer-sequence-number.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/resolve/resolve-ref-block-id.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(1).toBe(1) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/resolve/resolve-validators.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/resolve/resolve-validators.ts: -------------------------------------------------------------------------------- 1 | import {get, pipe, Ok, Bad} from "../interaction/interaction" 2 | import {Interaction} from "@onflow/typedefs" 3 | 4 | export async function resolveValidators(ix: Interaction): Promise { 5 | const validators = get(ix, "ix.validators", []) 6 | return pipe( 7 | ix, 8 | validators.map((cb: Function) => (ix: Interaction) => cb(ix, {Ok, Bad})) 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /packages/sdk/src/resolve/resolve-voucher-intercept.ts: -------------------------------------------------------------------------------- 1 | import {get, isFn} from "../interaction/interaction" 2 | import {Interaction} from "@onflow/typedefs" 3 | import {createSignableVoucher} from "./voucher" 4 | 5 | export async function resolveVoucherIntercept( 6 | ix: Interaction 7 | ): Promise { 8 | const fn = get(ix, "ix.voucher-intercept") 9 | if (isFn(fn)) { 10 | await fn(createSignableVoucher(ix)) 11 | } 12 | return ix 13 | } 14 | -------------------------------------------------------------------------------- /packages/sdk/src/response/__snapshots__/response.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Response - Snapshot 1`] = ` 4 | { 5 | "account": null, 6 | "accountStatusEvent": null, 7 | "block": null, 8 | "blockDigest": null, 9 | "blockHeader": null, 10 | "collection": null, 11 | "encodedData": null, 12 | "event": null, 13 | "events": null, 14 | "heartbeat": null, 15 | "latestBlock": null, 16 | "networkParameters": null, 17 | "nodeVersionInfo": null, 18 | "streamConnection": null, 19 | "tag": null, 20 | "transaction": null, 21 | "transactionId": null, 22 | "transactionStatus": null, 23 | } 24 | `; 25 | -------------------------------------------------------------------------------- /packages/sdk/src/response/response.test.ts: -------------------------------------------------------------------------------- 1 | import {response} from "./response" 2 | 3 | test("Response - Snapshot", async () => { 4 | const resp = response() 5 | 6 | expect(resp).toMatchSnapshot() 7 | }) 8 | -------------------------------------------------------------------------------- /packages/sdk/src/response/response.ts: -------------------------------------------------------------------------------- 1 | const DEFAULT_RESPONSE = { 2 | tag: null, 3 | transaction: null, 4 | transactionStatus: null, 5 | transactionId: null, 6 | encodedData: null, 7 | events: null, 8 | event: null, 9 | accountStatusEvent: null, 10 | account: null, 11 | block: null, 12 | blockHeader: null, 13 | blockDigest: null, 14 | latestBlock: null, 15 | collection: null, 16 | networkParameters: null, 17 | streamConnection: null, 18 | heartbeat: null, 19 | nodeVersionInfo: null, 20 | } 21 | 22 | export const response = () => ({...DEFAULT_RESPONSE}) 23 | -------------------------------------------------------------------------------- /packages/sdk/src/test-utils/index.ts: -------------------------------------------------------------------------------- 1 | export {mockSend} from "./mock-send" 2 | export { 3 | authzFn, 4 | authzResolve, 5 | authzResolveMany, 6 | authzDeepResolveMany, 7 | sig, 8 | idof, 9 | } from "./authz-fn" 10 | export {run} from "./run" 11 | -------------------------------------------------------------------------------- /packages/sdk/src/test-utils/run.ts: -------------------------------------------------------------------------------- 1 | import {build} from "../build/build" 2 | import {resolve} from "../resolve/resolve" 3 | import {ref} from "../build/build-ref" 4 | import {Interaction} from "@onflow/typedefs" 5 | 6 | export const run = ( 7 | fns: Array<(ix: Interaction) => Interaction | Promise> = [] 8 | ) => build([ref("123"), ...fns]).then(resolve) 9 | -------------------------------------------------------------------------------- /packages/sdk/src/transport/index.ts: -------------------------------------------------------------------------------- 1 | export {send} from "./send/send" 2 | export {subscribe} from "./subscribe/subscribe" 3 | export {subscribeRaw} from "./subscribe/subscribe-raw" 4 | export {SubscriptionsNotSupportedError} from "./subscribe/errors" 5 | export * from "./subscribe/types" 6 | -------------------------------------------------------------------------------- /packages/sdk/src/transport/send/send.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(1).toBe(1) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/sdk/src/transport/subscribe/errors.ts: -------------------------------------------------------------------------------- 1 | export class SubscriptionsNotSupportedError extends Error { 2 | constructor() { 3 | super( 4 | `The current transport does not support subscriptions. If you have provided a custom transport (e.g. via \`sdk.transport\` configuration), ensure that it implements the subscribe method.` 5 | ) 6 | this.name = "SubscriptionsNotSupportedError" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/sdk/src/wallet-utils/index.ts: -------------------------------------------------------------------------------- 1 | export {validateSignableTransaction} from "./validate-tx" 2 | export {encodeMessageFromSignable} from "./encode-signable" 3 | -------------------------------------------------------------------------------- /packages/sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/transport-grpc/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"]] 3 | } 4 | -------------------------------------------------------------------------------- /packages/transport-grpc/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/transport-grpc/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/transport-grpc/src/send-get-network-parameters.js: -------------------------------------------------------------------------------- 1 | import {invariant} from "@onflow/util-invariant" 2 | import {AccessAPI, GetNetworkParametersRequest} from "@onflow/protobuf" 3 | import {unary as defaultUnary} from "./unary" 4 | 5 | export async function sendGetNetworkParameters(ix, context = {}, opts = {}) { 6 | invariant( 7 | opts.node, 8 | `SDK Send Get Network Parameters Error: opts.node must be defined.` 9 | ) 10 | invariant( 11 | context.response, 12 | `SDK Send Get Network Parameters Error: context.response must be defined.` 13 | ) 14 | 15 | const unary = opts.unary || defaultUnary 16 | 17 | ix = await ix 18 | 19 | const req = new GetNetworkParametersRequest() 20 | 21 | const res = await unary( 22 | opts.node, 23 | AccessAPI.GetNetworkParameters, 24 | req, 25 | context 26 | ) 27 | 28 | let ret = context.response() 29 | ret.tag = ix.tag 30 | 31 | let chainId = res.getChainId() 32 | ret.networkParameters = { 33 | chainId: chainId, 34 | } 35 | 36 | return ret 37 | } 38 | -------------------------------------------------------------------------------- /packages/transport-grpc/src/send-ping.js: -------------------------------------------------------------------------------- 1 | import {invariant} from "@onflow/util-invariant" 2 | import {AccessAPI, PingRequest} from "@onflow/protobuf" 3 | import {unary as defaultUnary} from "./unary" 4 | 5 | export async function sendPing(ix, context = {}, opts = {}) { 6 | invariant(opts.node, `SDK Send Ping Error: opts.node must be defined.`) 7 | invariant( 8 | context.response, 9 | `SDK Send Ping Error: context.response must be defined.` 10 | ) 11 | 12 | const unary = opts.unary || defaultUnary 13 | 14 | ix = await ix 15 | 16 | const req = new PingRequest() 17 | 18 | const res = await unary(opts.node, AccessAPI.Ping, req, context) 19 | 20 | let ret = context.response() 21 | ret.tag = ix.tag 22 | 23 | return ret 24 | } 25 | -------------------------------------------------------------------------------- /packages/transport-grpc/src/unary.js: -------------------------------------------------------------------------------- 1 | import {invariant} from "@onflow/util-invariant" 2 | import {grpc} from "@improbable-eng/grpc-web" 3 | import {NodeHttpTransport} from "@improbable-eng/grpc-web-node-http-transport" 4 | 5 | grpc.setDefaultTransport(NodeHttpTransport()) 6 | 7 | export async function unary(host, method, request, context) { 8 | invariant( 9 | context.config, 10 | `SDK GRPC Unary Error: context.config must be defined.` 11 | ) 12 | const metadataFromConfig = await context.config().get("grpc.metadata", {}) 13 | return new Promise((resolve, reject) => { 14 | grpc.unary(method, { 15 | request: request, 16 | host: host, 17 | metadata: new grpc.Metadata(metadataFromConfig), 18 | onEnd: ({status, statusMessage, message}) => { 19 | if (status === grpc.Code.OK) { 20 | resolve(message) 21 | } else { 22 | reject(new Error(statusMessage)) 23 | } 24 | }, 25 | }) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /packages/transport-grpc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | // Types should go into this directory. 7 | // Removing this would place the .d.ts files 8 | // next to the .js files 9 | "outDir": "types" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/transport-http/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "useBuiltIns": false 7 | } 8 | ], 9 | "@babel/preset-typescript" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /packages/transport-http/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/transport-http/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/transport-http/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Transport HTTP 3 | description: Sends an interaction to an access node via the HTTP Rest API and returns a response. 4 | --- 5 | 6 | # @onflow/transport-http 7 | 8 | A transport module which can send an interaction to an access node via the HTTP Rest api specification and return a response. 9 | 10 | ## Status 11 | 12 | - **Last Updated:** Jan 13th 2022 13 | - **Stable:** Yes 14 | - **Risk of Breaking Change:** Medium 15 | 16 | This package is working and in active development, breaking changes may happen. 17 | 18 | ## Install 19 | 20 | ```bash 21 | npm install --save @onflow/transport-http 22 | ``` -------------------------------------------------------------------------------- /packages/transport-http/src/index.ts: -------------------------------------------------------------------------------- 1 | export {sendExecuteScript} from "./send/send-execute-script" 2 | export {sendGetAccount} from "./send/send-get-account" 3 | export {sendGetBlockHeader} from "./send/send-get-block-header" 4 | export {sendGetBlock} from "./send/send-get-block" 5 | export {sendGetCollection} from "./send/send-get-collection" 6 | export {sendGetEvents} from "./send/send-get-events" 7 | export {sendGetTransaction} from "./send/send-get-transaction" 8 | export {sendGetTransactionStatus} from "./send/send-get-transaction-status" 9 | export {sendPing} from "./send/send-ping" 10 | export {sendTransaction} from "./send/send-transaction" 11 | export {sendGetNetworkParameters} from "./send/send-get-network-parameters" 12 | export {sendGetNodeVersionInfo} from "./send/send-get-node-version-info" 13 | export {connectSubscribeEvents} from "./send/connect-subscribe-events" 14 | export {send} from "./send/send-http" 15 | export {WebsocketError} from "./send/connect-ws" 16 | export {HTTPRequestError} from "./send/http-request.js" 17 | export {httpTransport} from "./transport" 18 | -------------------------------------------------------------------------------- /packages/transport-http/src/send/send-get-collection.js: -------------------------------------------------------------------------------- 1 | import {invariant} from "@onflow/util-invariant" 2 | import {httpRequest as defaultHttpRequest} from "./http-request.js" 3 | 4 | export async function sendGetCollection(ix, context = {}, opts = {}) { 5 | invariant( 6 | opts.node, 7 | `SDK Send Get Collection Error: opts.node must be defined.` 8 | ) 9 | invariant( 10 | context.response, 11 | `SDK Send Get Collection Error: context.response must be defined.` 12 | ) 13 | 14 | const httpRequest = opts.httpRequest || defaultHttpRequest 15 | 16 | const res = await httpRequest({ 17 | hostname: opts.node, 18 | path: `/v1/collections/${ix.collection.id}?expand=transactions`, 19 | method: "GET", 20 | body: null, 21 | }) 22 | 23 | const ret = context.response() 24 | ret.tag = ix.tag 25 | ret.collection = { 26 | id: res.id, 27 | transactionIds: res.transactions.map(transaction => transaction.id), 28 | } 29 | 30 | return ret 31 | } 32 | -------------------------------------------------------------------------------- /packages/transport-http/src/send/send-get-network-parameters.js: -------------------------------------------------------------------------------- 1 | import {invariant} from "@onflow/util-invariant" 2 | import {httpRequest as defaultHttpRequest} from "./http-request.js" 3 | 4 | export async function sendGetNetworkParameters(ix, context = {}, opts = {}) { 5 | invariant( 6 | opts.node, 7 | `SDK Send Get Network Parameters Error: opts.node must be defined.` 8 | ) 9 | invariant( 10 | context.response, 11 | `SDK Send Get Network Parameters Error: context.response must be defined.` 12 | ) 13 | 14 | const httpRequest = opts.httpRequest || defaultHttpRequest 15 | 16 | ix = await ix 17 | 18 | const res = await httpRequest({ 19 | hostname: opts.node, 20 | path: `/v1/network/parameters`, 21 | method: "GET", 22 | body: null, 23 | enableRequestLogging: opts.enableRequestLogging ?? true, 24 | }) 25 | 26 | let ret = context.response() 27 | ret.tag = ix.tag 28 | 29 | ret.networkParameters = { 30 | chainId: res.chain_id, 31 | } 32 | return ret 33 | } 34 | -------------------------------------------------------------------------------- /packages/transport-http/src/send/utils.js: -------------------------------------------------------------------------------- 1 | export function safeParseJSON(data) { 2 | try { 3 | return JSON.parse(data) 4 | } catch { 5 | return null 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/transport-http/src/subscribe/websocket.ts: -------------------------------------------------------------------------------- 1 | import _WebSocket from "isomorphic-ws" 2 | 3 | export const WebSocket = _WebSocket as (new ( 4 | url: string | URL, 5 | protocols?: string | string[] | undefined 6 | ) => WebSocket) & 7 | WebSocket 8 | -------------------------------------------------------------------------------- /packages/transport-http/src/transport.ts: -------------------------------------------------------------------------------- 1 | import {SdkTransport} from "@onflow/typedefs" 2 | import {send} from "./send/send-http" 3 | import {subscribe} from "./subscribe/subscribe" 4 | 5 | export const httpTransport: SdkTransport = { 6 | send, 7 | subscribe, 8 | } 9 | -------------------------------------------------------------------------------- /packages/transport-http/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/typedefs/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"]] 3 | } 4 | -------------------------------------------------------------------------------- /packages/typedefs/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": ["plugin:jsdoc/recommended"], 9 | "plugins": ["jsdoc"], 10 | "parserOptions": { 11 | "ecmaVersion": "latest", 12 | "sourceType": "module" 13 | }, 14 | "ignorePatterns": ["**/dist/"], 15 | "rules": { 16 | "jsdoc/require-jsdoc": [ 17 | "error", 18 | { 19 | "publicOnly": true 20 | } 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/typedefs/.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | 3 | !dist/** 4 | !types/** 5 | !package.json 6 | !README.md 7 | -------------------------------------------------------------------------------- /packages/typedefs/README.md: -------------------------------------------------------------------------------- 1 | JSDoc typedefs and TypeScript types. 2 | 3 | ```typescript 4 | 5 | import {CurrentUser} from "@onflow/typedefs" 6 | 7 | const newUser: CurrentUser = { 8 | addr: null, 9 | cid: null, 10 | expiresAt: null, 11 | f_type: 'User', 12 | f_vsn: '1.0.0', 13 | loggedIn: null, 14 | services: [] 15 | } 16 | 17 | ``` 18 | -------------------------------------------------------------------------------- /packages/typedefs/src/index.test.js: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/typedefs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/types/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/types/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/types/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"], 20 | "overrides": [ 21 | { 22 | "files": ["**/*.test.ts"], 23 | "env": { 24 | "jest": true 25 | }, 26 | "rules": { 27 | "jsdoc/require-jsdoc": 0 28 | } 29 | } 30 | ], 31 | "rules": { 32 | "@typescript-eslint/no-explicit-any": 0 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/types/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/types/WARNINGS.md: -------------------------------------------------------------------------------- 1 | # Warnings 2 | 3 | ## 0002 [U]Int* and Word* as Number 4 | 5 | - **Date:** March 4 2022 6 | - **Issue:** [#283](https://github.com/onflow/fcl-js/issues/283) 7 | - **Type:** Deprecation of accepting JavaScript numbers as values for [U]Int* and Word* as Number types. 8 | 9 | [U]Int* and Word* types will no longer accept Number as values for them in the near future. 10 | 11 | Please only pass String as value for [U]Int* and Word* types. 12 | 13 | 14 | ## 0001 [U]Fix64 as Number 15 | 16 | - **Date:** August 19 2020 17 | - **Issue:** [#283](https://github.com/onflow/fcl-js/issues/283) 18 | - **Type:** Deprecation of accepting JavaScript numbers as values for Fix64 and UFix64 types. 19 | 20 | Fix64 and UFix64 types will no longer accept numbers as values for them in the near future. 21 | 22 | Please pass only strings as values for Fix64 and UFix64 types. 23 | -------------------------------------------------------------------------------- /packages/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/util-actor/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/util-actor/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/util-actor/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "rules": { 20 | "@typescript-eslint/no-explicit-any": "off" 21 | }, 22 | "ignorePatterns": ["**/dist/"] 23 | } 24 | -------------------------------------------------------------------------------- /packages/util-actor/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/util-actor/README.md: -------------------------------------------------------------------------------- 1 | ### Actor 2 | 3 | > Asynchronous self-contained isolated state, can only be comunicated with via a first-in/first-out message queue called a mailbox. 4 | 5 | Please see the tests for examples. 6 | 7 | As this is an unstable internal tool used by the SDK and FCl, using it directly from your code is a massive risk. 8 | 9 | We will have documentation once we consider this utility stable. 10 | -------------------------------------------------------------------------------- /packages/util-actor/src/mailbox/README.md: -------------------------------------------------------------------------------- 1 | ### Mailbox 2 | 3 | > An async first-in/first-out queue, used to enforce order of the actors. 4 | 5 | ```javascript 6 | import {mailbox} from "..." 7 | 8 | const m = mailbox() 9 | 10 | m.deliver("foo") 11 | m.deliver("bar") 12 | m.deliver("baz") 13 | 14 | await m.receive() // "foo" 15 | await m.receive() // "bar" 16 | await m.receive() // "baz" 17 | ``` 18 | -------------------------------------------------------------------------------- /packages/util-actor/src/mailbox/index.ts: -------------------------------------------------------------------------------- 1 | export interface IMailbox { 2 | deliver(msg: T): Promise 3 | receive(): Promise 4 | } 5 | export const mailbox = (): IMailbox => { 6 | const queue: T[] = [] 7 | let next: ((msg: T) => void) | undefined 8 | 9 | return { 10 | async deliver(msg: T) { 11 | queue.push(msg) 12 | if (next) { 13 | next(queue.shift() as T) 14 | next = undefined 15 | } 16 | }, 17 | 18 | receive(): Promise { 19 | return new Promise(function innerReceive(resolve) { 20 | const msg = queue.shift() 21 | if (msg) return resolve(msg) 22 | next = resolve 23 | }) 24 | }, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/util-actor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/util-address/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/util-address/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/util-address/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"], 20 | "rules": { 21 | "@typescript-eslint/no-explicit-any": "off" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/util-address/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/util-address/README.md: -------------------------------------------------------------------------------- 1 | ```javascript 2 | 3 | import {withPrefix, sansPrefix, display} from "@onflow/util-address" 4 | 5 | const address = "0xc88ff43f1a87c679" 6 | assert(sansPrefix(address), "c88ff43f1a87c679") 7 | 8 | assert(withPrefix(address), address) 9 | assert(withPrefix(sansPrefix(address)), address) 10 | 11 | const Comp = ({ address }) => { 12 | return
13 | Flow Address 14 | {display(address)} 15 |
16 | } 17 | 18 | ``` 19 | -------------------------------------------------------------------------------- /packages/util-address/src/index.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/util-address/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/util-encode-key/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/util-encode-key/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/util-encode-key/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"], 20 | "rules": { 21 | "@typescript-eslint/no-explicit-any": "off" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/util-encode-key/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/util-encode-key/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/util-invariant/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"]] 3 | } 4 | -------------------------------------------------------------------------------- /packages/util-invariant/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/util-invariant/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/util-invariant/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/util-invariant/README.md: -------------------------------------------------------------------------------- 1 | ```javascript 2 | import {invariant} from "@onflow/util-invariant" 3 | 4 | function add(a, b) { 5 | invariant(typeof a === "number", "add(a, b) -- `a` needs to be a number", { a, b }) 6 | invariant(typeof b === "number", "add(a, b) -- `b` needs to be a number", { a, b }) 7 | return a + b 8 | } 9 | ``` 10 | -------------------------------------------------------------------------------- /packages/util-invariant/src/index.test.ts: -------------------------------------------------------------------------------- 1 | test("placeholder", () => { 2 | expect(0).toBe(0) 3 | }) 4 | -------------------------------------------------------------------------------- /packages/util-invariant/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Asserts fact is true, otherwise throw an error with invariant message 3 | * @param fact 4 | * @param msg 5 | * @param rest 6 | */ 7 | export function invariant( 8 | fact: boolean, 9 | msg: string, 10 | ...rest: any[] 11 | ): asserts fact { 12 | if (!fact) { 13 | const error = new Error(`INVARIANT ${msg}`) 14 | error.stack = error.stack 15 | ?.split("\n") 16 | ?.filter(d => !/at invariant/.test(d)) 17 | ?.join("\n") 18 | console.error("\n\n---\n\n", error, "\n\n", ...rest, "\n\n---\n\n") 19 | throw error 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/util-invariant/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/util-logger/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/util-logger/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/util-logger/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/util-logger/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/util-logger/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/util-rpc/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/util-rpc/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/util-rpc/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/util-rpc/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/util-rpc/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @onflow/util-rpc 2 | 3 | ## 0.0.2 4 | 5 | ### Patch Changes 6 | 7 | - [#1983](https://github.com/onflow/fcl-js/pull/1983) [`18d24c8bad7efa0d8741d74f0cf299f89b3622c7`](https://github.com/onflow/fcl-js/commit/18d24c8bad7efa0d8741d74f0cf299f89b3622c7) Thanks [@jribbink](https://github.com/jribbink)! - Update dependencies 8 | 9 | ## 0.0.2-alpha.0 10 | 11 | ### Patch Changes 12 | 13 | - [#1983](https://github.com/onflow/fcl-js/pull/1983) [`18d24c8bad7efa0d8741d74f0cf299f89b3622c7`](https://github.com/onflow/fcl-js/commit/18d24c8bad7efa0d8741d74f0cf299f89b3622c7) Thanks [@jribbink](https://github.com/jribbink)! - Update dependencies 14 | 15 | ## 0.0.1 16 | 17 | - Initial release 18 | -------------------------------------------------------------------------------- /packages/util-rpc/README.md: -------------------------------------------------------------------------------- 1 | # @onflow/util-rpc 2 | 3 | Lightweight utility for creating transport-agnostic, bidirectional JSON-RPC channels. 4 | 5 | # Status 6 | 7 | - **Last Updated:** Aug 6th, 2024 8 | - **Stable:** No 9 | - **Risk of Breaking Change:** Yes 10 | 11 | # Install 12 | 13 | ```bash 14 | npm install --save @onflow/util-rpc 15 | ``` 16 | 17 | # Usage 18 | 19 | ```javascript 20 | import {RpcClient} from "@onflow/util-rpc" 21 | 22 | const rpc = new RpcClient(...) 23 | rpc.connect(...) 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/util-rpc/src/index.ts: -------------------------------------------------------------------------------- 1 | export {RpcClient} from "./rpc-client" 2 | export type {RpcNotification, RpcRequest} from "./rpc-client" 3 | export {RpcError, RpcErrorCode} from "./rpc-error" 4 | -------------------------------------------------------------------------------- /packages/util-rpc/src/messages.ts: -------------------------------------------------------------------------------- 1 | export type RpcRequestMessage = { 2 | jsonrpc: "2.0" 3 | id: number 4 | method: string 5 | params: any 6 | } 7 | 8 | export type RpcNotificationMessage = { 9 | jsonrpc: "2.0" 10 | method: string 11 | params: any 12 | } 13 | 14 | export type RpcResponseMessage = { 15 | jsonrpc: "2.0" 16 | id: number 17 | result: any 18 | } 19 | 20 | export type RpcErrorMessage = { 21 | jsonrpc: "2.0" 22 | id: number 23 | error: { 24 | code: number 25 | message: string 26 | data?: any 27 | } 28 | } 29 | 30 | export type RpcMessage = 31 | | RpcRequestMessage 32 | | RpcNotificationMessage 33 | | RpcResponseMessage 34 | | RpcErrorMessage 35 | -------------------------------------------------------------------------------- /packages/util-rpc/src/rpc-error.ts: -------------------------------------------------------------------------------- 1 | export enum RpcErrorCode { 2 | INVALID_REQUEST = -32600, 3 | METHOD_NOT_FOUND = -32601, 4 | INVALID_PARAMS = -32602, 5 | INTERNAL_ERROR = -32603, 6 | PARSE_ERROR = -32700, 7 | } 8 | 9 | export class RpcError extends Error { 10 | constructor( 11 | public code: RpcErrorCode, 12 | public message: string, 13 | public data?: any 14 | ) { 15 | super(message) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/util-rpc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/util-semver/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"]] 3 | } 4 | -------------------------------------------------------------------------------- /packages/util-semver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@onflow/util-semver", 3 | "version": "1.0.3", 4 | "description": "A lightweight semver implementation for use in FCL", 5 | "main": "dist/index.js", 6 | "module": "dist/index.module.js", 7 | "source": "src/index.ts", 8 | "types": "types/index.d.ts", 9 | "scripts": { 10 | "prepublishOnly": "npm test && npm run build", 11 | "test": "jest", 12 | "build": "fcl-bundle", 13 | "test:watch": "jest --watch", 14 | "start": "fcl-bundle --watch" 15 | }, 16 | "devDependencies": { 17 | "@onflow/fcl-bundle": "1.7.0", 18 | "jest": "^29.7.0" 19 | }, 20 | "dependencies": { 21 | "@babel/runtime": "^7.25.7" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/onflow/fcl-js.git" 26 | }, 27 | "author": "Flow Blockchain", 28 | "license": "Apache-2.0", 29 | "bugs": { 30 | "url": "https://github.com/onflow/fcl-js/issues" 31 | }, 32 | "homepage": "https://flow.com" 33 | } 34 | -------------------------------------------------------------------------------- /packages/util-semver/src/index.ts: -------------------------------------------------------------------------------- 1 | export {compare} from "./compare" 2 | -------------------------------------------------------------------------------- /packages/util-semver/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/util-template/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/util-template/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/util-template/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/util-template/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/util-template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | }, 9 | "exclude": ["src/__snapshots__"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/util-uid/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env"], "@babel/preset-typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/util-uid/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults and supports es6-module 2 | maintained node versions 3 | -------------------------------------------------------------------------------- /packages/util-uid/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "plugin:jsdoc/recommended-typescript", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "plugins": ["jsdoc", "@typescript-eslint"], 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": "latest", 17 | "sourceType": "module" 18 | }, 19 | "ignorePatterns": ["**/dist/"] 20 | } 21 | -------------------------------------------------------------------------------- /packages/util-uid/.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /packages/util-uid/README.md: -------------------------------------------------------------------------------- 1 | # @onflow/util-rpc 2 | 3 | Lightweight utility for transport-agnostic, bidirectional RPC communication. 4 | 5 | # Status 6 | 7 | - **Last Updated:** Aug 6th, 2024 8 | - **Stable:** No 9 | - **Risk of Breaking Change:** Yes 10 | 11 | # Install 12 | 13 | ```bash 14 | npm install --save @onflow/util-rpc 15 | ``` 16 | 17 | # Usage 18 | 19 | ```javascript 20 | import {RpcClient} from "@onflow/util-rpc" 21 | 22 | const uniqueIdentifier = new RpcClient(...) 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/util-uid/src/util-uid.test.ts: -------------------------------------------------------------------------------- 1 | import {uid} from "./util-uid" 2 | 3 | test("it should generate a unique 32 character alphanumeric string", () => { 4 | const set = new Set() 5 | for (let i = 0; i < 1000; i++) { 6 | const id = uid() 7 | expect(id).toMatch(/^[a-zA-Z0-9]{32}$/) 8 | expect(set.has(id)).toBe(false) 9 | set.add(id) 10 | } 11 | expect(set.size).toBe(1000) 12 | }) 13 | -------------------------------------------------------------------------------- /packages/util-uid/src/util-uid.ts: -------------------------------------------------------------------------------- 1 | const HEX = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" 2 | const T = HEX.length 3 | 4 | /** 5 | * Generates a random unique identifier 6 | * @returns 32 character alphanumeric string 7 | */ 8 | export function uid(): string { 9 | let str = "", 10 | num = 32 11 | while (num--) str += HEX[(Math.random() * T) | 0] 12 | return str 13 | } 14 | -------------------------------------------------------------------------------- /packages/util-uid/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | // Change this to match your project 4 | "include": ["src/**/*"], 5 | "compilerOptions": { 6 | "declarationDir": "types", 7 | "rootDir": "src" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // Change this to match your project 3 | "exclude": ["**/*.test.ts", "**/*.test.js"], 4 | "compilerOptions": { 5 | "moduleResolution": "Bundler", 6 | "module": "ESNext", 7 | "target": "ES2015", 8 | // Useful for error cause 9 | "lib": ["ES2015", "WebWorker", "DOM", "ES2022.Error"], 10 | "types": ["node", "jest"], 11 | // Tells TypeScript to read JS files, as 12 | // normally they are ignored as source files 13 | "allowJs": true, 14 | // Generate d.ts files 15 | "declaration": true, 16 | // This compiler run should 17 | // only output d.ts files 18 | "emitDeclarationOnly": true, 19 | // go to js file when using IDE functions like 20 | // "Go to Definition" in VSCode 21 | "declarationMap": false, 22 | "strict": true, 23 | "allowSyntheticDefaultImports": true 24 | } 25 | } 26 | --------------------------------------------------------------------------------