├── .dockerignore
├── .editorconfig
├── .gitattributes
├── .github
├── settings.yml
└── workflows
│ └── go.yml
├── .gitignore
├── .golangci.yml
├── .vscode
└── settings.json
├── CHANGELOG.md
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── MAINTAINERS.md
├── Makefile
├── README.md
├── SECURITY.md
├── cmd
├── client.go
├── client_eventstreams.go
├── client_eventstreams_delete.go
├── client_eventstreams_delete_test.go
├── client_eventstreams_list.go
├── client_eventstreams_list_test.go
├── client_listeners.go
├── client_listeners_delete.go
├── client_listeners_delete_test.go
├── client_listeners_list.go
├── client_listeners_list_test.go
├── client_test.go
├── migrate.go
└── migrate_test.go
├── codecov.yml
├── config.md
├── db
└── migrations
│ └── postgres
│ ├── 000001_create_transactions_table.down.sql
│ ├── 000001_create_transactions_table.up.sql
│ ├── 000002_create_receipts_table.down.sql
│ ├── 000002_create_receipts_table.up.sql
│ ├── 000003_create_confirmations_table.down.sql
│ ├── 000003_create_confirmations_table.up.sql
│ ├── 000004_create_txhistory_table.down.sql
│ ├── 000004_create_txhistory_table.up.sql
│ ├── 000005_create_checkpoints_table.down.sql
│ ├── 000005_create_checkpoints_table.up.sql
│ ├── 000006_create_eventstreams_table.down.sql
│ ├── 000006_create_eventstreams_table.up.sql
│ ├── 000007_create_listeners_table.down.sql
│ ├── 000007_create_listeners_table.up.sql
│ ├── 000008_create_txhistory_idx.down.sql
│ ├── 000008_create_txhistory_idx.up.sql
│ ├── 000009_add_transactions_status_index.down.sql
│ ├── 000009_add_transactions_status_index.up.sql
│ ├── 000010_add_listeners_type.down.sql
│ └── 000010_add_listeners_type.up.sql
├── go.mod
├── go.sum
├── grafana_dash
└── Event process metrics-1717595375618.json
├── images
├── fftm_event_streams_architecture.jpg
└── firefly_connector_framework_architecture.jpg
├── internal
├── apiclient
│ ├── eventstreams.go
│ ├── eventstreams_test.go
│ ├── fftm_client.go
│ └── fftm_client_test.go
├── blocklistener
│ ├── blocklistener.go
│ └── blocklistener_test.go
├── confirmations
│ ├── confirmations.go
│ ├── confirmations_test.go
│ ├── confirmed_block_listener.go
│ ├── confirmed_block_listener_test.go
│ ├── receipt_checker.go
│ └── receipt_checker_test.go
├── events
│ ├── eventstream.go
│ ├── eventstream_test.go
│ ├── listener.go
│ ├── webhooks.go
│ ├── webhooks_test.go
│ ├── websockets.go
│ └── websockets_test.go
├── metrics
│ ├── event_metrics.go
│ ├── event_metrics_test.go
│ ├── metrics.go
│ └── metrics_test.go
├── persistence
│ ├── dbmigration
│ │ ├── leveldb2postgres.go
│ │ ├── leveldb2postgres_test.go
│ │ ├── migration.go
│ │ └── migration_test.go
│ ├── leveldb
│ │ ├── leveldb_persistence.go
│ │ ├── leveldb_persistence_test.go
│ │ ├── nonces.go
│ │ └── nonces_test.go
│ ├── persistence.go
│ ├── persistence_test.go
│ └── postgres
│ │ ├── checkpoints.go
│ │ ├── checkpoints_test.go
│ │ ├── confirmations.go
│ │ ├── confirmations_test.go
│ │ ├── eventstreams.go
│ │ ├── eventstreams_test.go
│ │ ├── listeners.go
│ │ ├── listeners_test.go
│ │ ├── postgres.go
│ │ ├── postgres_test.go
│ │ ├── receipts.go
│ │ ├── receipts_test.go
│ │ ├── sqlpersistence.go
│ │ ├── sqlpersistence_test.go
│ │ ├── transaction_writer.go
│ │ ├── transaction_writer_test.go
│ │ ├── transactions.go
│ │ ├── transactions_test.go
│ │ ├── txhistory.go
│ │ └── txhistory_test.go
├── tmconfig
│ ├── tmconfig.go
│ └── tmconfig_test.go
├── tmmsgs
│ ├── en_api_descriptions.go
│ ├── en_config_descriptions.go
│ └── en_error_messages.go
└── ws
│ ├── wsconn.go
│ ├── wsserver.go
│ └── wsserver_test.go
├── mocks
├── apiclientmocks
│ └── fftm_client.go
├── confirmationsmocks
│ └── manager.go
├── eventsmocks
│ └── stream.go
├── ffcapimocks
│ └── api.go
├── metricsmocks
│ ├── event_metrics_emitter.go
│ └── transaction_handler_metrics.go
├── persistencemocks
│ ├── persistence.go
│ ├── rich_query.go
│ └── transaction_persistence.go
├── txhandlermocks
│ ├── managed_tx_event_handler.go
│ └── transaction_handler.go
└── wsmocks
│ ├── web_socket_channels.go
│ └── web_socket_server.go
├── pkg
├── apitypes
│ ├── api_types.go
│ ├── api_types_test.go
│ ├── base_request.go
│ ├── base_request_test.go
│ ├── managed_tx.go
│ ├── managed_tx_test.go
│ ├── query_request.go
│ ├── tx_request.go
│ ├── txreceipt_request.go
│ ├── ulid.go
│ └── ulid_test.go
├── ffcapi
│ ├── address_balance.go
│ ├── api.go
│ ├── api_test.go
│ ├── block_info_by_hash.go
│ ├── block_info_by_number.go
│ ├── contract_deploy_prepare.go
│ ├── event_listener_add.go
│ ├── event_listener_hwm.go
│ ├── event_listener_remove.go
│ ├── event_stream_start.go
│ ├── event_stream_stopped.go
│ ├── gas_estimate.go
│ ├── gas_price_estimate.go
│ ├── is_live.go
│ ├── is_ready.go
│ ├── method_call.go
│ ├── new_block_listener.go
│ ├── next_nonce_for_signer.go
│ ├── submission_error.go
│ ├── submission_error_test.go
│ ├── transaction_prepare.go
│ ├── transaction_receipt.go
│ └── transaction_send.go
├── fftm
│ ├── address_management.go
│ ├── address_management_test.go
│ ├── api.go
│ ├── api_test.go
│ ├── config_docs_generate_test.go
│ ├── config_docs_test.go
│ ├── gas_management.go
│ ├── manager.go
│ ├── manager_test.go
│ ├── route__root_command.go
│ ├── route_delete_eventstream.go
│ ├── route_delete_eventstream_listener.go
│ ├── route_delete_eventstream_listener_test.go
│ ├── route_delete_eventstream_test.go
│ ├── route_delete_subscription.go
│ ├── route_delete_subscription_test.go
│ ├── route_delete_transaction.go
│ ├── route_delete_transaction_test.go
│ ├── route_get_address_balance.go
│ ├── route_get_address_balance_test.go
│ ├── route_get_eventstream.go
│ ├── route_get_eventstream_listener.go
│ ├── route_get_eventstream_listener_test.go
│ ├── route_get_eventstream_listeners.go
│ ├── route_get_eventstream_listeners_test.go
│ ├── route_get_eventstream_test.go
│ ├── route_get_eventstreams.go
│ ├── route_get_eventstreams_test.go
│ ├── route_get_gas_price.go
│ ├── route_get_gas_price_test.go
│ ├── route_get_status_live.go
│ ├── route_get_status_live_test.go
│ ├── route_get_status_ready.go
│ ├── route_get_status_ready_test.go
│ ├── route_get_subscription.go
│ ├── route_get_subscription_test.go
│ ├── route_get_subscriptions.go
│ ├── route_get_subscriptions_test.go
│ ├── route_get_transaction.go
│ ├── route_get_transaction_confirmations.go
│ ├── route_get_transaction_confirmations_test.go
│ ├── route_get_transaction_history.go
│ ├── route_get_transaction_history_test.go
│ ├── route_get_transaction_receipt.go
│ ├── route_get_transaction_receipt_test.go
│ ├── route_get_transaction_test.go
│ ├── route_get_transactions.go
│ ├── route_get_transactions_test.go
│ ├── route_patch_eventstream.go
│ ├── route_patch_eventstream_listener.go
│ ├── route_patch_eventstream_listener_test.go
│ ├── route_patch_eventstream_test.go
│ ├── route_patch_subscription.go
│ ├── route_patch_subscription_test.go
│ ├── route_post_eventstream.go
│ ├── route_post_eventstream_listener_reset.go
│ ├── route_post_eventstream_listener_reset_test.go
│ ├── route_post_eventstream_listeners.go
│ ├── route_post_eventstream_listeners_test.go
│ ├── route_post_eventstream_resume.go
│ ├── route_post_eventstream_resume_test.go
│ ├── route_post_eventstream_suspend.go
│ ├── route_post_eventstream_suspend_test.go
│ ├── route_post_eventstream_test.go
│ ├── route_post_subscription_reset.go
│ ├── route_post_subscription_reset_test.go
│ ├── route_post_subscriptions.go
│ ├── route_post_subscriptions_test.go
│ ├── route_post_transaction_resume.go
│ ├── route_post_transaction_resume_test.go
│ ├── route_post_transaction_suspend.go
│ ├── route_post_transaction_suspend_test.go
│ ├── routes.go
│ ├── status_management.go
│ ├── status_management_test.go
│ ├── stream_management.go
│ ├── stream_management_test.go
│ ├── transaction_events_handler.go
│ ├── transaction_events_handler_test.go
│ ├── transaction_management.go
│ └── transaction_management_test.go
└── txhandler
│ ├── registry
│ ├── registry.go
│ └── registry_test.go
│ ├── simple
│ ├── config.go
│ ├── metrics.go
│ ├── policyloop.go
│ ├── policyloop_test.go
│ ├── simple_transaction_hander_test.go
│ └── simple_transaction_handler.go
│ └── txhandler.go
└── test
├── empty-config.fftm.yaml
├── firefly.fftm.yaml
└── quick-fail.fftm.yaml
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/node_modules
2 | **/coverage
3 | **/.nyc_output
4 | firefly-transaction-manager
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*.{yaml,yml,json}]
4 | end_of_line = lf
5 | insert_final_newline = true
6 | indent_style = space
7 | indent_size = 2
8 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.go licensefile=.githooks/license-maintainer/LICENSE-go
--------------------------------------------------------------------------------
/.github/settings.yml:
--------------------------------------------------------------------------------
1 | repository:
2 | name: firefly-transaction-manager
3 | default_branch: main
4 | has_downloads: false
5 | has_issues: true
6 | has_projects: false
7 | has_wiki: false
8 | archived: false
9 | private: false
10 | allow_squash_merge: false
11 | allow_merge_commit: false
12 | allow_rebase_merge: true
13 |
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | name: Go
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | container: golang:1.23-bookworm
14 | defaults:
15 | run:
16 | shell: bash # needed for codecov
17 | services:
18 | postgres:
19 | image: postgres
20 | env:
21 | POSTGRES_PASSWORD: f1refly
22 | options: >-
23 | --health-cmd pg_isready
24 | --health-interval 10s
25 | --health-timeout 5s
26 | --health-retries 5
27 | steps:
28 | - uses: actions/checkout@v4
29 | with:
30 | fetch-depth: 0
31 |
32 | - name: Fetch history # See https://github.com/actions/checkout/issues/477
33 | run: |-
34 | git config --global --add safe.directory $PWD
35 | git fetch origin
36 |
37 | - name: Build and Test
38 | env:
39 | TEST_FLAGS: -v
40 | POSTGRES_HOSTNAME: postgres
41 | POSTGRES_PASSWORD: f1refly
42 | POSTGRES_PORT: 5432
43 | run: make
44 |
45 | - name: Upload coverage
46 | run: bash <(curl -s https://codecov.io/bash)
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/*.jar
2 | firefly-transaction-manager
3 | coverage.txt
4 | **/debug.test
5 | .DS_Store
6 | __debug*
7 | .vscode/*.log
8 | *.iml
9 | .idea/
10 |
--------------------------------------------------------------------------------
/.golangci.yml:
--------------------------------------------------------------------------------
1 | run:
2 | tests: false
3 | skip-dirs:
4 | - "mocks"
5 | linters-settings:
6 | golint: {}
7 | gocritic:
8 | enabled-checks: []
9 | disabled-checks:
10 | - regexpMust
11 | gosec:
12 | excludes:
13 | - G402
14 | goheader:
15 | values:
16 | regexp:
17 | COMPANY: .*
18 | YEAR_FUZZY: '\d\d\d\d(,\d\d\d\d)?'
19 | template: |-
20 | Copyright © {{ YEAR_FUZZY }} {{ COMPANY }}
21 |
22 | SPDX-License-Identifier: Apache-2.0
23 |
24 | Licensed under the Apache License, Version 2.0 (the "License");
25 | you may not use this file except in compliance with the License.
26 | You may obtain a copy of the License at
27 |
28 | http://www.apache.org/licenses/LICENSE-2.0
29 |
30 | Unless required by applicable law or agreed to in writing, software
31 | distributed under the License is distributed on an "AS IS" BASIS,
32 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33 | See the License for the specific language governing permissions and
34 | limitations under the License.
35 | linters:
36 | disable-all: false
37 | enable:
38 | - bodyclose
39 | - dogsled
40 | - errcheck
41 | - goconst
42 | - gocritic
43 | - gocyclo
44 | - gofmt
45 | - goheader
46 | - goimports
47 | - goprintffuncname
48 | - gosec
49 | - gosimple
50 | - govet
51 | - ineffassign
52 | - misspell
53 | - nakedret
54 | - revive
55 | - staticcheck
56 | - stylecheck
57 | - typecheck
58 | - unconvert
59 | - unparam
60 | - unused
61 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "go.formatFlags": ["-s"],
3 | "go.lintTool": "golangci-lint",
4 | "cSpell.words": [
5 | "apiclient",
6 | "APIID",
7 | "apitypes",
8 | "badurl",
9 | "blocklistener",
10 | "ccache",
11 | "Compat",
12 | "confirmationsmocks",
13 | "dataexchange",
14 | "Debugf",
15 | "devdocs",
16 | "Devel",
17 | "distmode",
18 | "Dont",
19 | "ehtype",
20 | "estype",
21 | "ethconnect",
22 | "ethtypes",
23 | "eventsmocks",
24 | "eventstream",
25 | "eventstreams",
26 | "fabconnect",
27 | "ffapi",
28 | "ffcapi",
29 | "ffcapimocks",
30 | "ffcore",
31 | "FFDX",
32 | "ffenum",
33 | "ffexclude",
34 | "ffexcludeinput",
35 | "ffexcludeoutput",
36 | "ffievents",
37 | "FFIID",
38 | "ffimethods",
39 | "ffresty",
40 | "ffstruct",
41 | "fftm",
42 | "fftmrequest",
43 | "fftypes",
44 | "finalizers",
45 | "getkin",
46 | "GJSON",
47 | "goleveldb",
48 | "httpserver",
49 | "hyperledger",
50 | "idempotence",
51 | "Infof",
52 | "IPFS",
53 | "jsonmap",
54 | "Kaleido",
55 | "leveldb",
56 | "loadbalanced",
57 | "logrus",
58 | "metricsmocks",
59 | "mtxs",
60 | "NATS",
61 | "Nowarn",
62 | "oapispec",
63 | "oklog",
64 | "openapi",
65 | "optype",
66 | "persistencemocks",
67 | "pluggable",
68 | "policyengine",
69 | "policyloop",
70 | "protocolid",
71 | "restapi",
72 | "resty",
73 | "santhosh",
74 | "secp",
75 | "sigs",
76 | "stretchr",
77 | "syndtr",
78 | "sysmessaging",
79 | "tekuri",
80 | "tmconfig",
81 | "tmmsgs",
82 | "Tracef",
83 | "txcommon",
84 | "txcommonmocks",
85 | "txhandler",
86 | "txhandlerfactory",
87 | "txhandlermocks",
88 | "txhistory",
89 | "txid",
90 | "txns",
91 | "txtype",
92 | "txwriter",
93 | "unflushed",
94 | "unmarshalled",
95 | "unmarshalling",
96 | "upgrader",
97 | "upsert",
98 | "upserts",
99 | "Warnf",
100 | "whconfig",
101 | "workloaddistribution",
102 | "wsclient",
103 | "wsconfig",
104 | "wsmocks"
105 | ],
106 | "go.testTimeout": "20s"
107 | }
108 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | [FireFly Transaction Manager Releases](https://github.com/hyperledger/firefly-transaction-manager/releases)
4 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: Apache-2.0
2 |
3 | * @hyperledger/firefly-transaction-manager-maintainers
4 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct Guidelines
2 |
3 | Please review the Hyperledger [Code of
4 | Conduct](https://wiki.hyperledger.org/community/hyperledger-project-code-of-conduct)
5 | before participating. It is important that we keep things civil.
6 |
7 | 
This work is licensed under a Creative Commons Attribution 4.0 International License.
8 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing
2 |
3 | We welcome contributions to the FireFly Project in many forms, and
4 | there's always plenty to do!
5 |
6 | Please visit the
7 | [contributors guide](https://hyperledger.github.io/firefly//contributors/contributors.html) in the
8 | docs to learn how to make contributions to this exciting project.
9 |
10 | 
This work is licensed under a Creative Commons Attribution 4.0 International License.
11 |
--------------------------------------------------------------------------------
/MAINTAINERS.md:
--------------------------------------------------------------------------------
1 | # firefly-transaction-manager-maintainers
2 |
3 | The following is the list of current maintainers this repo:
4 |
5 | | Name | GitHub | Email | LFID |
6 | | ----------------- | --------------- | ---------------------------- | ----------------- |
7 | | Peter Broadhurst | peterbroadhurst | peter.broadhurst@kaleido.io | peterbroadhurst |
8 | | Enrique Lacal | enriquel8 | enrique.lacal@kaleido.io | enriquelacal |
9 | | Andrew Richardson | awrichar | andrew.richardson@kaleido.io | Andrew.Richardson |
10 | | Chengxuan Xing | Chengxuan | chengxuan.xing@kaleido.io | chengxuanxing |
11 |
12 | This list is to be kept up to date as maintainers are added or removed.
13 |
14 | For the full list of maintainers across all repos, the expectations of a maintainer and the process for becoming a maintainer, please see the [FireFly Maintainers page on the Hyperledger Wiki](https://wiki.hyperledger.org/display/FIR/Maintainers).
15 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | VGO=go
2 | GOFILES := $(shell find internal pkg -name '*.go' -print)
3 | GOBIN := $(shell $(VGO) env GOPATH)/bin
4 | LINT := $(GOBIN)/golangci-lint
5 | MOCKERY := $(GOBIN)/mockery
6 |
7 | # Expect that FireFly compiles with CGO disabled
8 | CGO_ENABLED=0
9 | GOGC=30
10 |
11 | .DELETE_ON_ERROR:
12 |
13 | all: build test go-mod-tidy
14 | test: deps lint
15 | $(VGO) test ./internal/... ./pkg/... -cover -coverprofile=coverage.txt -covermode=atomic -timeout=30s ${TEST_FLAGS}
16 | coverage.html:
17 | $(VGO) tool cover -html=coverage.txt
18 | coverage: test coverage.html
19 | lint:
20 | $(VGO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.8
21 | GOGC=20 $(LINT) run -v --timeout 5m
22 |
23 | ${MOCKERY}:
24 | $(VGO) install github.com/vektra/mockery/v2@v2.43.1
25 |
26 | define makemock
27 | mocks: mocks-$(strip $(1))-$(strip $(2))
28 | mocks-$(strip $(1))-$(strip $(2)): ${MOCKERY}
29 | ${MOCKERY} --case underscore --dir $(1) --name $(2) --outpkg $(3) --output mocks/$(strip $(3))
30 | endef
31 |
32 | $(eval $(call makemock, pkg/ffcapi, API, ffcapimocks))
33 | $(eval $(call makemock, pkg/txhandler, TransactionHandler, txhandlermocks))
34 | $(eval $(call makemock, pkg/txhandler, ManagedTxEventHandler, txhandlermocks))
35 | $(eval $(call makemock, internal/metrics, TransactionHandlerMetrics, metricsmocks))
36 | $(eval $(call makemock, internal/metrics, EventMetricsEmitter, metricsmocks))
37 | $(eval $(call makemock, internal/confirmations, Manager, confirmationsmocks))
38 | $(eval $(call makemock, internal/persistence, Persistence, persistencemocks))
39 | $(eval $(call makemock, internal/persistence, TransactionPersistence, persistencemocks))
40 | $(eval $(call makemock, internal/persistence, RichQuery, persistencemocks))
41 | $(eval $(call makemock, internal/ws, WebSocketChannels, wsmocks))
42 | $(eval $(call makemock, internal/ws, WebSocketServer, wsmocks))
43 | $(eval $(call makemock, internal/events, Stream, eventsmocks))
44 | $(eval $(call makemock, internal/apiclient, FFTMClient, apiclientmocks))
45 |
46 | go-mod-tidy: .ALWAYS
47 | $(VGO) mod tidy
48 | build: test
49 | .ALWAYS: ;
50 | clean:
51 | $(VGO) clean
52 | deps:
53 | $(VGO) get ./internal/... ./pkg/...
54 | $(VGO) get -t ./internal/... ./pkg/...
55 | reference:
56 | $(VGO) test ./pkg/fftm -timeout=10s -tags docs
57 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Hyperledger Security Policy
2 |
3 | ## Reporting a Security Bug
4 |
5 | If you think you have discovered a security issue in any of the Hyperledger projects, we'd love to
6 | hear from you. We will take all security bugs seriously and if confirmed upon investigation we will
7 | patch it within a reasonable amount of time and release a public security bulletin discussing the
8 | impact and credit the discoverer.
9 |
10 | There are two ways to report a security bug. The easiest is to email a description of the flaw and
11 | any related information (e.g. reproduction steps, version) to
12 | [security at hyperledger dot org](mailto:security@hyperledger.org).
13 |
14 | The other way is to file a confidential security bug in our
15 | [JIRA bug tracking system](https://jira.hyperledger.org). Be sure to set the “Security Level” to
16 | “Security issue”.
17 |
18 | The process by which the Hyperledger Security Team handles security bugs is documented further in
19 | our [Defect Response page](https://wiki.hyperledger.org/display/SEC/Defect+Response) on our
20 | [wiki](https://wiki.hyperledger.org).
--------------------------------------------------------------------------------
/cmd/client_eventstreams.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package cmd
18 |
19 | import (
20 | "github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
21 | "github.com/spf13/cobra"
22 | )
23 |
24 | var eventStreamID string
25 |
26 | func clientEventStreamsCommand(clientFactory func() (apiclient.FFTMClient, error)) *cobra.Command {
27 | clientEventStreamsCmd := &cobra.Command{
28 | Use: "eventstreams ",
29 | Short: "Make API requests to an blockchain connector instance",
30 | }
31 | clientEventStreamsCmd.AddCommand(clientEventStreamsListCommand(clientFactory))
32 | clientEventStreamsCmd.AddCommand(clientEventStreamsDeleteCommand(clientFactory))
33 | return clientEventStreamsCmd
34 | }
35 |
--------------------------------------------------------------------------------
/cmd/client_eventstreams_delete.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2025 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package cmd
18 |
19 | import (
20 | "context"
21 | "fmt"
22 | "strings"
23 |
24 | "github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
25 | "github.com/spf13/cobra"
26 | )
27 |
28 | func clientEventStreamsDeleteCommand(clientFactory func() (apiclient.FFTMClient, error)) *cobra.Command {
29 | clientEventStreamsDeleteCmd := &cobra.Command{
30 | Use: "delete",
31 | Short: "Delete event streams",
32 | Long: "",
33 | RunE: func(_ *cobra.Command, _ []string) error {
34 | client, err := clientFactory()
35 | if err != nil {
36 | return err
37 | }
38 | if eventStreamID == "" && nameRegex == "" {
39 | return fmt.Errorf("eventstream or name flag must be set")
40 | }
41 | if eventStreamID != "" && nameRegex != "" {
42 | return fmt.Errorf("eventstream and name flags cannot be combined")
43 | }
44 | if eventStreamID != "" {
45 | err := client.DeleteEventStream(context.Background(), eventStreamID)
46 | if err != nil {
47 | if !(strings.Contains(err.Error(), "FF21046") && ignoreNotFound) {
48 | return err
49 | }
50 | }
51 | }
52 | if nameRegex != "" {
53 | err := client.DeleteEventStreamsByName(context.Background(), nameRegex)
54 | if err != nil {
55 | return err
56 | }
57 | }
58 | return nil
59 | },
60 | }
61 | clientEventStreamsDeleteCmd.Flags().StringVarP(&eventStreamID, "eventstream", "", "", "The ID of the event stream")
62 | clientEventStreamsDeleteCmd.Flags().StringVarP(&nameRegex, "name", "", "", "A regular expression for matching the event stream name")
63 | return clientEventStreamsDeleteCmd
64 | }
65 |
--------------------------------------------------------------------------------
/cmd/client_eventstreams_list.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2025 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package cmd
18 |
19 | import (
20 | "context"
21 | "encoding/json"
22 | "fmt"
23 |
24 | "github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
25 | "github.com/spf13/cobra"
26 | )
27 |
28 | func clientEventStreamsListCommand(clientFactory func() (apiclient.FFTMClient, error)) *cobra.Command {
29 | clientEventStreamsListCmd := &cobra.Command{
30 | Use: "list",
31 | Short: "List event streams",
32 | Long: "",
33 | RunE: func(_ *cobra.Command, _ []string) error {
34 | client, err := clientFactory()
35 | if err != nil {
36 | return err
37 | }
38 | eventStreams, err := client.GetEventStreams(context.Background())
39 | if err != nil {
40 | return err
41 | }
42 | json, _ := json.MarshalIndent(eventStreams, "", " ")
43 | fmt.Println(string(json))
44 | return nil
45 | },
46 | }
47 | return clientEventStreamsListCmd
48 | }
49 |
--------------------------------------------------------------------------------
/cmd/client_eventstreams_list_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package cmd
18 |
19 | import (
20 | "fmt"
21 | "testing"
22 |
23 | "github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
24 | "github.com/hyperledger/firefly-transaction-manager/mocks/apiclientmocks"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestEventStreamsList(t *testing.T) {
31 | mc := apiclientmocks.NewFFTMClient(t)
32 | cmd := buildClientCommand(func() (apiclient.FFTMClient, error) { return mc, nil })
33 | cmd.SetArgs([]string{"eventstreams", "list"})
34 | mc.On("GetEventStreams", mock.Anything).Return([]apitypes.EventStream{}, nil)
35 | err := cmd.Execute()
36 | assert.NoError(t, err)
37 | mc.AssertExpectations(t)
38 | }
39 |
40 | func TestEventStreamsListError(t *testing.T) {
41 | mc := apiclientmocks.NewFFTMClient(t)
42 | cmd := buildClientCommand(func() (apiclient.FFTMClient, error) { return mc, nil })
43 | cmd.SetArgs([]string{"eventstreams", "list"})
44 | mc.On("GetEventStreams", mock.Anything).Return(nil, fmt.Errorf("pop"))
45 | err := cmd.Execute()
46 | assert.Regexp(t, "pop", err)
47 | mc.AssertExpectations(t)
48 | }
49 |
50 | func TestEventStreamsListBadClientConfig(t *testing.T) {
51 | mc := apiclientmocks.NewFFTMClient(t)
52 | cmd := buildClientCommand(func() (apiclient.FFTMClient, error) { return mc, fmt.Errorf("pop") })
53 | cmd.SetArgs([]string{"eventstreams", "list"})
54 | err := cmd.Execute()
55 | assert.Regexp(t, "pop", err)
56 | mc.AssertExpectations(t)
57 | }
58 |
--------------------------------------------------------------------------------
/cmd/client_listeners.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package cmd
18 |
19 | import (
20 | "github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
21 | "github.com/spf13/cobra"
22 | )
23 |
24 | var listenerID string
25 |
26 | func clientListenersCommand(clientFactory func() (apiclient.FFTMClient, error)) *cobra.Command {
27 | clientListenersCmd := &cobra.Command{
28 | Use: "listeners ",
29 | Short: "Make API requests to an blockchain connector instance",
30 | }
31 | clientListenersCmd.PersistentFlags().StringVarP(&eventStreamID, "eventstream", "", "", "The event stream ID")
32 | clientListenersCmd.AddCommand(clientListenersListCommand(clientFactory))
33 | clientListenersCmd.AddCommand(clientListenersDeleteCommand(clientFactory))
34 | return clientListenersCmd
35 | }
36 |
--------------------------------------------------------------------------------
/cmd/client_listeners_delete.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2025 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package cmd
18 |
19 | import (
20 | "context"
21 | "fmt"
22 | "strings"
23 |
24 | "github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
25 | "github.com/spf13/cobra"
26 | )
27 |
28 | func clientListenersDeleteCommand(clientFactory func() (apiclient.FFTMClient, error)) *cobra.Command {
29 | clientListenersDeleteCmd := &cobra.Command{
30 | Use: "delete",
31 | Short: "Delete event streams",
32 | Long: "",
33 | RunE: func(_ *cobra.Command, _ []string) error {
34 | client, err := clientFactory()
35 | if err != nil {
36 | return err
37 | }
38 | if eventStreamID == "" {
39 | return fmt.Errorf("eventstream flag not set")
40 | }
41 | if listenerID == "" && nameRegex == "" {
42 | return fmt.Errorf("listener or name flag must be set")
43 | }
44 | if listenerID != "" && nameRegex != "" {
45 | return fmt.Errorf("listener and name flags cannot be combined")
46 | }
47 | if listenerID != "" {
48 | err := client.DeleteListener(context.Background(), eventStreamID, listenerID)
49 | if err != nil {
50 | if !(strings.Contains(err.Error(), "FF21046") && ignoreNotFound) {
51 | return err
52 | }
53 | }
54 | }
55 | if nameRegex != "" {
56 | err := client.DeleteListenersByName(context.Background(), eventStreamID, nameRegex)
57 | if err != nil {
58 | return err
59 | }
60 | }
61 | return nil
62 | },
63 | }
64 | clientListenersDeleteCmd.Flags().StringVarP(&listenerID, "listener", "", "", "The ID of the listener")
65 | clientListenersDeleteCmd.Flags().StringVarP(&nameRegex, "name", "", "", "A regular expression for matching the listener name")
66 | return clientListenersDeleteCmd
67 | }
68 |
--------------------------------------------------------------------------------
/cmd/client_listeners_list.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2025 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package cmd
18 |
19 | import (
20 | "context"
21 | "encoding/json"
22 | "fmt"
23 |
24 | "github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
25 | "github.com/spf13/cobra"
26 | )
27 |
28 | func clientListenersListCommand(clientFactory func() (apiclient.FFTMClient, error)) *cobra.Command {
29 | clientListenersListCmd := &cobra.Command{
30 | Use: "list",
31 | Short: "List listeners",
32 | Long: "",
33 | RunE: func(_ *cobra.Command, _ []string) error {
34 | client, err := clientFactory()
35 | if err != nil {
36 | return err
37 | }
38 | if eventStreamID == "" {
39 | return fmt.Errorf("eventstream flag not set")
40 | }
41 | listeners, err := client.GetListeners(context.Background(), eventStreamID)
42 | if err != nil {
43 | return err
44 | }
45 | json, _ := json.MarshalIndent(listeners, "", " ")
46 | fmt.Println(string(json))
47 | return nil
48 | },
49 | }
50 | return clientListenersListCmd
51 | }
52 |
--------------------------------------------------------------------------------
/cmd/client_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package cmd
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/config"
23 | "github.com/hyperledger/firefly-common/pkg/fftls"
24 | "github.com/hyperledger/firefly-transaction-manager/internal/apiclient"
25 | "github.com/stretchr/testify/assert"
26 | )
27 |
28 | func TestClientCommand(t *testing.T) {
29 | cmd := ClientCommand()
30 | err := cmd.Execute()
31 | assert.NoError(t, err)
32 | }
33 |
34 | func TestCreateDefaultClient(t *testing.T) {
35 | client, err := createClient()
36 | assert.NotNil(t, client)
37 | assert.NoError(t, err)
38 | }
39 |
40 | func TestCreateClientTLSFail(t *testing.T) {
41 | cfg := config.RootSection("fftm_client")
42 | apiclient.InitConfig(cfg)
43 | tlsConf := cfg.SubSection("tls")
44 | tlsConf.Set(fftls.HTTPConfTLSEnabled, true)
45 | tlsConf.Set(fftls.HTTPConfTLSCAFile, "!!!badness")
46 | _, err := createClient()
47 | assert.Regexp(t, "FF00153", err)
48 | }
49 |
--------------------------------------------------------------------------------
/cmd/migrate.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2025 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package cmd
18 |
19 | import (
20 | "context"
21 |
22 | "github.com/hyperledger/firefly-transaction-manager/internal/persistence/dbmigration"
23 | "github.com/spf13/cobra"
24 | )
25 |
26 | func MigrateCommand(initConfig func() error) *cobra.Command {
27 | return buildMigrateCommand(initConfig)
28 | }
29 |
30 | func buildMigrateCommand(initConfig func() error) *cobra.Command {
31 | migrateCmd := &cobra.Command{
32 | Use: "migrate ",
33 | Short: "Migration tools",
34 | }
35 | migrateCmd.AddCommand(buildLeveldb2postgresCommand(initConfig))
36 |
37 | return migrateCmd
38 | }
39 |
40 | func buildLeveldb2postgresCommand(initConfig func() error) *cobra.Command {
41 | leveldb2postgresEventStreamsCmd := &cobra.Command{
42 | Use: "leveldb2postgres",
43 | Short: "Migrate from LevelDB to PostgreSQL persistence",
44 | RunE: func(_ *cobra.Command, _ []string) error {
45 | if err := initConfig(); err != nil {
46 | return err
47 | }
48 | return dbmigration.MigrateLevelDBToPostgres(context.Background())
49 | },
50 | }
51 | return leveldb2postgresEventStreamsCmd
52 | }
53 |
--------------------------------------------------------------------------------
/cmd/migrate_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package cmd
18 |
19 | import (
20 | "fmt"
21 | "testing"
22 |
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmconfig"
24 | "github.com/stretchr/testify/assert"
25 | )
26 |
27 | func TestMigrateCommandFailInit(t *testing.T) {
28 | cmd := MigrateCommand(func() error {
29 | return fmt.Errorf("pop")
30 | })
31 | cmd.SetArgs([]string{"leveldb2postgres"})
32 | err := cmd.Execute()
33 | assert.Regexp(t, "pop", err)
34 | }
35 |
36 | func TestMigrateCommandFailRun(t *testing.T) {
37 | cmd := MigrateCommand(func() error {
38 | tmconfig.Reset()
39 | return nil
40 | })
41 | cmd.SetArgs([]string{"leveldb2postgres"})
42 | err := cmd.Execute()
43 | assert.Regexp(t, "FF21050", err)
44 | }
45 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | status:
3 | project:
4 | default:
5 | threshold: 0.1%
6 | patch:
7 | default:
8 | threshold: 0.1%
9 | ignore:
10 | - "mocks/**/*.go"
11 |
--------------------------------------------------------------------------------
/db/migrations/postgres/000001_create_transactions_table.down.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | DROP INDEX transactions_id;
3 | DROP INDEX transactions_nonce;
4 | DROP TABLE transactions;
5 | COMMIT;
6 |
--------------------------------------------------------------------------------
/db/migrations/postgres/000001_create_transactions_table.up.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | CREATE TABLE transactions (
3 | seq SERIAL PRIMARY KEY,
4 | id TEXT NOT NULL,
5 | created BIGINT NOT NULL,
6 | updated BIGINT NOT NULL,
7 | status VARCHAR(65) NOT NULL,
8 | delete BIGINT,
9 | tx_from TEXT,
10 | tx_to TEXT,
11 | tx_nonce VARCHAR(65),
12 | tx_gas VARCHAR(65),
13 | tx_value VARCHAR(65),
14 | tx_gasprice TEXT,
15 | tx_data TEXT NOT NULL,
16 | tx_hash TEXT NOT NULL,
17 | policy_info TEXT,
18 | first_submit BIGINT,
19 | last_submit BIGINT,
20 | error_message TEXT NOT NULL
21 | );
22 | CREATE UNIQUE INDEX transactions_id ON transactions(id);
23 | CREATE UNIQUE INDEX transactions_nonce ON transactions(tx_from, tx_nonce);
24 | CREATE INDEX transactions_hash ON transactions(tx_hash);
25 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000002_create_receipts_table.down.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | DROP INDEX receipts_id;
3 | DROP TABLE receipts;
4 | COMMIT;
5 |
--------------------------------------------------------------------------------
/db/migrations/postgres/000002_create_receipts_table.up.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | CREATE TABLE receipts (
3 | seq SERIAL PRIMARY KEY,
4 | id TEXT NOT NULL,
5 | created BIGINT NOT NULL,
6 | updated BIGINT NOT NULL,
7 | block_number VARCHAR(65),
8 | tx_index VARCHAR(65),
9 | block_hash TEXT NOT NULL,
10 | success BOOLEAN NOT NULL,
11 | protocol_id TEXT NOT NULL,
12 | extra_info TEXT,
13 | contract_loc TEXT
14 | );
15 | CREATE UNIQUE INDEX receipts_id ON receipts(id);
16 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000003_create_confirmations_table.down.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | DROP INDEX confirmations_id;
3 | DROP INDEX confirmations_txid;
4 | DROP TABLE confirmations;
5 | COMMIT;
6 |
--------------------------------------------------------------------------------
/db/migrations/postgres/000003_create_confirmations_table.up.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | CREATE TABLE confirmations (
3 | seq SERIAL PRIMARY KEY,
4 | id UUID NOT NULL,
5 | created BIGINT NOT NULL,
6 | updated BIGINT NOT NULL,
7 | tx_id TEXT NOT NULL,
8 | block_number BIGINT NOT NULL,
9 | block_hash TEXT NOT NULL,
10 | parent_hash TEXT NOT NULL
11 | );
12 | CREATE UNIQUE INDEX confirmations_id ON confirmations(id);
13 | CREATE INDEX confirmations_txid ON confirmations(tx_id);
14 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000004_create_txhistory_table.down.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | DROP INDEX IF EXISTS txhistory_id;
3 | DROP INDEX IF EXISTS txhistory_txid;
4 | DROP TABLE txhistory;
5 | COMMIT;
6 |
--------------------------------------------------------------------------------
/db/migrations/postgres/000004_create_txhistory_table.up.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | CREATE TABLE txhistory (
3 | seq SERIAL PRIMARY KEY,
4 | id UUID NOT NULL,
5 | time BIGINT NOT NULL,
6 | last_occurrence BIGINT NOT NULL,
7 | tx_id TEXT NOT NULL,
8 | status TEXT NOT NULL,
9 | action TEXT NOT NULL,
10 | count INT NOT NULL,
11 | error TEXT,
12 | error_time BIGINT,
13 | info TEXT
14 | );
15 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000005_create_checkpoints_table.down.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | DROP INDEX checkpoints_id;
3 | DROP TABLE checkpoints;
4 | COMMIT;
5 |
--------------------------------------------------------------------------------
/db/migrations/postgres/000005_create_checkpoints_table.up.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | CREATE TABLE checkpoints (
3 | seq SERIAL PRIMARY KEY,
4 | id UUID NOT NULL,
5 | created BIGINT NOT NULL,
6 | updated BIGINT NOT NULL,
7 | listeners JSON
8 | );
9 | CREATE UNIQUE INDEX checkpoints_id ON checkpoints(id);
10 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000006_create_eventstreams_table.down.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | DROP INDEX eventstreams_id;
3 | DROP INDEX eventstreams_name;
4 | DROP TABLE eventstreams;
5 | COMMIT;
6 |
--------------------------------------------------------------------------------
/db/migrations/postgres/000006_create_eventstreams_table.up.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | CREATE TABLE eventstreams (
3 | seq SERIAL PRIMARY KEY,
4 | id UUID NOT NULL,
5 | created BIGINT NOT NULL,
6 | updated BIGINT NOT NULL,
7 | name TEXT,
8 | suspended BOOLEAN,
9 | stream_type TEXT,
10 | error_handling TEXT,
11 | batch_size BIGINT,
12 | batch_timeout TEXT NOT NULL,
13 | retry_timeout TEXT NOT NULL,
14 | blocked_retry_timeout TEXT NOT NULL,
15 | webhook_config TEXT,
16 | websocket_config TEXT
17 | );
18 | CREATE UNIQUE INDEX eventstreams_id ON eventstreams(id);
19 | CREATE UNIQUE INDEX eventstreams_name ON eventstreams(name);
20 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000007_create_listeners_table.down.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | DROP INDEX listeners_id;
3 | DROP INDEX listeners_name;
4 | DROP INDEX listeners_stream;
5 | DROP TABLE listeners;
6 | COMMIT;
7 |
--------------------------------------------------------------------------------
/db/migrations/postgres/000007_create_listeners_table.up.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | CREATE TABLE listeners (
3 | seq SERIAL PRIMARY KEY,
4 | id UUID NOT NULL,
5 | created BIGINT NOT NULL,
6 | updated BIGINT NOT NULL,
7 | name TEXT,
8 | stream_id UUID NOT NULL,
9 | filters TEXT,
10 | options TEXT,
11 | signature TEXT,
12 | from_block TEXT
13 | );
14 | CREATE UNIQUE INDEX listeners_id ON listeners(id);
15 | CREATE UNIQUE INDEX listeners_name ON listeners(name); -- global uniqueness on names
16 | CREATE INDEX listeners_stream ON listeners(stream_id);
17 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000008_create_txhistory_idx.down.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | DROP INDEX IF EXISTS txhistory_id;
3 | DROP INDEX IF EXISTS txhistory_txid;
4 | COMMIT;
5 |
--------------------------------------------------------------------------------
/db/migrations/postgres/000008_create_txhistory_idx.up.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | -- Allow nil data on transactions, for example for a simple transfer operation
3 | ALTER TABLE transactions ALTER COLUMN tx_data DROP NOT NULL;
4 |
5 | -- Correct TXHistory indexes if created by an invalid 000004 migration (no longer in codebase).
6 | DROP INDEX IF EXISTS txhistory_id;
7 | DROP INDEX IF EXISTS txhistory_txid;
8 |
9 | -- Create corrected TXHistory indexes
10 | CREATE UNIQUE INDEX txhistory_id ON txhistory(id);
11 | CREATE INDEX txhistory_txid ON txhistory(tx_id);
12 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000009_add_transactions_status_index.down.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | DROP INDEX IF EXISTS transactions_status;
3 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000009_add_transactions_status_index.up.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 | CREATE INDEX transactions_status ON transactions(status);
3 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000010_add_listeners_type.down.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 |
3 | ALTER TABLE listeners DROP COLUMN "type";
4 |
5 | COMMIT;
--------------------------------------------------------------------------------
/db/migrations/postgres/000010_add_listeners_type.up.sql:
--------------------------------------------------------------------------------
1 | BEGIN;
2 |
3 | ALTER TABLE listeners ADD COLUMN "type" VARCHAR(64);
4 | UPDATE listeners SET "type" = 'events';
5 | ALTER TABLE listeners ALTER COLUMN "type" SET NOT NULL;
6 |
7 | COMMIT;
--------------------------------------------------------------------------------
/images/fftm_event_streams_architecture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperledger/firefly-transaction-manager/7a882ddaeaf2e7b9b2203a053402576e436debd9/images/fftm_event_streams_architecture.jpg
--------------------------------------------------------------------------------
/images/firefly_connector_framework_architecture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperledger/firefly-transaction-manager/7a882ddaeaf2e7b9b2203a053402576e436debd9/images/firefly_connector_framework_architecture.jpg
--------------------------------------------------------------------------------
/internal/apiclient/fftm_client.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package apiclient
18 |
19 | import (
20 | "context"
21 |
22 | "github.com/go-resty/resty/v2"
23 | "github.com/hyperledger/firefly-common/pkg/config"
24 | "github.com/hyperledger/firefly-common/pkg/ffresty"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | )
27 |
28 | type FFTMClient interface {
29 | GetEventStreams(ctx context.Context) ([]apitypes.EventStream, error)
30 | GetListeners(ctx context.Context, eventStreamID string) ([]apitypes.Listener, error)
31 | DeleteEventStream(ctx context.Context, eventStreamID string) error
32 | DeleteEventStreamsByName(ctx context.Context, nameRegex string) error
33 | DeleteListener(ctx context.Context, eventStreamID, listenerID string) error
34 | DeleteListenersByName(ctx context.Context, eventStreamID, nameRegex string) error
35 | }
36 |
37 | type fftmClient struct {
38 | client *resty.Client
39 | }
40 |
41 | func InitConfig(conf config.Section) {
42 | ffresty.InitConfig(conf)
43 | }
44 |
45 | func NewFFTMClient(ctx context.Context, staticConfig config.Section) (FFTMClient, error) {
46 | client, err := ffresty.New(ctx, staticConfig)
47 | if err != nil {
48 | return nil, err
49 | }
50 | return &fftmClient{
51 | client: client,
52 | }, nil
53 | }
54 |
--------------------------------------------------------------------------------
/internal/apiclient/fftm_client_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package apiclient
18 |
19 | import (
20 | "context"
21 | "net/http"
22 | "net/http/httptest"
23 | "testing"
24 |
25 | "github.com/hyperledger/firefly-common/pkg/config"
26 | "github.com/hyperledger/firefly-common/pkg/fftls"
27 | "github.com/stretchr/testify/assert"
28 | )
29 |
30 | func newTestClientServer(t *testing.T, handler func(w http.ResponseWriter, r *http.Request)) (FFTMClient, *httptest.Server) {
31 | server := httptest.NewServer(http.HandlerFunc(handler))
32 | config := config.RootSection("fftm_client")
33 | InitConfig(config)
34 | config.Set("url", server.URL)
35 | client, err := NewFFTMClient(context.Background(), config)
36 | assert.NoError(t, err)
37 | return client, server
38 | }
39 |
40 | func TestBadTLSCreds(t *testing.T) {
41 | config := config.RootSection("fftm_client")
42 | InitConfig(config)
43 | tlsConf := config.SubSection("tls")
44 | tlsConf.Set(fftls.HTTPConfTLSEnabled, true)
45 | tlsConf.Set(fftls.HTTPConfTLSCAFile, "!!!badness")
46 | _, err := NewFFTMClient(context.Background(), config)
47 | assert.Regexp(t, "FF00153", err)
48 | }
49 |
--------------------------------------------------------------------------------
/internal/blocklistener/blocklistener_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package blocklistener
18 |
19 | import (
20 | "context"
21 | "testing"
22 |
23 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
24 | "github.com/stretchr/testify/assert"
25 | )
26 |
27 | type testBlockConsumer struct {
28 | c chan *ffcapi.BlockHashEvent
29 | }
30 |
31 | func (tbc *testBlockConsumer) NewBlockHashes() chan<- *ffcapi.BlockHashEvent {
32 | return tbc.c
33 | }
34 |
35 | func TestBlockListenerDoesNotBlock(t *testing.T) {
36 |
37 | unBuffered := make(chan *ffcapi.BlockHashEvent, 1)
38 | ctx, cancelCtx := context.WithCancel(context.Background())
39 |
40 | buffered, blockListenerDone := BufferChannel(ctx, &testBlockConsumer{c: unBuffered})
41 |
42 | for i := 0; i < 100; i++ {
43 | buffered <- &ffcapi.BlockHashEvent{}
44 | }
45 |
46 | // Get the one that was stuck in the pipe
47 | bhe := <-unBuffered
48 | assert.False(t, bhe.GapPotential)
49 |
50 | // We should get the unblocking one too, with GapPotential set
51 | bhe = <-unBuffered
52 | assert.True(t, bhe.GapPotential)
53 |
54 | // Block it again
55 | for i := 0; i < 100; i++ {
56 | buffered <- &ffcapi.BlockHashEvent{}
57 | }
58 |
59 | // And check we can exit while blocked
60 | cancelCtx()
61 | <-blockListenerDone
62 |
63 | }
64 |
65 | func TestExitOnContextCancel(t *testing.T) {
66 |
67 | unBuffered := make(chan *ffcapi.BlockHashEvent)
68 | ctx, cancelCtx := context.WithCancel(context.Background())
69 | cancelCtx()
70 |
71 | _, blockListenerDone := BufferChannel(ctx, &testBlockConsumer{c: unBuffered})
72 | <-blockListenerDone
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/internal/metrics/event_metrics_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package metrics
18 |
19 | import (
20 | "context"
21 | "testing"
22 | )
23 |
24 | func TestTransactionHandlerEventMetricsEmitters(t *testing.T) {
25 | ctx := context.Background()
26 | mm, cancel := newTestMetricsManager(t)
27 | defer cancel()
28 | mm.metricsEnabled = true
29 |
30 | mm.RecordBlockHashProcessMetrics(ctx, 1)
31 | mm.RecordBlockHashBatchSizeMetric(ctx, 1)
32 | mm.RecordBlockHashQueueingMetrics(ctx, 1)
33 | mm.RecordConfirmationMetrics(ctx, 1)
34 | mm.RecordNotificationProcessMetrics(ctx, "test", 1)
35 | mm.RecordNotificationQueueingMetrics(ctx, "test", 1)
36 | mm.RecordReceiptCheckMetrics(ctx, "test", 1)
37 | mm.RecordReceiptMetrics(ctx, 1)
38 | }
39 |
--------------------------------------------------------------------------------
/internal/persistence/dbmigration/leveldb2postgres.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package dbmigration
18 |
19 | import (
20 | "context"
21 | "time"
22 |
23 | "github.com/hyperledger/firefly-common/pkg/i18n"
24 | "github.com/hyperledger/firefly-transaction-manager/internal/persistence/leveldb"
25 | "github.com/hyperledger/firefly-transaction-manager/internal/persistence/postgres"
26 | "github.com/hyperledger/firefly-transaction-manager/internal/tmconfig"
27 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
28 | )
29 |
30 | func MigrateLevelDBToPostgres(ctx context.Context) (err error) {
31 | m := &dbMigration{}
32 |
33 | tmconfig.PostgresSection.Set(postgres.ConfigTXWriterBatchTimeout, 0) // single go-routine, no point in batching
34 | tmconfig.PostgresSection.Set(postgres.ConfigTXWriterCount, 1)
35 | nonceStateTimeout := 0 * time.Second
36 | if m.source, err = leveldb.NewLevelDBPersistence(ctx, nonceStateTimeout); err != nil {
37 | return i18n.NewError(ctx, tmmsgs.MsgPersistenceInitFail, "leveldb", err)
38 | }
39 | defer m.source.Close(ctx)
40 | if m.target, err = postgres.NewPostgresPersistence(ctx, tmconfig.PostgresSection, nonceStateTimeout, postgres.ForMigration); err != nil {
41 | return i18n.NewError(ctx, tmmsgs.MsgPersistenceInitFail, "postgres", err)
42 | }
43 | defer m.target.Close(ctx)
44 |
45 | return m.run(ctx)
46 | }
47 |
--------------------------------------------------------------------------------
/internal/persistence/persistence_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package persistence
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/fftypes"
23 | "github.com/stretchr/testify/assert"
24 | )
25 |
26 | func TestJSONOrStringNull(t *testing.T) {
27 | assert.Nil(t, JSONOrString(nil))
28 | }
29 |
30 | func TestJSONOrStringGoodJSON(t *testing.T) {
31 | assert.Equal(t, `{ "good": "json"}`, (string)(*JSONOrString(fftypes.JSONAnyPtr(`{ "good": "json"}`))))
32 | }
33 |
34 | func TestJSONOrStringBadJSON(t *testing.T) {
35 | assert.Equal(t, "\"\\\"bad\\\": \\\"json\\\"}\"", (string)(*JSONOrString(fftypes.JSONAnyPtr(`"bad": "json"}`))))
36 | }
37 |
--------------------------------------------------------------------------------
/internal/persistence/postgres/checkpoints_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package postgres
18 |
19 | import (
20 | "encoding/json"
21 | "testing"
22 |
23 | "github.com/hyperledger/firefly-common/pkg/fftypes"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | "github.com/stretchr/testify/assert"
26 | )
27 |
28 | func TestCheckpointsPSQ(t *testing.T) {
29 |
30 | ctx, p, _, done := initTestPSQL(t)
31 | defer done()
32 |
33 | cp1 := &apitypes.EventStreamCheckpoint{
34 | StreamID: fftypes.NewUUID(),
35 | Listeners: apitypes.CheckpointListeners{
36 | *fftypes.NewUUID(): json.RawMessage(`{"some":"data"}`),
37 | },
38 | }
39 | err := p.WriteCheckpoint(ctx, cp1)
40 | assert.NoError(t, err)
41 |
42 | cp2, err := p.GetCheckpoint(ctx, cp1.StreamID)
43 | assert.NoError(t, err)
44 | assert.NotNil(t, cp2.Time)
45 | assert.NotNil(t, cp2.FirstCheckpoint)
46 | cp1.Time = cp2.Time
47 | cp1.FirstCheckpoint = cp2.FirstCheckpoint
48 | assert.Equal(t, cp1, cp2)
49 |
50 | err = p.DeleteCheckpoint(ctx, cp1.StreamID)
51 | assert.NoError(t, err)
52 |
53 | cp3, err := p.GetCheckpoint(ctx, cp1.StreamID)
54 | assert.Nil(t, cp3)
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/internal/tmconfig/tmconfig_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package tmconfig
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/config"
23 | "github.com/stretchr/testify/assert"
24 | )
25 |
26 | const configDir = "../../test/data/config"
27 |
28 | func TestInitConfigOK(t *testing.T) {
29 | Reset()
30 |
31 | assert.Equal(t, 50, config.GetInt(EventStreamsDefaultsBatchSize))
32 | }
33 |
--------------------------------------------------------------------------------
/mocks/txhandlermocks/managed_tx_event_handler.go:
--------------------------------------------------------------------------------
1 | // Code generated by mockery v2.43.1. DO NOT EDIT.
2 |
3 | package txhandlermocks
4 |
5 | import (
6 | context "context"
7 |
8 | apitypes "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
9 |
10 | mock "github.com/stretchr/testify/mock"
11 | )
12 |
13 | // ManagedTxEventHandler is an autogenerated mock type for the ManagedTxEventHandler type
14 | type ManagedTxEventHandler struct {
15 | mock.Mock
16 | }
17 |
18 | // HandleEvent provides a mock function with given fields: ctx, e
19 | func (_m *ManagedTxEventHandler) HandleEvent(ctx context.Context, e apitypes.ManagedTransactionEvent) error {
20 | ret := _m.Called(ctx, e)
21 |
22 | if len(ret) == 0 {
23 | panic("no return value specified for HandleEvent")
24 | }
25 |
26 | var r0 error
27 | if rf, ok := ret.Get(0).(func(context.Context, apitypes.ManagedTransactionEvent) error); ok {
28 | r0 = rf(ctx, e)
29 | } else {
30 | r0 = ret.Error(0)
31 | }
32 |
33 | return r0
34 | }
35 |
36 | // NewManagedTxEventHandler creates a new instance of ManagedTxEventHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
37 | // The first argument is typically a *testing.T value.
38 | func NewManagedTxEventHandler(t interface {
39 | mock.TestingT
40 | Cleanup(func())
41 | }) *ManagedTxEventHandler {
42 | mock := &ManagedTxEventHandler{}
43 | mock.Mock.Test(t)
44 |
45 | t.Cleanup(func() { mock.AssertExpectations(t) })
46 |
47 | return mock
48 | }
49 |
--------------------------------------------------------------------------------
/mocks/wsmocks/web_socket_channels.go:
--------------------------------------------------------------------------------
1 | // Code generated by mockery v2.43.1. DO NOT EDIT.
2 |
3 | package wsmocks
4 |
5 | import (
6 | ws "github.com/hyperledger/firefly-transaction-manager/internal/ws"
7 | mock "github.com/stretchr/testify/mock"
8 | )
9 |
10 | // WebSocketChannels is an autogenerated mock type for the WebSocketChannels type
11 | type WebSocketChannels struct {
12 | mock.Mock
13 | }
14 |
15 | // GetChannels provides a mock function with given fields: topic
16 | func (_m *WebSocketChannels) GetChannels(topic string) (chan<- interface{}, chan<- interface{}, <-chan *ws.WebSocketCommandMessageOrError) {
17 | ret := _m.Called(topic)
18 |
19 | if len(ret) == 0 {
20 | panic("no return value specified for GetChannels")
21 | }
22 |
23 | var r0 chan<- interface{}
24 | var r1 chan<- interface{}
25 | var r2 <-chan *ws.WebSocketCommandMessageOrError
26 | if rf, ok := ret.Get(0).(func(string) (chan<- interface{}, chan<- interface{}, <-chan *ws.WebSocketCommandMessageOrError)); ok {
27 | return rf(topic)
28 | }
29 | if rf, ok := ret.Get(0).(func(string) chan<- interface{}); ok {
30 | r0 = rf(topic)
31 | } else {
32 | if ret.Get(0) != nil {
33 | r0 = ret.Get(0).(chan<- interface{})
34 | }
35 | }
36 |
37 | if rf, ok := ret.Get(1).(func(string) chan<- interface{}); ok {
38 | r1 = rf(topic)
39 | } else {
40 | if ret.Get(1) != nil {
41 | r1 = ret.Get(1).(chan<- interface{})
42 | }
43 | }
44 |
45 | if rf, ok := ret.Get(2).(func(string) <-chan *ws.WebSocketCommandMessageOrError); ok {
46 | r2 = rf(topic)
47 | } else {
48 | if ret.Get(2) != nil {
49 | r2 = ret.Get(2).(<-chan *ws.WebSocketCommandMessageOrError)
50 | }
51 | }
52 |
53 | return r0, r1, r2
54 | }
55 |
56 | // SendReply provides a mock function with given fields: message
57 | func (_m *WebSocketChannels) SendReply(message interface{}) {
58 | _m.Called(message)
59 | }
60 |
61 | // NewWebSocketChannels creates a new instance of WebSocketChannels. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
62 | // The first argument is typically a *testing.T value.
63 | func NewWebSocketChannels(t interface {
64 | mock.TestingT
65 | Cleanup(func())
66 | }) *WebSocketChannels {
67 | mock := &WebSocketChannels{}
68 | mock.Mock.Test(t)
69 |
70 | t.Cleanup(func() { mock.AssertExpectations(t) })
71 |
72 | return mock
73 | }
74 |
--------------------------------------------------------------------------------
/mocks/wsmocks/web_socket_server.go:
--------------------------------------------------------------------------------
1 | // Code generated by mockery v2.43.1. DO NOT EDIT.
2 |
3 | package wsmocks
4 |
5 | import (
6 | http "net/http"
7 |
8 | ws "github.com/hyperledger/firefly-transaction-manager/internal/ws"
9 | mock "github.com/stretchr/testify/mock"
10 | )
11 |
12 | // WebSocketServer is an autogenerated mock type for the WebSocketServer type
13 | type WebSocketServer struct {
14 | mock.Mock
15 | }
16 |
17 | // Close provides a mock function with given fields:
18 | func (_m *WebSocketServer) Close() {
19 | _m.Called()
20 | }
21 |
22 | // GetChannels provides a mock function with given fields: topic
23 | func (_m *WebSocketServer) GetChannels(topic string) (chan<- interface{}, chan<- interface{}, <-chan *ws.WebSocketCommandMessageOrError) {
24 | ret := _m.Called(topic)
25 |
26 | if len(ret) == 0 {
27 | panic("no return value specified for GetChannels")
28 | }
29 |
30 | var r0 chan<- interface{}
31 | var r1 chan<- interface{}
32 | var r2 <-chan *ws.WebSocketCommandMessageOrError
33 | if rf, ok := ret.Get(0).(func(string) (chan<- interface{}, chan<- interface{}, <-chan *ws.WebSocketCommandMessageOrError)); ok {
34 | return rf(topic)
35 | }
36 | if rf, ok := ret.Get(0).(func(string) chan<- interface{}); ok {
37 | r0 = rf(topic)
38 | } else {
39 | if ret.Get(0) != nil {
40 | r0 = ret.Get(0).(chan<- interface{})
41 | }
42 | }
43 |
44 | if rf, ok := ret.Get(1).(func(string) chan<- interface{}); ok {
45 | r1 = rf(topic)
46 | } else {
47 | if ret.Get(1) != nil {
48 | r1 = ret.Get(1).(chan<- interface{})
49 | }
50 | }
51 |
52 | if rf, ok := ret.Get(2).(func(string) <-chan *ws.WebSocketCommandMessageOrError); ok {
53 | r2 = rf(topic)
54 | } else {
55 | if ret.Get(2) != nil {
56 | r2 = ret.Get(2).(<-chan *ws.WebSocketCommandMessageOrError)
57 | }
58 | }
59 |
60 | return r0, r1, r2
61 | }
62 |
63 | // Handler provides a mock function with given fields: w, r
64 | func (_m *WebSocketServer) Handler(w http.ResponseWriter, r *http.Request) {
65 | _m.Called(w, r)
66 | }
67 |
68 | // SendReply provides a mock function with given fields: message
69 | func (_m *WebSocketServer) SendReply(message interface{}) {
70 | _m.Called(message)
71 | }
72 |
73 | // NewWebSocketServer creates a new instance of WebSocketServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
74 | // The first argument is typically a *testing.T value.
75 | func NewWebSocketServer(t interface {
76 | mock.TestingT
77 | Cleanup(func())
78 | }) *WebSocketServer {
79 | mock := &WebSocketServer{}
80 | mock.Mock.Test(t)
81 |
82 | t.Cleanup(func() { mock.AssertExpectations(t) })
83 |
84 | return mock
85 | }
86 |
--------------------------------------------------------------------------------
/pkg/apitypes/base_request.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package apitypes
18 |
19 | import "encoding/json"
20 |
21 | // BaseRequest is the common headers to all requests, and captures the full input payload for later decoding to a specific type
22 | type BaseRequest struct {
23 | headerDecoder
24 | fullPayload []byte
25 | }
26 |
27 | type headerDecoder struct {
28 | Headers RequestHeaders `json:"headers"`
29 | }
30 |
31 | func (br *BaseRequest) UnmarshalJSON(data []byte) error {
32 | br.fullPayload = data
33 | return json.Unmarshal(data, &br.headerDecoder)
34 | }
35 |
36 | func (br *BaseRequest) UnmarshalTo(o interface{}) error {
37 | return json.Unmarshal(br.fullPayload, &o)
38 | }
39 |
40 | type RequestHeaders struct {
41 | ID string `ffstruct:"fftmrequest" json:"id"`
42 | Type RequestType `json:"type"`
43 | }
44 |
45 | type RequestType string
46 |
47 | const (
48 | RequestTypeSendTransaction RequestType = "SendTransaction"
49 | RequestTypeQuery RequestType = "Query"
50 | RequestTypeDeploy RequestType = "DeployContract"
51 | RequestTypeTransactionReceipt RequestType = "TransactionReceipt"
52 | )
53 |
--------------------------------------------------------------------------------
/pkg/apitypes/base_request_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package apitypes
18 |
19 | import (
20 | "encoding/json"
21 | "testing"
22 |
23 | "github.com/hyperledger/firefly-common/pkg/fftypes"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
25 | "github.com/stretchr/testify/assert"
26 | )
27 |
28 | func TestBaseRequestDecoding(t *testing.T) {
29 |
30 | sampleRequest := &TransactionRequest{
31 | Headers: RequestHeaders{
32 | Type: RequestTypeSendTransaction,
33 | ID: fftypes.NewUUID().String(),
34 | },
35 | TransactionInput: ffcapi.TransactionInput{
36 | TransactionHeaders: ffcapi.TransactionHeaders{
37 | From: "0x12345",
38 | },
39 | },
40 | }
41 |
42 | j, err := json.Marshal(&sampleRequest)
43 | assert.NoError(t, err)
44 |
45 | var br BaseRequest
46 | err = json.Unmarshal(j, &br)
47 | assert.NoError(t, err)
48 |
49 | assert.Equal(t, RequestTypeSendTransaction, br.Headers.Type)
50 | assert.Equal(t, sampleRequest.Headers.ID, br.Headers.ID)
51 |
52 | var receivedRequest TransactionRequest
53 | err = br.UnmarshalTo(&receivedRequest)
54 | assert.NoError(t, err)
55 |
56 | assert.Equal(t, "0x12345", receivedRequest.TransactionInput.From)
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/pkg/apitypes/query_request.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2024 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package apitypes
18 |
19 | import (
20 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
21 | )
22 |
23 | // QueryRequest is the request payload to send to perform a synchronous query against the blockchain state
24 | type QueryRequest struct {
25 | Headers RequestHeaders `json:"headers"`
26 | ffcapi.TransactionInput
27 | BlockNumber *string `json:"blockNumber,omitempty"`
28 | }
29 |
30 | // QueryResponse is the response payload for a query
31 | type QueryResponse ffcapi.QueryInvokeResponse
32 |
--------------------------------------------------------------------------------
/pkg/apitypes/tx_request.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package apitypes
18 |
19 | import (
20 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
21 | )
22 |
23 | // TransactionRequest is the payload sent to initiate a new transaction
24 | type TransactionRequest struct {
25 | Headers RequestHeaders `json:"headers"`
26 | ffcapi.TransactionInput
27 | }
28 |
29 | // ContractDeployRequest is the payload sent to initiate a new transaction
30 | type ContractDeployRequest struct {
31 | Headers RequestHeaders `json:"headers"`
32 | ffcapi.ContractDeployPrepareRequest
33 | }
34 |
--------------------------------------------------------------------------------
/pkg/apitypes/txreceipt_request.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2024 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package apitypes
18 |
19 | import (
20 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
21 | )
22 |
23 | // TransactionReceiptRequest is the request payload to query for a receipt
24 | type TransactionReceiptRequest struct {
25 | Headers RequestHeaders `json:"headers"`
26 | ffcapi.TransactionReceiptRequest
27 | }
28 |
29 | // TransactionReceiptResponse is the response payload for a query
30 | type TransactionReceiptResponse struct {
31 | ffcapi.TransactionReceiptResponseBase
32 | Events []*EventWithContext `json:"events,omitempty"` // this is the serialization format for events (historical complexity)
33 | }
34 |
--------------------------------------------------------------------------------
/pkg/apitypes/ulid.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package apitypes
18 |
19 | import (
20 | "crypto/rand"
21 | "time"
22 |
23 | "github.com/hyperledger/firefly-common/pkg/fftypes"
24 | "github.com/oklog/ulid/v2"
25 | )
26 |
27 | var ulidReader = &ulid.LockedMonotonicReader{
28 | MonotonicReader: &ulid.MonotonicEntropy{
29 | Reader: rand.Reader,
30 | },
31 | }
32 |
33 | // NewULID returns a Universally Unique Lexicographically Sortable Identifier (ULID).
34 | // For consistency we impersonate the formatting of a UUID, so they can be used
35 | // interchangeably.
36 | // This can be used in database tables to ensure monotonic increasing identifiers.
37 | func NewULID() *fftypes.UUID {
38 | u := ulid.MustNew(ulid.Timestamp(time.Now()), ulidReader)
39 | return (*fftypes.UUID)(&u)
40 | }
41 |
--------------------------------------------------------------------------------
/pkg/apitypes/ulid_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package apitypes
18 |
19 | import (
20 | "strings"
21 | "testing"
22 |
23 | "github.com/stretchr/testify/assert"
24 | )
25 |
26 | func TestULID(t *testing.T) {
27 | u1 := NewULID()
28 | u2 := NewULID()
29 | assert.Negative(t, strings.Compare(u1.String(), u2.String()))
30 | }
31 |
--------------------------------------------------------------------------------
/pkg/ffcapi/address_balance.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import "github.com/hyperledger/firefly-common/pkg/fftypes"
20 |
21 | type AddressBalanceRequest struct {
22 | Address string `json:"address"`
23 | BlockTag string `json:"blockTag"`
24 | }
25 |
26 | type AddressBalanceResponse struct {
27 | Balance *fftypes.FFBigInt `json:"balance"`
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/ffcapi/block_info_by_hash.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | type BlockInfoByHashRequest struct {
20 | BlockHash string `json:"blockHash"`
21 | }
22 |
23 | type BlockInfoByHashResponse struct {
24 | BlockInfo
25 | }
26 |
--------------------------------------------------------------------------------
/pkg/ffcapi/block_info_by_number.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | type BlockInfoByNumberRequest struct {
24 | BlockNumber *fftypes.FFBigInt `json:"blockNumber"`
25 | AllowCache bool `json:"allowCache"`
26 | ExpectedParentHash string `json:"expectedParentHash"` // If set then a mismatched parent hash should be considered a cache miss (if the connector does caching)
27 | }
28 |
29 | type BlockInfoByNumberResponse struct {
30 | BlockInfo
31 | }
32 |
--------------------------------------------------------------------------------
/pkg/ffcapi/contract_deploy_prepare.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | type ContractDeployPrepareRequest struct {
24 | TransactionHeaders
25 | Definition *fftypes.JSONAny `json:"definition"` // such as an ABI for EVM
26 | Contract *fftypes.JSONAny `json:"contract"` // such as the Bytecode for EVM
27 | Params []*fftypes.JSONAny `json:"params"` // such as the inputs to the constructor for EVM
28 | Errors []*fftypes.JSONAny `json:"errors"` // such as the errors spec for EVM
29 | }
30 |
--------------------------------------------------------------------------------
/pkg/ffcapi/event_listener_add.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | const (
24 | FromBlockEarliest = "earliest"
25 | FromBlockLatest = "latest"
26 | )
27 |
28 | type EventListenerOptions struct {
29 | FromBlock string // The instruction for the first block to index from (when there is no previous checkpoint). Special "earliest" and "latest" strings should be supported as well as blockchain specific block ID (like a decimal number etc.)
30 | Filters []fftypes.JSONAny // The blockchain specific list of filters. The top-level array is an OR list. The semantics within each entry is defined by the blockchain
31 | Options *fftypes.JSONAny // Blockchain specific set of options, such as the first block to detect events from (can be null)
32 | }
33 |
34 | type EventListenerVerifyOptionsRequest struct {
35 | EventListenerOptions
36 | }
37 |
38 | type EventListenerVerifyOptionsResponse struct {
39 | ResolvedSignature string
40 | ResolvedOptions fftypes.JSONAny
41 | }
42 |
43 | type EventListenerAddRequest struct {
44 | EventListenerOptions
45 | ListenerID *fftypes.UUID // Unique UUID for the event listener, that should be included in each event
46 | StreamID *fftypes.UUID // The event stream (previously started) to which events should be delivered
47 | Name string // Descriptive name of the listener, provided by the user, or defaulted to the signature. Not guaranteed to be unique. Should be included in the event info
48 | Checkpoint EventListenerCheckpoint // The last persisted checkpoint for this event stream
49 | }
50 |
51 | type EventListenerAddResponse struct {
52 | }
53 |
--------------------------------------------------------------------------------
/pkg/ffcapi/event_listener_hwm.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | type EventListenerHWMRequest struct {
24 | StreamID *fftypes.UUID `json:"streamId"`
25 | ListenerID *fftypes.UUID `json:"listenerId"`
26 | }
27 |
28 | type EventListenerHWMResponse struct {
29 | Checkpoint EventListenerCheckpoint `json:"checkpoint"`
30 | Catchup bool `json:"catchup,omitempty"` // informational only - informs an operator that the stream is catching up
31 | }
32 |
--------------------------------------------------------------------------------
/pkg/ffcapi/event_listener_remove.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | type EventListenerRemoveRequest struct {
24 | StreamID *fftypes.UUID `json:"streamId"`
25 | ListenerID *fftypes.UUID `json:"listenerId"`
26 | }
27 |
28 | type EventListenerRemoveResponse struct {
29 | }
30 |
--------------------------------------------------------------------------------
/pkg/ffcapi/event_stream_start.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "context"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/fftypes"
23 | )
24 |
25 | type EventStreamStartRequest struct {
26 | ID *fftypes.UUID // UUID of the stream, which we be referenced in any future add/remove listener requests
27 | StreamContext context.Context // Context that will be cancelled when the event stream needs to stop - no further events will be consumed after this, so all pushes to the stream should select on the done channel too
28 | EventStream chan<- *ListenerEvent // The event stream to push events to as they are detected, and checkpoints regularly even if there are no events - remember to select on Done as well when pushing events
29 | BlockListener chan<- *BlockHashEvent // The connector should push new blocks to every stream, marking if it's possible blocks were missed (due to reconnect). The stream guarantees to always consume from this channel, until the stream context closes.
30 | InitialListeners []*EventListenerAddRequest // Initial list of event listeners to start with the stream - allows these to be started concurrently
31 | }
32 |
33 | type EventStreamStartResponse struct {
34 | }
35 |
--------------------------------------------------------------------------------
/pkg/ffcapi/event_stream_stopped.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | type EventStreamStoppedRequest struct {
24 | ID *fftypes.UUID // UUID of the stream, which we be referenced in any future add/remove listener requests
25 | }
26 |
27 | type EventStreamStoppedResponse struct {
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/ffcapi/gas_estimate.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import "github.com/hyperledger/firefly-common/pkg/fftypes"
20 |
21 | type GasEstimateRequest struct {
22 | TransactionInput
23 | }
24 |
25 | type GasEstimateResponse struct {
26 | GasEstimate *fftypes.FFBigInt `json:"gasEstimate"`
27 | }
28 |
--------------------------------------------------------------------------------
/pkg/ffcapi/gas_price_estimate.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import "github.com/hyperledger/firefly-common/pkg/fftypes"
20 |
21 | type GasPriceEstimateRequest struct {
22 | }
23 |
24 | type GasPriceEstimateResponse struct {
25 | GasPrice *fftypes.JSONAny `json:"gasPrice"`
26 | }
27 |
--------------------------------------------------------------------------------
/pkg/ffcapi/is_live.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | type LiveResponse struct {
20 | Up bool `json:"up"`
21 | }
22 |
--------------------------------------------------------------------------------
/pkg/ffcapi/is_ready.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import "github.com/hyperledger/firefly-common/pkg/fftypes"
20 |
21 | type ReadyResponse struct {
22 | Ready bool `json:"ready"`
23 | DownstreamDetails *fftypes.JSONAny `json:"downstreamDetails"` // The data output from the method call - can be array or object structure
24 | }
25 |
--------------------------------------------------------------------------------
/pkg/ffcapi/method_call.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2024 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | // QueryInvokeRequest requests execution of a smart contract method in order to either:
24 | // 1) Query state
25 | // 2) Attempt to extract the revert reason from an on-chain failure to execute a transaction
26 | //
27 | // See the list of standard error reasons that should be returned for situations that can be
28 | // detected by the back-end connector.
29 | type QueryInvokeRequest struct {
30 | TransactionInput
31 | BlockNumber *string `json:"blockNumber,omitempty"`
32 | }
33 |
34 | type QueryInvokeResponse struct {
35 | Outputs *fftypes.JSONAny `json:"outputs"` // The data output from the method call - can be array or object structure
36 | }
37 |
--------------------------------------------------------------------------------
/pkg/ffcapi/new_block_listener.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "context"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/fftypes"
23 | )
24 |
25 | type NewBlockListenerRequest struct {
26 | ID *fftypes.UUID // unique identifier for this listener
27 | ListenerContext context.Context // Context that will be cancelled when the listener needs to stop - no further events will be consumed after this, so all pushes to the listener should select on the done channel too
28 | BlockListener chan<- *BlockHashEvent // The connector should push new blocks to every listener, marking if it's possible blocks were missed (due to reconnect). The listener guarantees to always consume from this channel, until the listener context closes.
29 | }
30 |
31 | type NewBlockListenerResponse struct {
32 | }
33 |
--------------------------------------------------------------------------------
/pkg/ffcapi/next_nonce_for_signer.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | // NextNonceForSignerRequest used to do a query for the next nonce to use for a
24 | // given signing identity. This is only used when there are no pending
25 | // operations outstanding for this signer known to the transaction manager.
26 | type NextNonceForSignerRequest struct {
27 | Signer string `json:"signer"`
28 | }
29 |
30 | type NextNonceForSignerResponse struct {
31 | Nonce *fftypes.FFBigInt `json:"nonce"`
32 | }
33 |
--------------------------------------------------------------------------------
/pkg/ffcapi/submission_error.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | type SubmissionError struct {
20 | Error string `json:"error"`
21 | // When submissionRejected: true, the failure is considered final and the operation should transition directly to failed.
22 | // This should be returned in all cases where the FFCAPI connector or underlying blockchain node has evaluated the transaction
23 | // during the prepare phase, and determined it will fail if it were submitted.
24 | // The idempotencyKey is "spent" in these scenarios in the FF Core layer, but the transaction is never recorded into the FFTM
25 | // database, so the nonce is not spent, and the transaction is never submitted.
26 | SubmissionRejected bool `json:"submissionRejected,omitempty"`
27 | }
28 |
29 | func MapSubmissionRejected(reason ErrorReason) bool {
30 | switch reason {
31 | case ErrorReasonInvalidInputs,
32 | ErrorReasonTransactionReverted,
33 | ErrorReasonInsufficientFunds:
34 | // These reason codes are considered as rejections of the transaction - see ffcapi.SubmissionError
35 | return true
36 | default:
37 | // Everything else is eligible for idempotent retry of submission
38 | return false
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/pkg/ffcapi/submission_error_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/stretchr/testify/assert"
23 | )
24 |
25 | func TestMapSubmissionError(t *testing.T) {
26 | assert.True(t, MapSubmissionRejected(ErrorReasonTransactionReverted))
27 | assert.True(t, MapSubmissionRejected(ErrorReasonInvalidInputs))
28 | assert.True(t, MapSubmissionRejected(ErrorReasonInsufficientFunds))
29 | assert.False(t, MapSubmissionRejected(ErrorReasonTransactionUnderpriced))
30 | assert.False(t, MapSubmissionRejected(""))
31 | }
32 |
--------------------------------------------------------------------------------
/pkg/ffcapi/transaction_prepare.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | // TransactionPrepareRequest is used to prepare a set of JSON formatted developer friendly
24 | // inputs, into a raw transaction ready for submission to the blockchain.
25 | //
26 | // The connector is responsible for encoding the transaction ready for submission,
27 | // and returning the hash for the transaction as well as a string serialization of
28 | // the pre-signed raw transaction in a format of its own choosing (hex etc.).
29 | // The hash is expected to be a function of:
30 | // - the method signature
31 | // - the signing identity
32 | // - the nonce
33 | // - the particular blockchain the transaction is submitted to
34 | // - the input parameters
35 | //
36 | // If "gas" is not supplied, the connector is expected to perform gas estimation
37 | // prior to generating the payload.
38 | //
39 | // See the list of standard error reasons that should be returned for situations that can be
40 | // detected by the back-end connector.
41 | type TransactionPrepareRequest struct {
42 | TransactionInput
43 | }
44 |
45 | type TransactionPrepareResponse struct {
46 | Gas *fftypes.FFBigInt `json:"gas"`
47 | TransactionData string `json:"transactionData"`
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/ffcapi/transaction_receipt.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | type TransactionReceiptRequest struct {
24 | TransactionHash string `json:"transactionHash"`
25 | IncludeLogs bool `json:"includeLogs"`
26 | EventFilters []fftypes.JSONAny `json:"eventFilters"`
27 | Methods []fftypes.JSONAny `json:"methods"`
28 | ExtractSigner bool `json:"extractSigner"`
29 | }
30 |
31 | type TransactionReceiptResponseBase struct {
32 | BlockNumber *fftypes.FFBigInt `json:"blockNumber"`
33 | TransactionIndex *fftypes.FFBigInt `json:"transactionIndex"`
34 | BlockHash string `json:"blockHash"`
35 | Success bool `json:"success"`
36 | ProtocolID string `json:"protocolId"`
37 | ExtraInfo *fftypes.JSONAny `json:"extraInfo,omitempty"`
38 | ContractLocation *fftypes.JSONAny `json:"contractLocation,omitempty"`
39 | Logs []fftypes.JSONAny `json:"logs,omitempty"` // all raw un-decoded logs should be included if includeLogs=true
40 | }
41 |
42 | type TransactionReceiptResponse struct {
43 | TransactionReceiptResponseBase
44 | Events []*Event `json:"events,omitempty"` // only for events that matched the filter, and were decoded
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/ffcapi/transaction_send.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package ffcapi
18 |
19 | import (
20 | "github.com/hyperledger/firefly-common/pkg/fftypes"
21 | )
22 |
23 | // TransactionSendRequest is used to send a transaction to the blockchain.
24 | // The connector is responsible for adding it to the transaction pool of the blockchain,
25 | // noting the transaction hash has already been calculated in the prepare step previously.
26 | type TransactionSendRequest struct {
27 | GasPrice *fftypes.JSONAny `json:"gasPrice,omitempty"` // can be a simple string/number, or a complex object - contract is between policy engine and blockchain connector
28 | TransactionHeaders
29 | TransactionData string `json:"transactionData"`
30 | PreSigned bool `json:"preSigned,omitempty"`
31 | }
32 |
33 | type TransactionSendResponse struct {
34 | TransactionHash string `json:"transactionHash"`
35 | }
36 |
--------------------------------------------------------------------------------
/pkg/fftm/address_management.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "context"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/log"
23 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
25 | )
26 |
27 | func (m *manager) getLiveBalance(ctx context.Context, address string, blockTag string) (resp *apitypes.LiveAddressBalance, err error) {
28 | resp = &apitypes.LiveAddressBalance{}
29 | balance, reason, err := m.connector.AddressBalance(ctx, &ffcapi.AddressBalanceRequest{Address: address, BlockTag: blockTag})
30 | if err == nil {
31 | resp.AddressBalanceResponse = *balance
32 | } else {
33 | log.L(ctx).Warnf("Failed to fetch live address balance: %s (reason: %s)", err, reason)
34 | return nil, err
35 | }
36 | return resp, nil
37 | }
38 |
--------------------------------------------------------------------------------
/pkg/fftm/address_management_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "context"
21 | "fmt"
22 | "testing"
23 |
24 | "github.com/hyperledger/firefly-common/pkg/fftypes"
25 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
26 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
27 | "github.com/stretchr/testify/assert"
28 | "github.com/stretchr/testify/mock"
29 | )
30 |
31 | func TestBalanceOK(t *testing.T) {
32 | _, m, cancel := newTestManager(t)
33 | defer cancel()
34 | m.Start()
35 |
36 | mca := m.connector.(*ffcapimocks.API)
37 | mca.On("AddressBalance", mock.Anything, mock.Anything).Return(&ffcapi.AddressBalanceResponse{Balance: fftypes.NewFFBigInt(999)}, ffcapi.ErrorReason(""), nil)
38 |
39 | res, err := m.getLiveBalance(context.Background(), "0x4a8c8f1717570f9774652075e249ded38124d708", "latest")
40 |
41 | assert.Nil(t, err)
42 | assert.NotNil(t, res)
43 | assert.Equal(t, int64(999), res.AddressBalanceResponse.Balance.Int64())
44 |
45 | res, err = m.getLiveBalance(context.Background(), "0x4a8c8f1717570f9774652075e249ded38124d708", "")
46 |
47 | assert.Nil(t, err)
48 | assert.NotNil(t, res)
49 | assert.Equal(t, int64(999), res.AddressBalanceResponse.Balance.Int64())
50 |
51 | mca.AssertExpectations(t)
52 | }
53 |
54 | func TestBalanceFail(t *testing.T) {
55 |
56 | _, m, cancel := newTestManager(t)
57 | defer cancel()
58 | m.Start()
59 |
60 | mca := m.connector.(*ffcapimocks.API)
61 | mca.On("AddressBalance", mock.Anything, mock.Anything).Return(nil, ffcapi.ErrorReason(""), fmt.Errorf("pop"))
62 |
63 | res, err := m.getLiveBalance(context.Background(), "0x4a8c8f1717570f9774652075e249ded38124d708", "")
64 |
65 | assert.Nil(t, res)
66 | assert.Regexp(t, "pop", err)
67 |
68 | mca.AssertExpectations(t)
69 | }
70 |
--------------------------------------------------------------------------------
/pkg/fftm/config_docs_generate_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | //go:build docs
18 | // +build docs
19 |
20 | package fftm
21 |
22 | import (
23 | "context"
24 | "os"
25 | "path/filepath"
26 | "testing"
27 |
28 | "github.com/hyperledger/firefly-common/pkg/config"
29 | "github.com/stretchr/testify/assert"
30 | )
31 |
32 | const configDocHeader = "# Configuration reference"
33 |
34 | func TestGenerateConfigDocs(t *testing.T) {
35 | // Initialize config of all plugins
36 | InitConfig()
37 | f, err := os.Create(filepath.Join("..", "..", "config.md"))
38 | assert.NoError(t, err)
39 | generatedConfig, err := config.GenerateConfigMarkdown(context.Background(), configDocHeader, config.GetKnownKeys())
40 | assert.NoError(t, err)
41 | _, err = f.Write(generatedConfig)
42 | assert.NoError(t, err)
43 | err = f.Close()
44 | assert.NoError(t, err)
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/config_docs_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | //go:build !docs
18 | // +build !docs
19 |
20 | package fftm
21 |
22 | import (
23 | "context"
24 | "crypto/sha1"
25 | "os"
26 | "path/filepath"
27 | "testing"
28 |
29 | "github.com/hyperledger/firefly-common/pkg/config"
30 | "github.com/stretchr/testify/assert"
31 | )
32 |
33 | const configDocHeader = "# Configuration reference"
34 |
35 | func TestConfigDocsUpToDate(t *testing.T) {
36 | // Initialize config of all plugins
37 | InitConfig()
38 | generatedConfig, err := config.GenerateConfigMarkdown(context.Background(), configDocHeader, config.GetKnownKeys())
39 | assert.NoError(t, err)
40 | configOnDisk, err := os.ReadFile(filepath.Join("..", "..", "config.md"))
41 | assert.NoError(t, err)
42 |
43 | generatedConfigHash := sha1.New()
44 | generatedConfigHash.Write(generatedConfig)
45 | configOnDiskHash := sha1.New()
46 | configOnDiskHash.Write(configOnDisk)
47 | assert.Equal(t, configOnDiskHash.Sum(nil), generatedConfigHash.Sum(nil), "The config reference docs generated by the code did not match the config.md file in git. Did you forget to run `make reference`?")
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/fftm/gas_management.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "context"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/log"
23 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
25 | )
26 |
27 | func (m *manager) getLiveGasPrice(ctx context.Context) (resp *apitypes.LiveGasPrice, err error) {
28 | resp = &apitypes.LiveGasPrice{}
29 | gasPrice, reason, err := m.connector.GasPriceEstimate(ctx, &ffcapi.GasPriceEstimateRequest{})
30 | if err == nil {
31 | resp.GasPriceEstimateResponse = *gasPrice
32 | } else {
33 | log.L(ctx).Warnf("Failed to fetch live gas price: %s (reason: %s)", err, reason)
34 | return nil, err
35 | }
36 | return resp, nil
37 | }
38 |
--------------------------------------------------------------------------------
/pkg/fftm/route_delete_eventstream.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | )
25 |
26 | var deleteEventStream = func(m *manager) *ffapi.Route {
27 | return &ffapi.Route{
28 | Name: "deleteEventStream",
29 | Path: "/eventstreams/{streamId}",
30 | Method: http.MethodDelete,
31 | PathParams: []*ffapi.PathParam{
32 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
33 | },
34 | QueryParams: nil,
35 | Description: tmmsgs.APIEndpointDeleteEventStream,
36 | JSONInputValue: nil,
37 | JSONOutputValue: nil,
38 | JSONOutputCodes: []int{http.StatusNoContent},
39 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
40 | err = m.deleteStream(r.Req.Context(), r.PP["streamId"])
41 | return nil, err
42 | },
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/pkg/fftm/route_delete_eventstream_listener.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var deleteEventStreamListener = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "deleteEventStreamListener",
30 | Path: "/eventstreams/{streamId}/listeners/{listenerId}",
31 | Method: http.MethodDelete,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
34 | {Name: "listenerId", Description: tmmsgs.APIParamListenerID},
35 | },
36 | QueryParams: nil,
37 | Description: tmmsgs.APIEndpointDeleteEventStreamListener,
38 | JSONInputValue: nil,
39 | JSONOutputValue: func() interface{} { return &apitypes.Listener{} },
40 | JSONOutputCodes: []int{http.StatusNoContent},
41 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
42 | return nil, m.deleteListener(r.Req.Context(), r.PP["streamId"], r.PP["listenerId"])
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_delete_eventstream_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/go-resty/resty/v2"
23 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestDeleteEventStream(t *testing.T) {
31 |
32 | url, m, done := newTestManager(t)
33 | defer done()
34 |
35 | mfc := m.connector.(*ffcapimocks.API)
36 | mfc.On("EventStreamStart", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStartResponse{}, ffcapi.ErrorReason(""), nil)
37 | mfc.On("EventStreamStopped", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStoppedResponse{}, ffcapi.ErrorReason(""), nil).Maybe()
38 |
39 | err := m.Start()
40 | assert.NoError(t, err)
41 |
42 | // Create stream
43 | var es apitypes.EventStream
44 | res, err := resty.New().R().
45 | SetBody(&apitypes.EventStream{
46 | Name: strPtr("my event stream"),
47 | }).
48 | SetResult(&es).
49 | Post(url + "/eventstreams")
50 | assert.NoError(t, err)
51 | assert.Equal(t, 200, res.StatusCode())
52 |
53 | // Then delete it
54 | res, err = resty.New().R().
55 | SetResult(&es).
56 | Delete(url + "/eventstreams/" + es.ID.String())
57 | assert.NoError(t, err)
58 | assert.Equal(t, 204, res.StatusCode())
59 |
60 | assert.Nil(t, m.eventStreams[(*es.ID)])
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/pkg/fftm/route_delete_subscription.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var deleteSubscription = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "deleteSubscription",
30 | Path: "/subscriptions/{listenerId}",
31 | Deprecated: true, // in favor of "/eventstreams/{streamId}/listeners/{listenerId}"
32 | Method: http.MethodDelete,
33 | PathParams: []*ffapi.PathParam{
34 | {Name: "listenerId", Description: tmmsgs.APIParamListenerID},
35 | },
36 | QueryParams: nil,
37 | Description: tmmsgs.APIEndpointDeleteSubscription,
38 | JSONInputValue: nil,
39 | JSONOutputValue: func() interface{} { return &apitypes.Listener{} },
40 | JSONOutputCodes: []int{http.StatusNoContent},
41 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
42 | return nil, m.deleteListener(r.Req.Context(), "" /* no streamId on this path */, r.PP["listenerId"])
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_delete_transaction.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var deleteTransaction = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "deleteTransaction",
30 | Path: "/transactions/{transactionId}",
31 | Method: http.MethodDelete,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "transactionId", Description: tmmsgs.APIParamTransactionID},
34 | },
35 | QueryParams: nil,
36 | Description: tmmsgs.APIEndpointDeleteTransaction,
37 | JSONInputValue: nil,
38 | JSONOutputValue: func() interface{} { return &apitypes.ManagedTX{} },
39 | JSONOutputCodes: []int{http.StatusOK, http.StatusAccepted},
40 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
41 | r.SuccessStatus, output, err = m.requestTransactionDeletion(r.Req.Context(), r.PP["transactionId"])
42 | return output, err
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_delete_transaction_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "fmt"
21 | "testing"
22 |
23 | "github.com/go-resty/resty/v2"
24 | "github.com/hyperledger/firefly-transaction-manager/mocks/txhandlermocks"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestDeleteTransaction(t *testing.T) {
31 |
32 | url, m, done := newTestManager(t)
33 | defer done()
34 | tx := newTestTxn(t, m, "0x0aaaaa", 10001, apitypes.TxStatusSucceeded)
35 | txID := tx.ID
36 |
37 | err := m.Start()
38 | assert.NoError(t, err)
39 |
40 | var txOut *apitypes.ManagedTX
41 | res, err := resty.New().R().
42 | SetResult(&txOut).
43 | Delete(fmt.Sprintf("%s/transactions/%s", url, txID))
44 | assert.NoError(t, err)
45 | assert.Equal(t, 202, res.StatusCode())
46 | assert.Equal(t, txID, txOut.ID)
47 | }
48 |
49 | func TestDeleteTransactionFailed(t *testing.T) {
50 | url, m, done := newTestManager(t)
51 | defer done()
52 |
53 | err := m.Start()
54 | assert.NoError(t, err)
55 | mth := txhandlermocks.TransactionHandler{}
56 | mth.On("HandleCancelTransaction", mock.Anything, "1234").Return(nil, fmt.Errorf("error")).Once()
57 | m.txHandler = &mth
58 |
59 | var txOut *apitypes.ManagedTX
60 | res, err := resty.New().R().
61 | SetResult(&txOut).
62 | Delete(fmt.Sprintf("%s/transactions/%s", url, "1234"))
63 | assert.NoError(t, err)
64 | assert.Equal(t, 500, res.StatusCode())
65 | }
66 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_address_balance.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var getAddressBalance = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "getBalance",
30 | Path: "/gastoken/balances/{address}",
31 | Method: http.MethodGet,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "address", Description: tmmsgs.APIParamSignerAddress},
34 | },
35 | QueryParams: []*ffapi.QueryParam{
36 | {Name: "blocktag", Description: tmmsgs.APIParamBlocktag},
37 | },
38 | Description: tmmsgs.APIEndpointGetAddressBalance,
39 | JSONInputValue: nil,
40 | JSONOutputValue: func() interface{} { return &apitypes.LiveAddressBalance{} },
41 | JSONOutputCodes: []int{http.StatusOK},
42 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
43 | return m.getLiveBalance(r.Req.Context(), r.PP["address"], r.QP["blocktag"])
44 | },
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_address_balance_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "encoding/json"
21 | "fmt"
22 | "testing"
23 |
24 | "github.com/go-resty/resty/v2"
25 | "github.com/hyperledger/firefly-common/pkg/fftypes"
26 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
27 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
28 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
29 | "github.com/stretchr/testify/assert"
30 | "github.com/stretchr/testify/mock"
31 | )
32 |
33 | func TestGetAddressBalanceOK(t *testing.T) {
34 | url, m, done := newTestManager(t)
35 | defer done()
36 |
37 | mfc := m.connector.(*ffcapimocks.API)
38 |
39 | mfc.On("AddressBalance", mock.Anything, mock.Anything).Return(&ffcapi.AddressBalanceResponse{Balance: fftypes.NewFFBigInt(999)}, ffcapi.ErrorReason(""), nil)
40 |
41 | err := m.Start()
42 | assert.NoError(t, err)
43 |
44 | var liv apitypes.LiveAddressBalance
45 | res, err := resty.New().R().
46 | SetResult(&liv).
47 | Get(url + "/gastoken/balances/0x4a8c8f1717570f9774652075e249ded38124d708")
48 | assert.NoError(t, err)
49 | assert.Equal(t, 200, res.StatusCode())
50 | var responseObj fftypes.JSONObject
51 | err = json.Unmarshal(res.Body(), &responseObj)
52 | assert.NoError(t, err)
53 | assert.Equal(t, responseObj.GetString("balance"), "999")
54 | }
55 |
56 | func TestGetAddressBalanceBadAddress(t *testing.T) {
57 | url, m, done := newTestManager(t)
58 | defer done()
59 |
60 | mfc := m.connector.(*ffcapimocks.API)
61 | mfc.On("AddressBalance", mock.Anything, mock.Anything).Return(nil, ffcapi.ErrorReason(""), fmt.Errorf("pop"))
62 |
63 | err := m.Start()
64 | assert.NoError(t, err)
65 |
66 | var liv apitypes.LiveAddressBalance
67 | res, err := resty.New().R().
68 | SetResult(&liv).
69 | Get(url + "/gastoken/balances/0x4a8c8f1717570f9774652075e249ded38124d708")
70 | assert.NoError(t, err)
71 | assert.Equal(t, 500, res.StatusCode())
72 | }
73 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_eventstream.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var getEventStream = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "getEventStream",
30 | Path: "/eventstreams/{streamId}",
31 | Method: http.MethodGet,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
34 | },
35 | QueryParams: nil,
36 | Description: tmmsgs.APIEndpointGetEventStream,
37 | JSONInputValue: nil,
38 | JSONOutputValue: func() interface{} { return &apitypes.EventStreamWithStatus{} },
39 | JSONOutputCodes: []int{http.StatusOK},
40 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
41 | return m.getStream(r.Req.Context(), r.PP["streamId"])
42 | },
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_eventstream_listener.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var getEventStreamListener = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "getEventStreamListener",
30 | Path: "/eventstreams/{streamId}/listeners/{listenerId}",
31 | Method: http.MethodGet,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
34 | {Name: "listenerId", Description: tmmsgs.APIParamListenerID},
35 | },
36 | QueryParams: nil,
37 | Description: tmmsgs.APIEndpointGetEventStreamListener,
38 | JSONInputValue: nil,
39 | JSONOutputValue: func() interface{} { return &apitypes.Listener{} },
40 | JSONOutputCodes: []int{http.StatusOK},
41 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
42 | return m.getListener(r.Req.Context(), r.PP["streamId"], r.PP["listenerId"])
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_eventstream_listeners.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/persistence"
24 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | )
27 |
28 | var getEventStreamListeners = func(m *manager) *ffapi.Route {
29 | route := &ffapi.Route{
30 | Name: "getEventStreamListeners",
31 | Path: "/eventstreams/{streamId}/listeners",
32 | Method: http.MethodGet,
33 | PathParams: []*ffapi.PathParam{
34 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
35 | },
36 | Description: tmmsgs.APIEndpointGetEventStreamListeners,
37 | JSONInputValue: nil,
38 | JSONOutputValue: func() interface{} { return []*apitypes.Listener{} },
39 | JSONOutputCodes: []int{http.StatusOK},
40 | }
41 | if m.richQueryEnabled {
42 | route.FilterFactory = persistence.ListenerFilters
43 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
44 | return r.FilterResult(m.getStreamListenersRich(r.Req.Context(), r.PP["streamId"], r.Filter))
45 | }
46 | } else {
47 | // Very limited query support
48 | route.QueryParams = []*ffapi.QueryParam{
49 | {Name: "limit", Description: tmmsgs.APIParamLimit},
50 | {Name: "after", Description: tmmsgs.APIParamAfter},
51 | }
52 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
53 | return m.getStreamListenersByCreateTime(r.Req.Context(), r.QP["after"], r.QP["limit"], r.PP["streamId"])
54 | }
55 | }
56 | return route
57 | }
58 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_eventstream_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/go-resty/resty/v2"
23 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestGetEventStream(t *testing.T) {
31 |
32 | url, m, done := newTestManager(t)
33 | defer done()
34 |
35 | mfc := m.connector.(*ffcapimocks.API)
36 | mfc.On("EventStreamStart", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStartResponse{}, ffcapi.ErrorReason(""), nil)
37 | mfc.On("EventStreamStopped", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStoppedResponse{}, ffcapi.ErrorReason(""), nil).Maybe()
38 |
39 | err := m.Start()
40 | assert.NoError(t, err)
41 |
42 | // Create stream
43 | var es apitypes.EventStream
44 | res, err := resty.New().R().
45 | SetBody(&apitypes.EventStream{
46 | Name: strPtr("my event stream"),
47 | }).
48 | SetResult(&es).
49 | Post(url + "/eventstreams")
50 | assert.NoError(t, err)
51 | assert.Equal(t, 200, res.StatusCode())
52 |
53 | // Then get it
54 | var ess apitypes.EventStreamWithStatus
55 | res, err = resty.New().R().
56 | SetResult(&ess).
57 | Get(url + "/eventstreams/" + es.ID.String())
58 | assert.NoError(t, err)
59 | assert.Equal(t, 200, res.StatusCode())
60 |
61 | assert.Equal(t, es.ID, ess.ID)
62 | assert.Equal(t, apitypes.EventStreamStatusStarted, ess.Status)
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_eventstreams.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/persistence"
24 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | )
27 |
28 | var getEventStreams = func(m *manager) *ffapi.Route {
29 | route := &ffapi.Route{
30 | Name: "getEventStreams",
31 | Path: "/eventstreams",
32 | Method: http.MethodGet,
33 | PathParams: nil,
34 | Description: tmmsgs.APIEndpointGetEventStreams,
35 | JSONInputValue: nil,
36 | JSONOutputValue: func() interface{} { return []*apitypes.EventStream{} },
37 | JSONOutputCodes: []int{http.StatusOK},
38 | }
39 | if m.richQueryEnabled {
40 | route.FilterFactory = persistence.EventStreamFilters
41 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
42 | return r.FilterResult(m.persistence.RichQuery().ListStreams(r.Req.Context(), r.Filter))
43 | }
44 | } else {
45 | // Very limited query support
46 | route.QueryParams = []*ffapi.QueryParam{
47 | {Name: "limit", Description: tmmsgs.APIParamLimit},
48 | {Name: "after", Description: tmmsgs.APIParamAfter},
49 | }
50 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
51 | return m.getStreams(r.Req.Context(), r.QP["after"], r.QP["limit"])
52 | }
53 | }
54 | return route
55 | }
56 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_gas_price.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
23 |
24 | "github.com/hyperledger/firefly-common/pkg/ffapi"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | )
27 |
28 | var getGasPrice = func(m *manager) *ffapi.Route {
29 | return &ffapi.Route{
30 | Name: "getGasPrice",
31 | Path: "/gasprice",
32 | Method: http.MethodGet,
33 | PathParams: nil,
34 | QueryParams: nil,
35 | Description: tmmsgs.APIEndpointGetGasPrice,
36 | JSONInputValue: nil,
37 | JSONOutputValue: func() interface{} { return &apitypes.LiveGasPrice{} },
38 | JSONOutputCodes: []int{http.StatusOK},
39 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
40 | return m.getLiveGasPrice(r.Req.Context())
41 | },
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_gas_price_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "encoding/json"
21 | "fmt"
22 | "testing"
23 |
24 | "github.com/go-resty/resty/v2"
25 | "github.com/hyperledger/firefly-common/pkg/fftypes"
26 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
27 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
28 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
29 | "github.com/stretchr/testify/assert"
30 | "github.com/stretchr/testify/mock"
31 | )
32 |
33 | func TestGetGasPriceOK(t *testing.T) {
34 | url, m, done := newTestManager(t)
35 | defer done()
36 |
37 | mfc := m.connector.(*ffcapimocks.API)
38 |
39 | mfc.On("GasPriceEstimate", mock.Anything, mock.Anything).Return(&ffcapi.GasPriceEstimateResponse{GasPrice: fftypes.JSONAnyPtr("123456")}, ffcapi.ErrorReason(""), nil)
40 |
41 | err := m.Start()
42 | assert.NoError(t, err)
43 |
44 | var liv apitypes.LiveGasPrice
45 | res, err := resty.New().R().
46 | SetResult(&liv).
47 | Get(url + "/gasprice")
48 | assert.NoError(t, err)
49 | assert.Equal(t, 200, res.StatusCode())
50 | var responseObj fftypes.JSONObject
51 | err = json.Unmarshal(res.Body(), &responseObj)
52 | assert.NoError(t, err)
53 | assert.Equal(t, responseObj.GetString("gasPrice"), "123456")
54 | }
55 |
56 | func TestGetGasPriceBad(t *testing.T) {
57 | url, m, done := newTestManager(t)
58 | defer done()
59 |
60 | mfc := m.connector.(*ffcapimocks.API)
61 | mfc.On("GasPriceEstimate", mock.Anything, mock.Anything).Return(nil, ffcapi.ErrorReason(""), fmt.Errorf("pop"))
62 |
63 | err := m.Start()
64 | assert.NoError(t, err)
65 |
66 | var liv apitypes.LiveGasPrice
67 | res, err := resty.New().R().
68 | SetResult(&liv).
69 | Get(url + "/gasprice")
70 | assert.NoError(t, err)
71 | assert.Equal(t, 500, res.StatusCode())
72 | }
73 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_status_live_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "github.com/go-resty/resty/v2"
21 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
22 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
23 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
24 | "github.com/stretchr/testify/assert"
25 | "github.com/stretchr/testify/mock"
26 | "testing"
27 | )
28 |
29 | func TestGetLiveStatus(t *testing.T) {
30 | url, m, done := newTestManager(t)
31 | defer done()
32 |
33 | mfc := m.connector.(*ffcapimocks.API)
34 | mfc.On("IsLive", mock.Anything).Return(&ffcapi.LiveResponse{Up: true}, ffcapi.ErrorReason(""), nil)
35 |
36 | err := m.Start()
37 | assert.NoError(t, err)
38 |
39 | var liv apitypes.LiveStatus
40 | res, err := resty.New().R().
41 | SetResult(&liv).
42 | Get(url + "/status/live")
43 | assert.NoError(t, err)
44 | assert.Equal(t, 200, res.StatusCode())
45 | }
46 |
47 | func TestGetStatus(t *testing.T) {
48 | url, m, done := newTestManager(t)
49 | defer done()
50 |
51 | mfc := m.connector.(*ffcapimocks.API)
52 | mfc.On("IsLive", mock.Anything, mock.Anything).Return(&ffcapi.LiveResponse{Up: true}, ffcapi.ErrorReason(""), nil)
53 |
54 | err := m.Start()
55 | assert.NoError(t, err)
56 |
57 | var liv apitypes.LiveStatus
58 | res, err := resty.New().R().
59 | SetResult(&liv).
60 | Get(url + "/status")
61 | assert.NoError(t, err)
62 | assert.Equal(t, 200, res.StatusCode())
63 | }
64 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_status_ready.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
23 |
24 | "github.com/hyperledger/firefly-common/pkg/ffapi"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | )
27 |
28 | var deprecatedGetReadyStatus = func(m *manager) *ffapi.Route {
29 | return &ffapi.Route{
30 | Name: "getReadyStatus",
31 | Path: "/status/ready",
32 | Method: http.MethodGet,
33 | PathParams: nil,
34 | QueryParams: nil,
35 | Description: tmmsgs.APIEndpointGetStatusReady,
36 | JSONInputValue: nil,
37 | JSONOutputValue: func() interface{} { return &apitypes.ReadyStatus{} },
38 | JSONOutputCodes: []int{http.StatusOK},
39 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
40 | return m.getReadyStatus(r.Req.Context())
41 | },
42 | }
43 | }
44 |
45 | var getReadiness = func(m *manager) *ffapi.Route {
46 | return &ffapi.Route{
47 | Name: "getReadiness",
48 | Path: "/readyz",
49 | Method: http.MethodGet,
50 | PathParams: nil,
51 | QueryParams: nil,
52 | Description: tmmsgs.APIEndpointGetReadiness,
53 | JSONInputValue: nil,
54 | JSONOutputValue: func() interface{} { return &apitypes.ReadyStatus{} },
55 | JSONOutputCodes: []int{http.StatusOK},
56 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
57 | return m.getReadyStatus(r.Req.Context())
58 | },
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_status_ready_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "github.com/go-resty/resty/v2"
21 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
22 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
23 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
24 | "github.com/stretchr/testify/assert"
25 | "github.com/stretchr/testify/mock"
26 | "testing"
27 | )
28 |
29 | func TestGetReadyStatus(t *testing.T) {
30 | url, m, done := newTestManager(t)
31 | defer done()
32 |
33 | mfc := m.connector.(*ffcapimocks.API)
34 | mfc.On("IsReady", mock.Anything).Return(&ffcapi.ReadyResponse{Ready: true}, ffcapi.ErrorReason(""), nil)
35 |
36 | err := m.Start()
37 | assert.NoError(t, err)
38 |
39 | var liv apitypes.LiveStatus
40 | res, err := resty.New().R().
41 | SetResult(&liv).
42 | Get(url + "/status/ready")
43 | assert.NoError(t, err)
44 | assert.Equal(t, 200, res.StatusCode())
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_subscription.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var getSubscription = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "getSubscription",
30 | Path: "/subscriptions/{listenerId}",
31 | Deprecated: true, // in favor of "/eventstreams/{streamId}/listeners/{listenerId}"
32 | Method: http.MethodGet,
33 | PathParams: []*ffapi.PathParam{
34 | {Name: "listenerId", Description: tmmsgs.APIParamListenerID},
35 | },
36 | QueryParams: nil,
37 | Description: tmmsgs.APIEndpointGetSubscription,
38 | JSONInputValue: nil,
39 | JSONOutputValue: func() interface{} { return &apitypes.Listener{} },
40 | JSONOutputCodes: []int{http.StatusOK},
41 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
42 | return m.getListener(r.Req.Context(), "" /* no streamId on this path */, r.PP["listenerId"])
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_subscriptions.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/persistence"
24 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | )
27 |
28 | var getSubscriptions = func(m *manager) *ffapi.Route {
29 |
30 | route := &ffapi.Route{
31 | Name: "getSubscriptions",
32 | Path: "/subscriptions",
33 | Deprecated: true, // in favor of "/eventstreams/{id}/listeners"
34 | Method: http.MethodGet,
35 | PathParams: nil,
36 | Description: tmmsgs.APIEndpointGetSubscriptions,
37 | JSONInputValue: nil,
38 | JSONOutputValue: func() interface{} { return []*apitypes.Listener{} },
39 | JSONOutputCodes: []int{http.StatusOK},
40 | }
41 | if m.richQueryEnabled {
42 | route.FilterFactory = persistence.ListenerFilters
43 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
44 | return r.FilterResult(m.persistence.RichQuery().ListListeners(r.Req.Context(), r.Filter))
45 | }
46 | } else {
47 | // Very limited query support
48 | route.QueryParams = []*ffapi.QueryParam{
49 | {Name: "limit", Description: tmmsgs.APIParamLimit},
50 | {Name: "after", Description: tmmsgs.APIParamAfter},
51 | }
52 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
53 | return m.getListeners(r.Req.Context(), r.QP["after"], r.QP["limit"])
54 | }
55 | }
56 | return route
57 | }
58 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_transaction.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 | "strings"
22 |
23 | "github.com/hyperledger/firefly-common/pkg/ffapi"
24 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | )
27 |
28 | var getTransaction = func(m *manager) *ffapi.Route {
29 | return &ffapi.Route{
30 | Name: "getTransaction",
31 | Path: "/transactions/{transactionId}",
32 | Method: http.MethodGet,
33 | PathParams: []*ffapi.PathParam{
34 | {Name: "transactionId", Description: tmmsgs.APIParamTransactionID},
35 | },
36 | QueryParams: []*ffapi.QueryParam{
37 | {Name: "history", Description: tmmsgs.APIParamHistory, IsBool: true},
38 | },
39 | Description: tmmsgs.APIEndpointGetTransaction,
40 | JSONInputValue: nil,
41 | JSONOutputValue: func() interface{} { return &apitypes.TXWithStatus{} },
42 | JSONOutputCodes: []int{http.StatusOK},
43 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
44 | return m.getTransactionByIDWithStatus(r.Req.Context(), r.PP["transactionId"], strings.EqualFold(r.QP["history"], "true"))
45 | },
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_transaction_confirmations.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-common/pkg/i18n"
24 | "github.com/hyperledger/firefly-transaction-manager/internal/persistence"
25 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
26 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
27 | )
28 |
29 | var getTransactionConfirmations = func(m *manager) *ffapi.Route {
30 | route := &ffapi.Route{
31 | Name: "getTransactionConfirmations",
32 | Path: "/transactions/{transactionId}/confirmations",
33 | Method: http.MethodGet,
34 | PathParams: []*ffapi.PathParam{
35 | {Name: "transactionId", Description: tmmsgs.APIParamTransactionID},
36 | },
37 | Description: tmmsgs.APIEndpointGetTransactionConfirmations,
38 | JSONInputValue: nil,
39 | JSONOutputValue: func() interface{} { return []*apitypes.ConfirmationRecord{} },
40 | JSONOutputCodes: []int{http.StatusOK},
41 | }
42 | if m.richQueryEnabled {
43 | route.FilterFactory = persistence.ConfirmationFilters
44 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
45 | return r.FilterResult(m.persistence.RichQuery().ListTransactionConfirmations(r.Req.Context(), r.PP["transactionId"], r.Filter))
46 | }
47 | } else {
48 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
49 | return nil, i18n.NewError(r.Req.Context(), tmmsgs.MsgOpNotSupportedWithoutRichQuery)
50 | }
51 | }
52 | return route
53 | }
54 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_transaction_confirmations_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "fmt"
21 | "testing"
22 |
23 | "github.com/go-resty/resty/v2"
24 | "github.com/hyperledger/firefly-common/pkg/dbsql"
25 | "github.com/hyperledger/firefly-common/pkg/fftypes"
26 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
27 | "github.com/stretchr/testify/assert"
28 | "github.com/stretchr/testify/mock"
29 | )
30 |
31 | func TestGetTransactionConfirmationsOK(t *testing.T) {
32 |
33 | url, _, mrc, done := newTestManagerMockRichDB(t)
34 | defer done()
35 |
36 | id1 := fftypes.NewUUID()
37 | mrc.On("ListTransactionConfirmations", mock.Anything, "tx1", mock.Anything).Return(
38 | []*apitypes.ConfirmationRecord{{TransactionID: "tx1", ResourceBase: dbsql.ResourceBase{ID: id1}}}, nil, nil,
39 | )
40 |
41 | var out []*apitypes.ConfirmationRecord
42 | res, err := resty.New().R().
43 | SetResult(&out).
44 | Get(fmt.Sprintf("%s/transactions/%s/confirmations", url, "tx1"))
45 | assert.NoError(t, err)
46 | assert.Equal(t, 200, res.StatusCode())
47 | assert.Equal(t, id1, out[0].ID)
48 | }
49 |
50 | func TestGetTransactionConfirmationsNoRichQuery(t *testing.T) {
51 |
52 | url, _, done := newTestManagerMockNoRichDB(t)
53 | defer done()
54 |
55 | var txOut apitypes.ManagedTX
56 | var errorOut fftypes.RESTError
57 | res, err := resty.New().R().
58 | SetResult(&txOut).
59 | SetError(&errorOut).
60 | Get(fmt.Sprintf("%s/transactions/%s/confirmations", url, "tx1"))
61 | assert.NoError(t, err)
62 | assert.Equal(t, 501, res.StatusCode())
63 | assert.Regexp(t, "FF21085", errorOut.Error)
64 | }
65 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_transaction_history.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-common/pkg/i18n"
24 | "github.com/hyperledger/firefly-transaction-manager/internal/persistence"
25 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
26 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
27 | )
28 |
29 | var getTransactionHistory = func(m *manager) *ffapi.Route {
30 | route := &ffapi.Route{
31 | Name: "getTransactionHistory",
32 | Path: "/transactions/{transactionId}/history",
33 | Method: http.MethodGet,
34 | PathParams: []*ffapi.PathParam{
35 | {Name: "transactionId", Description: tmmsgs.APIParamTransactionID},
36 | },
37 | Description: tmmsgs.APIEndpointGetTransactionHistory,
38 | JSONInputValue: nil,
39 | JSONOutputValue: func() interface{} { return []*apitypes.TXHistoryRecord{} },
40 | JSONOutputCodes: []int{http.StatusOK},
41 | }
42 | if m.richQueryEnabled {
43 | route.FilterFactory = persistence.TXHistoryFilters
44 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
45 | return r.FilterResult(m.persistence.RichQuery().ListTransactionHistory(r.Req.Context(), r.PP["transactionId"], r.Filter))
46 | }
47 | } else {
48 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
49 | return nil, i18n.NewError(r.Req.Context(), tmmsgs.MsgOpNotSupportedWithoutRichQuery)
50 | }
51 | }
52 | return route
53 | }
54 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_transaction_history_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "fmt"
21 | "testing"
22 |
23 | "github.com/go-resty/resty/v2"
24 | "github.com/hyperledger/firefly-common/pkg/fftypes"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestGetTransactionHistoryOK(t *testing.T) {
31 |
32 | url, _, mrc, done := newTestManagerMockRichDB(t)
33 | defer done()
34 |
35 | id1 := fftypes.NewUUID()
36 | mrc.On("ListTransactionHistory", mock.Anything, "tx1", mock.Anything).Return(
37 | []*apitypes.TXHistoryRecord{{TransactionID: "tx1", ID: id1}}, nil, nil,
38 | )
39 |
40 | var out []*apitypes.TXHistoryRecord
41 | res, err := resty.New().R().
42 | SetResult(&out).
43 | Get(fmt.Sprintf("%s/transactions/%s/history", url, "tx1"))
44 | assert.NoError(t, err)
45 | assert.Equal(t, 200, res.StatusCode())
46 | assert.Equal(t, id1, out[0].ID)
47 | }
48 |
49 | func TestGetTransactionHistoryNoRichQuery(t *testing.T) {
50 |
51 | url, _, done := newTestManagerMockNoRichDB(t)
52 | defer done()
53 |
54 | var txOut apitypes.ManagedTX
55 | var errorOut fftypes.RESTError
56 | res, err := resty.New().R().
57 | SetResult(&txOut).
58 | SetError(&errorOut).
59 | Get(fmt.Sprintf("%s/transactions/%s/history", url, "tx1"))
60 | assert.NoError(t, err)
61 | assert.Equal(t, 501, res.StatusCode())
62 | assert.Regexp(t, "FF21085", errorOut.Error)
63 | }
64 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_transaction_receipt.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
25 | )
26 |
27 | var getTransactionReceipt = func(m *manager) *ffapi.Route {
28 | route := &ffapi.Route{
29 | Name: "getTransactionReceipt",
30 | Path: "/transactions/{transactionId}/receipt",
31 | Method: http.MethodGet,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "transactionId", Description: tmmsgs.APIParamTransactionID},
34 | },
35 | Description: tmmsgs.APIEndpointGetTransactionReceipt,
36 | JSONInputValue: nil,
37 | JSONOutputValue: func() interface{} { return &ffcapi.TransactionReceiptResponse{} },
38 | JSONOutputCodes: []int{http.StatusOK},
39 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
40 | return m.persistence.GetTransactionReceipt(r.Req.Context(), r.PP["transactionId"])
41 | },
42 | }
43 | return route
44 | }
45 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_transaction_receipt_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "fmt"
21 | "testing"
22 |
23 | "github.com/go-resty/resty/v2"
24 | "github.com/hyperledger/firefly-common/pkg/fftypes"
25 | "github.com/hyperledger/firefly-transaction-manager/mocks/persistencemocks"
26 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
27 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
28 | "github.com/stretchr/testify/assert"
29 | "github.com/stretchr/testify/mock"
30 | )
31 |
32 | func TestGetTransactionReceiptOK(t *testing.T) {
33 |
34 | url, m, done := newTestManagerMockNoRichDB(t)
35 | defer done()
36 |
37 | mpm := m.persistence.(*persistencemocks.Persistence)
38 | mpm.On("GetTransactionReceipt", mock.Anything, "tx1").Return(
39 | &ffcapi.TransactionReceiptResponse{
40 | TransactionReceiptResponseBase: ffcapi.TransactionReceiptResponseBase{
41 | BlockHash: "0x123456",
42 | },
43 | }, nil,
44 | )
45 |
46 | var out apitypes.ReceiptRecord
47 | res, err := resty.New().R().
48 | SetResult(&out).
49 | Get(fmt.Sprintf("%s/transactions/%s/receipt", url, "tx1"))
50 | assert.NoError(t, err)
51 | assert.Equal(t, 200, res.StatusCode())
52 | assert.Equal(t, "0x123456", out.BlockHash)
53 | }
54 |
55 | func TestGetTransactionReceiptNotFound(t *testing.T) {
56 |
57 | url, m, done := newTestManagerMockNoRichDB(t)
58 | defer done()
59 |
60 | mpm := m.persistence.(*persistencemocks.Persistence)
61 | mpm.On("GetTransactionReceipt", mock.Anything, "tx1").Return(nil, nil)
62 |
63 | var errRes fftypes.RESTError
64 | res, err := resty.New().R().
65 | SetError(&errRes).
66 | Get(fmt.Sprintf("%s/transactions/%s/receipt", url, "tx1"))
67 | assert.NoError(t, err)
68 | assert.Equal(t, 404, res.StatusCode())
69 | assert.Regexp(t, "FF00164", errRes.Error)
70 | }
71 |
--------------------------------------------------------------------------------
/pkg/fftm/route_get_transactions.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 | "strings"
22 |
23 | "github.com/hyperledger/firefly-common/pkg/ffapi"
24 | "github.com/hyperledger/firefly-transaction-manager/internal/persistence"
25 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
26 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
27 | )
28 |
29 | var getTransactions = func(m *manager) *ffapi.Route {
30 | route := &ffapi.Route{
31 | Name: "getTransactions",
32 | Path: "/transactions",
33 | Method: http.MethodGet,
34 | PathParams: nil,
35 | Description: tmmsgs.APIEndpointGetTransactions,
36 | JSONInputValue: nil,
37 | JSONOutputValue: func() interface{} { return []*apitypes.ManagedTX{} },
38 | JSONOutputCodes: []int{http.StatusOK},
39 | }
40 | if m.richQueryEnabled {
41 | route.FilterFactory = persistence.TransactionFilters
42 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
43 | return r.FilterResult(m.persistence.RichQuery().ListTransactions(r.Req.Context(), r.Filter))
44 | }
45 | } else {
46 | // Very limited query support
47 | route.QueryParams = []*ffapi.QueryParam{
48 | {Name: "limit", Description: tmmsgs.APIParamLimit},
49 | {Name: "after", Description: tmmsgs.APIParamAfter},
50 | {Name: "signer", Description: tmmsgs.APIParamTXSigner},
51 | {Name: "pending", Description: tmmsgs.APIParamTXPending, IsBool: true},
52 | {Name: "direction", Description: tmmsgs.APIParamSortDirection},
53 | }
54 | route.JSONHandler = func(r *ffapi.APIRequest) (output interface{}, err error) {
55 | return m.getTransactions(r.Req.Context(), r.QP["after"], r.QP["limit"], r.QP["signer"], strings.EqualFold(r.QP["pending"], "true"), r.QP["direction"])
56 | }
57 | }
58 | return route
59 | }
60 |
--------------------------------------------------------------------------------
/pkg/fftm/route_patch_eventstream.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var patchEventStream = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "patchEventStream",
30 | Path: "/eventstreams/{streamId}",
31 | Method: http.MethodPatch,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
34 | },
35 | QueryParams: nil,
36 | Description: tmmsgs.APIEndpointPatchEventStream,
37 | JSONInputValue: func() interface{} { return &apitypes.EventStream{} },
38 | JSONOutputValue: func() interface{} { return &apitypes.EventStream{} },
39 | JSONOutputCodes: []int{http.StatusOK},
40 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
41 | return m.updateStream(r.Req.Context(), r.PP["streamId"], r.Input.(*apitypes.EventStream))
42 | },
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/pkg/fftm/route_patch_eventstream_listener.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var patchEventStreamListener = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "patchEventStreamListener",
30 | Path: "/eventstreams/{streamId}/listeners/{listenerId}",
31 | Method: http.MethodPatch,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
34 | {Name: "listenerId", Description: tmmsgs.APIParamListenerID},
35 | },
36 | QueryParams: nil,
37 | Description: tmmsgs.APIEndpointPatchEventStreamListener,
38 | JSONInputValue: func() interface{} { return &apitypes.Listener{} },
39 | JSONOutputValue: func() interface{} { return &apitypes.Listener{} },
40 | JSONOutputCodes: []int{http.StatusOK},
41 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
42 | return m.updateExistingListener(r.Req.Context(), r.PP["streamId"], r.PP["listenerId"], r.Input.(*apitypes.Listener), false)
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_patch_eventstream_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/go-resty/resty/v2"
23 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestPatchEventStream(t *testing.T) {
31 |
32 | url, m, done := newTestManager(t)
33 | defer done()
34 |
35 | mfc := m.connector.(*ffcapimocks.API)
36 | mfc.On("EventStreamStart", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStartResponse{}, ffcapi.ErrorReason(""), nil)
37 | mfc.On("EventStreamStopped", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStoppedResponse{}, ffcapi.ErrorReason(""), nil).Maybe()
38 |
39 | err := m.Start()
40 | assert.NoError(t, err)
41 |
42 | // Create stream
43 | var es apitypes.EventStream
44 | res, err := resty.New().R().
45 | SetBody(&apitypes.EventStream{
46 | Name: strPtr("my event stream"),
47 | }).
48 | SetResult(&es).
49 | Post(url + "/eventstreams")
50 | assert.NoError(t, err)
51 | assert.Equal(t, 200, res.StatusCode())
52 |
53 | // Then update it
54 | res, err = resty.New().R().
55 | SetBody(&apitypes.EventStream{
56 | Name: strPtr("my renamed event stream"),
57 | }).
58 | SetResult(&es).
59 | Patch(url + "/eventstreams/" + es.ID.String())
60 | assert.NoError(t, err)
61 | assert.Equal(t, 200, res.StatusCode())
62 | assert.NotNil(t, es.ID)
63 | assert.NotNil(t, es.Created)
64 | assert.NotEqual(t, es.Created, es.Updated)
65 | assert.Equal(t, "my renamed event stream", *es.Name)
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/pkg/fftm/route_patch_subscription.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var patchSubscription = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "patchSubscription",
30 | Path: "/subscriptions/{listenerId}",
31 | Deprecated: true, // in favor of "/eventstreams/{streamId}/listeners/{listenerId}"
32 | Method: http.MethodPatch,
33 | PathParams: []*ffapi.PathParam{
34 | {Name: "listenerId", Description: tmmsgs.APIParamListenerID},
35 | },
36 | QueryParams: nil,
37 | Description: tmmsgs.APIEndpointPatchSubscription,
38 | JSONInputValue: func() interface{} { return &apitypes.Listener{} },
39 | JSONOutputValue: func() interface{} { return &apitypes.Listener{} },
40 | JSONOutputCodes: []int{http.StatusOK},
41 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
42 | return m.updateExistingListener(r.Req.Context(), "" /* no streamId on this path */, r.PP["listenerId"], r.Input.(*apitypes.Listener), false)
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_eventstream.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var postEventStream = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "postEventStream",
30 | Path: "/eventstreams",
31 | Method: http.MethodPost,
32 | PathParams: nil,
33 | QueryParams: nil,
34 | Description: tmmsgs.APIEndpointPostEventStream,
35 | JSONInputValue: func() interface{} { return &apitypes.EventStream{} },
36 | JSONOutputValue: func() interface{} { return &apitypes.EventStream{} },
37 | JSONOutputCodes: []int{http.StatusOK},
38 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
39 | return m.createAndStoreNewStream(r.Req.Context(), r.Input.(*apitypes.EventStream))
40 | },
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_eventstream_listener_reset.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var postEventStreamListenerReset = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "postEventStreamListenerReset",
30 | Path: "/eventstreams/{streamId}/listeners/{listenerId}/reset",
31 | Method: http.MethodPost,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
34 | {Name: "listenerId", Description: tmmsgs.APIParamListenerID},
35 | },
36 | QueryParams: nil,
37 | Description: tmmsgs.APIEndpointPostEventStreamListenerReset,
38 | JSONInputValue: func() interface{} { return &apitypes.Listener{} },
39 | JSONOutputValue: func() interface{} { return &apitypes.Listener{} },
40 | JSONOutputCodes: []int{http.StatusOK},
41 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
42 | return m.updateExistingListener(r.Req.Context(), r.PP["streamId"], r.PP["listenerId"], r.Input.(*apitypes.Listener), true)
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_eventstream_listeners.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var postEventStreamListeners = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "postEventStreamListeners",
30 | Path: "/eventstreams/{streamId}/listeners",
31 | Method: http.MethodPost,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
34 | },
35 | QueryParams: nil,
36 | Description: tmmsgs.APIEndpointPostEventStreamListener,
37 | JSONInputValue: func() interface{} { return &apitypes.Listener{} },
38 | JSONOutputValue: func() interface{} { return &apitypes.Listener{} },
39 | JSONOutputCodes: []int{http.StatusOK},
40 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
41 | return m.createAndStoreNewStreamListener(r.Req.Context(), r.PP["streamId"], r.Input.(*apitypes.Listener))
42 | },
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_eventstream_listeners_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "fmt"
21 | "testing"
22 |
23 | "github.com/go-resty/resty/v2"
24 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
27 | "github.com/stretchr/testify/assert"
28 | "github.com/stretchr/testify/mock"
29 | )
30 |
31 | func TestPostEventStreamListeners(t *testing.T) {
32 |
33 | url, m, done := newTestManager(t)
34 | defer done()
35 |
36 | err := m.Start()
37 | assert.NoError(t, err)
38 |
39 | mfc := m.connector.(*ffcapimocks.API)
40 | mfc.On("EventStreamStart", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStartResponse{}, ffcapi.ErrorReason(""), nil)
41 | mfc.On("EventListenerVerifyOptions", mock.Anything, mock.Anything).Return(&ffcapi.EventListenerVerifyOptionsResponse{}, ffcapi.ErrorReason(""), nil)
42 | mfc.On("EventListenerAdd", mock.Anything, mock.Anything).Return(&ffcapi.EventListenerAddResponse{}, ffcapi.ErrorReason(""), nil)
43 | mfc.On("EventListenerRemove", mock.Anything, mock.Anything).Return(&ffcapi.EventListenerRemoveResponse{}, ffcapi.ErrorReason(""), nil).Maybe()
44 | mfc.On("EventStreamStopped", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStoppedResponse{}, ffcapi.ErrorReason(""), nil).Maybe()
45 |
46 | // Create a stream
47 | var es1 apitypes.EventStream
48 | res, err := resty.New().R().SetBody(&apitypes.EventStream{Name: strPtr("stream1")}).SetResult(&es1).Post(url + "/eventstreams")
49 | assert.NoError(t, err)
50 | assert.Equal(t, 200, res.StatusCode())
51 |
52 | // Create a listener
53 | var l1 apitypes.Listener
54 | res, err = resty.New().R().SetBody(&apitypes.Listener{Name: strPtr("listener1"), StreamID: es1.ID}).SetResult(&l1).Post(fmt.Sprintf("%s/eventstreams/%s/listeners", url, es1.ID))
55 | assert.NoError(t, err)
56 | assert.Equal(t, 200, res.StatusCode())
57 |
58 | mfc.AssertExpectations(t)
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_eventstream_resume.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var postEventStreamResume = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "postEventStreamResume",
30 | Path: "/eventstreams/{streamId}/resume",
31 | Method: http.MethodPost,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
34 | },
35 | QueryParams: nil,
36 | Description: tmmsgs.APIEndpointPostEventStreamResume,
37 | JSONInputValue: func() interface{} { return struct{}{} }, // empty input
38 | JSONOutputValue: func() interface{} { return struct{}{} }, // empty output
39 | JSONOutputCodes: []int{http.StatusOK},
40 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
41 | falsy := false
42 | _, err = m.updateStream(r.Req.Context(), r.PP["streamId"], &apitypes.EventStream{
43 | Suspended: &falsy,
44 | })
45 | return &struct{}{}, err
46 | },
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_eventstream_resume_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/go-resty/resty/v2"
23 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestPostEventStreamResume(t *testing.T) {
31 |
32 | url, m, done := newTestManager(t)
33 | defer done()
34 |
35 | mfc := m.connector.(*ffcapimocks.API)
36 | mfc.On("EventStreamStart", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStartResponse{}, ffcapi.ErrorReason(""), nil)
37 | mfc.On("EventStreamStopped", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStoppedResponse{}, ffcapi.ErrorReason(""), nil).Maybe()
38 |
39 | err := m.Start()
40 | assert.NoError(t, err)
41 |
42 | // Create stream
43 | var es apitypes.EventStream
44 | truthy := true
45 | res, err := resty.New().R().
46 | SetBody(&apitypes.EventStream{
47 | Name: strPtr("my event stream"),
48 | Suspended: &truthy,
49 | }).
50 | SetResult(&es).
51 | Post(url + "/eventstreams")
52 | assert.NoError(t, err)
53 | assert.Equal(t, 200, res.StatusCode())
54 |
55 | // Then suspend it
56 | res, err = resty.New().R().
57 | SetBody(&struct{}{}).
58 | SetResult(&es).
59 | Post(url + "/eventstreams/" + es.ID.String() + "/resume")
60 | assert.NoError(t, err)
61 | assert.Equal(t, 200, res.StatusCode())
62 |
63 | assert.Equal(t, apitypes.EventStreamStatusStarted, m.eventStreams[(*es.ID)].Status())
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_eventstream_suspend.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var postEventStreamSuspend = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "postEventStreamSuspend",
30 | Path: "/eventstreams/{streamId}/suspend",
31 | Method: http.MethodPost,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "streamId", Description: tmmsgs.APIParamStreamID},
34 | },
35 | QueryParams: nil,
36 | Description: tmmsgs.APIEndpointPostEventStreamSuspend,
37 | JSONInputValue: func() interface{} { return struct{}{} }, // empty input
38 | JSONOutputValue: func() interface{} { return struct{}{} }, // empty output
39 | JSONOutputCodes: []int{http.StatusOK},
40 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
41 | truthy := true
42 | _, err = m.updateStream(r.Req.Context(), r.PP["streamId"], &apitypes.EventStream{
43 | Suspended: &truthy,
44 | })
45 | return &struct{}{}, err
46 | },
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_eventstream_suspend_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/go-resty/resty/v2"
23 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestPostEventStreamSuspend(t *testing.T) {
31 |
32 | url, m, done := newTestManager(t)
33 | defer done()
34 |
35 | mfc := m.connector.(*ffcapimocks.API)
36 | mfc.On("EventStreamStart", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStartResponse{}, ffcapi.ErrorReason(""), nil)
37 | mfc.On("EventStreamStopped", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStoppedResponse{}, ffcapi.ErrorReason(""), nil).Maybe()
38 |
39 | err := m.Start()
40 | assert.NoError(t, err)
41 |
42 | // Create stream
43 | var es apitypes.EventStream
44 | res, err := resty.New().R().
45 | SetBody(&apitypes.EventStream{
46 | Name: strPtr("my event stream"),
47 | }).
48 | SetResult(&es).
49 | Post(url + "/eventstreams")
50 | assert.NoError(t, err)
51 | assert.Equal(t, 200, res.StatusCode())
52 |
53 | // Then suspend it
54 | res, err = resty.New().R().
55 | SetBody(&struct{}{}).
56 | SetResult(&es).
57 | Post(url + "/eventstreams/" + es.ID.String() + "/suspend")
58 | assert.NoError(t, err)
59 | assert.Equal(t, 200, res.StatusCode())
60 |
61 | assert.Equal(t, apitypes.EventStreamStatusStopped, m.eventStreams[(*es.ID)].Status())
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_eventstream_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/go-resty/resty/v2"
23 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestPostNewEventStream(t *testing.T) {
31 |
32 | url, m, done := newTestManager(t)
33 | defer done()
34 |
35 | mfc := m.connector.(*ffcapimocks.API)
36 | mfc.On("EventStreamStart", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStartResponse{}, ffcapi.ErrorReason(""), nil)
37 | mfc.On("EventStreamStopped", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStoppedResponse{}, ffcapi.ErrorReason(""), nil).Maybe()
38 |
39 | err := m.Start()
40 | assert.NoError(t, err)
41 |
42 | var es apitypes.EventStream
43 | res, err := resty.New().R().
44 | SetBody(&apitypes.EventStream{
45 | Name: strPtr("my event stream"),
46 | }).
47 | SetResult(&es).
48 | Post(url + "/eventstreams")
49 | assert.NoError(t, err)
50 | assert.Equal(t, 200, res.StatusCode())
51 | assert.NotNil(t, es.ID)
52 | assert.NotNil(t, es.Created)
53 | assert.Equal(t, es.Created, es.Updated)
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_subscription_reset.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var postSubscriptionReset = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "postSubscriptionReset",
30 | Path: "/subscriptions/{listenerId}/reset",
31 | Deprecated: true, // in favor of "/eventstreams/{streamId}/listeners/{listenerId}"
32 | Method: http.MethodPost,
33 | PathParams: []*ffapi.PathParam{
34 | {Name: "listenerId", Description: tmmsgs.APIParamListenerID},
35 | },
36 | QueryParams: nil,
37 | Description: tmmsgs.APIEndpointPostSubscriptionReset,
38 | JSONInputValue: func() interface{} { return &apitypes.Listener{} },
39 | JSONOutputValue: func() interface{} { return &apitypes.Listener{} },
40 | JSONOutputCodes: []int{http.StatusOK},
41 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
42 | return m.updateExistingListener(r.Req.Context(), "" /* no streamId on this path */, r.PP["listenerId"], r.Input.(*apitypes.Listener), true)
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_subscriptions.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var postSubscriptions = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "postSubscriptions",
30 | Path: "/subscriptions",
31 | Deprecated: true, // in favor of "/eventstreams/{id}/listeners"
32 | Method: http.MethodPost,
33 | PathParams: nil,
34 | QueryParams: nil,
35 | Description: tmmsgs.APIEndpointPostSubscriptions,
36 | JSONInputValue: func() interface{} { return &apitypes.Listener{} },
37 | JSONOutputValue: func() interface{} { return &apitypes.Listener{} },
38 | JSONOutputCodes: []int{http.StatusOK},
39 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
40 | return m.createAndStoreNewListener(r.Req.Context(), r.Input.(*apitypes.Listener))
41 | },
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_subscriptions_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "testing"
21 |
22 | "github.com/go-resty/resty/v2"
23 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestPostSubscriptions(t *testing.T) {
31 |
32 | url, m, done := newTestManager(t)
33 | defer done()
34 |
35 | err := m.Start()
36 | assert.NoError(t, err)
37 |
38 | mfc := m.connector.(*ffcapimocks.API)
39 | mfc.On("EventStreamStart", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStartResponse{}, ffcapi.ErrorReason(""), nil)
40 | mfc.On("EventListenerVerifyOptions", mock.Anything, mock.Anything).Return(&ffcapi.EventListenerVerifyOptionsResponse{}, ffcapi.ErrorReason(""), nil)
41 | mfc.On("EventListenerAdd", mock.Anything, mock.Anything).Return(&ffcapi.EventListenerAddResponse{}, ffcapi.ErrorReason(""), nil)
42 | mfc.On("EventListenerRemove", mock.Anything, mock.Anything).Return(&ffcapi.EventListenerRemoveResponse{}, ffcapi.ErrorReason(""), nil).Maybe()
43 | mfc.On("EventStreamStopped", mock.Anything, mock.Anything).Return(&ffcapi.EventStreamStoppedResponse{}, ffcapi.ErrorReason(""), nil).Maybe()
44 |
45 | // Create a stream
46 | var es1 apitypes.EventStream
47 | res, err := resty.New().R().SetBody(&apitypes.EventStream{Name: strPtr("stream1")}).SetResult(&es1).Post(url + "/eventstreams")
48 | assert.NoError(t, err)
49 | assert.Equal(t, 200, res.StatusCode())
50 |
51 | // Create a listener
52 | var l1 apitypes.Listener
53 | res, err = resty.New().R().SetBody(&apitypes.Listener{Name: strPtr("listener1"), StreamID: es1.ID}).SetResult(&l1).Post(url + "/subscriptions")
54 | assert.NoError(t, err)
55 | assert.Equal(t, 200, res.StatusCode())
56 |
57 | mfc.AssertExpectations(t)
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_transaction_resume.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var postTransactionResume = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "postTransactionResume",
30 | Path: "/transactions/{transactionId}/resume",
31 | Method: http.MethodPost,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "transactionId", Description: tmmsgs.APIParamTransactionID},
34 | },
35 | QueryParams: nil,
36 | Description: tmmsgs.APIEndpointPostTransactionResume,
37 | JSONInputValue: func() interface{} { return &struct{}{} },
38 | JSONOutputValue: func() interface{} { return &apitypes.ManagedTX{} },
39 | JSONOutputCodes: []int{http.StatusOK, http.StatusAccepted},
40 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
41 | r.SuccessStatus, output, err = m.requestTransactionResume(r.Req.Context(), r.PP["transactionId"])
42 | return output, err
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_transaction_resume_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "fmt"
21 | "testing"
22 |
23 | "github.com/go-resty/resty/v2"
24 | "github.com/hyperledger/firefly-transaction-manager/mocks/txhandlermocks"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestPostTransactionResume(t *testing.T) {
31 |
32 | url, m, done := newTestManager(t)
33 | defer done()
34 | tx := newTestTxn(t, m, "0x0aaaaa", 10001, apitypes.TxStatusSucceeded)
35 | txID := tx.ID
36 |
37 | err := m.Start()
38 | assert.NoError(t, err)
39 |
40 | var txOut *apitypes.ManagedTX
41 | res, err := resty.New().R().
42 | SetResult(&txOut).
43 | SetBody(struct{}{}).
44 | Post(fmt.Sprintf("%s/transactions/%s/resume", url, txID))
45 | assert.NoError(t, err)
46 | assert.Equal(t, 202, res.StatusCode())
47 | assert.Equal(t, txID, txOut.ID)
48 | }
49 |
50 | func TestPostTransactionResumeFailed(t *testing.T) {
51 | url, m, done := newTestManager(t)
52 | defer done()
53 |
54 | err := m.Start()
55 | assert.NoError(t, err)
56 | mth := txhandlermocks.TransactionHandler{}
57 | mth.On("HandleResumeTransaction", mock.Anything, "1234").Return(nil, fmt.Errorf("error")).Once()
58 | m.txHandler = &mth
59 |
60 | var txOut *apitypes.ManagedTX
61 | res, err := resty.New().R().
62 | SetResult(&txOut).
63 | SetBody(struct{}{}).
64 | Post(fmt.Sprintf("%s/transactions/%s/resume", url, "1234"))
65 | assert.NoError(t, err)
66 | assert.Equal(t, 500, res.StatusCode())
67 | }
68 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_transaction_suspend.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "net/http"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/ffapi"
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
25 | )
26 |
27 | var postTransactionSuspend = func(m *manager) *ffapi.Route {
28 | return &ffapi.Route{
29 | Name: "postTransactionSuspend",
30 | Path: "/transactions/{transactionId}/suspend",
31 | Method: http.MethodPost,
32 | PathParams: []*ffapi.PathParam{
33 | {Name: "transactionId", Description: tmmsgs.APIParamTransactionID},
34 | },
35 | QueryParams: nil,
36 | Description: tmmsgs.APIEndpointPostTransactionSuspend,
37 | JSONInputValue: func() interface{} { return &struct{}{} },
38 | JSONOutputValue: func() interface{} { return &apitypes.ManagedTX{} },
39 | JSONOutputCodes: []int{http.StatusOK, http.StatusAccepted},
40 | JSONHandler: func(r *ffapi.APIRequest) (output interface{}, err error) {
41 | r.SuccessStatus, output, err = m.requestTransactionSuspend(r.Req.Context(), r.PP["transactionId"])
42 | return output, err
43 | },
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/fftm/route_post_transaction_suspend_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "fmt"
21 | "testing"
22 |
23 | "github.com/go-resty/resty/v2"
24 | "github.com/hyperledger/firefly-transaction-manager/mocks/txhandlermocks"
25 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
26 | "github.com/stretchr/testify/assert"
27 | "github.com/stretchr/testify/mock"
28 | )
29 |
30 | func TestPostTransactionSuspend(t *testing.T) {
31 |
32 | url, m, done := newTestManager(t)
33 | defer done()
34 | tx := newTestTxn(t, m, "0x0aaaaa", 10001, apitypes.TxStatusSucceeded)
35 | txID := tx.ID
36 |
37 | err := m.Start()
38 | assert.NoError(t, err)
39 |
40 | var txOut *apitypes.ManagedTX
41 | res, err := resty.New().R().
42 | SetResult(&txOut).
43 | SetBody(struct{}{}).
44 | Post(fmt.Sprintf("%s/transactions/%s/suspend", url, txID))
45 | assert.NoError(t, err)
46 | assert.Equal(t, 202, res.StatusCode())
47 | assert.Equal(t, txID, txOut.ID)
48 | }
49 |
50 | func TestPostTransactionSuspendFailed(t *testing.T) {
51 | url, m, done := newTestManager(t)
52 | defer done()
53 |
54 | err := m.Start()
55 | assert.NoError(t, err)
56 | mth := txhandlermocks.TransactionHandler{}
57 | mth.On("HandleSuspendTransaction", mock.Anything, "1234").Return(nil, fmt.Errorf("error")).Once()
58 | m.txHandler = &mth
59 |
60 | var txOut *apitypes.ManagedTX
61 | res, err := resty.New().R().
62 | SetResult(&txOut).
63 | SetBody(struct{}{}).
64 | Post(fmt.Sprintf("%s/transactions/%s/suspend", url, "1234"))
65 | assert.NoError(t, err)
66 | assert.Equal(t, 500, res.StatusCode())
67 | }
68 |
--------------------------------------------------------------------------------
/pkg/fftm/routes.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2025 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import "github.com/hyperledger/firefly-common/pkg/ffapi"
20 |
21 | func (m *manager) routes() []*ffapi.Route {
22 | return []*ffapi.Route{
23 | deleteEventStream(m),
24 | deleteEventStreamListener(m),
25 | deleteSubscription(m),
26 | deleteTransaction(m),
27 | getEventStream(m),
28 | getEventStreamListener(m),
29 | getEventStreamListeners(m),
30 | getEventStreams(m),
31 | deprecatedGetStatus(m),
32 | getSubscription(m),
33 | getSubscriptions(m),
34 | deprecatedGetLiveStatus(m), // TODO: remove this route from the API routes, they are already in the monitoring routes
35 | deprecatedGetReadyStatus(m), // TODO: remove this route from the API routes, they are already in the monitoring routes
36 | getTransaction(m),
37 | getTransactionConfirmations(m),
38 | getTransactionHistory(m),
39 | getTransactionReceipt(m),
40 | getTransactions(m),
41 | patchEventStream(m),
42 | patchEventStreamListener(m),
43 | patchSubscription(m),
44 | postEventStream(m),
45 | postEventStreamListenerReset(m),
46 | postEventStreamListeners(m),
47 | postEventStreamResume(m),
48 | postEventStreamSuspend(m),
49 | postRootCommand(m),
50 | postSubscriptionReset(m),
51 | postSubscriptions(m),
52 | getAddressBalance(m),
53 | getGasPrice(m),
54 | postTransactionSuspend(m),
55 | postTransactionResume(m),
56 | }
57 | }
58 |
59 | func (m *manager) monitoringRoutes() []*ffapi.Route {
60 | return []*ffapi.Route{
61 | getReadiness(m),
62 | getLiveness(m),
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/pkg/fftm/status_management.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "context"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/log"
23 | "github.com/hyperledger/firefly-transaction-manager/pkg/apitypes"
24 | )
25 |
26 | func (m *manager) getLiveStatus(ctx context.Context) (resp *apitypes.LiveStatus, err error) {
27 | resp = &apitypes.LiveStatus{}
28 | status, _, err := m.connector.IsLive(ctx)
29 | if err == nil {
30 | resp.LiveResponse = *status
31 | } else {
32 | log.L(ctx).Warnf("Failed to fetch live status: %s", err)
33 | return nil, err
34 | }
35 | return resp, nil
36 | }
37 |
38 | func (m *manager) getReadyStatus(ctx context.Context) (resp *apitypes.ReadyStatus, err error) {
39 | resp = &apitypes.ReadyStatus{}
40 | status, _, err := m.connector.IsReady(ctx)
41 | if err == nil {
42 | resp.ReadyResponse = *status
43 | } else {
44 | log.L(ctx).Warnf("Failed to fetch ready status: %s", err)
45 | return nil, err
46 | }
47 | return resp, nil
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/fftm/status_management_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package fftm
18 |
19 | import (
20 | "fmt"
21 | "github.com/hyperledger/firefly-transaction-manager/mocks/ffcapimocks"
22 | "github.com/hyperledger/firefly-transaction-manager/pkg/ffcapi"
23 | "github.com/stretchr/testify/assert"
24 | "github.com/stretchr/testify/mock"
25 | "testing"
26 | )
27 |
28 | func TestGetLiveStatusError(t *testing.T) {
29 | _, m, close := newTestManager(t)
30 | defer close()
31 |
32 | mfc := m.connector.(*ffcapimocks.API)
33 | mfc.On("IsLive", mock.Anything, mock.Anything).Return(nil, ffcapi.ErrorReason(""), fmt.Errorf("failed to get live status"))
34 |
35 | _, err := m.getLiveStatus(m.ctx)
36 | assert.Error(t, err)
37 |
38 | mfc.AssertExpectations(t)
39 | }
40 |
41 | func TestGetReadyStatusError(t *testing.T) {
42 | _, m, close := newTestManager(t)
43 | defer close()
44 |
45 | mfc := m.connector.(*ffcapimocks.API)
46 | mfc.On("IsReady", mock.Anything, mock.Anything).Return(nil, ffcapi.ErrorReason(""), fmt.Errorf("failed to get ready status"))
47 |
48 | _, err := m.getReadyStatus(m.ctx)
49 | assert.Error(t, err)
50 |
51 | mfc.AssertExpectations(t)
52 | }
53 |
--------------------------------------------------------------------------------
/pkg/txhandler/registry/registry.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2023 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package txhandlerfactory
18 |
19 | import (
20 | "context"
21 |
22 | "github.com/hyperledger/firefly-common/pkg/config"
23 | "github.com/hyperledger/firefly-common/pkg/i18n"
24 | "github.com/hyperledger/firefly-transaction-manager/internal/tmconfig"
25 | "github.com/hyperledger/firefly-transaction-manager/internal/tmmsgs"
26 | "github.com/hyperledger/firefly-transaction-manager/pkg/txhandler"
27 | )
28 |
29 | var txHandlers = make(map[string]Factory)
30 |
31 | func NewTransactionHandler(ctx context.Context, baseConfig config.Section, name string) (txhandler.TransactionHandler, error) {
32 | factory, ok := txHandlers[name]
33 | if !ok {
34 | return nil, i18n.NewError(ctx, tmmsgs.MsgTransactionHandlerNotRegistered, name)
35 | }
36 | return factory.NewTransactionHandler(ctx, baseConfig.SubSection(name))
37 | }
38 |
39 | type Factory interface {
40 | Name() string
41 | InitConfig(conf config.Section)
42 | NewTransactionHandler(ctx context.Context, conf config.Section) (txhandler.TransactionHandler, error)
43 | }
44 |
45 | func RegisterHandler(factory Factory) string {
46 | name := factory.Name()
47 | txHandlers[name] = factory
48 | // init the new transaction handler configurations
49 | factory.InitConfig(tmconfig.TransactionHandlerBaseConfig.SubSection(name))
50 | return name
51 | }
52 |
--------------------------------------------------------------------------------
/pkg/txhandler/registry/registry_test.go:
--------------------------------------------------------------------------------
1 | // Copyright © 2022 Kaleido, Inc.
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | package txhandlerfactory
18 |
19 | import (
20 | "context"
21 | "testing"
22 |
23 | "github.com/hyperledger/firefly-transaction-manager/internal/tmconfig"
24 | "github.com/hyperledger/firefly-transaction-manager/pkg/txhandler/simple"
25 | "github.com/spf13/viper"
26 | "github.com/stretchr/testify/assert"
27 | )
28 |
29 | func TestRegistryWithDeprecatedConfig(t *testing.T) {
30 | tmconfig.Reset()
31 | viper.SetDefault(string(tmconfig.DeprecatedPolicyEngineName), "simple")
32 | RegisterHandler(&simple.TransactionHandlerFactory{})
33 | tmconfig.DeprecatedPolicyEngineBaseConfig.SubSection("simple").Set(simple.FixedGasPrice, "12345")
34 | p, err := NewTransactionHandler(context.Background(), tmconfig.DeprecatedPolicyEngineBaseConfig, "simple")
35 | assert.NotNil(t, p)
36 | assert.NoError(t, err)
37 |
38 | p, err = NewTransactionHandler(context.Background(), tmconfig.DeprecatedPolicyEngineBaseConfig, "bob")
39 | assert.Nil(t, p)
40 | assert.Regexp(t, "FF21070", err)
41 |
42 | }
43 |
44 | func TestRegistry(t *testing.T) {
45 | tmconfig.Reset()
46 | RegisterHandler(&simple.TransactionHandlerFactory{})
47 |
48 | tmconfig.TransactionHandlerBaseConfig.SubSection("simple").Set(simple.FixedGasPrice, "12345")
49 | p, err := NewTransactionHandler(context.Background(), tmconfig.TransactionHandlerBaseConfig, "simple")
50 | assert.NotNil(t, p)
51 | assert.NoError(t, err)
52 |
53 | p, err = NewTransactionHandler(context.Background(), tmconfig.TransactionHandlerBaseConfig, "bob")
54 | assert.Nil(t, p)
55 | assert.Regexp(t, "FF21070", err)
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/test/empty-config.fftm.yaml:
--------------------------------------------------------------------------------
1 | manager:
2 | no-name-set: "should have a name to start"
3 | api:
4 | port: 0 # allocate one
--------------------------------------------------------------------------------
/test/firefly.fftm.yaml:
--------------------------------------------------------------------------------
1 | manager:
2 | name: test
3 | policyengine:
4 | simple:
5 | fixedGasPrice: 12345
6 | api:
7 | port: 0 # allocate one
--------------------------------------------------------------------------------
/test/quick-fail.fftm.yaml:
--------------------------------------------------------------------------------
1 | manager:
2 | name: test
3 | operations:
4 | fullScan:
5 | startupMaxRetries: 1
6 | minimumDelay: 1ms
7 | policyengine:
8 | simple:
9 | fixedGasPrice: 12345
10 | ffcore:
11 | url: http://localhost:99999
12 | api:
13 | port: 0 # allocate one
--------------------------------------------------------------------------------