├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── labels.yml ├── pull_request_template.md ├── release.yml └── workflows │ ├── add-issues-to-devx-project.yml │ ├── ci.yml │ └── sync-labels.yml ├── .gitignore ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── README_zh_CN.md ├── SECURITY.md ├── access ├── README.md ├── client.go ├── grpc │ ├── client.go │ ├── convert │ │ ├── convert.go │ │ └── convert_test.go │ ├── errors.go │ ├── grpc.go │ ├── grpc_test.go │ └── mocks │ │ ├── ExecutionDataRPCClient.go │ │ └── RPCClient.go ├── http │ ├── client.go │ ├── client_test.go │ ├── convert │ │ ├── convert.go │ │ └── convert_test.go │ ├── handler.go │ ├── handler_test.go │ ├── http.go │ ├── internal │ │ └── unittest │ │ │ └── fixtures.go │ ├── mock_handler.go │ └── models │ │ ├── model_account.go │ │ ├── model_account__expandable.go │ │ ├── model_account_public_key.go │ │ ├── model_aggregated_signature.go │ │ ├── model_block.go │ │ ├── model_block__expandable.go │ │ ├── model_block_events.go │ │ ├── model_block_header.go │ │ ├── model_block_height.go │ │ ├── model_block_payload.go │ │ ├── model_block_seal.go │ │ ├── model_chunk.go │ │ ├── model_collection.go │ │ ├── model_collection__expandable.go │ │ ├── model_collection_guarantee.go │ │ ├── model_error.go │ │ ├── model_event.go │ │ ├── model_execution_result.go │ │ ├── model_hashing_algorithm.go │ │ ├── model_inline_response_200.go │ │ ├── model_links.go │ │ ├── model_network_parameters.go │ │ ├── model_node_version_info.go │ │ ├── model_one_of_block_height.go │ │ ├── model_proposal_key.go │ │ ├── model_scripts_body.go │ │ ├── model_signing_algorithm.go │ │ ├── model_transaction.go │ │ ├── model_transaction__expandable.go │ │ ├── model_transaction_execution.go │ │ ├── model_transaction_result.go │ │ ├── model_transaction_result__expandable.go │ │ ├── model_transaction_signature.go │ │ ├── model_transaction_status.go │ │ └── model_transactions_body.go └── mocks │ └── Client.go ├── account.go ├── account_proof.go ├── account_proof_test.go ├── account_test.go ├── address.go ├── address_test.go ├── block.go ├── check-headers.sh ├── client └── client.go ├── collection.go ├── crypto ├── awskms │ ├── awskms.go │ ├── awskms_test.go │ └── signer.go ├── cloudkms │ ├── cloudkms.go │ ├── cloudkms_test.go │ └── signer.go ├── crypto.go ├── crypto_test.go ├── hash.go └── internal │ └── util.go ├── crypto_adx_flag.mk ├── decode.go ├── decode_test.go ├── doc.go ├── docs ├── error-codes.mdx ├── flow-docs.json ├── index.mdx ├── migration-v0.25.0.md └── sdk-banner.svg ├── event.go ├── event_type_factory.go ├── event_type_factory_test.go ├── examples ├── Makefile ├── README.md ├── add_account_key │ └── main.go ├── cloudkms │ └── main.go ├── create_account │ └── main.go ├── deploy_contract │ └── main.go ├── examples.go ├── execute_script │ └── main.go ├── flow.json ├── get_accounts │ └── main.go ├── get_blocks │ └── main.go ├── get_collection │ └── main.go ├── get_events │ └── main.go ├── get_execution_data │ └── main.go ├── get_network_parameters │ └── main.go ├── get_transactions │ └── main.go ├── go.mod ├── go.sum ├── great-token.cdc ├── http_grpc_clients │ └── main.go ├── modify_account │ └── main.go ├── send_and_subscribe_transaction_statuses │ └── main.go ├── send_transactions │ └── main.go ├── storage_usage │ └── main.go ├── stream_account_statuses │ └── main.go ├── stream_block_digests │ └── main.go ├── stream_block_headers │ └── main.go ├── stream_blocks │ └── main.go ├── stream_events │ └── main.go ├── stream_events_reconnect │ └── main.go ├── stream_execution_data │ └── main.go ├── transaction_arguments │ └── main.go ├── transaction_scaling │ └── main.go ├── transaction_signing │ ├── multi_party │ │ └── main.go │ ├── multi_party_multisig │ │ └── main.go │ ├── multi_party_two_authorizers │ │ └── main.go │ ├── single_party │ │ └── main.go │ └── single_party_multisig │ │ └── main.go ├── verify_events │ └── main.go └── verify_signature │ ├── user_signature │ └── main.go │ ├── user_signature_validate_all │ └── main.go │ └── user_signature_validate_any │ └── main.go ├── execution_data.go ├── execution_result.go ├── flow.go ├── go.mod ├── go.sum ├── sign.go ├── templates ├── accounts.go └── accounts_test.go ├── test ├── entities.go ├── greetings.go └── signer.go ├── transaction.go └── transaction_test.go /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [Makefile] 8 | indent_style = tab 9 | indent_size = 4 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Report a problem or bug 4 | title: '' 5 | labels: bug 6 | --- 7 | 8 | ## Instructions 9 | 10 | Please fill out the template below to the best of your ability and include a label indicating which tool/service you were working with when you encountered the problem. 11 | 12 | ### Problem 13 | 14 | 15 | 16 | ### Steps to Reproduce 17 | 18 | 19 | 20 | ### Acceptance Criteria 21 | 22 | 23 | 24 | ### Context 25 | 26 | 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | --- 7 | 8 | **Is your feature request related to a problem? Please describe.** 9 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 10 | 11 | **Describe the solution you'd like** 12 | A clear and concise description of what you want to happen. 13 | 14 | **Describe alternatives you've considered** 15 | A clear and concise description of any alternative solutions or features you've considered. 16 | 17 | **Additional context** 18 | Add any other context or screenshots about the feature request here. 19 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | 8 | - package-ecosystem: "gomod" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | ignore: 13 | - dependency-name: "github.com/onflow/crypto" 14 | - dependency-name: "github.com/onflow/cadence" 15 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | - color: fbca04 2 | description: "" 3 | name: Breaking Change 4 | - color: 3E4B9E 5 | description: "" 6 | name: Epic 7 | - color: 0e8a16 8 | description: "" 9 | name: Feature 10 | - color: d4c5f9 11 | description: "" 12 | name: Feedback 13 | - color: 1d76db 14 | description: "" 15 | name: Improvement 16 | - color: efbd7f 17 | description: "" 18 | name: Needs Definition 19 | - color: f99875 20 | description: "" 21 | name: Needs Estimation 22 | - color: efa497 23 | description: "" 24 | name: Needs Test Cases 25 | - color: fcadab 26 | description: "" 27 | name: P-High 28 | - color: bfd4f2 29 | description: "" 30 | name: P-Low 31 | - color: ddcd3e 32 | description: "" 33 | name: P-Medium 34 | - color: CCCCCC 35 | description: "" 36 | name: Technical Debt 37 | - color: d73a4a 38 | description: Something isn't working 39 | name: Bug 40 | - color: c2e0c6 41 | description: "" 42 | name: Bugfix 43 | - color: cfd3d7 44 | description: This issue or pull request already exists 45 | name: Duplicate 46 | - color: 7057ff 47 | description: Good for newcomers 48 | name: Good First Issue 49 | - color: d876e3 50 | description: Further information is requested 51 | name: Question 52 | - color: 0075ca 53 | description: Improvements or additions to documentation 54 | name: Documentation 55 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Closes: #??? 2 | 3 | ## Description 4 | 5 | 8 | 9 | ______ 10 | 11 | For contributor use: 12 | 13 | - [ ] Targeted PR against `master` branch 14 | - [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work. 15 | - [ ] Code follows the [standards mentioned here](https://github.com/onflow/flow-go-sdk/blob/master/CONTRIBUTING.md#styleguides). 16 | - [ ] Updated relevant documentation 17 | - [ ] Re-reviewed `Files changed` in the Github PR explorer 18 | - [ ] Added appropriate labels 19 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | categories: 3 | - title: 💥 Breaking Changes 4 | labels: 5 | - Breaking Change 6 | - title: ⭐ Features 7 | labels: 8 | - Feature 9 | - title: 🛠 Improvements 10 | labels: 11 | - Improvement 12 | - title: 🐞 Bug Fixes 13 | labels: 14 | - Bugfix 15 | - title: 📖 Documentation 16 | labels: 17 | - Documentation 18 | - title: Other Changes 19 | labels: 20 | - "*" 21 | -------------------------------------------------------------------------------- /.github/workflows/add-issues-to-devx-project.yml: -------------------------------------------------------------------------------- 1 | name: Adds all issues to the DevEx 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@v1.0.2 14 | with: 15 | project-url: https://github.com/orgs/onflow/projects/13 16 | github-token: ${{ secrets.GH_ACTION_FOR_PROJECTS }} 17 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - 'v**' 8 | - 'feature/**' 9 | pull_request: 10 | branches: 11 | - master 12 | - 'v**' 13 | - 'feature/**' 14 | 15 | jobs: 16 | test: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | - uses: actions/setup-go@v4 23 | with: 24 | go-version: '1.22' 25 | - name: Run tests 26 | run: | 27 | make ci 28 | make check-tidy 29 | make check-headers 30 | - name: Upload coverage report 31 | uses: codecov/codecov-action@v5 32 | with: 33 | file: ./coverage.txt 34 | flags: unittests 35 | -------------------------------------------------------------------------------- /.github/workflows/sync-labels.yml: -------------------------------------------------------------------------------- 1 | name: Sync Labels 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - .github/labels.yml 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: micnncim/action-label-syncer@v1 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | with: 19 | manifest: .github/labels.yml 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Test binary, build with `go test -c` 2 | *.test 3 | 4 | # Output of the Go coverage tool 5 | *.out 6 | 7 | # Coverage artifacts 8 | coverage.zip 9 | cover.json 10 | cover-summary 11 | index.html 12 | coverage.txt 13 | 14 | # Since we have tooling that uses node 15 | node_modules 16 | 17 | .DS_Store 18 | 19 | /flow.json 20 | 21 | # IDE related files 22 | .idea 23 | .vscode 24 | git 25 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @janezpodhostnik @chasefleming @nvdtf @jribbink 2 | /crypto/** @tarakby 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Ensure go bin path is in path (especially for CI) 2 | PATH := $(PATH):$(GOPATH)/bin 3 | 4 | # include script to possibly set a crypto flag for older machines 5 | include crypto_adx_flag.mk 6 | 7 | CGO_FLAG := CGO_CFLAGS=$(CRYPTO_FLAG) 8 | 9 | .PHONY: test 10 | test: 11 | GO111MODULE=on $(CGO_FLAG) go test -coverprofile=coverage.txt ./... 12 | 13 | .PHONY: coverage 14 | coverage: test 15 | go tool cover -html=coverage.txt 16 | 17 | .PHONY: generate 18 | generate: 19 | go install github.com/vektra/mockery/v2@v2.53.3 20 | go generate ./... 21 | 22 | .PHONY: ci 23 | ci: check-tidy test coverage 24 | 25 | # Ensure there is no unused dependency being added by accident and all generated code is committed 26 | .PHONY: check-tidy 27 | check-tidy: generate 28 | go mod tidy 29 | git diff --exit-code 30 | 31 | .PHONY: check-headers 32 | check-headers: 33 | @./check-headers.sh 34 | 35 | .PHONY: generate-openapi 36 | generate-openapi: 37 | swagger-codegen generate -l go -i https://raw.githubusercontent.com/onflow/flow/master/openapi/access.yaml -D packageName=models,modelDocs=false,models -o access/http/models; 38 | go fmt ./access/http/models 39 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Flow Go SDK 2 | Copyright 2019-2024 Flow Foundation 3 | 4 | This product includes software developed at the Flow Foundation (https://flow.com/flow-foundation). 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://docs.onflow.org/bounties/responsible-disclosure/) 13 | -------------------------------------------------------------------------------- /access/README.md: -------------------------------------------------------------------------------- 1 | ## Access Package 2 | The access package implements network communication with the access nodes APIs. 3 | It also defines an `access.Client` interface exposing all the common API interactions. 4 | 5 | ### Design 6 | Each implementation (currently `grpc` and `http`) include the following parts: 7 | - **Base Client** is the client that implements the client interface exposing 8 | all generic functionality. 9 | - **Client** is the network specific client that exposes any additional 10 | options possible by the specific API implementation. 11 | - **Handler** takes care of actual network communication implementing 12 | the communication protocol. 13 | 14 | 15 | ### Usage 16 | If you want to use the base client you should save the instance to 17 | the client interface, which would allow you to easily switch between network 18 | implementations like so: 19 | 20 | **General Usage** 21 | ```go 22 | // common client interface 23 | var flowClient access.Client 24 | 25 | // initialize an http emulator client 26 | flowClient, err := http.NewClient(http.EmulatorHost) 27 | 28 | // initialize a gPRC emulator client 29 | flowClient, err = grpc.NewClient(grpc.EmulatorHost) 30 | ``` 31 | 32 | **Transport-Specific Features** 33 | 34 | Rather than using a generic version of the HTTP or gRPC client, 35 | you instantiate a base HTTP or gRPC client to use specific features of either API format. 36 | 37 | For example, use `grpc.NewBaseClient` to set custom gRPC transport credentials. 38 | instantiate the client like so: 39 | ```go 40 | // initialize http specific client 41 | httpClient, err := http.NewBaseClient(http.EMULATOR_URL) 42 | 43 | // initialize grpc specific client 44 | grpcClient, err := grpc.NewBaseClient( 45 | grpc.EMULATOR_URL, 46 | grpcOpts.WithTransportCredentials(insecure.NewCredentials()), 47 | ) 48 | ``` 49 | Read more about this [in the docs](https://docs.onflow.org/flow-go-sdk/). 50 | 51 | ## Development 52 | 53 | ### Testing 54 | The testing suite is using mock network handlers which can be generated 55 | by running the following command in the project root directory: 56 | ``` 57 | make generate 58 | ``` 59 | -------------------------------------------------------------------------------- /access/grpc/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package grpc 20 | 21 | import ( 22 | "fmt" 23 | 24 | "google.golang.org/grpc/status" 25 | ) 26 | 27 | const errorMessagePrefix = "client: " 28 | 29 | func errorMessage(format string, a ...interface{}) string { 30 | return errorMessagePrefix + fmt.Sprintf(format, a...) 31 | } 32 | 33 | // An RPCError is an error returned by an RPC call to an Access API. 34 | // 35 | // An RPC error can be unwrapped to produce the original gRPC error. 36 | type RPCError struct { 37 | GRPCErr error 38 | } 39 | 40 | func newRPCError(gRPCErr error) RPCError { 41 | return RPCError{GRPCErr: gRPCErr} 42 | } 43 | 44 | func (e RPCError) Error() string { 45 | return errorMessage(e.GRPCErr.Error()) 46 | } 47 | 48 | func (e RPCError) Unwrap() error { 49 | return e.GRPCErr 50 | } 51 | 52 | // GRPCStatus returns the gRPC status for this error. 53 | // 54 | // This function satisfies the interface defined in the status.FromError function. 55 | func (e RPCError) GRPCStatus() *status.Status { 56 | s, _ := status.FromError(e.GRPCErr) 57 | return s 58 | } 59 | 60 | const ( 61 | entityBlock = "flow.Block" 62 | entityBlockHeader = "flow.BlockHeader" 63 | entityCollection = "flow.Collection" 64 | entityTransaction = "flow.Transaction" 65 | entityTransactionResult = "flow.TransactionResult" 66 | entityAccount = "flow.Account" 67 | entityEvent = "flow.Event" 68 | entityCadenceValue = "cadence.Value" 69 | ) 70 | 71 | // An EntityToMessageError indicates that an entity could not be converted to a protobuf message. 72 | type EntityToMessageError struct { 73 | Entity string 74 | Err error 75 | } 76 | 77 | func newEntityToMessageError(entity string, err error) EntityToMessageError { 78 | return EntityToMessageError{ 79 | Entity: entity, 80 | Err: err, 81 | } 82 | } 83 | 84 | func (e EntityToMessageError) Error() string { 85 | return errorMessage("failed to construct protobuf message from %s entity: %s", e.Entity, e.Err.Error()) 86 | } 87 | 88 | func (e EntityToMessageError) Unwrap() error { 89 | return e.Err 90 | } 91 | 92 | // A MessageToEntityError indicates that a protobuf message could not be converted to an SDK entity. 93 | type MessageToEntityError struct { 94 | Entity string 95 | Err error 96 | } 97 | 98 | func newMessageToEntityError(entity string, err error) MessageToEntityError { 99 | return MessageToEntityError{ 100 | Entity: entity, 101 | Err: err, 102 | } 103 | } 104 | 105 | func (e MessageToEntityError) Error() string { 106 | return errorMessage("failed to construct %s entity from protobuf value: %s", e.Entity, e.Err.Error()) 107 | } 108 | 109 | func (e MessageToEntityError) Unwrap() error { 110 | return e.Err 111 | } 112 | -------------------------------------------------------------------------------- /access/http/models/model_account.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type Account struct { 12 | Address string `json:"address"` 13 | // Flow balance of the account. 14 | Balance string `json:"balance"` 15 | Keys []AccountPublicKey `json:"keys,omitempty"` 16 | Contracts map[string]string `json:"contracts,omitempty"` 17 | Expandable *AccountExpandable `json:"_expandable"` 18 | Links *Links `json:"_links,omitempty"` 19 | } 20 | -------------------------------------------------------------------------------- /access/http/models/model_account__expandable.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type AccountExpandable struct { 12 | Keys string `json:"keys,omitempty"` 13 | Contracts string `json:"contracts,omitempty"` 14 | } 15 | -------------------------------------------------------------------------------- /access/http/models/model_account_public_key.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type AccountPublicKey struct { 12 | // Index of the public key. 13 | Index string `json:"index"` 14 | // Hex encoded public key. 15 | PublicKey string `json:"public_key"` 16 | SigningAlgorithm *SigningAlgorithm `json:"signing_algorithm"` 17 | HashingAlgorithm *HashingAlgorithm `json:"hashing_algorithm"` 18 | // Current account sequence number. 19 | SequenceNumber string `json:"sequence_number"` 20 | // Weight of the key. 21 | Weight string `json:"weight"` 22 | // Flag indicating whether the key is active or not. 23 | Revoked bool `json:"revoked"` 24 | } 25 | -------------------------------------------------------------------------------- /access/http/models/model_aggregated_signature.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type AggregatedSignature struct { 12 | VerifierSignatures []string `json:"verifier_signatures"` 13 | SignerIds []string `json:"signer_ids"` 14 | } 15 | -------------------------------------------------------------------------------- /access/http/models/model_block.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type Block struct { 12 | Header *BlockHeader `json:"header"` 13 | Payload *BlockPayload `json:"payload,omitempty"` 14 | ExecutionResult *ExecutionResult `json:"execution_result,omitempty"` 15 | Expandable *BlockExpandable `json:"_expandable"` 16 | Links *Links `json:"_links,omitempty"` 17 | BlockStatus string `json:"block_status"` 18 | } 19 | -------------------------------------------------------------------------------- /access/http/models/model_block__expandable.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type BlockExpandable struct { 12 | Payload string `json:"payload,omitempty"` 13 | ExecutionResult string `json:"execution_result,omitempty"` 14 | } 15 | -------------------------------------------------------------------------------- /access/http/models/model_block_events.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | import ( 12 | "time" 13 | ) 14 | 15 | type BlockEvents struct { 16 | BlockId string `json:"block_id,omitempty"` 17 | BlockHeight string `json:"block_height,omitempty"` 18 | BlockTimestamp time.Time `json:"block_timestamp,omitempty"` 19 | Events []Event `json:"events,omitempty"` 20 | Links *Links `json:"_links,omitempty"` 21 | } 22 | -------------------------------------------------------------------------------- /access/http/models/model_block_header.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | import ( 12 | "time" 13 | ) 14 | 15 | type BlockHeader struct { 16 | Id string `json:"id"` 17 | ParentId string `json:"parent_id"` 18 | Height string `json:"height"` 19 | Timestamp time.Time `json:"timestamp"` 20 | ParentVoterSignature string `json:"parent_voter_signature"` 21 | } 22 | -------------------------------------------------------------------------------- /access/http/models/model_block_height.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type BlockHeight struct { 12 | } 13 | -------------------------------------------------------------------------------- /access/http/models/model_block_payload.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type BlockPayload struct { 12 | CollectionGuarantees []CollectionGuarantee `json:"collection_guarantees"` 13 | BlockSeals []BlockSeal `json:"block_seals"` 14 | } 15 | -------------------------------------------------------------------------------- /access/http/models/model_block_seal.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type BlockSeal struct { 12 | BlockId string `json:"block_id"` 13 | ResultId string `json:"result_id"` 14 | FinalState string `json:"final_state"` 15 | AggregatedApprovalSignatures []AggregatedSignature `json:"aggregated_approval_signatures"` 16 | } 17 | -------------------------------------------------------------------------------- /access/http/models/model_chunk.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type Chunk struct { 12 | CollectionIndex string `json:"collection_index"` 13 | StartState string `json:"start_state"` 14 | EventCollection string `json:"event_collection"` 15 | BlockId string `json:"block_id"` 16 | TotalComputationUsed string `json:"total_computation_used"` 17 | NumberOfTransactions string `json:"number_of_transactions"` 18 | Index string `json:"index"` 19 | EndState string `json:"end_state"` 20 | } 21 | -------------------------------------------------------------------------------- /access/http/models/model_collection.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type Collection struct { 12 | Id string `json:"id"` 13 | Transactions []Transaction `json:"transactions,omitempty"` 14 | Expandable *CollectionExpandable `json:"_expandable"` 15 | Links *Links `json:"_links,omitempty"` 16 | } 17 | -------------------------------------------------------------------------------- /access/http/models/model_collection__expandable.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type CollectionExpandable struct { 12 | Transactions []string `json:"transactions,omitempty"` 13 | } 14 | -------------------------------------------------------------------------------- /access/http/models/model_collection_guarantee.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type CollectionGuarantee struct { 12 | CollectionId string `json:"collection_id"` 13 | SignerIndices string `json:"signer_indices"` 14 | Signature string `json:"signature"` 15 | } 16 | -------------------------------------------------------------------------------- /access/http/models/model_error.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type ModelError struct { 12 | Code int32 `json:"code,omitempty"` 13 | Message string `json:"message,omitempty"` 14 | } 15 | -------------------------------------------------------------------------------- /access/http/models/model_event.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type Event struct { 12 | Type_ string `json:"type"` 13 | TransactionId string `json:"transaction_id"` 14 | TransactionIndex string `json:"transaction_index"` 15 | EventIndex string `json:"event_index"` 16 | Payload string `json:"payload"` 17 | } 18 | -------------------------------------------------------------------------------- /access/http/models/model_execution_result.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type ExecutionResult struct { 12 | Id string `json:"id"` 13 | BlockId string `json:"block_id"` 14 | Events []Event `json:"events"` 15 | Chunks []Chunk `json:"chunks,omitempty"` 16 | PreviousResultId string `json:"previous_result_id"` 17 | Links *Links `json:"_links,omitempty"` 18 | } 19 | -------------------------------------------------------------------------------- /access/http/models/model_hashing_algorithm.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type HashingAlgorithm string 12 | 13 | // List of HashingAlgorithm 14 | const ( 15 | SHA2_256_HashingAlgorithm HashingAlgorithm = "SHA2_256" 16 | SHA2_384_HashingAlgorithm HashingAlgorithm = "SHA2_384" 17 | SHA3_256_HashingAlgorithm HashingAlgorithm = "SHA3_256" 18 | SHA3_384_HashingAlgorithm HashingAlgorithm = "SHA3_384" 19 | KMAC128_HashingAlgorithm HashingAlgorithm = "KMAC128" 20 | ) 21 | -------------------------------------------------------------------------------- /access/http/models/model_inline_response_200.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type InlineResponse200 struct { 12 | Value string `json:"value,omitempty"` 13 | } 14 | -------------------------------------------------------------------------------- /access/http/models/model_links.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type Links struct { 12 | Self string `json:"_self,omitempty"` 13 | } 14 | -------------------------------------------------------------------------------- /access/http/models/model_network_parameters.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type NetworkParameters struct { 12 | ChainId string `json:"chain_id"` 13 | } 14 | -------------------------------------------------------------------------------- /access/http/models/model_node_version_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type NodeVersionInfo struct { 12 | Semver string `json:"semver"` 13 | Commit string `json:"commit"` 14 | SporkId string `json:"spork_id"` 15 | ProtocolVersion string `json:"protocol_version"` 16 | SporkRootBlockHeight string `json:"spork_root_block_height"` 17 | NodeRootBlockHeight string `json:"node_root_block_height"` 18 | } 19 | -------------------------------------------------------------------------------- /access/http/models/model_one_of_block_height.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type OneOfBlockHeight struct { 12 | } 13 | -------------------------------------------------------------------------------- /access/http/models/model_proposal_key.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type ProposalKey struct { 12 | Address string `json:"address"` 13 | KeyIndex string `json:"key_index"` 14 | SequenceNumber string `json:"sequence_number"` 15 | } 16 | -------------------------------------------------------------------------------- /access/http/models/model_scripts_body.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type ScriptsBody struct { 12 | // Base64 encoded content of the Cadence script. 13 | Script string `json:"script,omitempty"` 14 | // An array containing arguments each encoded as Base64 passed in the [JSON-Cadence interchange format](https://docs.onflow.org/cadence/json-cadence-spec/). 15 | Arguments []string `json:"arguments,omitempty"` 16 | } 17 | -------------------------------------------------------------------------------- /access/http/models/model_signing_algorithm.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type SigningAlgorithm string 12 | 13 | // List of SigningAlgorithm 14 | const ( 15 | BLSBLS12381_SigningAlgorithm SigningAlgorithm = "BLSBLS12381" 16 | ECDSAP256_SigningAlgorithm SigningAlgorithm = "ECDSAP256" 17 | ECDSA_SECP256K1_SigningAlgorithm SigningAlgorithm = "ECDSASecp256k1" 18 | ) 19 | -------------------------------------------------------------------------------- /access/http/models/model_transaction.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type Transaction struct { 12 | Id string `json:"id"` 13 | // Base64 encoded Cadence script. 14 | Script string `json:"script"` 15 | // Array of Base64 encoded arguments with in [JSON-Cadence interchange format](https://docs.onflow.org/cadence/json-cadence-spec/). 16 | Arguments []string `json:"arguments"` 17 | ReferenceBlockId string `json:"reference_block_id"` 18 | // The limit on the amount of computation a transaction is allowed to preform. 19 | GasLimit string `json:"gas_limit"` 20 | Payer string `json:"payer"` 21 | ProposalKey *ProposalKey `json:"proposal_key"` 22 | Authorizers []string `json:"authorizers"` 23 | PayloadSignatures []TransactionSignature `json:"payload_signatures"` 24 | EnvelopeSignatures []TransactionSignature `json:"envelope_signatures"` 25 | Result *TransactionResult `json:"result,omitempty"` 26 | Expandable *TransactionExpandable `json:"_expandable"` 27 | Links *Links `json:"_links,omitempty"` 28 | } 29 | -------------------------------------------------------------------------------- /access/http/models/model_transaction__expandable.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type TransactionExpandable struct { 12 | Result string `json:"result,omitempty"` 13 | } 14 | -------------------------------------------------------------------------------- /access/http/models/model_transaction_execution.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | // TransactionExecution : This value indicates whether the transaction execution succeded or not, this value should be checked when determining transaction success. 12 | type TransactionExecution string 13 | 14 | // List of TransactionExecution 15 | const ( 16 | PENDING_TransactionExecution TransactionExecution = "Pending" 17 | SUCCESS_TransactionExecution TransactionExecution = "Success" 18 | FAILURE_TransactionExecution TransactionExecution = "Failure" 19 | ) 20 | -------------------------------------------------------------------------------- /access/http/models/model_transaction_result.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type TransactionResult struct { 12 | BlockId string `json:"block_id"` 13 | CollectionId string `json:"collection_id"` 14 | Execution *TransactionExecution `json:"execution,omitempty"` 15 | Status *TransactionStatus `json:"status"` 16 | StatusCode int32 `json:"status_code"` 17 | // Provided transaction error in case the transaction wasn't successful. 18 | ErrorMessage string `json:"error_message"` 19 | ComputationUsed string `json:"computation_used"` 20 | Events []Event `json:"events"` 21 | Links *Links `json:"_links,omitempty"` 22 | } 23 | -------------------------------------------------------------------------------- /access/http/models/model_transaction_result__expandable.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type TransactionResultExpandable struct { 12 | Events string `json:"events,omitempty"` 13 | } 14 | -------------------------------------------------------------------------------- /access/http/models/model_transaction_signature.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type TransactionSignature struct { 12 | Address string `json:"address"` 13 | KeyIndex string `json:"key_index"` 14 | Signature string `json:"signature"` 15 | } 16 | -------------------------------------------------------------------------------- /access/http/models/model_transaction_status.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | // TransactionStatus : This value indicates the state of the transaction execution. Only sealed and expired are final and immutable states. 12 | type TransactionStatus string 13 | 14 | // List of TransactionStatus 15 | const ( 16 | PENDING_TransactionStatus TransactionStatus = "Pending" 17 | FINALIZED_TransactionStatus TransactionStatus = "Finalized" 18 | EXECUTED_TransactionStatus TransactionStatus = "Executed" 19 | SEALED_TransactionStatus TransactionStatus = "Sealed" 20 | EXPIRED_TransactionStatus TransactionStatus = "Expired" 21 | ) 22 | -------------------------------------------------------------------------------- /access/http/models/model_transactions_body.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Access API 3 | * 4 | * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) 5 | * 6 | * API version: 1.0.0 7 | * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) 8 | */ 9 | package models 10 | 11 | type TransactionsBody struct { 12 | // Base64 encoded content of the Cadence script. 13 | Script string `json:"script"` 14 | // An array containing arguments each encoded as Base64 passed in the [JSON-Cadence interchange format](https://docs.onflow.org/cadence/json-cadence-spec/). 15 | Arguments []string `json:"arguments"` 16 | ReferenceBlockId string `json:"reference_block_id"` 17 | // The limit on the amount of computation a transaction is allowed to preform. 18 | GasLimit string `json:"gas_limit"` 19 | Payer string `json:"payer"` 20 | ProposalKey *ProposalKey `json:"proposal_key"` 21 | Authorizers []string `json:"authorizers"` 22 | PayloadSignatures []TransactionSignature `json:"payload_signatures"` 23 | EnvelopeSignatures []TransactionSignature `json:"envelope_signatures"` 24 | } 25 | -------------------------------------------------------------------------------- /account_proof.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import ( 22 | "encoding/hex" 23 | "errors" 24 | "fmt" 25 | "strings" 26 | 27 | "github.com/onflow/go-ethereum/rlp" 28 | ) 29 | 30 | // AccountProofNonceMinLenBytes is the minimum length of account proof nonces in bytes. 31 | const AccountProofNonceMinLenBytes = 32 32 | 33 | var ( 34 | // ErrInvalidNonce is returned when the account proof nonce passed to a function is invalid. 35 | ErrInvalidNonce = errors.New("invalid nonce") 36 | // ErrInvalidAppID is returned when the account proof app ID passed to a function is invalid. 37 | ErrInvalidAppID = errors.New("invalid app ID") 38 | ) 39 | 40 | type canonicalAccountProof struct { 41 | AppID string 42 | Address []byte 43 | Nonce []byte 44 | } 45 | 46 | // EncodeAccountProofMessage creates a new account proof message for singing. The encoded message returned does not include 47 | // the user domain tag. 48 | func EncodeAccountProofMessage(address Address, appID, nonceHex string) ([]byte, error) { 49 | if appID == "" { 50 | return nil, fmt.Errorf("%w: appID can't be empty", ErrInvalidAppID) 51 | } 52 | 53 | nonceBytes, err := hex.DecodeString(strings.TrimPrefix(nonceHex, "0x")) 54 | if err != nil { 55 | return nil, fmt.Errorf("%w: %s", ErrInvalidNonce, err) 56 | } 57 | 58 | if len(nonceBytes) < AccountProofNonceMinLenBytes { 59 | return nil, fmt.Errorf("%w: nonce must be at least %d bytes", ErrInvalidNonce, AccountProofNonceMinLenBytes) 60 | } 61 | 62 | msg, err := rlp.EncodeToBytes(&canonicalAccountProof{ 63 | AppID: appID, 64 | Address: address.Bytes(), 65 | Nonce: nonceBytes, 66 | }) 67 | if err != nil { 68 | return nil, fmt.Errorf("error encoding account proof message: %w", err) 69 | } 70 | 71 | return msg, nil 72 | } 73 | -------------------------------------------------------------------------------- /account_proof_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import ( 22 | "encoding/hex" 23 | "errors" 24 | "testing" 25 | 26 | "github.com/stretchr/testify/assert" 27 | ) 28 | 29 | func TestEncodeAccountProofMessage(t *testing.T) { 30 | type testCase struct { 31 | address Address 32 | nonce string 33 | appID string 34 | expectedResult string 35 | expectedErr error 36 | } 37 | 38 | for name, tc := range map[string]testCase{ 39 | "valid inputs": { 40 | address: HexToAddress("ABC123DEF456"), 41 | nonce: "3037366134636339643564623330316636626239323161663465346131393662", 42 | appID: "AWESOME-APP-ID", 43 | // nolint: lll 44 | expectedResult: "f8398e415745534f4d452d4150502d4944880000abc123def456a03037366134636339643564623330316636626239323161663465346131393662", 45 | }, 46 | "nonce invalid hex": { 47 | address: HexToAddress("ABC123DEF456"), 48 | nonce: "asdf", 49 | appID: "AWESOME-APP-ID", 50 | expectedErr: ErrInvalidNonce, 51 | }, 52 | "nonce too short": { 53 | address: HexToAddress("ABC123DEF456"), 54 | nonce: "222222", 55 | appID: "AWESOME-APP-ID", 56 | expectedErr: ErrInvalidNonce, 57 | }, 58 | "empty app ID": { 59 | address: HexToAddress("ABC123DEF456"), 60 | nonce: "222222", 61 | appID: "", 62 | expectedErr: ErrInvalidAppID, 63 | }, 64 | } { 65 | t.Run(name, func(t *testing.T) { 66 | // Check the output of EncodeAccountProofMessage against a pre-generated message from the flow-js-sdk 67 | msg, err := EncodeAccountProofMessage(tc.address, tc.appID, tc.nonce) 68 | if tc.expectedErr != nil { 69 | assert.True(t, errors.Is(err, tc.expectedErr)) 70 | } else { 71 | assert.NoError(t, err) 72 | assert.Equal(t, tc.expectedResult, hex.EncodeToString(msg)) 73 | } 74 | }) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /account_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import ( 22 | "crypto/rand" 23 | "fmt" 24 | "testing" 25 | 26 | "github.com/stretchr/testify/assert" 27 | 28 | "github.com/onflow/flow-go-sdk/crypto" 29 | ) 30 | 31 | func generateKey() crypto.PrivateKey { 32 | seed := make([]byte, 32) 33 | _, _ = rand.Read(seed) 34 | 35 | privateKey, _ := crypto.GeneratePrivateKey(crypto.ECDSA_P256, seed) 36 | return privateKey 37 | } 38 | 39 | func TestAccountKey(t *testing.T) { 40 | 41 | t.Run("Valid", func(t *testing.T) { 42 | privateKey := generateKey() 43 | weight := 500 44 | index := uint32(0) 45 | seq := uint64(1) 46 | 47 | key := AccountKey{ 48 | Index: index, 49 | PublicKey: privateKey.PublicKey(), 50 | SigAlgo: privateKey.Algorithm(), 51 | HashAlgo: crypto.SHA3_256, 52 | Weight: weight, 53 | SequenceNumber: seq, 54 | Revoked: false, 55 | } 56 | 57 | assert.True(t, privateKey.PublicKey().Equals(key.PublicKey)) 58 | assert.Equal(t, privateKey.Algorithm(), key.SigAlgo) 59 | assert.Equal(t, crypto.SHA3_256, key.HashAlgo) 60 | assert.Equal(t, key.Weight, weight) 61 | assert.Equal(t, key.SequenceNumber, seq) 62 | assert.Equal(t, key.Index, index) 63 | 64 | assert.NoError(t, key.Validate()) 65 | }) 66 | 67 | t.Run("Invalid Key Weights", func(t *testing.T) { 68 | privateKey := generateKey() 69 | key := AccountKey{ 70 | SigAlgo: privateKey.Algorithm(), 71 | PublicKey: privateKey.PublicKey(), 72 | HashAlgo: crypto.SHA3_256, 73 | } 74 | 75 | key.SetWeight(5000) 76 | assert.EqualError(t, key.Validate(), "invalid key weight: 5000") 77 | 78 | key.SetWeight(-1) 79 | assert.EqualError(t, key.Validate(), "invalid key weight: -1") 80 | }) 81 | 82 | t.Run("Key Algorithm", func(t *testing.T) { 83 | hashAlgos := []crypto.HashAlgorithm{ 84 | crypto.UnknownHashAlgorithm, 85 | crypto.SHA2_256, 86 | crypto.SHA2_384, 87 | crypto.SHA3_256, 88 | crypto.SHA3_384, 89 | crypto.Keccak256, 90 | } 91 | signAlgos := []crypto.SignatureAlgorithm{ 92 | crypto.UnknownSignatureAlgorithm, 93 | crypto.ECDSA_P256, 94 | crypto.ECDSA_secp256k1, 95 | } 96 | 97 | validPairs := map[crypto.SignatureAlgorithm]map[crypto.HashAlgorithm]bool{ 98 | crypto.ECDSA_P256: map[crypto.HashAlgorithm]bool{ 99 | crypto.SHA2_256: true, 100 | crypto.SHA3_256: true, 101 | }, 102 | crypto.ECDSA_secp256k1: map[crypto.HashAlgorithm]bool{ 103 | crypto.SHA2_256: true, 104 | crypto.SHA3_256: true, 105 | }, 106 | } 107 | 108 | key := AccountKey{} 109 | for _, s := range signAlgos { 110 | for _, h := range hashAlgos { 111 | key.SetSigAlgo(s) 112 | key.SetHashAlgo(h) 113 | if validPairs[s][h] { 114 | assert.NoError(t, key.Validate()) 115 | } else { 116 | assert.EqualError(t, key.Validate(), fmt.Sprintf("signing algorithm (%s) and hashing algorithm (%s) are not a valid pair for a Flow account key", s, h)) 117 | } 118 | } 119 | } 120 | }) 121 | } 122 | -------------------------------------------------------------------------------- /block.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import ( 22 | "time" 23 | ) 24 | 25 | // Block is a set of state mutations applied to the Flow blockchain. 26 | type Block struct { 27 | BlockHeader 28 | BlockPayload 29 | } 30 | 31 | // BlockHeader is a summary of a full block. 32 | type BlockHeader struct { 33 | ID Identifier 34 | ParentID Identifier 35 | Height uint64 36 | Timestamp time.Time 37 | Status BlockStatus 38 | PayloadHash []byte 39 | View uint64 40 | ParentVoterSigData []byte 41 | ProposerID Identifier 42 | ProposerSigData []byte 43 | ChainID Identifier 44 | ParentVoterIndices []byte 45 | LastViewTimeoutCertificate TimeoutCertificate 46 | ParentView uint64 47 | } 48 | 49 | type TimeoutCertificate struct { 50 | View uint64 51 | HighQCViews []uint64 52 | HighestQC QuorumCertificate 53 | SignerIndices []byte 54 | SigData []byte 55 | } 56 | 57 | type QuorumCertificate struct { 58 | View uint64 59 | BlockID Identifier 60 | SignerIndices []byte 61 | SigData []byte 62 | } 63 | 64 | // BlockStatus represents the status of a block. 65 | type BlockStatus int 66 | 67 | const ( 68 | // BlockStatusUnknown indicates that the block status is not known. 69 | BlockStatusUnknown BlockStatus = iota 70 | // BlockStatusFinalized is the status of a finalized block. 71 | BlockStatusFinalized 72 | // BlockStatusSealed is the status of a sealed block. 73 | BlockStatusSealed 74 | ) 75 | 76 | func BlockStatusFromString(s string) BlockStatus { 77 | switch s { 78 | case "BLOCK_FINALIZED": 79 | return BlockStatusFinalized 80 | case "BLOCK_SEALED": 81 | return BlockStatusSealed 82 | default: 83 | return BlockStatusUnknown 84 | } 85 | } 86 | 87 | // BlockPayload is the full contents of a block. 88 | // 89 | // A payload contains the collection guarantees and seals for a block. 90 | type BlockPayload struct { 91 | CollectionGuarantees []*CollectionGuarantee 92 | Seals []*BlockSeal 93 | Signatures [][]byte 94 | ExecutionReceiptMetaList []*ExecutionReceiptMeta 95 | ExecutionResultsList []*ExecutionResult 96 | ProtocolStateID Identifier 97 | } 98 | 99 | type ExecutionReceiptMeta struct { 100 | ExecutorID Identifier 101 | ResultID Identifier 102 | Spocks [][]byte 103 | ExecutorSignature []byte 104 | } 105 | 106 | // BlockSeal is the attestation by verification nodes that the transactions in a previously 107 | // executed block have been verified. 108 | type BlockSeal struct { 109 | // The ID of the block this Seal refers to (which will be of lower height than this block) 110 | BlockID Identifier 111 | 112 | // The ID of the execution receipt generated by the Verifier nodes; the work of verifying a 113 | // block produces the same receipt among all verifying nodes 114 | ExecutionReceiptID Identifier 115 | ExecutionReceiptSignatures [][]byte 116 | ResultApprovalSignatures [][]byte 117 | FinalState []byte 118 | ResultId Identifier 119 | AggregatedApprovalSigs []*AggregatedSignature 120 | } 121 | 122 | type AggregatedSignature struct { 123 | VerifierSignatures [][]byte 124 | SignerIds []Identifier 125 | } 126 | 127 | // BlockDigest holds lightweight block information which includes only block id, block height and block timestamp 128 | type BlockDigest struct { 129 | BlockID Identifier 130 | Height uint64 131 | Timestamp time.Time 132 | } 133 | -------------------------------------------------------------------------------- /check-headers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | files=$(find . -name \*.go -type f -print0 | xargs -0 grep -L -E '(Licensed under the Apache License)|(generated (from|by))') 4 | if [ -n "$files" ]; then 5 | echo "Missing license header in:" 6 | echo "$files" 7 | exit 1 8 | fi 9 | -------------------------------------------------------------------------------- /client/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // Package client provides grpc API implementation. 20 | // 21 | // Deprecated: client is deprecated use access package instead. 22 | package client 23 | 24 | import ( 25 | "github.com/onflow/flow/protobuf/go/flow/access" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/access/grpc" 29 | ) 30 | 31 | // New creates an gRPC client exposing all the common access APIs. 32 | // 33 | // Deprecated: use grpc.NewClient instead. 34 | // Read more in the migration guide: 35 | // https://github.com/onflow/flow-go-sdk/blob/main/docs/migration-v0.25.0.md 36 | var New = grpc.NewBaseClient 37 | 38 | // NewFromRPCClient initializes a Flow client using a pre-configured gRPC provider. 39 | // 40 | // Deprecated: use grpc.NewFromRPCClient instead. 41 | // Read more in the migration guide: 42 | // https://github.com/onflow/flow-go-sdk/blob/main/docs/migration-v0.25.0.md 43 | var NewFromRPCClient = grpc.NewFromRPCClient 44 | 45 | // Client is an gRPC client implementing all API access functions. 46 | // 47 | // Deprecated: migrate to access.Client instead or use grpc.BaseClient for grpc specific operations. 48 | // Read more in the migration guide: 49 | // https://github.com/onflow/flow-go-sdk/blob/main/docs/migration-v0.25.0.md 50 | type Client = grpc.BaseClient 51 | 52 | // An RPCClient is an RPC client for the Flow Access API. 53 | // 54 | // Deprecated: use access.client instead. 55 | // Read more in the migration guide: 56 | // https://github.com/onflow/flow-go-sdk/blob/main/docs/migration-v0.25.0.md 57 | type RPCClient interface { 58 | access.AccessAPIClient 59 | } 60 | 61 | // BlockEvents are the events that occurred in a specific block. 62 | // 63 | // Deprecated: use flow.BlockEvents instead. 64 | // Read more in the migration guide: 65 | // https://github.com/onflow/flow-go-sdk/blob/main/docs/migration-v0.25.0.md 66 | type BlockEvents = flow.BlockEvents 67 | 68 | // EventRangeQuery defines a query for Flow events. 69 | // 70 | // Deprecated: use grpc.EventRangeQuery instead. 71 | // Read more in the migration guide: 72 | // https://github.com/onflow/flow-go-sdk/blob/main/docs/migration-v0.25.0.md 73 | type EventRangeQuery = grpc.EventRangeQuery 74 | 75 | // RPCError is an error returned by an RPC call to an Access API. 76 | // 77 | // Deprecated: use grpc.RPCError instead. 78 | // Read more in the migration guide: 79 | // https://github.com/onflow/flow-go-sdk/blob/main/docs/migration-v0.25.0.md 80 | type RPCError = grpc.RPCError 81 | -------------------------------------------------------------------------------- /collection.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | // A Collection is a list of transactions bundled together for inclusion in a block. 22 | type Collection struct { 23 | TransactionIDs []Identifier 24 | } 25 | 26 | // ID returns the canonical SHA3-256 hash of this collection. 27 | func (c Collection) ID() Identifier { 28 | return HashToID(defaultEntityHasher.ComputeHash(c.Encode())) 29 | } 30 | 31 | // Encode returns the canonical RLP byte representation of this collection. 32 | func (c Collection) Encode() []byte { 33 | transactionIDs := make([][]byte, len(c.TransactionIDs)) 34 | for i, id := range c.TransactionIDs { 35 | transactionIDs[i] = id.Bytes() 36 | } 37 | 38 | temp := struct { 39 | TransactionIDs [][]byte 40 | }{ 41 | TransactionIDs: transactionIDs, 42 | } 43 | return mustRLPEncode(&temp) 44 | } 45 | 46 | // A CollectionGuarantee is an attestation signed by the nodes that have guaranteed a collection. 47 | type CollectionGuarantee struct { 48 | CollectionID Identifier 49 | ReferenceBlockID Identifier 50 | Signature []byte 51 | SignerIndices []byte 52 | } 53 | 54 | type FullCollection struct { 55 | Transactions []*Transaction 56 | } 57 | 58 | // Light returns the light, reference-only version of the collection. 59 | func (c FullCollection) Light() Collection { 60 | lc := Collection{TransactionIDs: make([]Identifier, 0, len(c.Transactions))} 61 | for _, tx := range c.Transactions { 62 | lc.TransactionIDs = append(lc.TransactionIDs, tx.ID()) 63 | } 64 | return lc 65 | } 66 | 67 | func (c FullCollection) ID() Identifier { 68 | return c.Light().ID() 69 | } 70 | -------------------------------------------------------------------------------- /crypto/awskms/awskms.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // Package awskms provides a AWS Key Management Service (KMS) 20 | // implementation of the crypto.Signer interface. 21 | // 22 | // The documentation for AWS KMS can be found here: https://docs.aws.amazon.com/kms/index.html 23 | package awskms 24 | 25 | import ( 26 | "context" 27 | "encoding/pem" 28 | "fmt" 29 | "strings" 30 | 31 | "github.com/aws/aws-sdk-go-v2/aws" 32 | kms "github.com/aws/aws-sdk-go-v2/service/kms" 33 | "github.com/aws/aws-sdk-go-v2/service/kms/types" 34 | 35 | "github.com/onflow/flow-go-sdk/crypto" 36 | ) 37 | 38 | const ( 39 | resouceArnFormat = "arn:aws:kms:%s:%s:key/%s" 40 | ) 41 | 42 | // Client is a client for interacting with the AWS KMS API 43 | // using types native to the Flow Go SDK. 44 | type Client struct { 45 | client *kms.Client 46 | } 47 | 48 | // Key is a reference to a AWS KMS asymmetric signing key. 49 | type Key struct { 50 | Region string `json:"region"` 51 | Account string `json:"account"` 52 | KeyID string `json:"keyId"` 53 | } 54 | 55 | // ARN returns the KMS arn for this KMS key. 56 | // For cross account key access, you need to pass the arn instead of just the keyID. 57 | func (k Key) ARN() string { 58 | return fmt.Sprintf( 59 | resouceArnFormat, 60 | k.Region, 61 | k.Account, 62 | k.KeyID, 63 | ) 64 | } 65 | 66 | // Example ARN format: "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab" 67 | func KeyFromResourceARN(resourceARN string) (Key, error) { 68 | key := Key{} 69 | spiltedARN := strings.Split(resourceARN, ":") 70 | if len(spiltedARN) != 6 { 71 | return key, fmt.Errorf("awskms: wrong format for the resourceARN: %s", resourceARN) 72 | } 73 | 74 | key.Region, key.Account = spiltedARN[3], spiltedARN[4] 75 | key.KeyID = strings.Split(spiltedARN[5], "/")[1] 76 | 77 | return key, nil 78 | } 79 | 80 | // NewClient creates a new AWS KMS client. 81 | func NewClient(cfg aws.Config) *Client { 82 | client := kms.NewFromConfig(cfg) 83 | return &Client{ 84 | client: client, 85 | } 86 | } 87 | 88 | // GetPublicKey fetches the public key portion of a KMS asymmetric signing key. 89 | // 90 | // KMS keys of the type `KeySpecEccNistP256` and `KeySpecEccSecgP256k1` 91 | // are the only keys supported by the SDK. 92 | // 93 | // Ref: https://github.com/aws/aws-sdk-go-v2/blob/main/service/kms/api_op_GetPublicKey.go 94 | func (c *Client) GetPublicKey(ctx context.Context, key Key) (crypto.PublicKey, crypto.HashAlgorithm, error) { 95 | 96 | keyArn := key.ARN() 97 | request := &kms.GetPublicKeyInput{ 98 | KeyId: &keyArn, 99 | } 100 | 101 | result, err := c.client.GetPublicKey(ctx, request) 102 | if err != nil { 103 | return nil, 104 | crypto.UnknownHashAlgorithm, 105 | fmt.Errorf("awskms: failed to fetch public key from KMS API: %w", err) 106 | } 107 | 108 | sigAlgo := parseSignatureAlgorithm(result.KeySpec) 109 | if sigAlgo == crypto.UnknownSignatureAlgorithm { 110 | return nil, 111 | crypto.UnknownHashAlgorithm, 112 | fmt.Errorf( 113 | "awskms: unsupported signature algorithm %s", 114 | result.KeySpec, 115 | ) 116 | } 117 | 118 | hashAlgo := parseHashAlgorithm(result.KeySpec) 119 | if hashAlgo == crypto.UnknownHashAlgorithm { 120 | return nil, 121 | crypto.UnknownHashAlgorithm, 122 | fmt.Errorf( 123 | "awskms: unsupported hash algorithm %s", 124 | result.KeySpec, 125 | ) 126 | } 127 | 128 | publicKeyBytes := result.PublicKey 129 | block := &pem.Block{ 130 | Type: "PUBLIC KEY", 131 | Bytes: publicKeyBytes, 132 | } 133 | publicKeyPEM := pem.EncodeToMemory(block) 134 | publicKey, err := crypto.DecodePublicKeyPEM(sigAlgo, string(publicKeyPEM)) 135 | 136 | if err != nil { 137 | return nil, 138 | crypto.UnknownHashAlgorithm, 139 | fmt.Errorf("awskms: failed to parse PEM public key: %w", err) 140 | } 141 | 142 | return publicKey, hashAlgo, nil 143 | } 144 | 145 | // KMSClient gives access to the kms.Client 146 | func (c *Client) KMSClient() *kms.Client { 147 | return c.client 148 | } 149 | 150 | // ParseSignatureAlgorithm returns the `SignatureAlgorithm` corresponding to the input KMS key type. 151 | func parseSignatureAlgorithm(keySpec types.KeySpec) crypto.SignatureAlgorithm { 152 | if keySpec == types.KeySpecEccNistP256 { 153 | return crypto.ECDSA_P256 154 | } 155 | 156 | if keySpec == types.KeySpecEccSecgP256k1 { 157 | return crypto.ECDSA_secp256k1 158 | } 159 | 160 | return crypto.UnknownSignatureAlgorithm 161 | } 162 | 163 | // ParseHashAlgorithm returns the `HashAlgorithm` corresponding to the input KMS key type. 164 | func parseHashAlgorithm(keySpec types.KeySpec) crypto.HashAlgorithm { 165 | if keySpec == types.KeySpecEccNistP256 || keySpec == types.KeySpecEccSecgP256k1 { 166 | return crypto.SHA2_256 167 | } 168 | 169 | // the function can be extended to return SHA3-256 if it becomes supported by KMS. 170 | return crypto.UnknownHashAlgorithm 171 | } 172 | -------------------------------------------------------------------------------- /crypto/awskms/awskms_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package awskms_test 20 | 21 | import ( 22 | "context" 23 | "os" 24 | "testing" 25 | 26 | "github.com/aws/aws-sdk-go-v2/config" 27 | "github.com/stretchr/testify/assert" 28 | "github.com/stretchr/testify/require" 29 | 30 | "github.com/onflow/flow-go-sdk/crypto" 31 | "github.com/onflow/flow-go-sdk/crypto/awskms" 32 | ) 33 | 34 | func TestKeyFromARN(t *testing.T) { 35 | key := awskms.Key{ 36 | Region: "us-west-2", 37 | Account: "111122223333", 38 | KeyID: "1234abcd-12ab-34cd-56ef-1234567890ab", 39 | } 40 | 41 | resourceARN := key.ARN() 42 | 43 | assert.Equal(t, resourceARN, "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab") 44 | 45 | keyFromResourceARN, err := awskms.KeyFromResourceARN(resourceARN) 46 | require.NoError(t, err) 47 | 48 | assert.Equal(t, key, keyFromResourceARN) 49 | } 50 | 51 | // TestManualKMSSigning tests signing using a KMS key. 52 | // This tests requires access to KMS and cannot be run by CI. 53 | // Please use this test manually by commenting t.Skip(), 54 | // when making any change to the KMS signing code. 55 | // AWS Credentials are required to run this test. 56 | func TestManualKMSSigning(t *testing.T) { 57 | // to comment when testing manually 58 | t.Skip() 59 | 60 | // KMS_TEST_KEY_RESOURCE_ARN is an env var containing the resource ARN of a KMS key you 61 | // have permissions to use. 62 | //os.Setenv("KMS_TEST_KEY_RESOURCE_ARN", "") 63 | id := os.Getenv(`KMS_TEST_KEY_RESOURCE_ARN`) 64 | t.Log(id) 65 | key, err := awskms.KeyFromResourceARN(id) 66 | require.NoError(t, err) 67 | 68 | // initialize the client 69 | ctx := context.Background() 70 | // AWS SDK uses the default credential chain to find the credentials. 71 | // You either need to export env variables, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN 72 | // or to install the aws kms CLI tool and set up your credentials (for instance in ~/.aws/credentials) 73 | //os.Setenv("AWS_ACCESS_KEY_ID", "") 74 | //os.Setenv("AWS_SECRET_ACCESS_KEY", "") 75 | //os.Setenv("AWS_SESSION_TOKEN", "") 76 | 77 | defaultCfg, err := config.LoadDefaultConfig(ctx) 78 | require.NoError(t, err) 79 | defaultCfg.Region = key.Region 80 | 81 | cl := awskms.NewClient(defaultCfg) 82 | require.NoError(t, err) 83 | 84 | // Get the public key 85 | pk, _, err := cl.GetPublicKey(ctx, key) 86 | require.NoError(t, err) 87 | 88 | // signer 89 | signer, err := cl.SignerForKey(ctx, key) 90 | require.NoError(t, err) 91 | 92 | signAndVerify := func(t *testing.T, msgLen int) { 93 | // Sign 94 | msg := make([]byte, msgLen) 95 | sig, err := signer.Sign(msg) 96 | require.NoError(t, err) 97 | 98 | // verify 99 | hasher := crypto.NewSHA2_256() 100 | valid, err := pk.Verify(sig, msg, hasher) 101 | require.NoError(t, err) 102 | assert.True(t, valid) 103 | } 104 | 105 | kmsPreHashLimit := 4096 106 | // AWS KMS supports signing messages without prehashing 107 | // up to 4096 bytes 108 | t.Run("short message", func(t *testing.T) { 109 | signAndVerify(t, kmsPreHashLimit) 110 | }) 111 | 112 | // google KMS does not support signing messages longer than 4096 113 | // without prehashing 114 | t.Run("long message", func(t *testing.T) { 115 | signAndVerify(t, kmsPreHashLimit+1) 116 | }) 117 | 118 | } 119 | -------------------------------------------------------------------------------- /crypto/awskms/signer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package awskms 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | kms "github.com/aws/aws-sdk-go-v2/service/kms" 26 | "github.com/aws/aws-sdk-go-v2/service/kms/types" 27 | 28 | "github.com/onflow/flow-go-sdk/crypto" 29 | "github.com/onflow/flow-go-sdk/crypto/internal" 30 | ) 31 | 32 | var _ crypto.Signer = (*Signer)(nil) 33 | 34 | // Signer is a AWS KMS implementation of crypto.Signer. 35 | type Signer struct { 36 | ctx context.Context 37 | client *kms.Client 38 | key Key 39 | // ECDSA is the only algorithm supported by this package. The signature algorithm 40 | // therefore represents the elliptic curve used. The curve is needed to parse the kms signature. 41 | curve crypto.SignatureAlgorithm 42 | // public key for easier access 43 | publicKey crypto.PublicKey 44 | // Hash algorithm associated to the KMS signing key 45 | hashAlgo crypto.HashAlgorithm 46 | } 47 | 48 | // SignerForKey returns a new AWS KMS signer for an asymmetric signing key version. 49 | // 50 | // Only ECDSA keys on P-256 and secp256k1 curves and SHA2-256 are supported. 51 | func (c *Client) SignerForKey( 52 | ctx context.Context, 53 | key Key, 54 | ) (*Signer, error) { 55 | pk, hashAlgo, err := c.GetPublicKey(ctx, key) 56 | if err != nil { 57 | return nil, err 58 | } 59 | 60 | return &Signer{ 61 | ctx: ctx, 62 | client: c.client, 63 | key: key, 64 | curve: pk.Algorithm(), 65 | publicKey: pk, 66 | hashAlgo: hashAlgo, 67 | }, nil 68 | } 69 | 70 | // Sign signs the given message using the KMS signing key for this signer. 71 | // 72 | // Reference: https://github.com/aws/aws-sdk-go-v2/blob/main/service/kms/api_op_Sign.go 73 | func (s *Signer) Sign(message []byte) ([]byte, error) { 74 | 75 | keyArn := s.key.ARN() 76 | // AWS KMS supports signing messages without pre-hashing 77 | // up to 4096 bytes. Beyond that limit, messages must be prehashed outside KMS. 78 | kmsPreHashLimit := 4096 79 | var request *kms.SignInput 80 | 81 | if len(message) <= kmsPreHashLimit { 82 | request = &kms.SignInput{ 83 | KeyId: &keyArn, 84 | Message: message, 85 | SigningAlgorithm: types.SigningAlgorithmSpecEcdsaSha256, 86 | } 87 | } else { 88 | // this is guaranteed to only return supported hash algos by KMS 89 | hasher, err := crypto.NewHasher(s.hashAlgo) 90 | if err != nil { 91 | return nil, fmt.Errorf("awskms: failed to sign: %w", err) 92 | } 93 | // pre-hash outside KMS 94 | hash := hasher.ComputeHash(message) 95 | // indicate the MessageType is digest 96 | request = &kms.SignInput{ 97 | KeyId: &keyArn, 98 | Message: hash, 99 | SigningAlgorithm: types.SigningAlgorithmSpecEcdsaSha256, 100 | MessageType: types.MessageTypeDigest, 101 | } 102 | } 103 | result, err := s.client.Sign(s.ctx, request) 104 | if err != nil { 105 | return nil, fmt.Errorf("awskms: failed to sign: %w", err) 106 | } 107 | sig, err := internal.ParseECDSASignature(result.Signature, s.curve) 108 | if err != nil { 109 | return nil, fmt.Errorf("awskms: failed to parse signature: %w", err) 110 | } 111 | return sig, nil 112 | } 113 | 114 | func (s *Signer) PublicKey() crypto.PublicKey { 115 | return s.publicKey 116 | } 117 | -------------------------------------------------------------------------------- /crypto/cloudkms/cloudkms_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package cloudkms_test 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | "os" 25 | "os/exec" 26 | "regexp" 27 | "testing" 28 | 29 | "github.com/stretchr/testify/assert" 30 | "github.com/stretchr/testify/require" 31 | 32 | "github.com/onflow/flow-go-sdk/crypto" 33 | "github.com/onflow/flow-go-sdk/crypto/cloudkms" 34 | ) 35 | 36 | func TestKeyFromResourceID(t *testing.T) { 37 | key := cloudkms.Key{ 38 | ProjectID: "my-project", 39 | LocationID: "global", 40 | KeyRingID: "flow", 41 | KeyID: "my-account", 42 | KeyVersion: "1", 43 | } 44 | 45 | resourceID := key.ResourceID() 46 | 47 | assert.Equal(t, resourceID, "projects/my-project/locations/global/keyRings/flow/cryptoKeys/my-account/cryptoKeyVersions/1") 48 | 49 | keyFromResourceID, err := cloudkms.KeyFromResourceID(resourceID) 50 | require.NoError(t, err) 51 | 52 | assert.Equal(t, key, keyFromResourceID) 53 | } 54 | 55 | // gcloudApplicationSignin signs in as an application user using gcloud command line tool 56 | // currently assumes gcloud is already installed on the machine 57 | // will by default pop a browser window to sign in 58 | func gcloudApplicationSignin(kms cloudkms.Key) error { 59 | googleAppCreds := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") 60 | if len(googleAppCreds) > 0 { 61 | return nil 62 | } 63 | 64 | proj := kms.ProjectID 65 | if len(proj) == 0 { 66 | return fmt.Errorf( 67 | "could not get GOOGLE_APPLICATION_CREDENTIALS, no google service account JSON provided but private key type is KMS", 68 | ) 69 | } 70 | 71 | loginCmd := exec.Command("gcloud", "auth", "application-default", "login", fmt.Sprintf("--project=%s", proj)) 72 | 73 | output, err := loginCmd.CombinedOutput() 74 | if err != nil { 75 | return fmt.Errorf("Failed to run %q: %s\n", loginCmd.String(), err) 76 | } 77 | 78 | squareBracketRegex := regexp.MustCompile(`(?s)\[(.*)\]`) 79 | regexResult := squareBracketRegex.FindAllStringSubmatch(string(output), -1) 80 | // Should only be one value. Second index since first index contains the square brackets 81 | googleApplicationCreds := regexResult[0][1] 82 | 83 | os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", googleApplicationCreds) 84 | 85 | return nil 86 | } 87 | 88 | // TestManualKMSSigning tests signing using a KMS key. 89 | // This tests requires access to KMS and cannot be run by CI. 90 | // Please use this test manually by commenting t.Skip(), 91 | // when making any change to the KMS signing code. 92 | // This test assumes gcloud CLI is already installed on 93 | // your machine. 94 | func TestManualKMSSigning(t *testing.T) { 95 | // to comment when testing manually 96 | t.Skip() 97 | 98 | // KMS_TEST_KEY_RESOURCE_ID is an env var containing the resource ID of a KMS key you 99 | // have permissions to use. 100 | id := os.Getenv(`KMS_TEST_KEY_RESOURCE_ID`) 101 | t.Log(id) 102 | key, err := cloudkms.KeyFromResourceID(id) 103 | require.NoError(t, err) 104 | 105 | // get google kms permission 106 | err = gcloudApplicationSignin(key) 107 | require.NoError(t, err) 108 | 109 | // initialize the client 110 | ctx := context.Background() 111 | cl, err := cloudkms.NewClient(ctx) 112 | require.NoError(t, err) 113 | 114 | // Get the public key 115 | pk, _, err := cl.GetPublicKey(ctx, key) 116 | require.NoError(t, err) 117 | 118 | // signer 119 | signer, err := cl.SignerForKey(ctx, key) 120 | require.NoError(t, err) 121 | 122 | signAndVerify := func(t *testing.T, msgLen int) { 123 | // Sign 124 | msg := make([]byte, msgLen) 125 | sig, err := signer.Sign(msg) 126 | require.NoError(t, err) 127 | 128 | // verify 129 | hasher := crypto.NewSHA2_256() 130 | valid, err := pk.Verify(sig, msg, hasher) 131 | require.NoError(t, err) 132 | assert.True(t, valid) 133 | } 134 | 135 | kmsPreHashLimit := 65536 136 | // google KMS supports signing messages without prehashing 137 | // up to 65536 bytes 138 | t.Run("short message", func(t *testing.T) { 139 | signAndVerify(t, kmsPreHashLimit) 140 | }) 141 | 142 | // google KMS does not support signing messages longer than 65536 143 | // without prehashing 144 | t.Run("long message", func(t *testing.T) { 145 | signAndVerify(t, kmsPreHashLimit+1) 146 | }) 147 | 148 | } 149 | -------------------------------------------------------------------------------- /crypto/cloudkms/signer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package cloudkms 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | "hash/crc32" 25 | 26 | kms "cloud.google.com/go/kms/apiv1" 27 | "cloud.google.com/go/kms/apiv1/kmspb" 28 | "google.golang.org/protobuf/types/known/wrapperspb" 29 | 30 | "github.com/onflow/flow-go-sdk/crypto" 31 | "github.com/onflow/flow-go-sdk/crypto/internal" 32 | ) 33 | 34 | var _ crypto.Signer = (*Signer)(nil) 35 | 36 | // Signer is a Google Cloud KMS implementation of crypto.Signer. 37 | type Signer struct { 38 | ctx context.Context 39 | client *kms.KeyManagementClient 40 | key Key 41 | // ECDSA is the only algorithm supported by this package. The signature algorithm 42 | // therefore represents the elliptic curve used. The curve is needed to parse the kms signature. 43 | curve crypto.SignatureAlgorithm 44 | // public key for easier access 45 | publicKey crypto.PublicKey 46 | // Hash algorithm associated to the KMS signing key 47 | hashAlgo crypto.HashAlgorithm 48 | } 49 | 50 | // SignerForKey returns a new Google Cloud KMS signer for an asymmetric signing key version. 51 | // 52 | // Only ECDSA keys on P-256 and secp256k1 curves and SHA2-256 are supported. 53 | func (c *Client) SignerForKey( 54 | ctx context.Context, 55 | key Key, 56 | ) (*Signer, error) { 57 | pk, hashAlgo, err := c.GetPublicKey(ctx, key) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | return &Signer{ 63 | ctx: ctx, 64 | client: c.client, 65 | key: key, 66 | curve: pk.Algorithm(), 67 | publicKey: pk, 68 | hashAlgo: hashAlgo, 69 | }, nil 70 | } 71 | 72 | // Sign signs the given message using the KMS signing key for this signer. 73 | // 74 | // Reference: https://cloud.google.com/kms/docs/create-validate-signatures 75 | func (s *Signer) Sign(message []byte) ([]byte, error) { 76 | 77 | // Google KMS supports signing messages without pre-hashing 78 | // up to 65536 bytes. Beyond that limit, messages must be 79 | // prehashed outside KMS. 80 | kmsPreHashLimit := 65536 81 | 82 | var request *kmspb.AsymmetricSignRequest 83 | if len(message) <= kmsPreHashLimit { 84 | // hash within KMS 85 | request = &kmspb.AsymmetricSignRequest{ 86 | Name: s.key.ResourceID(), 87 | Data: message, 88 | DataCrc32C: checksum(message), 89 | } 90 | } else { 91 | // this is guaranteed to only return supported hash algos by KMS, 92 | // since `s.hashAlgo` has been checked when the signer object was created. 93 | hasher, err := crypto.NewHasher(s.hashAlgo) 94 | if err != nil { 95 | return nil, fmt.Errorf("cloudkms: failed to sign: %w", err) 96 | } 97 | // pre-hash outside KMS 98 | hash := hasher.ComputeHash(message) 99 | request = &kmspb.AsymmetricSignRequest{ 100 | Name: s.key.ResourceID(), 101 | Digest: getDigest(s.hashAlgo, hash), 102 | DigestCrc32C: checksum(hash), 103 | } 104 | } 105 | result, err := s.client.AsymmetricSign(s.ctx, request) 106 | if err != nil { 107 | return nil, fmt.Errorf("cloudkms: failed to sign: %w", err) 108 | } 109 | sig, err := internal.ParseECDSASignature(result.Signature, s.curve) 110 | if err != nil { 111 | return nil, fmt.Errorf("cloudkms: failed to parse signature: %w", err) 112 | } 113 | return sig, nil 114 | } 115 | 116 | func checksum(data []byte) *wrapperspb.Int64Value { 117 | // compute CRC32 118 | table := crc32.MakeTable(crc32.Castagnoli) 119 | checksum := crc32.Checksum(data, table) 120 | val := wrapperspb.Int64(int64(checksum)) 121 | return val 122 | } 123 | 124 | func (s *Signer) PublicKey() crypto.PublicKey { 125 | return s.publicKey 126 | } 127 | 128 | // returns the Digest structure for the hashing algoroithm and hash value, required by the 129 | // signing prehash request 130 | // This function only covers algorithms supported by KMS. It should be extended 131 | // whenever a new hashing algorithm needs to be supported (for instance SHA3-256) 132 | func getDigest(algo crypto.HashAlgorithm, hash []byte) *kmspb.Digest { 133 | if algo == crypto.SHA2_256 { 134 | return &kmspb.Digest{ 135 | Digest: &kmspb.Digest_Sha256{ 136 | Sha256: hash, 137 | }, 138 | } 139 | } 140 | return nil 141 | } 142 | -------------------------------------------------------------------------------- /crypto/hash.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package crypto 20 | 21 | import ( 22 | "errors" 23 | "fmt" 24 | 25 | "github.com/onflow/crypto" 26 | "github.com/onflow/crypto/hash" 27 | ) 28 | 29 | type Hasher = hash.Hasher 30 | type Hash = hash.Hash 31 | 32 | // HashAlgorithm is an identifier for a hash algorithm. 33 | type HashAlgorithm = hash.HashingAlgorithm 34 | 35 | const ( 36 | UnknownHashAlgorithm HashAlgorithm = hash.UnknownHashingAlgorithm 37 | SHA2_256 = hash.SHA2_256 38 | SHA2_384 = hash.SHA2_384 39 | SHA3_256 = hash.SHA3_256 40 | SHA3_384 = hash.SHA3_384 41 | Keccak256 = hash.Keccak_256 42 | KMAC128 = hash.KMAC128 43 | ) 44 | 45 | // StringToHashAlgorithm converts a string to a HashAlgorithm. 46 | func StringToHashAlgorithm(s string) HashAlgorithm { 47 | switch s { 48 | case SHA2_256.String(): 49 | return SHA2_256 50 | case SHA3_256.String(): 51 | return SHA3_256 52 | case SHA2_384.String(): 53 | return SHA2_384 54 | case SHA3_384.String(): 55 | return SHA3_384 56 | case Keccak256.String(): 57 | return Keccak256 58 | case KMAC128.String(): 59 | return KMAC128 60 | 61 | default: 62 | return UnknownHashAlgorithm 63 | } 64 | } 65 | 66 | // NewHasher initializes and returns a new hasher with the given hash algorithm. 67 | // 68 | // This function returns an error if the hash algorithm is invalid. 69 | // KMAC128 cannot be instantiated with this function. Use `NewKMAC_128` instead. 70 | func NewHasher(algo HashAlgorithm) (Hasher, error) { 71 | switch algo { 72 | case SHA2_256: 73 | return NewSHA2_256(), nil 74 | case SHA2_384: 75 | return NewSHA2_384(), nil 76 | case SHA3_256: 77 | return NewSHA3_256(), nil 78 | case SHA3_384: 79 | return NewSHA3_384(), nil 80 | case Keccak256: 81 | return NewKeccak_256(), nil 82 | case KMAC128: 83 | return nil, errors.New("KMAC128 can't be instantiated with this function") 84 | default: 85 | return nil, fmt.Errorf("invalid hash algorithm %s", algo) 86 | } 87 | } 88 | 89 | // NewSHA2_256 returns a new instance of SHA2-256 hasher. 90 | func NewSHA2_256() Hasher { 91 | return hash.NewSHA2_256() 92 | } 93 | 94 | // NewSHA2_384 returns a new instance of SHA2-384 hasher. 95 | func NewSHA2_384() Hasher { 96 | return hash.NewSHA2_384() 97 | } 98 | 99 | // NewSHA3_256 returns a new instance of SHA3-256 hasher. 100 | func NewSHA3_256() Hasher { 101 | return hash.NewSHA3_256() 102 | } 103 | 104 | // NewSHA3_384 returns a new instance of SHA3-384 hasher. 105 | func NewSHA3_384() Hasher { 106 | return hash.NewSHA3_384() 107 | } 108 | 109 | // NewKeccak_256 returns a new instance of Keccak256 hasher. 110 | func NewKeccak_256() Hasher { 111 | return hash.NewKeccak_256() 112 | } 113 | 114 | // NewKMAC_128 returns a new KMAC instance 115 | // - `key` is the KMAC key (the key size is compared to the security level). 116 | // - `customizer` is the customization string. It can be left empty if no customization 117 | // is required. 118 | // 119 | // NewKeccak_256 returns a new instance of KMAC128 120 | func NewKMAC_128(key []byte, customizer []byte, outputSize int) (Hasher, error) { 121 | return hash.NewKMAC_128(key, customizer, outputSize) 122 | } 123 | 124 | // NewBLSHasher returns a hasher that can be used for BLS signing and verifying. 125 | // It abstracts the complexities of meeting the right conditions of a BLS 126 | // hasher. 127 | // 128 | // The hasher returned is the the expand-message step in the BLS hash-to-curve. 129 | // It uses a xof (extendable output function) based on KMAC128. It therefore has 130 | // a 128-bytes output. 131 | // The `tag` parameter is a domain separation string. 132 | // 133 | // Check https://pkg.go.dev/github.com/onflow/crypto#NewExpandMsgXOFKMAC128 for 134 | // more info on the hasher generation underneath. 135 | func NewBLSHasher(tag string) hash.Hasher { 136 | return crypto.NewExpandMsgXOFKMAC128(tag) 137 | } 138 | -------------------------------------------------------------------------------- /crypto/internal/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package internal 19 | 20 | import ( 21 | "encoding/asn1" 22 | "fmt" 23 | "math/big" 24 | 25 | "github.com/onflow/flow-go-sdk/crypto" 26 | ) 27 | 28 | // ParseECDSASignature parses an ECDSA asn1 structure (R,S) into a slice of bytes as required by the `Siger.Sign` method. 29 | func ParseECDSASignature(kmsSignature []byte, curve crypto.SignatureAlgorithm) ([]byte, error) { 30 | var parsedSig struct{ R, S *big.Int } 31 | if _, err := asn1.Unmarshal(kmsSignature, &parsedSig); err != nil { 32 | return nil, fmt.Errorf("asn1.Unmarshal: %w", err) 33 | } 34 | 35 | curveOrderLen := curveOrder(curve) 36 | signature := make([]byte, 2*curveOrderLen) 37 | 38 | // left pad R and S with zeroes 39 | rBytes := parsedSig.R.Bytes() 40 | sBytes := parsedSig.S.Bytes() 41 | copy(signature[curveOrderLen-len(rBytes):], rBytes) 42 | copy(signature[len(signature)-len(sBytes):], sBytes) 43 | 44 | return signature, nil 45 | } 46 | 47 | // returns the curve order size in bytes (used to pad R and S of the ECDSA signature) 48 | // Only P-256 and secp256k1 are supported. The calling function should make sure 49 | // the function is only called with one of the 2 curves. 50 | func curveOrder(curve crypto.SignatureAlgorithm) int { 51 | switch curve { 52 | case crypto.ECDSA_P256: 53 | return 32 54 | case crypto.ECDSA_secp256k1: 55 | return 32 56 | default: 57 | panic("parameter is not supported") 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /crypto_adx_flag.mk: -------------------------------------------------------------------------------- 1 | # This script can be imported by Makefiles in order to set the `CRYPTO_FLAG` automatically. 2 | # The `CRYPTO_FLAG` is a Go command flag that should be used when the machine's CPU executing 3 | # the command may not support ADX instructions. 4 | # For new machines that support ADX instructions, the `CRYPTO_FLAG` flag is not needed (or set 5 | # to an empty string). 6 | 7 | # First detect ADX support: 8 | # `ADX_SUPPORT` is 1 if ADX instructions are supported on the current machine and 0 otherwise. 9 | ifeq ($(shell uname -s),Linux) 10 | # detect ADX support on the CURRENT linux machine. 11 | ADX_SUPPORT := $(shell if ([ -f "/proc/cpuinfo" ] && grep -q -e '^flags.*\badx\b' /proc/cpuinfo); then echo 1; else echo 0; fi) 12 | else 13 | # on non-linux machines, set the flag to 1 by default 14 | ADX_SUPPORT := 1 15 | endif 16 | 17 | # Then, set `CRYPTO_FLAG` 18 | # the crypto package uses BLST source files underneath which may use ADX instructions. 19 | ifeq ($(ADX_SUPPORT), 1) 20 | # if ADX instructions are supported on the current machine, default is to use a fast ADX implementation 21 | CRYPTO_FLAG := "" 22 | else 23 | # if ADX instructions aren't supported, this CGO flags uses a slower non-ADX implementation 24 | CRYPTO_FLAG := "-O -D__BLST_PORTABLE__" 25 | endif -------------------------------------------------------------------------------- /decode.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import ( 22 | // NOTE: always import Cadence's stdlib package, 23 | // as it registers the type ID decoder for the Flow types, 24 | // e.g. `flow.AccountCreated` 25 | _ "github.com/onflow/cadence/stdlib" 26 | "github.com/onflow/flow/protobuf/go/flow/entities" 27 | ) 28 | 29 | type EventEncodingVersion = entities.EventEncodingVersion 30 | 31 | const ( 32 | EventEncodingVersionCCF = entities.EventEncodingVersion_CCF_V0 33 | EventEncodingVersionJSONCDC = entities.EventEncodingVersion_JSON_CDC_V0 34 | ) 35 | -------------------------------------------------------------------------------- /decode_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow_test 20 | 21 | import ( 22 | "testing" 23 | 24 | "github.com/onflow/cadence/common" 25 | "github.com/onflow/cadence/stdlib" 26 | "github.com/stretchr/testify/assert" 27 | "github.com/stretchr/testify/require" 28 | 29 | "github.com/onflow/flow-go-sdk" 30 | ) 31 | 32 | func TestDecodeFlowTypeID(t *testing.T) { 33 | location, qualifiedIdentifier, err := common.DecodeTypeID(nil, flow.EventAccountCreated) 34 | require.NoError(t, err) 35 | assert.Equal(t, stdlib.FlowLocation{}, location) 36 | assert.Equal(t, "AccountCreated", qualifiedIdentifier) 37 | } 38 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // Package flow provides libraries and tools for building Go applications on Flow. 20 | package flow 21 | -------------------------------------------------------------------------------- /docs/error-codes.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/flow-go-sdk/error-codes.mdx 4 | -------------------------------------------------------------------------------- /docs/flow-docs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "displayName": "Flow Go SDK", 4 | "sidebars": { 5 | "": [ 6 | { 7 | "title": "Flow Go SDK", 8 | "items": [ 9 | { 10 | "title": "Getting Started", 11 | "href": "" 12 | }, 13 | { 14 | "title": "Error Codes", 15 | "href": "error-codes" 16 | } 17 | ] 18 | } 19 | ] 20 | } 21 | } -------------------------------------------------------------------------------- /docs/index.mdx: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/tree/main/docs/tooling/flow-go-sdk/index.mdx 4 | -------------------------------------------------------------------------------- /docs/migration-v0.25.0.md: -------------------------------------------------------------------------------- 1 | # This document has been moved to a new location: 2 | 3 | https://github.com/onflow/docs/blob/main/docs/tools/clients/flow-go-sdk/migration-v0.25.0.md 4 | -------------------------------------------------------------------------------- /event.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import ( 22 | "fmt" 23 | "time" 24 | 25 | "github.com/onflow/cadence" 26 | "github.com/onflow/cadence/stdlib" 27 | "github.com/onflow/crypto/hash" 28 | 29 | "github.com/onflow/flow-go-sdk/crypto" 30 | ) 31 | 32 | // List of built-in account event types. 33 | const ( 34 | EventAccountCreated string = "flow.AccountCreated" 35 | EventAccountKeyAdded string = "flow.AccountKeyAdded" 36 | EventAccountKeyRemoved string = "flow.AccountKeyRemoved" 37 | EventAccountContractAdded string = "flow.AccountContractAdded" 38 | EventAccountContractUpdated string = "flow.AccountContractUpdated" 39 | EventAccountContractRemoved string = "flow.AccountContractRemoved" 40 | ) 41 | 42 | type Event struct { 43 | // Type is the qualified event type. 44 | Type string 45 | // TransactionID is the ID of the transaction this event was emitted from. 46 | TransactionID Identifier 47 | // TransactionIndex is the index of the transaction this event was emitted from, within its containing block. 48 | TransactionIndex int 49 | // EventIndex is the index of the event within the transaction it was emitted from. 50 | EventIndex int 51 | // Value contains the event data. 52 | Value cadence.Event 53 | // Bytes representing event data. 54 | Payload []byte 55 | } 56 | 57 | // String returns the string representation of this event. 58 | func (e Event) String() string { 59 | return fmt.Sprintf("%s: %s", e.Type, e.ID()) 60 | } 61 | 62 | // ID returns the canonical SHA3-256 hash of this event. 63 | func (e Event) ID() string { 64 | return defaultEntityHasher.ComputeHash(e.Encode()).Hex() 65 | } 66 | 67 | // Encode returns the canonical RLP byte representation of this event. 68 | func (e Event) Encode() []byte { 69 | temp := struct { 70 | TransactionID []byte 71 | EventIndex uint 72 | }{ 73 | TransactionID: e.TransactionID[:], 74 | EventIndex: uint(e.EventIndex), 75 | } 76 | return mustRLPEncode(&temp) 77 | } 78 | 79 | // Fingerprint calculates a fingerprint of an event. 80 | func (e *Event) Fingerprint() []byte { 81 | 82 | return mustRLPEncode(struct { 83 | TxID []byte 84 | Index uint32 85 | Type string 86 | TransactionIndex uint32 87 | Payload []byte 88 | }{ 89 | TxID: e.TransactionID[:], 90 | Index: uint32(e.EventIndex), 91 | Type: string(e.Type), 92 | TransactionIndex: uint32(e.TransactionIndex), 93 | Payload: e.Payload[:], 94 | }) 95 | } 96 | 97 | // BlockEvents are the events that occurred in a specific block. 98 | type BlockEvents struct { 99 | BlockID Identifier 100 | Height uint64 101 | BlockTimestamp time.Time 102 | Events []Event 103 | } 104 | 105 | // CalculateEventsHash calculates hash of the events, in a way compatible with the events hash 106 | // propagated in Chunk. Providing list of events as emitted by transactions in given chunk, 107 | // hashes should match 108 | func CalculateEventsHash(es []Event) (crypto.Hash, error) { 109 | 110 | hasher := hash.NewSHA3_256() 111 | 112 | for _, event := range es { 113 | _, err := hasher.Write(event.Fingerprint()) 114 | if err != nil { 115 | return nil, err 116 | } 117 | } 118 | 119 | return hasher.SumHash(), nil 120 | } 121 | 122 | // An AccountCreatedEvent is emitted when a transaction creates a new Flow account. 123 | // 124 | // This event contains the following fields: 125 | // - Address: Address 126 | type AccountCreatedEvent Event 127 | 128 | // Address returns the address of the newly-created account. 129 | func (evt AccountCreatedEvent) Address() Address { 130 | address := cadence.SearchFieldByName( 131 | evt.Value, 132 | stdlib.AccountEventAddressParameter.Identifier, 133 | ).(cadence.Address) 134 | return BytesToAddress(address.Bytes()) 135 | } 136 | 137 | // EventFilter is used to filter events based on given parameters. 138 | type EventFilter struct { 139 | EventTypes []string 140 | Addresses []string 141 | Contracts []string 142 | } 143 | -------------------------------------------------------------------------------- /event_type_factory.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import ( 22 | "fmt" 23 | ) 24 | 25 | type eventTypeFactory struct { 26 | address string 27 | contractName string 28 | eventName string 29 | } 30 | 31 | func (f eventTypeFactory) WithAddressString(address string) eventTypeFactory { 32 | f.address = address 33 | return f 34 | } 35 | 36 | func (f eventTypeFactory) WithAddress(address Address) eventTypeFactory { 37 | f.address = address.Hex() 38 | return f 39 | } 40 | 41 | func (f eventTypeFactory) WithContractName(contract string) eventTypeFactory { 42 | f.contractName = contract 43 | return f 44 | } 45 | 46 | func (f eventTypeFactory) WithEventName(event string) eventTypeFactory { 47 | f.eventName = event 48 | return f 49 | } 50 | 51 | func (f eventTypeFactory) String() string { 52 | return fmt.Sprintf("A.%s.%s.%s", f.address, f.contractName, f.eventName) 53 | } 54 | 55 | // NewEventTypeFactory helper function for constructing event names 56 | func NewEventTypeFactory() eventTypeFactory { 57 | return eventTypeFactory{} 58 | } 59 | -------------------------------------------------------------------------------- /event_type_factory_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import ( 22 | "testing" 23 | 24 | "github.com/stretchr/testify/assert" 25 | ) 26 | 27 | func TestEventTypeFactory(t *testing.T) { 28 | assert.Equal(t, "A.7e60df042a9c0868.FlowToken.AccountCreated", NewEventTypeFactory(). 29 | WithEventName("AccountCreated"). 30 | WithAddressString("7e60df042a9c0868"). 31 | WithContractName("FlowToken"). 32 | String()) 33 | } 34 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all: get-blocks get-accounts get-events get-collection get-network-parameters get-transactions execute-script send-transactions create-account add-account-key deploy-contract storage-usage transaction-arguments single-party single-party-multisig multi-party multi-party-multisig user-signature user-signature-validate-all user-signature-validate-any http-grpc-clients modify-account get-execution-data 3 | 4 | .PHONY: create-account 5 | create-account: 6 | go run ./create_account/main.go 7 | 8 | .PHONY: add-account-key 9 | add-account-key: 10 | go run ./add_account_key/main.go 11 | 12 | .PHONY: deploy-contract 13 | deploy-contract: 14 | go run ./deploy_contract/main.go 15 | 16 | .PHONY: verify-events 17 | verify-events: 18 | go run ./verify_events/main.go 19 | 20 | .PHONY: storage-usage 21 | storage-usage: 22 | go run ./storage_usage/main.go 23 | 24 | .PHONY: transaction-arguments 25 | transaction-arguments: 26 | go run ./transaction_arguments/main.go 27 | 28 | .PHONY: single-party 29 | single-party: 30 | go run ./transaction_signing/single_party/main.go 31 | 32 | .PHONY: single-party-multisig 33 | single-party-multisig: 34 | go run ./transaction_signing/single_party_multisig/main.go 35 | 36 | .PHONY: multi-party 37 | multi-party: 38 | go run ./transaction_signing/multi_party/main.go 39 | 40 | .PHONY: multi-party-two-authorizers 41 | multi-party-two-authorizers: 42 | go run ./transaction_signing/multi_party_two_authorizers/main.go 43 | 44 | .PHONY: multi-party-multisig 45 | multi-party-multisig: 46 | go run ./transaction_signing/multi_party_multisig/main.go 47 | 48 | .PHONY: user-signature 49 | user-signature: 50 | go run ./verify_signature/user_signature/main.go 51 | 52 | .PHONY: get-blocks 53 | get-blocks: 54 | go run ./get_blocks/main.go 55 | 56 | .PHONY: get-accounts 57 | get-accounts: 58 | go run ./get_accounts/main.go 59 | 60 | .PHONY: get-events 61 | get-events: 62 | go run ./get_events/main.go 63 | 64 | .PHONY: get-collection 65 | get-collection: 66 | go run ./get_collection/main.go 67 | 68 | .PHONY: get-network-parameters 69 | get-network-parameters: 70 | go run ./get_network_parameters/main.go 71 | 72 | .PHONY: get-transactions 73 | get-transactions: 74 | go run ./get_transactions/main.go 75 | 76 | .PHONY: execute-script 77 | execute-script: 78 | go run ./execute_script/main.go 79 | 80 | .PHONY: send-transactions 81 | send-transactions: 82 | go run ./send_transactions/main.go 83 | 84 | .PHONY: user-signature-validate-all 85 | user-signature-validate-all: 86 | go run ./verify_signature/user_signature_validate_all/main.go 87 | 88 | .PHONY: user-signature-validate-any 89 | user-signature-validate-any: 90 | go run ./verify_signature/user_signature_validate_any/main.go 91 | 92 | .PHONY: http-grpc-clients 93 | http-grpc-clients: 94 | go run ./http_grpc_clients/main.go 95 | 96 | .PHONY: modify-account 97 | modify-account: 98 | go run ./modify_account/main.go 99 | 100 | .PHONY: get-execution-data 101 | get-execution-data: 102 | go run ./get_execution_data/main.go 103 | 104 | .PHONY: stream-events 105 | stream-events: 106 | go run ./stream_events/main.go 107 | 108 | .PHONY: stream-events-reconnect 109 | stream-events-reconnect: 110 | go run ./stream_events_reconnect/main.go 111 | 112 | .PHONY: stream-execution-data 113 | stream-execution-data: 114 | go run ./stream_execution_data/main.go 115 | .PHONY: stream-blocks 116 | stream-blocks: 117 | go run ./stream_blocks/main.go 118 | 119 | .PHONY: stream-block-headers 120 | stream-block-headers: 121 | go run ./stream_block_headers/main.go 122 | 123 | .PHONY: stream-block-digests 124 | stream-block-digests: 125 | go run ./stream_block_digests/main.go 126 | 127 | .PHONY: stream-account-statuses 128 | stream-account-statuses: 129 | go run ./stream_account_statuses/main.go 130 | 131 | .PHONY: send-and-subscribe-transaction-statuses 132 | send-and-subscribe-transaction-statuses: 133 | go run ./send_and_subscribe_transaction_statuses/main.go 134 | -------------------------------------------------------------------------------- /examples/add_account_key/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk" 26 | "github.com/onflow/flow-go-sdk/access/http" 27 | "github.com/onflow/flow-go-sdk/crypto" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | "github.com/onflow/flow-go-sdk/templates" 30 | ) 31 | 32 | func main() { 33 | AddAccountKeyDemo() 34 | } 35 | 36 | func AddAccountKeyDemo() { 37 | ctx := context.Background() 38 | 39 | flowClient, err := http.NewClient(http.EmulatorHost) 40 | examples.Handle(err) 41 | 42 | acctAddr, acctKey, acctSigner := examples.RandomAccount(flowClient) 43 | 44 | // Create the new key to add to your account 45 | myPrivateKey := examples.RandomPrivateKey() 46 | myAcctKey := flow.NewAccountKey(). 47 | FromPrivateKey(myPrivateKey). 48 | SetHashAlgo(crypto.SHA3_256). 49 | SetWeight(flow.AccountKeyWeightThreshold) 50 | 51 | addKeyTx, err := templates.AddAccountKey(acctAddr, myAcctKey) 52 | examples.Handle(err) 53 | 54 | referenceBlockID := examples.GetReferenceBlockId(flowClient) 55 | 56 | addKeyTx.SetProposalKey(acctAddr, acctKey.Index, acctKey.SequenceNumber) 57 | addKeyTx.SetReferenceBlockID(referenceBlockID) 58 | addKeyTx.SetPayer(acctAddr) 59 | 60 | // Sign the transaction with the new account. 61 | err = addKeyTx.SignEnvelope(acctAddr, acctKey.Index, acctSigner) 62 | examples.Handle(err) 63 | 64 | // Send the transaction to the network. 65 | err = flowClient.SendTransaction(ctx, *addKeyTx) 66 | examples.Handle(err) 67 | 68 | examples.WaitForSeal(ctx, flowClient, addKeyTx.ID()) 69 | 70 | fmt.Println("Public key added to account!") 71 | } 72 | -------------------------------------------------------------------------------- /examples/cloudkms/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/cadence" 28 | 29 | "github.com/onflow/flow-go-sdk" 30 | "github.com/onflow/flow-go-sdk/crypto/cloudkms" 31 | "github.com/onflow/flow-go-sdk/examples" 32 | "github.com/onflow/flow-go-sdk/test" 33 | ) 34 | 35 | func main() { 36 | GoogleCloudKMSDemo() 37 | } 38 | 39 | func GoogleCloudKMSDemo() { 40 | ctx := context.Background() 41 | 42 | flowClient, err := http.NewClient(http.EmulatorHost) 43 | examples.Handle(err) 44 | 45 | accountAddress := test.AddressGenerator().New() 46 | accountKeyID := 0 47 | 48 | accountKMSKey := cloudkms.Key{ 49 | ProjectID: "my-project", 50 | LocationID: "global", 51 | KeyRingID: "flow", 52 | KeyID: "my-account", 53 | KeyVersion: "1", 54 | } 55 | 56 | kmsClient, err := cloudkms.NewClient(ctx) 57 | if err != nil { 58 | panic(err) 59 | } 60 | 61 | accountKMSSigner, err := kmsClient.SignerForKey( 62 | ctx, 63 | accountKMSKey, 64 | ) 65 | if err != nil { 66 | panic(err) 67 | } 68 | 69 | serviceAccount, err := flowClient.GetAccount(ctx, accountAddress) 70 | if err != nil { 71 | panic(err) 72 | } 73 | 74 | latestBlock, err := flowClient.GetLatestBlockHeader(ctx, true) 75 | if err != nil { 76 | panic(err) 77 | } 78 | 79 | accountKey := serviceAccount.Keys[accountKeyID] 80 | 81 | tx := flow.NewTransaction(). 82 | SetScript(test.GreetingScript). 83 | SetReferenceBlockID(latestBlock.ID). 84 | SetProposalKey(accountAddress, accountKey.Index, accountKey.SequenceNumber). 85 | SetPayer(accountAddress) 86 | 87 | err = tx.AddArgument(cadence.String(test.GreetingGenerator().Random())) 88 | examples.Handle(err) 89 | 90 | err = tx.SignEnvelope(accountAddress, accountKey.Index, accountKMSSigner) 91 | examples.Handle(err) 92 | 93 | err = flowClient.SendTransaction(ctx, *tx) 94 | examples.Handle(err) 95 | 96 | examples.WaitForSeal(ctx, flowClient, tx.ID()) 97 | 98 | fmt.Println("Transaction complete!") 99 | } 100 | -------------------------------------------------------------------------------- /examples/create_account/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/crypto" 29 | "github.com/onflow/flow-go-sdk/examples" 30 | "github.com/onflow/flow-go-sdk/templates" 31 | ) 32 | 33 | func main() { 34 | CreateAccountDemo() 35 | } 36 | 37 | func CreateAccountDemo() { 38 | ctx := context.Background() 39 | flowClient, err := http.NewClient(http.EmulatorHost) 40 | examples.Handle(err) 41 | 42 | serviceAcctAddr, serviceAcctKey, serviceSigner := examples.ServiceAccount(flowClient) 43 | 44 | myPrivateKey := examples.RandomPrivateKey() 45 | myAcctKey := flow.NewAccountKey(). 46 | FromPrivateKey(myPrivateKey). 47 | SetHashAlgo(crypto.SHA3_256). 48 | SetWeight(flow.AccountKeyWeightThreshold) 49 | 50 | referenceBlockID := examples.GetReferenceBlockId(flowClient) 51 | createAccountTx, err := templates.CreateAccount([]*flow.AccountKey{myAcctKey}, nil, serviceAcctAddr) 52 | examples.Handle(err) 53 | createAccountTx.SetProposalKey( 54 | serviceAcctAddr, 55 | serviceAcctKey.Index, 56 | serviceAcctKey.SequenceNumber, 57 | ) 58 | createAccountTx.SetReferenceBlockID(referenceBlockID) 59 | createAccountTx.SetPayer(serviceAcctAddr) 60 | 61 | // Sign the transaction with the service account, which already exists 62 | // All new accounts must be created by an existing account 63 | err = createAccountTx.SignEnvelope(serviceAcctAddr, serviceAcctKey.Index, serviceSigner) 64 | examples.Handle(err) 65 | 66 | // Send the transaction to the network 67 | err = flowClient.SendTransaction(ctx, *createAccountTx) 68 | examples.Handle(err) 69 | 70 | accountCreationTxRes := examples.WaitForSeal(ctx, flowClient, createAccountTx.ID()) 71 | 72 | var myAddress flow.Address 73 | 74 | for _, event := range accountCreationTxRes.Events { 75 | if event.Type == flow.EventAccountCreated { 76 | accountCreatedEvent := flow.AccountCreatedEvent(event) 77 | myAddress = accountCreatedEvent.Address() 78 | } 79 | } 80 | 81 | fmt.Println("Account created with address:", myAddress.Hex()) 82 | } 83 | -------------------------------------------------------------------------------- /examples/execute_script/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "errors" 24 | "fmt" 25 | 26 | "github.com/onflow/flow-go-sdk/access/http" 27 | 28 | "github.com/onflow/cadence" 29 | 30 | "github.com/onflow/flow-go-sdk" 31 | "github.com/onflow/flow-go-sdk/examples" 32 | ) 33 | 34 | func main() { 35 | prepareDemo() 36 | demo() 37 | } 38 | 39 | func demo() { 40 | ctx := context.Background() 41 | flowClient, err := http.NewClient(http.EmulatorHost) 42 | examples.Handle(err) 43 | 44 | script := []byte(` 45 | access(all) fun main(a: Int): Int { 46 | return a + 10 47 | } 48 | `) 49 | args := []cadence.Value{cadence.NewInt(5)} 50 | value, err := flowClient.ExecuteScriptAtLatestBlock(ctx, script, args) 51 | 52 | examples.Handle(err) 53 | fmt.Printf("\nValue: %s", value.String()) 54 | 55 | complexScript := []byte(` 56 | access(all) struct User { 57 | access(all) var balance: UFix64 58 | access(all) var address: Address 59 | access(all) var name: String 60 | 61 | init(name: String, address: Address, balance: UFix64) { 62 | self.name = name 63 | self.address = address 64 | self.balance = balance 65 | } 66 | } 67 | 68 | access(all) fun main(name: String): User { 69 | return User( 70 | name: name, 71 | address: 0x1, 72 | balance: 10.0 73 | ) 74 | } 75 | `) 76 | args = []cadence.Value{cadence.String("Dete")} 77 | value, err = flowClient.ExecuteScriptAtLatestBlock(ctx, complexScript, args) 78 | printComplexScript(value, err) 79 | } 80 | 81 | type User struct { 82 | balance string 83 | address flow.Address 84 | name string 85 | } 86 | 87 | func printComplexScript(value cadence.Value, err error) { 88 | examples.Handle(err) 89 | fmt.Printf("\nString value: %s", value.String()) 90 | 91 | s := value.(cadence.Struct) 92 | balanceCdc, ok := s.FieldsMappedByName()["balance"].(cadence.UFix64) 93 | if !ok { 94 | examples.Handle(errors.New("incorrect balance")) 95 | } 96 | addressCdc, ok := s.FieldsMappedByName()["address"].(cadence.Address) 97 | if !ok { 98 | examples.Handle(errors.New("incorrect address")) 99 | } 100 | nameCdc, ok := s.FieldsMappedByName()["name"].(cadence.String) 101 | if !ok { 102 | examples.Handle(errors.New("incorrect name")) 103 | } 104 | 105 | u := User{ 106 | balance: balanceCdc.String(), 107 | address: flow.BytesToAddress(addressCdc.Bytes()), 108 | name: nameCdc.String(), 109 | } 110 | 111 | fmt.Printf("\nName: %s", u.name) 112 | fmt.Printf("\nAddress: 0x%s", u.address.String()) 113 | fmt.Printf("\nBalance: %s", u.balance) 114 | } 115 | 116 | func prepareDemo() { 117 | 118 | } 119 | -------------------------------------------------------------------------------- /examples/flow.json: -------------------------------------------------------------------------------- 1 | { 2 | "emulators": { 3 | "default": { 4 | "port": 3569, 5 | "serviceAccount": "emulator-account" 6 | } 7 | }, 8 | "contracts": { 9 | "FlowServiceAccount": { 10 | "aliases": { 11 | "emulator": "f8d6e0586b0a20c7" 12 | } 13 | }, 14 | "FlowFees": { 15 | "aliases": { 16 | "emulator": "e5a8b7f23e8b548f" 17 | } 18 | }, 19 | "FlowStorageFees": { 20 | "aliases": { 21 | "emulator": "f8d6e0586b0a20c7" 22 | } 23 | }, 24 | "FlowToken": { 25 | "aliases": { 26 | "emulator": "0ae53cb6e3f42a79" 27 | } 28 | }, 29 | "FungibleToken": { 30 | "aliases": { 31 | "emulator": "ee82856bf20e2aa6" 32 | } 33 | } 34 | }, 35 | "networks": { 36 | "emulator": "127.0.0.1:3569", 37 | "mainnet": "access.mainnet.nodes.onflow.org:9000", 38 | "testnet": "access.devnet.nodes.onflow.org:9000" 39 | }, 40 | "accounts": { 41 | "emulator-account": { 42 | "address": "f8d6e0586b0a20c7", 43 | "key": "b89228aafd909a353d89efb8d1d487b12903d84d4af26b9dfe63a9ef75d11297" 44 | } 45 | }, 46 | "deployments": {} 47 | } 48 | -------------------------------------------------------------------------------- /examples/get_accounts/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | demo() 33 | } 34 | 35 | func demo() { 36 | ctx := context.Background() 37 | flowClient, err := http.NewClient(http.EmulatorHost) 38 | examples.Handle(err) 39 | 40 | examples.RandomAccount(flowClient) 41 | 42 | // get account from the latest block 43 | address := flow.HexToAddress("f8d6e0586b0a20c7") 44 | account, err := flowClient.GetAccount(ctx, address) 45 | printAccount(account, err) 46 | 47 | // get account from the block by height 0 48 | account, err = flowClient.GetAccountAtBlockHeight(ctx, address, 0) 49 | printAccount(account, err) 50 | } 51 | 52 | func printAccount(account *flow.Account, err error) { 53 | examples.Handle(err) 54 | 55 | fmt.Printf("\nAddress: %s", account.Address.String()) 56 | fmt.Printf("\nBalance: %d", account.Balance) 57 | fmt.Printf("\nContracts: %d", len(account.Contracts)) 58 | fmt.Printf("\nKeys: %d\n", len(account.Keys)) 59 | } 60 | -------------------------------------------------------------------------------- /examples/get_blocks/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access" 26 | 27 | "github.com/onflow/flow-go-sdk/access/http" 28 | 29 | "github.com/onflow/flow-go-sdk" 30 | "github.com/onflow/flow-go-sdk/examples" 31 | ) 32 | 33 | func main() { 34 | demo() 35 | } 36 | 37 | func demo() { 38 | ctx := context.Background() 39 | var flowClient access.Client 40 | flowClient, err := http.NewClient(http.EmulatorHost) 41 | examples.Handle(err) 42 | 43 | examples.RandomAccount(flowClient) 44 | 45 | // get the latest sealed block 46 | isSealed := true 47 | latestBlock, err := flowClient.GetLatestBlock(ctx, isSealed) 48 | printBlock(latestBlock, err) 49 | 50 | // get the block by ID 51 | blockID := latestBlock.ID.String() 52 | blockByID, err := flowClient.GetBlockByID(ctx, flow.HexToID(blockID)) 53 | printBlock(blockByID, err) 54 | 55 | // get block by height 56 | blockByHeight, err := flowClient.GetBlockByHeight(ctx, 0) 57 | printBlock(blockByHeight, err) 58 | } 59 | 60 | func printBlock(block *flow.Block, err error) { 61 | examples.Handle(err) 62 | 63 | fmt.Printf("\nID: %s\n", block.ID) 64 | fmt.Printf("height: %d\n", block.Height) 65 | fmt.Printf("timestamp: %s\n\n", block.Timestamp) 66 | } 67 | -------------------------------------------------------------------------------- /examples/get_collection/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | id := prepareDemo() 33 | demo(id) 34 | } 35 | 36 | func demo(exampleCollectionID flow.Identifier) { 37 | ctx := context.Background() 38 | flowClient := examples.NewFlowGRPCClient() 39 | 40 | // get collection by ID 41 | collection, err := flowClient.GetCollection(ctx, exampleCollectionID) 42 | printCollection(collection, err) 43 | } 44 | 45 | func printCollection(collection *flow.Collection, err error) { 46 | examples.Handle(err) 47 | 48 | fmt.Printf("\nID: %s", collection.ID().String()) 49 | fmt.Printf("\nTransactions: %s", collection.TransactionIDs) 50 | } 51 | 52 | func prepareDemo() flow.Identifier { 53 | flowClient, err := http.NewClient(http.EmulatorHost) 54 | examples.Handle(err) 55 | 56 | examples.RandomAccount(flowClient) 57 | 58 | block, err := flowClient.GetBlockByHeight(context.Background(), 1) 59 | examples.Handle(err) 60 | 61 | return block.CollectionGuarantees[0].CollectionID 62 | } 63 | -------------------------------------------------------------------------------- /examples/get_events/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/flow-go-sdk/templates" 28 | 29 | "github.com/onflow/flow-go-sdk" 30 | "github.com/onflow/flow-go-sdk/examples" 31 | ) 32 | 33 | func main() { 34 | deployedContract, runScriptTx := preapreDemo() 35 | demo(deployedContract, runScriptTx) 36 | } 37 | 38 | func demo(deployedContract *flow.Account, runScriptTx *flow.Transaction) { 39 | ctx := context.Background() 40 | flowClient, err := http.NewClient(http.EmulatorHost) 41 | examples.Handle(err) 42 | 43 | // Query for account creation events by type 44 | result, err := flowClient.GetEventsForHeightRange(ctx, "flow.AccountCreated", 0, 30) 45 | printEvents(result, err) 46 | 47 | customType := flow.NewEventTypeFactory(). 48 | WithEventName("Add"). 49 | WithContractName("EventDemo"). 50 | WithAddress(deployedContract.Address). 51 | String() 52 | 53 | result, err = flowClient.GetEventsForHeightRange(ctx, customType, 0, 10) 54 | printEvents(result, err) 55 | 56 | // Get events directly from transaction result 57 | txResult, err := flowClient.GetTransactionResult(ctx, runScriptTx.ID()) 58 | examples.Handle(err) 59 | printEvent(txResult.Events) 60 | } 61 | 62 | func printEvents(result []flow.BlockEvents, err error) { 63 | examples.Handle(err) 64 | 65 | for _, block := range result { 66 | printEvent(block.Events) 67 | } 68 | } 69 | 70 | func printEvent(events []flow.Event) { 71 | for _, event := range events { 72 | fmt.Printf("\n\nType: %s", event.Type) 73 | fmt.Printf("\nValues: %v", event.Value) 74 | fmt.Printf("\nTransaction ID: %s", event.TransactionID) 75 | } 76 | } 77 | 78 | func preapreDemo() (*flow.Account, *flow.Transaction) { 79 | ctx := context.Background() 80 | flowClient, err := http.NewClient(http.EmulatorHost) 81 | examples.Handle(err) 82 | 83 | acctAddr, acctKey, acctSigner := examples.RandomAccount(flowClient) 84 | 85 | // Deploy a contract with an event defined 86 | contract := ` 87 | access(all) contract EventDemo { 88 | access(all) event Add(x: Int, y: Int, sum: Int) 89 | 90 | access(all) fun add(x: Int, y: Int) { 91 | let sum = x + y 92 | emit Add(x: x, y: y, sum: sum) 93 | } 94 | } 95 | ` 96 | 97 | contractAccount := examples.CreateAccountWithContracts(flowClient, 98 | nil, []templates.Contract{{ 99 | Name: "EventDemo", 100 | Source: contract, 101 | }}) 102 | 103 | // Send a tx that emits the event in the deployed contract 104 | script := fmt.Sprintf(` 105 | import EventDemo from 0x%s 106 | 107 | transaction { 108 | prepare(signer: auth(Storage) &Account) {} 109 | execute { 110 | EventDemo.add(x: 2, y: 3) 111 | } 112 | } 113 | `, contractAccount.Address.Hex()) 114 | 115 | referenceBlockID := examples.GetReferenceBlockId(flowClient) 116 | runScriptTx := flow.NewTransaction(). 117 | SetScript([]byte(script)). 118 | SetPayer(acctAddr). 119 | AddAuthorizer(acctAddr). 120 | SetReferenceBlockID(referenceBlockID). 121 | SetProposalKey(acctAddr, acctKey.Index, acctKey.SequenceNumber) 122 | 123 | err = runScriptTx.SignEnvelope(acctAddr, acctKey.Index, acctSigner) 124 | examples.Handle(err) 125 | 126 | err = flowClient.SendTransaction(ctx, *runScriptTx) 127 | examples.Handle(err) 128 | 129 | examples.WaitForSeal(ctx, flowClient, runScriptTx.ID()) 130 | 131 | return contractAccount, runScriptTx 132 | } 133 | -------------------------------------------------------------------------------- /examples/get_execution_data/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/grpc" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | demo() 33 | } 34 | 35 | func demo() { 36 | ctx := context.Background() 37 | flowClient, err := grpc.NewClient(grpc.TestnetHost) 38 | examples.Handle(err) 39 | 40 | block, err := flowClient.GetLatestBlock(ctx, true) 41 | examples.Handle(err) 42 | fmt.Printf("Block Height: %d\n", block.Height) 43 | fmt.Printf("Block ID: %s\n", block.ID) 44 | 45 | data, err := flowClient.GetExecutionDataByBlockID(ctx, block.ID) 46 | examples.Handle(err) 47 | printExecutionData(data) 48 | } 49 | 50 | func printExecutionData(ed *flow.ExecutionData) { 51 | for chunkNo, chunk := range ed.ChunkExecutionData { 52 | fmt.Printf("-- Chunk %d/%d --\n", chunkNo+1, len(ed.ChunkExecutionData)) 53 | fmt.Printf("Transactions: %d\n", len(chunk.Transactions)) 54 | for txNo, tx := range chunk.Transactions { 55 | fmt.Printf("Transaction %d/%d:\n", txNo+1, len(chunk.Transactions)) 56 | printTransaction(tx) 57 | } 58 | fmt.Printf("Events: %d\n", len(chunk.Events)) 59 | for eventNo, event := range chunk.Events { 60 | fmt.Printf("Event %d/%d: %s\n", eventNo+1, len(chunk.Events), event.Type) 61 | } 62 | if chunk.TrieUpdate != nil { 63 | modifiedAccounts := extractModifiedAccounts(chunk.TrieUpdate) 64 | fmt.Printf("Modified Accounts: %d\n", len(modifiedAccounts)) 65 | for i, acc := range modifiedAccounts { 66 | fmt.Printf("Account %d/%d: %s\n", i+1, len(modifiedAccounts), acc.Hex()) 67 | } 68 | fmt.Printf("TrieUpdate RootHash: %s\n", flow.BytesToHash(chunk.TrieUpdate.RootHash).Hex()) 69 | fmt.Printf("TrieUpdate Paths:\n") 70 | for pathNo, path := range chunk.TrieUpdate.Paths { 71 | fmt.Printf("Path %d/%d: %s", pathNo+1, len(chunk.TrieUpdate.Paths), flow.BytesToHash(path)) 72 | } 73 | fmt.Printf("TrieUpdate Payloads:\n") 74 | for payloadNo, payload := range chunk.TrieUpdate.Payloads { 75 | fmt.Printf("Payload %d/%d:\n", payloadNo+1, len(chunk.TrieUpdate.Payloads)) 76 | fmt.Printf("Value: %x\n", string(payload.Value)) 77 | for kpi, kp := range payload.KeyPart { 78 | fmt.Printf("KeyPart[%d].Type: %d\n", kpi, kp.Type) 79 | fmt.Printf("KeyPart[%d].Value: %x\n", kpi, kp.Value) 80 | } 81 | 82 | } 83 | } else { 84 | fmt.Printf("\nNo TrieUpdate") 85 | } 86 | } 87 | } 88 | 89 | func printTransaction(tx *flow.Transaction) { 90 | fmt.Printf("\nID: %s", tx.ID().String()) 91 | fmt.Printf("\nPayer: %s", tx.Payer.String()) 92 | fmt.Printf("\nProposer: %s", tx.ProposalKey.Address.String()) 93 | fmt.Printf("\nAuthorizers: %s", tx.Authorizers) 94 | } 95 | 96 | func extractModifiedAccounts(update *flow.TrieUpdate) []flow.Address { 97 | 98 | accounts := map[flow.Address]struct{}{} 99 | 100 | for _, payload := range update.Payloads { 101 | address := flow.BytesToAddress(payload.KeyPart[0].Value) 102 | accounts[address] = struct{}{} 103 | } 104 | 105 | addresses := make([]flow.Address, 0, len(accounts)) 106 | for address := range accounts { 107 | addresses = append(addresses, address) 108 | } 109 | 110 | return addresses 111 | } 112 | -------------------------------------------------------------------------------- /examples/get_network_parameters/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/flow-go-sdk/examples" 28 | ) 29 | 30 | func main() { 31 | GetNetworkParametersDemo() 32 | } 33 | 34 | func GetNetworkParametersDemo() { 35 | ctx := context.Background() 36 | flowClient, err := http.NewClient(http.EmulatorHost) 37 | examples.Handle(err) 38 | 39 | // get network parameters 40 | networkParameters, err := flowClient.GetNetworkParameters(ctx) 41 | examples.Handle(err) 42 | 43 | fmt.Printf("Chain ID: %s\n", networkParameters.ChainID) 44 | } 45 | -------------------------------------------------------------------------------- /examples/get_transactions/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | demo() 33 | } 34 | 35 | func demo() { 36 | ctx := context.Background() 37 | flowClient, err := http.NewClient(http.EmulatorHost) 38 | examples.Handle(err) 39 | 40 | txID := examples.RandomTransaction(flowClient).ID() 41 | 42 | tx, err := flowClient.GetTransaction(ctx, txID) 43 | printTransaction(tx, err) 44 | 45 | txr, err := flowClient.GetTransactionResult(ctx, txID) 46 | printTransactionResult(txr, err) 47 | } 48 | 49 | func printTransaction(tx *flow.Transaction, err error) { 50 | examples.Handle(err) 51 | 52 | fmt.Printf("\nID: %s", tx.ID().String()) 53 | fmt.Printf("\nPayer: %s", tx.Payer.String()) 54 | fmt.Printf("\nProposer: %s", tx.ProposalKey.Address.String()) 55 | fmt.Printf("\nAuthorizers: %s", tx.Authorizers) 56 | } 57 | 58 | func printTransactionResult(txr *flow.TransactionResult, err error) { 59 | examples.Handle(err) 60 | 61 | fmt.Printf("\nStatus: %s", txr.Status.String()) 62 | fmt.Printf("\nError: %v", txr.Error) 63 | } 64 | -------------------------------------------------------------------------------- /examples/great-token.cdc: -------------------------------------------------------------------------------- 1 | access(all) contract GreatToken { 2 | 3 | access(all) resource interface NFT { 4 | access(all) fun id(): Int { 5 | post { 6 | result > 0 7 | } 8 | } 9 | } 10 | 11 | access(all) resource GreatNFT: NFT { 12 | access(self) let _id: Int 13 | access(self) let _special: Bool 14 | 15 | access(all) fun id(): Int { 16 | return self._id 17 | } 18 | 19 | access(all) fun isSpecial(): Bool { 20 | return self._special 21 | } 22 | 23 | init(id: Int, isSpecial: Bool) { 24 | pre { 25 | id > 0 26 | } 27 | self._id = id 28 | self._special = isSpecial 29 | } 30 | } 31 | 32 | access(all) resource GreatNFTMinter { 33 | access(all) var nextID: Int 34 | access(all) let specialMod: Int 35 | 36 | access(all) fun mint(): @GreatNFT { 37 | var isSpecial = self.nextID % self.specialMod == 0 38 | let nft <- create GreatNFT(id: self.nextID, isSpecial: isSpecial) 39 | self.nextID = self.nextID + 1 40 | return <-nft 41 | } 42 | 43 | init(firstID: Int, specialMod: Int) { 44 | pre { 45 | firstID > 0 46 | specialMod > 1 47 | } 48 | self.nextID = firstID 49 | self.specialMod = specialMod 50 | } 51 | } 52 | 53 | access(all) fun createGreatNFTMinter(firstID: Int, specialMod: Int): @GreatNFTMinter { 54 | return <-create GreatNFTMinter(firstID: firstID, specialMod: specialMod) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/http_grpc_clients/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "google.golang.org/grpc/credentials/insecure" 26 | 27 | "github.com/onflow/flow-go-sdk/access" 28 | "github.com/onflow/flow-go-sdk/access/grpc" 29 | "github.com/onflow/flow-go-sdk/access/http" 30 | "github.com/onflow/flow-go-sdk/examples" 31 | 32 | grpcOpts "google.golang.org/grpc" 33 | ) 34 | 35 | func main() { 36 | ctx := context.Background() 37 | 38 | var flowClient access.Client 39 | 40 | // initialize a http emulator client 41 | flowClient, err := http.NewClient(http.EmulatorHost) 42 | examples.Handle(err) 43 | 44 | latestBlock, err := flowClient.GetLatestBlock(ctx, true) 45 | examples.Handle(err) 46 | 47 | fmt.Println("Block ID:", latestBlock.BlockHeader.ID.String()) 48 | 49 | // initialize a gPRC emulator client 50 | flowClient, err = grpc.NewClient(grpc.EmulatorHost) 51 | examples.Handle(err) 52 | 53 | latestBlock, err = flowClient.GetLatestBlock(ctx, true) 54 | examples.Handle(err) 55 | 56 | fmt.Println("Block ID:", latestBlock.BlockHeader.ID.String()) 57 | 58 | // initialize http specific client 59 | httpClient, err := http.NewBaseClient(http.EmulatorHost) 60 | examples.Handle(err) 61 | 62 | httpBlocks, err := httpClient.GetBlocksByHeights( 63 | ctx, 64 | http.HeightQuery{ 65 | Heights: []uint64{http.SEALED}, 66 | }, 67 | ) 68 | examples.Handle(err) 69 | 70 | fmt.Println("Block ID:", httpBlocks[0].ID.String()) 71 | 72 | // initialize grpc specific client 73 | grpcClient, err := grpc.NewBaseClient( 74 | grpc.EmulatorHost, 75 | grpcOpts.WithTransportCredentials(insecure.NewCredentials()), 76 | ) 77 | examples.Handle(err) 78 | 79 | grpcBlock, err := grpcClient.GetLatestBlockHeader(ctx, true) 80 | examples.Handle(err) 81 | 82 | fmt.Println("Block ID:", grpcBlock.ID.String()) 83 | } 84 | -------------------------------------------------------------------------------- /examples/modify_account/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/templates" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/access" 29 | "github.com/onflow/flow-go-sdk/access/grpc" 30 | "github.com/onflow/flow-go-sdk/crypto" 31 | "github.com/onflow/flow-go-sdk/examples" 32 | ) 33 | 34 | func main() { 35 | ModifyAccountDemo() 36 | } 37 | 38 | func prepareAndSendTx(ctx context.Context, client access.Client, tx flow.Transaction) { 39 | serviceAcctAddr, serviceAcctKey, serviceSigner := examples.ServiceAccount(client) 40 | tx.SetProposalKey( 41 | serviceAcctAddr, 42 | serviceAcctKey.Index, 43 | serviceAcctKey.SequenceNumber, 44 | ) 45 | 46 | referenceBlockID := examples.GetReferenceBlockId(client) 47 | tx.SetReferenceBlockID(referenceBlockID) 48 | tx.SetPayer(serviceAcctAddr) 49 | 50 | err := tx.SignEnvelope(serviceAcctAddr, serviceAcctKey.Index, serviceSigner) 51 | examples.Handle(err) 52 | 53 | err = client.SendTransaction(ctx, tx) 54 | examples.Handle(err) 55 | } 56 | 57 | func keysString(keys []*flow.AccountKey) string { 58 | k := "" 59 | for _, key := range keys { 60 | k = fmt.Sprintf("%s\n%s", k, key.PublicKey.String()) 61 | } 62 | return k 63 | } 64 | 65 | func contractsString(contracts map[string][]byte) string { 66 | k := "" 67 | for name, _ := range contracts { 68 | if k == "" { 69 | k = name 70 | continue 71 | } 72 | k = fmt.Sprintf("%s, %s", k, name) 73 | } 74 | return k 75 | } 76 | 77 | func ModifyAccountDemo() { 78 | ctx := context.Background() 79 | flowClient, err := grpc.NewClient(grpc.EmulatorHost) 80 | examples.Handle(err) 81 | 82 | serviceAcctAddr, _, _ := examples.ServiceAccount(flowClient) 83 | 84 | myPrivateKey := examples.RandomPrivateKey() 85 | myAcctKey := flow.NewAccountKey(). 86 | FromPrivateKey(myPrivateKey). 87 | SetHashAlgo(crypto.SHA3_256). 88 | SetWeight(flow.AccountKeyWeightThreshold) 89 | 90 | // create a new account without any contracts 91 | createAccountTx, err := templates.CreateAccount([]*flow.AccountKey{myAcctKey}, nil, serviceAcctAddr) 92 | examples.Handle(err) 93 | prepareAndSendTx(ctx, flowClient, *createAccountTx) 94 | 95 | acc, err := flowClient.GetAccount(ctx, serviceAcctAddr) 96 | examples.Handle(err) 97 | 98 | fmt.Printf("\nInitial account contracts: %s and keys: %s", contractsString(acc.Contracts), keysString(acc.Keys)) 99 | 100 | addContractTx := templates.AddAccountContract( 101 | serviceAcctAddr, 102 | templates.Contract{ 103 | Name: "Foo", 104 | Source: "access(all) contract Foo {}", 105 | }, 106 | ) 107 | prepareAndSendTx(ctx, flowClient, *addContractTx) 108 | 109 | acc, _ = flowClient.GetAccount(ctx, serviceAcctAddr) 110 | 111 | fmt.Printf("\nDeployed contracts on the account after 'Foo' deployment: %s", contractsString(acc.Contracts)) 112 | 113 | updateTx := templates.UpdateAccountContract( 114 | serviceAcctAddr, 115 | templates.Contract{ 116 | Name: "Foo", 117 | Source: "access(all) contract Foo { access(all) fun hello() {} }", 118 | }, 119 | ) 120 | prepareAndSendTx(ctx, flowClient, *updateTx) 121 | 122 | acc, _ = flowClient.GetAccount(ctx, serviceAcctAddr) 123 | fmt.Printf("\nContract 'Foo' after update: %s", acc.Contracts["Foo"]) 124 | 125 | removeContractTx := templates.RemoveAccountContract(serviceAcctAddr, "Foo") 126 | prepareAndSendTx(ctx, flowClient, *removeContractTx) 127 | 128 | acc, _ = flowClient.GetAccount(ctx, serviceAcctAddr) 129 | fmt.Printf("\nDeployed contracts on the account after 'Foo' removal: %s", contractsString((acc.Contracts))) 130 | 131 | newPrivKey := examples.RandomPrivateKey() 132 | newAcctKey := flow.NewAccountKey(). 133 | FromPrivateKey(newPrivKey). 134 | SetHashAlgo(crypto.SHA3_256). 135 | SetWeight(flow.AccountKeyWeightThreshold) 136 | 137 | addKeyTx, err := templates.AddAccountKey(serviceAcctAddr, newAcctKey) 138 | examples.Handle(err) 139 | prepareAndSendTx(ctx, flowClient, *addKeyTx) 140 | 141 | acc, _ = flowClient.GetAccount(ctx, serviceAcctAddr) 142 | fmt.Printf("\nAccount keys after adding new key: %s", keysString(acc.Keys)) 143 | 144 | removeKeyTx := templates.RemoveAccountKey(serviceAcctAddr, 1) 145 | prepareAndSendTx(ctx, flowClient, *removeKeyTx) 146 | 147 | acc, _ = flowClient.GetAccount(ctx, serviceAcctAddr) 148 | fmt.Printf("\nAccount keys after removing the last key: %s", keysString(acc.Keys)) 149 | } 150 | -------------------------------------------------------------------------------- /examples/send_and_subscribe_transaction_statuses/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | "log" 25 | 26 | "github.com/onflow/flow-go-sdk" 27 | "github.com/onflow/flow-go-sdk/access/grpc" 28 | "github.com/onflow/flow-go-sdk/crypto" 29 | "github.com/onflow/flow-go-sdk/examples" 30 | ) 31 | 32 | func main() { 33 | demo() 34 | } 35 | 36 | func demo() { 37 | ctx := context.Background() 38 | flowClient, err := grpc.NewClient(grpc.TestnetHost) 39 | examples.Handle(err) 40 | 41 | signerIndex := uint32(0) 42 | 43 | signerPublicAddress := flow.HexToAddress("YOUR_ACCOUNT_ADDRESS") 44 | signerAccount, err := flowClient.GetAccount(ctx, signerPublicAddress) 45 | if err != nil { 46 | log.Fatalf("Failed to get account: %v", err) 47 | } 48 | seqNumber := signerAccount.Keys[0].SequenceNumber 49 | 50 | privateKeyHex := "YOUR_PRIVATE_KEY" 51 | privateKey, err := crypto.DecodePrivateKeyHex(crypto.ECDSA_P256, privateKeyHex) 52 | if err != nil { 53 | log.Fatalf("Failed to decode private key: %v", err) 54 | } 55 | 56 | // Create crypto signer 57 | signer, err := crypto.NewInMemorySigner(privateKey, crypto.SHA3_256) 58 | if err != nil { 59 | log.Fatalf("Failed to decode private key: %v", err) 60 | } 61 | 62 | tx := flow.NewTransaction(). 63 | SetPayer(signerPublicAddress). 64 | SetProposalKey(signerPublicAddress, signerIndex, seqNumber). 65 | SetScript([]byte(` 66 | transaction { 67 | prepare(acc: &Account) {} 68 | execute { 69 | log("test") 70 | } 71 | } 72 | `)). 73 | AddAuthorizer(signerPublicAddress). 74 | SetReferenceBlockID(examples.GetReferenceBlockId(flowClient)) 75 | 76 | err = tx.SignEnvelope(signerPublicAddress, signerIndex, signer) 77 | examples.Handle(err) 78 | 79 | txResultChan, errChan, initErr := flowClient.SendAndSubscribeTransactionStatuses(ctx, *tx) 80 | examples.Handle(initErr) 81 | 82 | for { 83 | select { 84 | case <-ctx.Done(): 85 | return 86 | case txResult, ok := <-txResultChan: 87 | if !ok { 88 | examples.Print("transaction result channel is closed") 89 | return 90 | } 91 | examples.Print(txResult) 92 | case err := <-errChan: 93 | if err != nil { 94 | examples.Print(fmt.Errorf("~~~ ERROR: %w ~~~\n", err)) 95 | } 96 | return 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /examples/send_transactions/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | 24 | "github.com/onflow/flow-go-sdk/access/http" 25 | 26 | "github.com/onflow/flow-go-sdk" 27 | "github.com/onflow/flow-go-sdk/examples" 28 | ) 29 | 30 | func main() { 31 | demo() 32 | } 33 | 34 | func demo() { 35 | flowClient, err := http.NewClient(http.EmulatorHost) 36 | examples.Handle(err) 37 | 38 | serviceAcctAddr, serviceAcctKey, serviceSigner := examples.ServiceAccount(flowClient) 39 | 40 | tx := flow.NewTransaction(). 41 | SetPayer(serviceAcctAddr). 42 | SetProposalKey(serviceAcctAddr, serviceAcctKey.Index, serviceAcctKey.SequenceNumber). 43 | SetScript([]byte(` 44 | transaction { 45 | prepare(signer: auth(Storage) &Account) {} 46 | execute { 47 | log("test") 48 | } 49 | } 50 | `)). 51 | AddAuthorizer(serviceAcctAddr). 52 | SetReferenceBlockID(examples.GetReferenceBlockId(flowClient)) 53 | 54 | err = tx.SignEnvelope(serviceAcctAddr, serviceAcctKey.Index, serviceSigner) 55 | examples.Handle(err) 56 | 57 | err = flowClient.SendTransaction(context.Background(), *tx) 58 | examples.Handle(err) 59 | } 60 | -------------------------------------------------------------------------------- /examples/stream_account_statuses/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/grpc" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | demo() 33 | } 34 | 35 | func demo() { 36 | ctx := context.Background() 37 | flowClient, err := grpc.NewClient("access.testnet.nodes.onflow.org:9000") 38 | examples.Handle(err) 39 | 40 | header, err := flowClient.GetLatestBlockHeader(ctx, true) 41 | examples.Handle(err) 42 | fmt.Printf("Latest block height: %d\n", header.Height) 43 | fmt.Printf("Latest block ID: %s\n", header.ID) 44 | 45 | flowEVMTestnetAddress := "0x8c5303eaa26202d6" 46 | filter := flow.AccountStatusFilter{ 47 | EventFilter: flow.EventFilter{ 48 | Addresses: []string{flowEVMTestnetAddress}, 49 | }, 50 | } 51 | accountStatusesChan, errChan, initErr := flowClient.SubscribeAccountStatusesFromStartBlockID(ctx, header.ID, filter) 52 | examples.Handle(initErr) 53 | 54 | for { 55 | select { 56 | case <-ctx.Done(): 57 | return 58 | case accountStatus, ok := <-accountStatusesChan: 59 | if !ok { 60 | panic("account statuses channel is closed") 61 | } 62 | examples.Print(accountStatus) 63 | case err, ok := <-errChan: 64 | if !ok { 65 | panic("error channel is closed") 66 | } 67 | fmt.Printf("~~~ ERROR: %s ~~~\n", err.Error()) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /examples/stream_block_digests/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/grpc" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | demo() 33 | } 34 | 35 | func demo() { 36 | ctx := context.Background() 37 | flowClient, err := grpc.NewClient("access.testnet.nodes.onflow.org:9000") 38 | examples.Handle(err) 39 | 40 | header, err := flowClient.GetLatestBlockHeader(ctx, true) 41 | examples.Handle(err) 42 | fmt.Printf("Block Height: %d\n", header.Height) 43 | fmt.Printf("Block ID: %s\n", header.ID) 44 | 45 | blockDigestsChan, errChan, initErr := flowClient.SubscribeBlockDigestsFromStartBlockID(ctx, header.ID, flow.BlockStatusFinalized) 46 | examples.Handle(initErr) 47 | 48 | for { 49 | select { 50 | case <-ctx.Done(): 51 | return 52 | case blockDigest, ok := <-blockDigestsChan: 53 | if !ok { 54 | panic("block digest channel is closed") 55 | } 56 | examples.Print(blockDigest) 57 | case err, ok := <-errChan: 58 | if !ok { 59 | panic("error channel is closed") 60 | } 61 | fmt.Printf("~~~ ERROR: %s ~~~\n", err.Error()) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /examples/stream_block_headers/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/grpc" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | demo() 33 | } 34 | 35 | func demo() { 36 | ctx := context.Background() 37 | flowClient, err := grpc.NewClient("access.testnet.nodes.onflow.org:9000") 38 | examples.Handle(err) 39 | 40 | header, err := flowClient.GetLatestBlockHeader(ctx, true) 41 | examples.Handle(err) 42 | fmt.Printf("Latest block height: %d\n", header.Height) 43 | fmt.Printf("Latest block ID: %s\n", header.ID) 44 | 45 | blockHeadersChan, errChan, initErr := flowClient.SubscribeBlockHeadersFromStartBlockID(ctx, header.ID, flow.BlockStatusFinalized) 46 | examples.Handle(initErr) 47 | 48 | for { 49 | select { 50 | case <-ctx.Done(): 51 | return 52 | case blockHeader, ok := <-blockHeadersChan: 53 | if !ok { 54 | panic("block header channel is closed") 55 | } 56 | examples.Print(blockHeader) 57 | case err, ok := <-errChan: 58 | if !ok { 59 | panic("error channel is closed") 60 | } 61 | fmt.Printf("~~~ ERROR: %s ~~~\n", err.Error()) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /examples/stream_blocks/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/grpc" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | demo() 33 | } 34 | 35 | func demo() { 36 | ctx := context.Background() 37 | flowClient, err := grpc.NewClient("access.testnet.nodes.onflow.org:9000") 38 | examples.Handle(err) 39 | 40 | header, err := flowClient.GetLatestBlockHeader(ctx, true) 41 | examples.Handle(err) 42 | fmt.Printf("Latest block height: %d\n", header.Height) 43 | fmt.Printf("Latest block ID: %s\n", header.ID) 44 | 45 | blocksChan, errChan, initErr := flowClient.SubscribeBlocksFromStartBlockID(ctx, header.ID, flow.BlockStatusFinalized) 46 | examples.Handle(initErr) 47 | 48 | for { 49 | select { 50 | case <-ctx.Done(): 51 | return 52 | case block, ok := <-blocksChan: 53 | if !ok { 54 | panic("blocks channel is closed") 55 | } 56 | examples.Print(block) 57 | case err, ok := <-errChan: 58 | if !ok { 59 | panic("error channel is closed") 60 | } 61 | fmt.Printf("~~~ ERROR: %s ~~~\n", err.Error()) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /examples/stream_events/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/grpc" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | demo() 33 | } 34 | 35 | func demo() { 36 | ctx := context.Background() 37 | flowClient, err := grpc.NewClient(grpc.TestnetHost) 38 | examples.Handle(err) 39 | 40 | header, err := flowClient.GetLatestBlockHeader(ctx, true) 41 | examples.Handle(err) 42 | fmt.Printf("Block Height: %d\n", header.Height) 43 | fmt.Printf("Block ID: %s\n", header.ID) 44 | 45 | data, errChan, initErr := flowClient.SubscribeEventsByBlockID(ctx, header.ID, flow.EventFilter{}) 46 | examples.Handle(initErr) 47 | 48 | for { 49 | select { 50 | case <-ctx.Done(): 51 | return 52 | case eventData, ok := <-data: 53 | if !ok { 54 | panic("data subscription closed") 55 | } 56 | fmt.Printf("~~~ Height: %d ~~~\n", eventData.Height) 57 | printEvents(eventData.Events) 58 | case err, ok := <-errChan: 59 | if !ok { 60 | panic("error channel subscription closed") 61 | } 62 | fmt.Printf("~~~ ERROR: %s ~~~\n", err.Error()) 63 | } 64 | } 65 | } 66 | 67 | func printEvents(events []flow.Event) { 68 | for _, event := range events { 69 | fmt.Printf("\n\nType: %s", event.Type) 70 | fmt.Printf("\nValues: %v", event.Value) 71 | fmt.Printf("\nTransaction ID: %s", event.TransactionID) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /examples/stream_events_reconnect/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/grpc" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | demo() 33 | } 34 | 35 | // This is an example of streaming events, and handling reconnect when errors are encountered on the stream. 36 | 37 | func demo() { 38 | ctx := context.Background() 39 | flowClient, err := grpc.NewClient("access.testnet.nodes.onflow.org:9000") 40 | examples.Handle(err) 41 | 42 | header, err := flowClient.GetLatestBlockHeader(ctx, true) 43 | examples.Handle(err) 44 | fmt.Printf("Block Height: %d\n", header.Height) 45 | fmt.Printf("Block ID: %s\n", header.ID) 46 | 47 | data, errChan, initErr := flowClient.SubscribeEventsByBlockID(ctx, header.ID, flow.EventFilter{}) 48 | examples.Handle(initErr) 49 | 50 | reconnect := func(height uint64) { 51 | fmt.Printf("Reconnecting at block %d\n", height) 52 | 53 | var err error 54 | flowClient, err = grpc.NewClient("access.testnet.nodes.onflow.org:9000") 55 | examples.Handle(err) 56 | 57 | data, errChan, err = flowClient.SubscribeEventsByBlockHeight(ctx, height, flow.EventFilter{}) 58 | examples.Handle(err) 59 | } 60 | 61 | // track the most recently seen block height. we will use this when reconnecting 62 | lastHeight := header.Height 63 | for { 64 | select { 65 | case <-ctx.Done(): 66 | return 67 | 68 | case eventData, ok := <-data: 69 | if !ok { 70 | if ctx.Err() != nil { 71 | return // graceful shutdown 72 | } 73 | // unexpected close 74 | reconnect(lastHeight + 1) 75 | continue 76 | } 77 | 78 | fmt.Printf("~~~ Height: %d ~~~\n", eventData.Height) 79 | printEvents(eventData.Events) 80 | 81 | lastHeight = eventData.Height 82 | 83 | case err, ok := <-errChan: 84 | if !ok { 85 | if ctx.Err() != nil { 86 | return // graceful shutdown 87 | } 88 | // unexpected close 89 | reconnect(lastHeight + 1) 90 | continue 91 | } 92 | 93 | fmt.Printf("~~~ ERROR: %s ~~~\n", err.Error()) 94 | reconnect(lastHeight + 1) 95 | continue 96 | } 97 | } 98 | 99 | } 100 | 101 | func printEvents(events []flow.Event) { 102 | for _, event := range events { 103 | fmt.Printf("\nType: %s\n", event.Type) 104 | fmt.Printf("Values: %v\n", event.Value) 105 | fmt.Printf("Transaction ID: %s\n", event.TransactionID) 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /examples/stream_execution_data/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/grpc" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | demo() 33 | } 34 | 35 | func demo() { 36 | ctx := context.Background() 37 | flowClient, err := grpc.NewClient(grpc.TestnetHost) 38 | examples.Handle(err) 39 | 40 | header, err := flowClient.GetLatestBlockHeader(ctx, true) 41 | examples.Handle(err) 42 | fmt.Printf("Block Height: %d\n", header.Height) 43 | fmt.Printf("Block ID: %s\n", header.ID) 44 | 45 | data, errChan, initErr := flowClient.SubscribeExecutionDataByBlockID(ctx, header.ID) 46 | examples.Handle(initErr) 47 | 48 | for { 49 | select { 50 | case <-ctx.Done(): 51 | return 52 | case execData, ok := <-data: 53 | if !ok { 54 | panic("exec data subscription closed") 55 | } 56 | fmt.Printf("~~~ Height: %d ~~~\n", execData.Height) 57 | printExecutionData(execData.ExecutionData) 58 | case err, ok := <-errChan: 59 | if !ok { 60 | panic("error channel subscription closed") 61 | } 62 | fmt.Printf("~~~ ERROR: %s ~~~\n", err.Error()) 63 | } 64 | } 65 | 66 | } 67 | 68 | func printExecutionData(ed *flow.ExecutionData) { 69 | for chunkNo, chunk := range ed.ChunkExecutionData { 70 | fmt.Printf("-- Chunk %d/%d --\n", chunkNo+1, len(ed.ChunkExecutionData)) 71 | fmt.Printf("Transactions: %d\n", len(chunk.Transactions)) 72 | for txNo, tx := range chunk.Transactions { 73 | fmt.Printf("Transaction %d/%d:\n", txNo+1, len(chunk.Transactions)) 74 | printTransaction(tx) 75 | } 76 | fmt.Printf("Events: %d\n", len(chunk.Events)) 77 | for eventNo, event := range chunk.Events { 78 | fmt.Printf("Event %d/%d: %s\n", eventNo+1, len(chunk.Events), event.Type) 79 | } 80 | if chunk.TrieUpdate != nil { 81 | modifiedAccounts := extractModifiedAccounts(chunk.TrieUpdate) 82 | fmt.Printf("Modified Accounts: %d\n", len(modifiedAccounts)) 83 | for i, acc := range modifiedAccounts { 84 | fmt.Printf("Account %d/%d: %s\n", i+1, len(modifiedAccounts), acc.Hex()) 85 | } 86 | fmt.Printf("TrieUpdate RootHash: %s\n", flow.BytesToHash(chunk.TrieUpdate.RootHash).Hex()) 87 | fmt.Printf("TrieUpdate Paths:\n") 88 | for pathNo, path := range chunk.TrieUpdate.Paths { 89 | fmt.Printf("Path %d/%d: %s", pathNo+1, len(chunk.TrieUpdate.Paths), flow.BytesToHash(path)) 90 | } 91 | fmt.Printf("TrieUpdate Payloads:\n") 92 | for payloadNo, payload := range chunk.TrieUpdate.Payloads { 93 | fmt.Printf("Payload %d/%d:\n", payloadNo+1, len(chunk.TrieUpdate.Payloads)) 94 | fmt.Printf("Value: %x\n", string(payload.Value)) 95 | for kpi, kp := range payload.KeyPart { 96 | fmt.Printf("KeyPart[%d].Type: %d\n", kpi, kp.Type) 97 | fmt.Printf("KeyPart[%d].Value: %x\n", kpi, kp.Value) 98 | } 99 | 100 | } 101 | } else { 102 | fmt.Printf("\nNo TrieUpdate") 103 | } 104 | } 105 | } 106 | 107 | func printTransaction(tx *flow.Transaction) { 108 | fmt.Printf("\nID: %s", tx.ID().String()) 109 | fmt.Printf("\nPayer: %s", tx.Payer.String()) 110 | fmt.Printf("\nProposer: %s", tx.ProposalKey.Address.String()) 111 | fmt.Printf("\nAuthorizers: %s", tx.Authorizers) 112 | } 113 | 114 | func extractModifiedAccounts(update *flow.TrieUpdate) []flow.Address { 115 | 116 | accounts := map[flow.Address]struct{}{} 117 | 118 | for _, payload := range update.Payloads { 119 | address := flow.BytesToAddress(payload.KeyPart[0].Value) 120 | accounts[address] = struct{}{} 121 | } 122 | 123 | addresses := make([]flow.Address, 0, len(accounts)) 124 | for address := range accounts { 125 | addresses = append(addresses, address) 126 | } 127 | 128 | return addresses 129 | } 130 | -------------------------------------------------------------------------------- /examples/transaction_arguments/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/cadence" 28 | 29 | "github.com/onflow/flow-go-sdk" 30 | "github.com/onflow/flow-go-sdk/examples" 31 | "github.com/onflow/flow-go-sdk/test" 32 | ) 33 | 34 | func main() { 35 | TransactionArgumentsDemo() 36 | } 37 | 38 | func TransactionArgumentsDemo() { 39 | ctx := context.Background() 40 | flowClient, err := http.NewClient(http.EmulatorHost) 41 | examples.Handle(err) 42 | 43 | serviceAcctAddr, serviceAcctKey, serviceSigner := examples.ServiceAccount(flowClient) 44 | 45 | message := test.GreetingGenerator().Random() 46 | greeting := cadence.String(message) 47 | 48 | referenceBlockID := examples.GetReferenceBlockId(flowClient) 49 | tx := flow.NewTransaction(). 50 | SetScript(test.GreetingScript). 51 | SetProposalKey(serviceAcctAddr, serviceAcctKey.Index, serviceAcctKey.SequenceNumber). 52 | SetReferenceBlockID(referenceBlockID). 53 | SetPayer(serviceAcctAddr) 54 | 55 | err = tx.AddArgument(greeting) 56 | examples.Handle(err) 57 | 58 | fmt.Println("Sending transaction:") 59 | fmt.Println() 60 | fmt.Println("----------------") 61 | fmt.Println("Script:") 62 | fmt.Println(string(tx.Script)) 63 | fmt.Println("Arguments:") 64 | fmt.Printf("greeting: %s\n", greeting) 65 | fmt.Println("----------------") 66 | fmt.Println() 67 | 68 | err = tx.SignEnvelope(serviceAcctAddr, serviceAcctKey.Index, serviceSigner) 69 | examples.Handle(err) 70 | 71 | err = flowClient.SendTransaction(ctx, *tx) 72 | examples.Handle(err) 73 | 74 | _ = examples.WaitForSeal(ctx, flowClient, tx.ID()) 75 | } 76 | -------------------------------------------------------------------------------- /examples/transaction_signing/multi_party/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/crypto" 29 | "github.com/onflow/flow-go-sdk/examples" 30 | ) 31 | 32 | func main() { 33 | MultiPartySingleSignatureDemo() 34 | } 35 | 36 | func MultiPartySingleSignatureDemo() { 37 | ctx := context.Background() 38 | flowClient, err := http.NewClient(http.EmulatorHost) 39 | examples.Handle(err) 40 | 41 | privateKey1 := examples.RandomPrivateKey() 42 | privateKey3 := examples.RandomPrivateKey() 43 | 44 | key1 := flow.NewAccountKey(). 45 | SetPublicKey(privateKey1.PublicKey()). 46 | SetSigAlgo(privateKey1.Algorithm()). 47 | SetHashAlgo(crypto.SHA3_256). 48 | SetWeight(flow.AccountKeyWeightThreshold) 49 | 50 | key1Signer, err := crypto.NewInMemorySigner(privateKey1, key1.HashAlgo) 51 | examples.Handle(err) 52 | 53 | key3 := flow.NewAccountKey(). 54 | SetPublicKey(privateKey3.PublicKey()). 55 | SetSigAlgo(privateKey3.Algorithm()). 56 | SetHashAlgo(crypto.SHA3_256). 57 | SetWeight(flow.AccountKeyWeightThreshold) 58 | 59 | key3Signer, err := crypto.NewInMemorySigner(privateKey3, key3.HashAlgo) 60 | examples.Handle(err) 61 | 62 | account1 := examples.CreateAccount(flowClient, []*flow.AccountKey{key1}) 63 | account2 := examples.CreateAccount(flowClient, []*flow.AccountKey{key3}) 64 | // Add some flow for the transaction fees 65 | examples.FundAccountInEmulator(flowClient, account2.Address, 1.0) 66 | 67 | referenceBlockID := examples.GetReferenceBlockId(flowClient) 68 | 69 | tx := flow.NewTransaction(). 70 | SetScript([]byte(` 71 | transaction { 72 | prepare(signer: auth(Storage) &Account) { log(signer.address) } 73 | } 74 | `)). 75 | SetComputeLimit(100). 76 | SetProposalKey(account1.Address, account1.Keys[0].Index, account1.Keys[0].SequenceNumber). 77 | SetReferenceBlockID(referenceBlockID). 78 | SetPayer(account2.Address). 79 | AddAuthorizer(account1.Address) 80 | 81 | // account 1 signs the payload with key 1 82 | err = tx.SignPayload(account1.Address, account1.Keys[0].Index, key1Signer) 83 | examples.Handle(err) 84 | 85 | // account 2 signs the envelope with key 3 86 | err = tx.SignEnvelope(account2.Address, account2.Keys[0].Index, key3Signer) 87 | examples.Handle(err) 88 | 89 | err = flowClient.SendTransaction(ctx, *tx) 90 | examples.Handle(err) 91 | 92 | examples.WaitForSeal(ctx, flowClient, tx.ID()) 93 | 94 | fmt.Println("Transaction complete!") 95 | } 96 | -------------------------------------------------------------------------------- /examples/transaction_signing/multi_party_multisig/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/crypto" 29 | "github.com/onflow/flow-go-sdk/examples" 30 | ) 31 | 32 | func main() { 33 | MultiPartyMultiSignatureDemo() 34 | } 35 | 36 | func MultiPartyMultiSignatureDemo() { 37 | ctx := context.Background() 38 | flowClient, err := http.NewClient(http.EmulatorHost) 39 | examples.Handle(err) 40 | 41 | privateKey1 := examples.RandomPrivateKey() 42 | privateKey2 := examples.RandomPrivateKey() 43 | privateKey3 := examples.RandomPrivateKey() 44 | privateKey4 := examples.RandomPrivateKey() 45 | 46 | key1 := flow.NewAccountKey(). 47 | SetPublicKey(privateKey1.PublicKey()). 48 | SetSigAlgo(privateKey1.Algorithm()). 49 | SetHashAlgo(crypto.SHA3_256). 50 | SetWeight(flow.AccountKeyWeightThreshold / 2) 51 | 52 | key1Signer, err := crypto.NewInMemorySigner(privateKey1, key1.HashAlgo) 53 | examples.Handle(err) 54 | 55 | key2 := flow.NewAccountKey(). 56 | SetPublicKey(privateKey2.PublicKey()). 57 | SetSigAlgo(privateKey2.Algorithm()). 58 | SetHashAlgo(crypto.SHA3_256). 59 | SetWeight(flow.AccountKeyWeightThreshold / 2) 60 | 61 | key2Signer, err := crypto.NewInMemorySigner(privateKey2, key2.HashAlgo) 62 | examples.Handle(err) 63 | 64 | key3 := flow.NewAccountKey(). 65 | SetPublicKey(privateKey3.PublicKey()). 66 | SetSigAlgo(privateKey3.Algorithm()). 67 | SetHashAlgo(crypto.SHA3_256). 68 | SetWeight(flow.AccountKeyWeightThreshold / 2) 69 | 70 | key3Signer, err := crypto.NewInMemorySigner(privateKey3, key3.HashAlgo) 71 | examples.Handle(err) 72 | 73 | key4 := flow.NewAccountKey(). 74 | SetPublicKey(privateKey4.PublicKey()). 75 | SetSigAlgo(privateKey4.Algorithm()). 76 | SetHashAlgo(crypto.SHA3_256). 77 | SetWeight(flow.AccountKeyWeightThreshold / 2) 78 | 79 | key4Signer, err := crypto.NewInMemorySigner(privateKey4, key4.HashAlgo) 80 | examples.Handle(err) 81 | 82 | account1 := examples.CreateAccount(flowClient, []*flow.AccountKey{key1, key2}) 83 | account2 := examples.CreateAccount(flowClient, []*flow.AccountKey{key3, key4}) 84 | // Add some flow for the transaction fees 85 | examples.FundAccountInEmulator(flowClient, account2.Address, 1.0) 86 | 87 | referenceBlockID := examples.GetReferenceBlockId(flowClient) 88 | 89 | tx := flow.NewTransaction(). 90 | SetScript([]byte(` 91 | transaction { 92 | prepare(signer: auth(Storage) &Account) { log(signer.address) } 93 | } 94 | `)). 95 | SetComputeLimit(100). 96 | SetProposalKey(account1.Address, account1.Keys[0].Index, account1.Keys[0].SequenceNumber). 97 | SetReferenceBlockID(referenceBlockID). 98 | SetPayer(account2.Address). 99 | AddAuthorizer(account1.Address) 100 | 101 | // account 1 signs the payload with key 1 102 | err = tx.SignPayload(account1.Address, account1.Keys[0].Index, key1Signer) 103 | examples.Handle(err) 104 | 105 | // account 1 signs the payload with key 2 106 | err = tx.SignPayload(account1.Address, account1.Keys[1].Index, key2Signer) 107 | examples.Handle(err) 108 | 109 | // account 2 signs the envelope with key 3 110 | err = tx.SignEnvelope(account2.Address, account2.Keys[0].Index, key3Signer) 111 | examples.Handle(err) 112 | 113 | // account 2 signs the envelope with key 4 114 | err = tx.SignEnvelope(account2.Address, account2.Keys[1].Index, key4Signer) 115 | examples.Handle(err) 116 | 117 | err = flowClient.SendTransaction(ctx, *tx) 118 | examples.Handle(err) 119 | 120 | examples.WaitForSeal(ctx, flowClient, tx.ID()) 121 | 122 | fmt.Println("Transaction complete!") 123 | } 124 | -------------------------------------------------------------------------------- /examples/transaction_signing/multi_party_two_authorizers/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | "github.com/onflow/flow-go-sdk/crypto" 29 | "github.com/onflow/flow-go-sdk/examples" 30 | ) 31 | 32 | func main() { 33 | MultiPartySingleSignatureDemo() 34 | } 35 | 36 | func MultiPartySingleSignatureDemo() { 37 | ctx := context.Background() 38 | flowClient, err := http.NewClient(http.EmulatorHost) 39 | examples.Handle(err) 40 | 41 | privateKey1 := examples.RandomPrivateKey() 42 | privateKey3 := examples.RandomPrivateKey() 43 | 44 | key1 := flow.NewAccountKey(). 45 | SetPublicKey(privateKey1.PublicKey()). 46 | SetSigAlgo(privateKey1.Algorithm()). 47 | SetHashAlgo(crypto.SHA3_256). 48 | SetWeight(flow.AccountKeyWeightThreshold) 49 | 50 | key1Signer, err := crypto.NewInMemorySigner(privateKey1, key1.HashAlgo) 51 | examples.Handle(err) 52 | 53 | key3 := flow.NewAccountKey(). 54 | SetPublicKey(privateKey3.PublicKey()). 55 | SetSigAlgo(privateKey3.Algorithm()). 56 | SetHashAlgo(crypto.SHA3_256). 57 | SetWeight(flow.AccountKeyWeightThreshold) 58 | 59 | key3Signer, err := crypto.NewInMemorySigner(privateKey3, key3.HashAlgo) 60 | examples.Handle(err) 61 | 62 | account1 := examples.CreateAccount(flowClient, []*flow.AccountKey{key1}) 63 | account2 := examples.CreateAccount(flowClient, []*flow.AccountKey{key3}) 64 | // Add some flow for the transaction fees 65 | examples.FundAccountInEmulator(flowClient, account2.Address, 1.0) 66 | 67 | referenceBlockID := examples.GetReferenceBlockId(flowClient) 68 | tx := flow.NewTransaction(). 69 | SetScript([]byte(` 70 | transaction { 71 | prepare(signer1: auth(Storage) &Account, signer2: auth(Storage) &Account) { 72 | log(signer1.address) 73 | log(signer2.address) 74 | } 75 | }`)). 76 | SetComputeLimit(100). 77 | SetProposalKey(account1.Address, account1.Keys[0].Index, account1.Keys[0].SequenceNumber). 78 | SetReferenceBlockID(referenceBlockID). 79 | SetPayer(account2.Address). 80 | AddAuthorizer(account1.Address). 81 | AddAuthorizer(account2.Address) 82 | 83 | // account 1 signs the payload with key 1 84 | err = tx.SignPayload(account1.Address, account1.Keys[0].Index, key1Signer) 85 | examples.Handle(err) 86 | 87 | // account 2 signs the envelope with key 3 88 | err = tx.SignEnvelope(account2.Address, account2.Keys[0].Index, key3Signer) 89 | examples.Handle(err) 90 | 91 | err = flowClient.SendTransaction(ctx, *tx) 92 | examples.Handle(err) 93 | 94 | examples.WaitForSeal(ctx, flowClient, tx.ID()) 95 | 96 | fmt.Println("Transaction complete!") 97 | } 98 | -------------------------------------------------------------------------------- /examples/transaction_signing/single_party/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk" 26 | "github.com/onflow/flow-go-sdk/access/http" 27 | "github.com/onflow/flow-go-sdk/crypto" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | SinglePartySingleSignatureDemo() 33 | } 34 | 35 | func SinglePartySingleSignatureDemo() { 36 | ctx := context.Background() 37 | flowClient, err := http.NewClient(http.EmulatorHost) 38 | examples.Handle(err) 39 | 40 | privateKey1 := examples.RandomPrivateKey() 41 | 42 | key1 := flow.NewAccountKey(). 43 | SetPublicKey(privateKey1.PublicKey()). 44 | SetSigAlgo(privateKey1.Algorithm()). 45 | SetHashAlgo(crypto.SHA3_256). 46 | SetWeight(flow.AccountKeyWeightThreshold) 47 | 48 | key1Signer, err := crypto.NewInMemorySigner(privateKey1, key1.HashAlgo) 49 | examples.Handle(err) 50 | 51 | account1 := examples.CreateAccount(flowClient, []*flow.AccountKey{key1}) 52 | // Add some flow for the transaction fees 53 | examples.FundAccountInEmulator(flowClient, account1.Address, 1.0) 54 | 55 | referenceBlockID := examples.GetReferenceBlockId(flowClient) 56 | tx := flow.NewTransaction(). 57 | SetScript([]byte(` 58 | transaction { 59 | prepare(signer: auth(Storage) &Account) { log(signer.address) } 60 | } 61 | `)). 62 | SetComputeLimit(100). 63 | SetProposalKey(account1.Address, account1.Keys[0].Index, account1.Keys[0].SequenceNumber). 64 | SetReferenceBlockID(referenceBlockID). 65 | SetPayer(account1.Address). 66 | AddAuthorizer(account1.Address) 67 | 68 | // account 1 signs the envelope with key 1 69 | err = tx.SignEnvelope(account1.Address, account1.Keys[0].Index, key1Signer) 70 | examples.Handle(err) 71 | 72 | err = flowClient.SendTransaction(ctx, *tx) 73 | examples.Handle(err) 74 | 75 | examples.WaitForSeal(ctx, flowClient, tx.ID()) 76 | 77 | fmt.Println("Transaction complete!") 78 | } 79 | -------------------------------------------------------------------------------- /examples/transaction_signing/single_party_multisig/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk" 26 | "github.com/onflow/flow-go-sdk/access/http" 27 | "github.com/onflow/flow-go-sdk/crypto" 28 | "github.com/onflow/flow-go-sdk/examples" 29 | ) 30 | 31 | func main() { 32 | SinglePartyMultiSignatureDemo() 33 | } 34 | 35 | func SinglePartyMultiSignatureDemo() { 36 | ctx := context.Background() 37 | flowClient, err := http.NewClient(http.EmulatorHost) 38 | examples.Handle(err) 39 | 40 | privateKey1 := examples.RandomPrivateKey() 41 | privateKey2 := examples.RandomPrivateKey() 42 | 43 | key1 := flow.NewAccountKey(). 44 | SetPublicKey(privateKey1.PublicKey()). 45 | SetSigAlgo(privateKey1.Algorithm()). 46 | SetHashAlgo(crypto.SHA3_256). 47 | SetWeight(flow.AccountKeyWeightThreshold / 2) 48 | 49 | key1Signer, err := crypto.NewInMemorySigner(privateKey1, key1.HashAlgo) 50 | examples.Handle(err) 51 | 52 | key2 := flow.NewAccountKey(). 53 | SetPublicKey(privateKey2.PublicKey()). 54 | SetSigAlgo(privateKey2.Algorithm()). 55 | SetHashAlgo(crypto.SHA3_256). 56 | SetWeight(flow.AccountKeyWeightThreshold / 2) 57 | 58 | key2Signer, err := crypto.NewInMemorySigner(privateKey2, key2.HashAlgo) 59 | examples.Handle(err) 60 | 61 | account1 := examples.CreateAccount(flowClient, []*flow.AccountKey{key1, key2}) 62 | // Add some flow for the transaction fees 63 | examples.FundAccountInEmulator(flowClient, account1.Address, 1.0) 64 | 65 | referenceBlockID := examples.GetReferenceBlockId(flowClient) 66 | tx := flow.NewTransaction(). 67 | SetScript([]byte(` 68 | transaction { 69 | prepare(signer: auth(Storage) &Account) { log(signer.address) } 70 | } 71 | `)). 72 | SetComputeLimit(100). 73 | SetProposalKey(account1.Address, account1.Keys[0].Index, account1.Keys[0].SequenceNumber). 74 | SetReferenceBlockID(referenceBlockID). 75 | SetPayer(account1.Address). 76 | AddAuthorizer(account1.Address) 77 | 78 | // account 1 signs the envelope with key 1 79 | err = tx.SignEnvelope(account1.Address, account1.Keys[0].Index, key1Signer) 80 | examples.Handle(err) 81 | 82 | // account 1 signs the envelope with key 2 83 | err = tx.SignEnvelope(account1.Address, account1.Keys[1].Index, key2Signer) 84 | examples.Handle(err) 85 | 86 | err = flowClient.SendTransaction(ctx, *tx) 87 | examples.Handle(err) 88 | 89 | examples.WaitForSeal(ctx, flowClient, tx.ID()) 90 | 91 | fmt.Println("Transaction complete!") 92 | } 93 | -------------------------------------------------------------------------------- /examples/verify_events/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "fmt" 24 | 25 | "github.com/onflow/flow-go-sdk/access/http" 26 | 27 | "github.com/onflow/flow-go-sdk" 28 | 29 | "github.com/onflow/flow-go-sdk/examples" 30 | ) 31 | 32 | func main() { 33 | VerifyEventsDemo() 34 | } 35 | 36 | // VerifyEventsDemo showcases how clients can verify events they received. 37 | // In mature Flow we provision different methods to verify the subset of events queried, however 38 | // for now the only verification available is the hash of all the events emitted in a Chunk/Collection. 39 | // This hash is verified by Verification Nodes so it's correctness is checked. 40 | // For users, its possible to get all the events for chunk, calculate and compare the resulting hash 41 | func VerifyEventsDemo() { 42 | ctx := context.Background() 43 | flowClient, err := http.NewClient(http.TestnetHost) 44 | examples.Handle(err) 45 | 46 | latestBlockHeader, err := flowClient.GetLatestBlockHeader(ctx, true) 47 | examples.Handle(err) 48 | 49 | block, err := flowClient.GetBlockByID(ctx, latestBlockHeader.ID) 50 | examples.Handle(err) 51 | 52 | executionResult, err := flowClient.GetExecutionResultForBlockID(ctx, block.ID) 53 | examples.Handle(err) 54 | 55 | totalEvents := 0 56 | 57 | for i, colGuarantee := range block.CollectionGuarantees { 58 | collection, err := flowClient.GetCollection(ctx, colGuarantee.CollectionID) 59 | examples.Handle(err) 60 | 61 | events := make([]flow.Event, 0) 62 | 63 | // only way to get all the events regardless of the type is querying by transaction 64 | for _, txID := range collection.TransactionIDs { 65 | transactionResult, err := flowClient.GetTransactionResult(ctx, txID) 66 | examples.Handle(err) 67 | 68 | for _, event := range transactionResult.Events { 69 | events = append(events, event) 70 | } 71 | } 72 | 73 | calculatedEventsHash, err := flow.CalculateEventsHash(events) 74 | examples.Handle(err) 75 | 76 | // there should be more chunks (one last is system chunk), so we don't check range here 77 | chunk := executionResult.Chunks[i] 78 | 79 | if !calculatedEventsHash.Equal(chunk.EventCollection) { 80 | examples.Handle(fmt.Errorf("events hash mismatch, expected %s, calculated %s", chunk.EventCollection, calculatedEventsHash)) 81 | } 82 | 83 | totalEvents += len(events) 84 | } 85 | 86 | fmt.Printf("Events verified for block %s, total %d events\n", block.ID, totalEvents) 87 | } 88 | -------------------------------------------------------------------------------- /examples/verify_signature/user_signature/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "encoding/hex" 24 | "fmt" 25 | 26 | "github.com/onflow/flow-go-sdk/access/http" 27 | 28 | "github.com/onflow/cadence" 29 | 30 | "github.com/onflow/flow-go-sdk" 31 | "github.com/onflow/flow-go-sdk/crypto" 32 | "github.com/onflow/flow-go-sdk/examples" 33 | "github.com/onflow/flow-go-sdk/test" 34 | ) 35 | 36 | func main() { 37 | UserSignatureDemo() 38 | } 39 | 40 | var script = []byte(` 41 | import Crypto 42 | 43 | access(all) fun main( 44 | rawPublicKeys: [String], 45 | weights: [UFix64], 46 | signatures: [String], 47 | toAddress: Address, 48 | fromAddress: Address, 49 | amount: UFix64, 50 | domainSeparationTag: String, 51 | ): Bool { 52 | let keyList = Crypto.KeyList() 53 | 54 | var i = 0 55 | for rawPublicKey in rawPublicKeys { 56 | keyList.add( 57 | PublicKey( 58 | publicKey: rawPublicKey.decodeHex(), 59 | signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 60 | ), 61 | hashAlgorithm: HashAlgorithm.SHA3_256, 62 | weight: weights[i], 63 | ) 64 | i = i + 1 65 | } 66 | 67 | let signatureSet: [Crypto.KeyListSignature] = [] 68 | 69 | var j = 0 70 | for signature in signatures { 71 | signatureSet.append( 72 | Crypto.KeyListSignature( 73 | keyIndex: j, 74 | signature: signature.decodeHex() 75 | ) 76 | ) 77 | j = j + 1 78 | } 79 | 80 | // assemble the same message in cadence 81 | let message = toAddress.toBytes() 82 | .concat(fromAddress.toBytes()) 83 | .concat(amount.toBigEndianBytes()) 84 | 85 | return keyList.verify( 86 | signatureSet: signatureSet, 87 | signedData: message, 88 | domainSeparationTag: domainSeparationTag, 89 | ) 90 | } 91 | `) 92 | 93 | func UserSignatureDemo() { 94 | ctx := context.Background() 95 | flowClient, err := http.NewClient(http.EmulatorHost) 96 | examples.Handle(err) 97 | 98 | // create the keys 99 | privateKeyAlice := examples.RandomPrivateKey() 100 | publicKeyAlice := privateKeyAlice.PublicKey() 101 | 102 | privateKeyBob := examples.RandomPrivateKey() 103 | publicKeyBob := privateKeyBob.PublicKey() 104 | 105 | // create the message that will be signed 106 | addresses := test.AddressGenerator() 107 | 108 | toAddress := cadence.Address(addresses.New()) 109 | fromAddress := cadence.Address(addresses.New()) 110 | amount, err := cadence.NewUFix64("100.00") 111 | examples.Handle(err) 112 | 113 | message := append(toAddress.Bytes(), fromAddress.Bytes()...) 114 | message = append(message, amount.ToBigEndianBytes()...) 115 | 116 | signerAlice, err := crypto.NewInMemorySigner(privateKeyAlice, crypto.SHA3_256) 117 | examples.Handle(err) 118 | signerBob, err := crypto.NewInMemorySigner(privateKeyBob, crypto.SHA3_256) 119 | examples.Handle(err) 120 | 121 | // sign the message with Alice and Bob 122 | signatureAlice, err := flow.SignUserMessage(signerAlice, message) 123 | examples.Handle(err) 124 | 125 | signatureBob, err := flow.SignUserMessage(signerBob, message) 126 | examples.Handle(err) 127 | 128 | publicKeys := cadence.NewArray([]cadence.Value{ 129 | cadence.String(hex.EncodeToString(publicKeyAlice.Encode())), 130 | cadence.String(hex.EncodeToString(publicKeyBob.Encode())), 131 | }) 132 | 133 | // each signature has half weight 134 | weightAlice, err := cadence.NewUFix64("0.5") 135 | examples.Handle(err) 136 | 137 | weightBob, err := cadence.NewUFix64("0.5") 138 | examples.Handle(err) 139 | 140 | weights := cadence.NewArray([]cadence.Value{ 141 | weightAlice, 142 | weightBob, 143 | }) 144 | 145 | signatures := cadence.NewArray([]cadence.Value{ 146 | cadence.String(hex.EncodeToString(signatureAlice)), 147 | cadence.String(hex.EncodeToString(signatureBob)), 148 | }) 149 | 150 | domainSeparationTag := cadence.String(flow.UserDomainTag[:]) 151 | 152 | // call the script to verify the signatures on chain 153 | value, err := flowClient.ExecuteScriptAtLatestBlock( 154 | ctx, 155 | script, 156 | []cadence.Value{ 157 | publicKeys, 158 | weights, 159 | signatures, 160 | toAddress, 161 | fromAddress, 162 | amount, 163 | domainSeparationTag, 164 | }, 165 | ) 166 | examples.Handle(err) 167 | 168 | // the signatures should be valid 169 | if value == cadence.NewBool(true) { 170 | fmt.Println("Signature verification succeeded") 171 | } else { 172 | fmt.Println("Signature verification failed") 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /examples/verify_signature/user_signature_validate_all/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "encoding/hex" 24 | "fmt" 25 | 26 | "github.com/onflow/flow-go-sdk/access/http" 27 | 28 | "github.com/onflow/cadence" 29 | 30 | "github.com/onflow/flow-go-sdk" 31 | "github.com/onflow/flow-go-sdk/crypto" 32 | "github.com/onflow/flow-go-sdk/examples" 33 | ) 34 | 35 | func main() { 36 | UserSignatureValidateAll() 37 | } 38 | 39 | var script = []byte(` 40 | import Crypto 41 | 42 | access(all) fun main( 43 | address: Address, 44 | signatures: [String], 45 | keyIndexes: [Int], 46 | message: String, 47 | domainSeparationTag: String, 48 | ): Bool { 49 | let keyList = Crypto.KeyList() 50 | 51 | let account = getAccount(address) 52 | let keys = account.keys 53 | 54 | for keyIndex in keyIndexes { 55 | if let key = keys.get(keyIndex: keyIndex) { 56 | if key.isRevoked { 57 | // cannot verify: the key at this index is revoked 58 | return false 59 | } 60 | keyList.add( 61 | PublicKey( 62 | publicKey: key.publicKey.publicKey, 63 | signatureAlgorithm: key.publicKey.signatureAlgorithm 64 | ), 65 | hashAlgorithm: key.hashAlgorithm, 66 | weight: key.weight / 1000.0, 67 | ) 68 | } else { 69 | // cannot verify: they key at this index doesn't exist 70 | return false 71 | } 72 | } 73 | 74 | let signatureSet: [Crypto.KeyListSignature] = [] 75 | 76 | var i = 0 77 | for signature in signatures { 78 | signatureSet.append( 79 | Crypto.KeyListSignature( 80 | keyIndex: i, 81 | signature: signature.decodeHex() 82 | ) 83 | ) 84 | i = i + 1 85 | } 86 | 87 | return keyList.verify( 88 | signatureSet: signatureSet, 89 | signedData: message.utf8, 90 | domainSeparationTag: domainSeparationTag, 91 | ) 92 | } 93 | `) 94 | 95 | func UserSignatureValidateAll() { 96 | ctx := context.Background() 97 | flowClient, err := http.NewClient(http.EmulatorHost) 98 | examples.Handle(err) 99 | 100 | privateKeyAlice := examples.RandomPrivateKey() 101 | accountKeyAlice := flow.NewAccountKey(). 102 | FromPrivateKey(privateKeyAlice). 103 | SetHashAlgo(crypto.SHA3_256). 104 | SetWeight(flow.AccountKeyWeightThreshold / 2) 105 | 106 | privateKeyBob := examples.RandomPrivateKey() 107 | accountKeyBob := flow.NewAccountKey(). 108 | FromPrivateKey(privateKeyBob). 109 | SetHashAlgo(crypto.SHA3_256). 110 | SetWeight(flow.AccountKeyWeightThreshold / 2) 111 | 112 | // create the account with two keys 113 | account := examples.CreateAccount(flowClient, []*flow.AccountKey{accountKeyAlice, accountKeyBob}) 114 | 115 | // create the message that will be signed 116 | message := []byte("ananas") 117 | 118 | signerAlice, err := crypto.NewInMemorySigner(privateKeyAlice, crypto.SHA3_256) 119 | examples.Handle(err) 120 | signerBob, err := crypto.NewInMemorySigner(privateKeyBob, crypto.SHA3_256) 121 | examples.Handle(err) 122 | 123 | // sign the message with Alice and Bob 124 | signatureAlice, err := flow.SignUserMessage(signerAlice, message) 125 | examples.Handle(err) 126 | 127 | signatureBob, err := flow.SignUserMessage(signerBob, message) 128 | examples.Handle(err) 129 | 130 | signatures := cadence.NewArray([]cadence.Value{ 131 | cadence.String(hex.EncodeToString(signatureBob)), 132 | cadence.String(hex.EncodeToString(signatureAlice)), 133 | }) 134 | 135 | // the signature indexes correspond to the key indexes on the address 136 | signatureIndexes := cadence.NewArray([]cadence.Value{ 137 | cadence.NewInt(1), 138 | cadence.NewInt(0), 139 | }) 140 | 141 | domainSeparationTag := flow.UserDomainTag[:] 142 | 143 | // call the script to verify the signatures on chain 144 | value, err := flowClient.ExecuteScriptAtLatestBlock( 145 | ctx, 146 | script, 147 | []cadence.Value{ 148 | cadence.BytesToAddress(account.Address.Bytes()), 149 | signatures, 150 | signatureIndexes, 151 | cadence.String(message), 152 | cadence.String(domainSeparationTag), 153 | }, 154 | ) 155 | examples.Handle(err) 156 | 157 | // the signatures should be valid 158 | if value == cadence.NewBool(true) { 159 | fmt.Println("Signature verification succeeded") 160 | } else { 161 | fmt.Println("Signature verification failed") 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /examples/verify_signature/user_signature_validate_any/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "context" 23 | "encoding/hex" 24 | "fmt" 25 | 26 | "github.com/onflow/flow-go-sdk/access/http" 27 | 28 | "github.com/onflow/cadence" 29 | 30 | "github.com/onflow/flow-go-sdk" 31 | "github.com/onflow/flow-go-sdk/crypto" 32 | "github.com/onflow/flow-go-sdk/examples" 33 | ) 34 | 35 | func main() { 36 | UserSignatureValidateAny() 37 | } 38 | 39 | var script = []byte(` 40 | import Crypto 41 | 42 | access(all) fun main( 43 | address: Address, 44 | signature: String, 45 | message: String, 46 | domainSeparationTag: String 47 | ): Bool { 48 | let keyList = Crypto.KeyList() 49 | 50 | let account = getAccount(address) 51 | let keys = account.keys 52 | 53 | let signatureBytes = signature.decodeHex() 54 | let messageBytes = message.utf8 55 | 56 | var i = 0 57 | while true { 58 | if let key = keys.get(keyIndex: i) { 59 | if key.isRevoked { 60 | // do not check revoked keys 61 | i = i + 1 62 | continue 63 | } 64 | let pk = PublicKey( 65 | publicKey: key.publicKey.publicKey, 66 | signatureAlgorithm: key.publicKey.signatureAlgorithm 67 | ) 68 | if pk.verify( 69 | signature: signatureBytes, 70 | signedData: messageBytes, 71 | domainSeparationTag: domainSeparationTag, 72 | hashAlgorithm: key.hashAlgorithm 73 | ) { 74 | // this key is good 75 | 76 | return true 77 | } 78 | } else { 79 | // checked all the keys, none of them match 80 | return false 81 | } 82 | i = i + 1 83 | } 84 | 85 | return false 86 | } 87 | `) 88 | 89 | func UserSignatureValidateAny() { 90 | ctx := context.Background() 91 | flowClient, err := http.NewClient(http.EmulatorHost) 92 | examples.Handle(err) 93 | 94 | privateKeyAlice := examples.RandomPrivateKey() 95 | accountKeyAlice := flow.NewAccountKey(). 96 | FromPrivateKey(privateKeyAlice). 97 | SetHashAlgo(crypto.SHA3_256). 98 | SetWeight(flow.AccountKeyWeightThreshold / 2) 99 | 100 | privateKeyBob := examples.RandomPrivateKey() 101 | accountKeyBob := flow.NewAccountKey(). 102 | FromPrivateKey(privateKeyBob). 103 | SetHashAlgo(crypto.SHA3_256). 104 | SetWeight(flow.AccountKeyWeightThreshold / 2) 105 | 106 | // create the account with two keys 107 | account := examples.CreateAccount(flowClient, []*flow.AccountKey{accountKeyAlice, accountKeyBob}) 108 | 109 | // create the message that will be signed with one key 110 | message := []byte("ananas") 111 | 112 | signerAlice, err := crypto.NewInMemorySigner(privateKeyAlice, crypto.SHA3_256) 113 | examples.Handle(err) 114 | 115 | // sign the message only with Alice 116 | signatureAlice, err := flow.SignUserMessage(signerAlice, message) 117 | examples.Handle(err) 118 | 119 | domainSeparationTag := flow.UserDomainTag[:] 120 | 121 | // call the script to verify the signature on chain 122 | value, err := flowClient.ExecuteScriptAtLatestBlock( 123 | ctx, 124 | script, 125 | []cadence.Value{ 126 | cadence.BytesToAddress(account.Address.Bytes()), 127 | cadence.String(hex.EncodeToString(signatureAlice)), 128 | cadence.String(message), 129 | cadence.String(domainSeparationTag), 130 | }, 131 | ) 132 | examples.Handle(err) 133 | 134 | // the signature should be valid 135 | if value == cadence.NewBool(true) { 136 | fmt.Println("Signature verification succeeded") 137 | } else { 138 | fmt.Println("Signature verification failed") 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /execution_data.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import "time" 22 | 23 | type ExecutionData struct { 24 | BlockID Identifier 25 | ChunkExecutionData []*ChunkExecutionData 26 | } 27 | 28 | type ExecutionDataStreamResponse struct { 29 | Height uint64 30 | ExecutionData *ExecutionData 31 | BlockTimestamp time.Time 32 | } 33 | 34 | type ChunkExecutionData struct { 35 | Transactions []*Transaction 36 | Events []*Event 37 | TrieUpdate *TrieUpdate 38 | TransactionResults []*LightTransactionResult 39 | } 40 | 41 | type TrieUpdate struct { 42 | RootHash []byte 43 | Paths [][]byte 44 | Payloads []*Payload 45 | } 46 | 47 | type Payload struct { 48 | KeyPart []*KeyPart 49 | Value []byte 50 | } 51 | 52 | type KeyPart struct { 53 | Type uint16 54 | Value []byte 55 | } 56 | 57 | type LightTransactionResult struct { 58 | // TransactionID is the ID of the transaction this result was emitted from. 59 | TransactionID Identifier 60 | // Failed is true if the transaction's execution failed resulting in an error, false otherwise. 61 | Failed bool 62 | // ComputationUsed is amount of computation used while executing the transaction. 63 | ComputationUsed uint64 64 | } 65 | -------------------------------------------------------------------------------- /execution_result.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import "github.com/onflow/flow-go-sdk/crypto" 22 | 23 | type ExecutionResult struct { 24 | PreviousResultID Identifier // commit of the previous ER 25 | BlockID Identifier // commit of the current block 26 | Chunks []*Chunk 27 | ServiceEvents []*ServiceEvent 28 | } 29 | 30 | type Chunk struct { 31 | CollectionIndex uint 32 | StartState StateCommitment // start state when starting executing this chunk 33 | EventCollection crypto.Hash // Hash of events generated by executing results 34 | BlockID Identifier // Block id of the execution result this chunk belongs to 35 | TotalComputationUsed uint64 // total amount of computation used by running all txs in this chunk 36 | NumberOfTransactions uint16 // number of transactions inside the collection 37 | Index uint64 // chunk index inside the ER (starts from zero) 38 | EndState StateCommitment // EndState inferred from next chunk or from the ER 39 | } 40 | 41 | type ServiceEvent struct { 42 | Type string 43 | Payload []byte 44 | } 45 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/onflow/flow-go-sdk 2 | 3 | go 1.23.7 4 | 5 | require ( 6 | cloud.google.com/go/kms v1.21.2 7 | github.com/aws/aws-sdk-go-v2 v1.36.3 8 | github.com/aws/aws-sdk-go-v2/config v1.29.14 9 | github.com/aws/aws-sdk-go-v2/service/kms v1.38.3 10 | github.com/onflow/cadence v1.6.0 11 | github.com/onflow/crypto v0.25.3 12 | github.com/onflow/flow/protobuf/go/flow v0.4.7 13 | github.com/onflow/go-ethereum v1.14.8 14 | github.com/onflow/sdks v0.6.0-preview.1 15 | github.com/pkg/errors v0.9.1 16 | github.com/stretchr/testify v1.10.0 17 | google.golang.org/api v0.232.0 18 | google.golang.org/grpc v1.72.0 19 | google.golang.org/protobuf v1.36.6 20 | ) 21 | 22 | require ( 23 | cloud.google.com/go v0.120.0 // indirect 24 | cloud.google.com/go/auth v0.16.1 // indirect 25 | cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect 26 | cloud.google.com/go/compute/metadata v0.6.0 // indirect 27 | cloud.google.com/go/iam v1.5.0 // indirect 28 | cloud.google.com/go/longrunning v0.6.6 // indirect 29 | github.com/SaveTheRbtz/mph v0.1.1-0.20240117162131-4166ec7869bc // indirect 30 | github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect 31 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect 32 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect 33 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect 34 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect 35 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect 36 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect 37 | github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect 38 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect 39 | github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect 40 | github.com/aws/smithy-go v1.22.2 // indirect 41 | github.com/bits-and-blooms/bitset v1.10.0 // indirect 42 | github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect 43 | github.com/davecgh/go-spew v1.1.1 // indirect 44 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect 45 | github.com/felixge/httpsnoop v1.0.4 // indirect 46 | github.com/fxamacker/cbor/v2 v2.8.1-0.20250402194037-6f932b086829 // indirect 47 | github.com/fxamacker/circlehash v0.3.0 // indirect 48 | github.com/go-logr/logr v1.4.2 // indirect 49 | github.com/go-logr/stdr v1.2.2 // indirect 50 | github.com/golang/protobuf v1.5.4 // indirect 51 | github.com/google/s2a-go v0.1.9 // indirect 52 | github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect 53 | github.com/googleapis/gax-go/v2 v2.14.1 // indirect 54 | github.com/holiman/uint256 v1.3.1 // indirect 55 | github.com/k0kubun/pp v3.0.1+incompatible // indirect 56 | github.com/klauspost/cpuid/v2 v2.2.6 // indirect 57 | github.com/kr/pretty v0.3.1 // indirect 58 | github.com/kr/text v0.2.0 // indirect 59 | github.com/logrusorgru/aurora/v4 v4.0.0 // indirect 60 | github.com/mattn/go-colorable v0.1.13 // indirect 61 | github.com/mattn/go-isatty v0.0.20 // indirect 62 | github.com/onflow/atree v0.10.0 // indirect 63 | github.com/pmezard/go-difflib v1.0.0 // indirect 64 | github.com/rivo/uniseg v0.4.4 // indirect 65 | github.com/rogpeppe/go-internal v1.13.1 // indirect 66 | github.com/stretchr/objx v0.5.2 // indirect 67 | github.com/texttheater/golang-levenshtein/levenshtein v0.0.0-20200805054039-cae8b0eaed6c // indirect 68 | github.com/turbolent/prettier v0.0.0-20220320183459-661cc755135d // indirect 69 | github.com/x448/float16 v0.8.4 // indirect 70 | github.com/zeebo/blake3 v0.2.4 // indirect 71 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 72 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect 73 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect 74 | go.opentelemetry.io/otel v1.35.0 // indirect 75 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 76 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 77 | golang.org/x/crypto v0.37.0 // indirect 78 | golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect 79 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect 80 | golang.org/x/net v0.39.0 // indirect 81 | golang.org/x/oauth2 v0.30.0 // indirect 82 | golang.org/x/sync v0.14.0 // indirect 83 | golang.org/x/sys v0.32.0 // indirect 84 | golang.org/x/text v0.24.0 // indirect 85 | golang.org/x/time v0.11.0 // indirect 86 | golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect 87 | gonum.org/v1/gonum v0.16.0 // indirect 88 | google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect 89 | google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect 90 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect 91 | gopkg.in/yaml.v3 v3.0.1 // indirect 92 | pgregory.net/rapid v1.1.0 // indirect 93 | ) 94 | -------------------------------------------------------------------------------- /sign.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package flow 20 | 21 | import ( 22 | "fmt" 23 | 24 | "github.com/onflow/flow-go-sdk/crypto" 25 | ) 26 | 27 | const domainTagLength = 32 28 | 29 | // TransactionDomainTag is the prefix of all signed transaction payloads. 30 | // 31 | // A domain tag is encoded as UTF-8 bytes, right padded to a total length of 32 bytes. 32 | var TransactionDomainTag = mustPadDomainTag("FLOW-V0.0-transaction") 33 | 34 | // UserDomainTag is the prefix of all signed user space payloads. 35 | // 36 | // A domain tag is encoded as UTF-8 bytes, right padded to a total length of 32 bytes. 37 | var UserDomainTag = mustPadDomainTag("FLOW-V0.0-user") 38 | 39 | func mustPadDomainTag(s string) [domainTagLength]byte { 40 | paddedTag, err := padDomainTag(s) 41 | if err != nil { 42 | panic(err) 43 | } 44 | 45 | return paddedTag 46 | } 47 | 48 | // padDomainTag returns a new padded domain tag from the given string. This function returns an error if the domain 49 | // tag is too long. 50 | func padDomainTag(tag string) (paddedTag [domainTagLength]byte, err error) { 51 | if len(tag) > domainTagLength { 52 | return paddedTag, fmt.Errorf("domain tag %s cannot be longer than %d characters", tag, domainTagLength) 53 | } 54 | 55 | copy(paddedTag[:], tag) 56 | 57 | return paddedTag, nil 58 | } 59 | 60 | // SignUserMessage signs a message in the user domain. 61 | // 62 | // User messages are distinct from other signed messages (i.e. transactions), and can be 63 | // verified directly in on-chain Cadence code. 64 | func SignUserMessage(signer crypto.Signer, message []byte) ([]byte, error) { 65 | message = append(UserDomainTag[:], message...) 66 | return signer.Sign(message) 67 | } 68 | -------------------------------------------------------------------------------- /templates/accounts_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package templates_test 20 | 21 | import ( 22 | "testing" 23 | 24 | "github.com/stretchr/testify/require" 25 | 26 | "github.com/onflow/flow-go-sdk" 27 | "github.com/onflow/flow-go-sdk/templates" 28 | ) 29 | 30 | func TestCreateAccount(t *testing.T) { 31 | // Converting transaction arguments to Cadence values can increase their size. 32 | // If this is not taken into account the transaction can quickly grow over the maximum transaction size limit. 33 | t.Run("Transaction should not grow uncontrollably in size", func(t *testing.T) { 34 | contractLen := 1000 35 | contractCode := make([]byte, contractLen) 36 | 37 | tx, err := templates.CreateAccount( 38 | []*flow.AccountKey{}, 39 | []templates.Contract{{ 40 | Name: "contract", 41 | Source: string(contractCode), 42 | }}, 43 | flow.HexToAddress("01")) 44 | 45 | require.NoError(t, err) 46 | 47 | txSize := len(tx.Script) 48 | argumentsSize := 0 49 | for _, argument := range tx.Arguments { 50 | argumentsSize += len(argument) 51 | } 52 | require.Less(t, txSize, 1000, "The create account script should not grow over 1kB.") 53 | require.Less(t, argumentsSize, contractLen*2+500, 54 | "The create account argument size should not grow over "+ 55 | "2 times the contract code (converted to hex) + 500 bytes of extra data.") 56 | }) 57 | } 58 | -------------------------------------------------------------------------------- /test/greetings.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package test 20 | 21 | import ( 22 | "math/rand" 23 | "time" 24 | ) 25 | 26 | var GreetingScript = []byte(` 27 | transaction(greeting: String) { 28 | execute { 29 | log(greeting.concat(", World!")) 30 | } 31 | } 32 | `) 33 | 34 | const ( 35 | greetingMsgAF = "Hi" 36 | greetingMsgSQ = "Hi" 37 | greetingMsgAM = "ሃይ" 38 | greetingMsgAR = "مرحبا" 39 | greetingMsgEU = "Hi" 40 | greetingMsgBN = "হাই" 41 | greetingMsgBS = "Zdravo" 42 | greetingMsgCA = "Hola" 43 | greetingMsgHR = "Bok" 44 | greetingMsgDA = "Hej" 45 | greetingMsgNL = "Hoi" 46 | greetingMsgET = "Tere" 47 | greetingMsgFI = "Moi" 48 | greetingMsgEN = "Hi" 49 | greetingMsgEL = "Γεια" 50 | greetingMsgHE = "היי" 51 | greetingMsgIS = "Hæ" 52 | greetingMsgID = "Hai" 53 | greetingMsgIT = "Ciao" 54 | greetingMsgJA = "こんにちは" 55 | greetingMsgKO = "안녕" 56 | greetingMsgLT = "Sveiki" 57 | greetingMsgMK = "Здраво" 58 | greetingMsgPT = "Oi" 59 | greetingMsgPA = "ਸਤ ਸ੍ਰੀ ਅਕਾਲ" 60 | greetingMsgSK = "Ahoj" 61 | greetingMsgSL = "Zdravo" 62 | greetingMsgSB = "Hej" 63 | greetingMsgTH = "สวัสดี" 64 | greetingMsgTR = "Merhaba" 65 | greetingMsgUR = "ہیلو" 66 | greetingMsgVI = "Chào" 67 | greetingMsgCY = "Hi" 68 | greetingMsgBG = "здрасти" 69 | greetingMsgRU = "Здравствуй" 70 | greetingMsgFR = "Bonjour" 71 | greetingMsgNB = "Hei" 72 | greetingMsgNN = "Hei" 73 | greetingMsgRO = "Bună" 74 | greetingMsgDE = "Hallo" 75 | greetingMsgGH = "Haigh" 76 | greetingMsgZH = "你好" 77 | greetingMsgPL = "Cześć" 78 | greetingMsgBE = "прывітанне" 79 | greetingMsgHI = "नमस्ते" 80 | greetingMsgHU = "Szia" 81 | greetingMsgUK = "Привіт" 82 | greetingMsgES = "Hola" 83 | ) 84 | 85 | var greetings []string 86 | 87 | func init() { 88 | greetings = []string{ 89 | greetingMsgAF, 90 | greetingMsgSQ, 91 | greetingMsgAM, 92 | greetingMsgAR, 93 | greetingMsgEU, 94 | greetingMsgBN, 95 | greetingMsgBS, 96 | greetingMsgCA, 97 | greetingMsgHR, 98 | greetingMsgDA, 99 | greetingMsgNL, 100 | greetingMsgET, 101 | greetingMsgFI, 102 | greetingMsgEN, 103 | greetingMsgEL, 104 | greetingMsgHE, 105 | greetingMsgIS, 106 | greetingMsgID, 107 | greetingMsgIT, 108 | greetingMsgJA, 109 | greetingMsgKO, 110 | greetingMsgLT, 111 | greetingMsgMK, 112 | greetingMsgPT, 113 | greetingMsgPA, 114 | greetingMsgSK, 115 | greetingMsgSL, 116 | greetingMsgSB, 117 | greetingMsgTH, 118 | greetingMsgTR, 119 | greetingMsgUR, 120 | greetingMsgVI, 121 | greetingMsgCY, 122 | greetingMsgBG, 123 | greetingMsgRU, 124 | greetingMsgFR, 125 | greetingMsgNB, 126 | greetingMsgNN, 127 | greetingMsgRO, 128 | greetingMsgDE, 129 | greetingMsgGH, 130 | greetingMsgZH, 131 | greetingMsgPL, 132 | greetingMsgBE, 133 | greetingMsgHI, 134 | greetingMsgHU, 135 | greetingMsgUK, 136 | greetingMsgES, 137 | } 138 | 139 | rand.Seed(time.Now().Unix()) 140 | } 141 | 142 | type Greetings struct { 143 | count int 144 | } 145 | 146 | func GreetingGenerator() *Greetings { 147 | return &Greetings{0} 148 | } 149 | 150 | func (g *Greetings) New() string { 151 | defer func() { g.count++ }() 152 | return greetings[g.count%len(greetings)] 153 | } 154 | 155 | func (g *Greetings) Random() string { 156 | return greetings[rand.Intn(len(greetings))] 157 | } 158 | -------------------------------------------------------------------------------- /test/signer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Flow Go SDK 3 | * 4 | * Copyright Flow Foundation 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package test 20 | 21 | import "github.com/onflow/flow-go-sdk/crypto" 22 | 23 | type MockSigner []byte 24 | 25 | func (s MockSigner) Sign(message []byte) ([]byte, error) { 26 | return s, nil 27 | } 28 | 29 | func (s MockSigner) PublicKey() crypto.PublicKey { 30 | return nil 31 | } 32 | --------------------------------------------------------------------------------