-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PLT-7701, PLT-7702, PLT-7703, PLT-8427: Implement remaining 1-1 endpoints #128
Changes from 11 commits
641c5db
93aaaaf
652a201
be3e2ad
2ecf468
fc0a315
9dd619a
6efc9d5
d29184f
3c831c0
56ea3ee
efe215d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
### @marlowe.io/runtime-rest-client | ||
|
||
- PLT-7701: Extend the rest client with procedure `getContractSourceById`. (Implemented in [PR-128](https://github.com/input-output-hk/marlowe-ts-sdk/pull/128)) | ||
- PLT-7702: Extend the rest client with procedure `getContractSourceAdjacency`. (Implemented in [PR-128](https://github.com/input-output-hk/marlowe-ts-sdk/pull/128)) | ||
- PLT-7703: Extend the rest client with procedure `getContractSourceClosure`. (Implemented in [PR-128](https://github.com/input-output-hk/marlowe-ts-sdk/pull/128)) | ||
- PLT-8427: Extend the rest client with procedure `getNextStepsForContract`. (Implemented in [PR-128](https://github.com/input-output-hk/marlowe-ts-sdk/pull/128)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ import * as E from "fp-ts/lib/Either.js"; | |
import { pipe } from "fp-ts/lib/function.js"; | ||
import { formatValidationErrors } from "jsonbigint-io-ts-reporters"; | ||
|
||
import { BuiltinByteString } from "@marlowe.io/language-core-v1"; | ||
import { BuiltinByteString, Contract } from "@marlowe.io/language-core-v1"; | ||
import { Bundle, Label } from "@marlowe.io/marlowe-object"; | ||
import { AxiosInstance } from "axios"; | ||
|
||
|
@@ -40,3 +40,94 @@ export const createContractSources = (axiosInstance: AxiosInstance) => { | |
); | ||
}; | ||
}; | ||
|
||
export interface GetContractBySourceIdRequest { | ||
contractSourceId: BuiltinByteString; | ||
expand?: boolean; | ||
} | ||
|
||
export type GetContractBySourceIdResponse = Contract; | ||
|
||
const GetContractBySourceIdResponseGuard: t.Type<GetContractBySourceIdResponse> = | ||
G.Contract; | ||
|
||
export const getContractSourceById = | ||
(axiosInstance: AxiosInstance) => | ||
async ({ | ||
contractSourceId, | ||
expand, | ||
}: GetContractBySourceIdRequest): Promise<GetContractBySourceIdResponse> => { | ||
const response = await axiosInstance.get( | ||
`/contracts/sources/${encodeURIComponent(contractSourceId)}`, | ||
{ params: { expand } } | ||
); | ||
Comment on lines
+65
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding error handling for the HTTP request to handle network errors or non-200 status codes. Also applies to: 96-98, 126-128 |
||
return pipe( | ||
GetContractBySourceIdResponseGuard.decode(response.data), | ||
E.match( | ||
(e) => { | ||
throw formatValidationErrors(e); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider improving error handling by wrapping validation errors in a user-friendly message or a custom error type to avoid exposing internal details and to provide more informative messages to the caller. Also applies to: 103-103, 133-133 |
||
}, | ||
(e) => e | ||
) | ||
); | ||
}; | ||
bjornkihlberg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export interface GetContractSourceAdjacencyRequest { | ||
contractSourceId: BuiltinByteString; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe a type alias might clarify the intent.
We could asses also if a Branded type makes sense to show that not all strings are the same There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have we figured out yet how we want to do branded types? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, using t.brand from io-ts There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reconsider the implementation of a type alias for |
||
} | ||
|
||
export interface GetContractSourceAdjacencyResponse { | ||
results: BuiltinByteString[]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shows the importance of the type alias There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair point. |
||
} | ||
|
||
const GetContractSourceAdjacencyResponseGuard: t.Type<GetContractSourceAdjacencyResponse> = | ||
t.type({ results: t.array(G.BuiltinByteString) }); | ||
|
||
export const getContractSourceAdjacency = | ||
(axiosInstance: AxiosInstance) => | ||
async ({ | ||
contractSourceId, | ||
}: GetContractSourceAdjacencyRequest): Promise<GetContractSourceAdjacencyResponse> => { | ||
const response = await axiosInstance.get( | ||
`/contracts/sources/${encodeURIComponent(contractSourceId)}/adjacency` | ||
); | ||
return pipe( | ||
GetContractSourceAdjacencyResponseGuard.decode(response.data), | ||
E.match( | ||
(e) => { | ||
throw formatValidationErrors(e); | ||
}, | ||
(e) => e | ||
) | ||
); | ||
}; | ||
bjornkihlberg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export interface GetContractSourceClosureRequest { | ||
contractSourceId: BuiltinByteString; | ||
} | ||
|
||
export interface GetContractSourceClosureResponse { | ||
results: BuiltinByteString[]; | ||
} | ||
|
||
const GetContractSourceClosureResponseGuard: t.Type<GetContractSourceClosureResponse> = | ||
t.type({ results: t.array(G.BuiltinByteString) }); | ||
|
||
export const getContractSourceClosure = | ||
(axiosInstance: AxiosInstance) => | ||
async ({ | ||
contractSourceId, | ||
}: GetContractSourceClosureRequest): Promise<GetContractSourceClosureResponse> => { | ||
const response = await axiosInstance.get( | ||
`/contracts/sources/${encodeURIComponent(contractSourceId)}/closure` | ||
); | ||
return pipe( | ||
GetContractSourceClosureResponseGuard.decode(response.data), | ||
E.match( | ||
(e) => { | ||
throw formatValidationErrors(e); | ||
}, | ||
(e) => e | ||
) | ||
); | ||
}; | ||
bjornkihlberg marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -27,8 +27,8 @@ import * as Contracts from "./contract/endpoints/collection.js"; | |||||
import * as Transaction from "./contract/transaction/endpoints/singleton.js"; | ||||||
import * as Transactions from "./contract/transaction/endpoints/collection.js"; | ||||||
import * as Sources from "./contract/endpoints/sources.js"; | ||||||
import * as Next from "./contract/next/endpoint.js"; | ||||||
import { TransactionsRange } from "./contract/transaction/endpoints/collection.js"; | ||||||
import * as ContractNext from "./contract/next/endpoint.js"; | ||||||
import { unsafeTaskEither } from "@marlowe.io/adapter/fp-ts"; | ||||||
import { | ||||||
ContractId, | ||||||
|
@@ -40,8 +40,6 @@ import { | |||||
import { submitContractViaAxios } from "./contract/endpoints/singleton.js"; | ||||||
import { ContractDetails } from "./contract/details.js"; | ||||||
import { TransactionDetails } from "./contract/transaction/details.js"; | ||||||
import { CreateContractSourcesResponse } from "./contract/endpoints/sources.js"; | ||||||
import { BuildCreateContractTxRequestWithContract } from "./contract/index.js"; | ||||||
// import curlirize from 'axios-curlirize'; | ||||||
|
||||||
/** | ||||||
|
@@ -89,14 +87,52 @@ export interface RestClient { | |||||
createContractSources( | ||||||
mainId: Label, | ||||||
bundle: Bundle | ||||||
): Promise<CreateContractSourcesResponse>; | ||||||
): Promise<Sources.CreateContractSourcesResponse>; | ||||||
|
||||||
/** | ||||||
* Gets the contract associated with given source id | ||||||
* @throws DecodingError - If the response from the server can't be decoded | ||||||
* @see {@link https://docs.marlowe.iohk.io/api/get-contract-source-by-id | The backend documentation} | ||||||
*/ | ||||||
getContractSourceById( | ||||||
request: Sources.GetContractBySourceIdRequest | ||||||
): Promise<Sources.GetContractBySourceIdResponse>; | ||||||
|
||||||
/** | ||||||
* Get the contract source IDs which are adjacent to a contract source (they appear directly in the contract source). | ||||||
* @throws DecodingError - If the response from the server can't be decoded | ||||||
* @see {@link https://docs.marlowe.iohk.io/api/get-adjacent-contract-source-i-ds-by-id | The backend documentation} | ||||||
*/ | ||||||
getContractSourceAdjacency( | ||||||
request: Sources.GetContractSourceAdjacencyRequest | ||||||
): Promise<Sources.GetContractSourceAdjacencyResponse>; | ||||||
|
||||||
/** | ||||||
* Get the contract source IDs which appear in the full hierarchy of a contract source (including the ID of the contract source itself). | ||||||
* @throws DecodingError - If the response from the server can't be decoded | ||||||
* @see {@link https://docs.marlowe.iohk.io/api/get-contract-source-closure-by-id | The backend documentation} | ||||||
*/ | ||||||
getContractSourceClosure( | ||||||
request: Sources.GetContractSourceClosureRequest | ||||||
): Promise<Sources.GetContractSourceClosureResponse>; | ||||||
|
||||||
/** | ||||||
* Get inputs which could be performed on a contract within a time range by the requested parties. | ||||||
* @throws DecodingError - If the response from the server can't be decoded | ||||||
* @see {@link https://docs.marlowe.iohk.io/api/get-next-contract-steps | The backend documentation} | ||||||
*/ | ||||||
getNextStepsForContract( | ||||||
request: Next.GetNextStepsForContractRequest | ||||||
): Promise<Next.GetNextStepsForContractResponse>; | ||||||
|
||||||
/** | ||||||
* Gets a single contract by id | ||||||
* @param contractId The id of the contract to get | ||||||
* @throws DecodingError - If the response from the server can't be decoded | ||||||
* @see {@link https://docs.marlowe.iohk.io/api/get-contract-by-id | The backend documentation} | ||||||
*/ | ||||||
getContractById(contractId: ContractId): Promise<ContractDetails>; | ||||||
|
||||||
/** | ||||||
* Submits a signed contract creation transaction | ||||||
* @see {@link https://docs.marlowe.iohk.io/api/submit-contract-to-chain | The backend documentation} | ||||||
|
@@ -105,6 +141,7 @@ export interface RestClient { | |||||
contractId: ContractId, | ||||||
txEnvelope: TextEnvelope | ||||||
): Promise<void>; | ||||||
|
||||||
/** | ||||||
* Gets a paginated list of {@link contract.TxHeader } for a given contract. | ||||||
* @see {@link https://docs.marlowe.iohk.io/api/get-transactions-for-contract | The backend documentation } | ||||||
|
@@ -116,6 +153,7 @@ export interface RestClient { | |||||
contractId: ContractId, | ||||||
range?: TransactionsRange | ||||||
): Promise<Transactions.GetTransactionsForContractResponse>; | ||||||
|
||||||
/** | ||||||
* Create an unsigned transaction which applies inputs to a contract. | ||||||
* @see {@link https://docs.marlowe.iohk.io/api/apply-inputs-to-contract | The backend documentation} | ||||||
|
@@ -126,6 +164,7 @@ export interface RestClient { | |||||
applyInputsToContract( | ||||||
request: Transactions.ApplyInputsToContractRequest | ||||||
): Promise<Transactions.TransactionTextEnvelope>; | ||||||
|
||||||
// getTransactionById: Transaction.GET; // - https://docs.marlowe.iohk.io/api/get-transaction-by-id | ||||||
/** | ||||||
* Submit a signed transaction (generated with {@link @marlowe.io/runtime-rest-client!index.RestClient#applyInputsToContract} and signed with the {@link @marlowe.io/wallet!api.WalletAPI#signTx} procedure) that applies inputs to a contract. | ||||||
|
@@ -195,13 +234,6 @@ export interface RestClient { | |||||
*/ | ||||||
healthcheck(): Promise<Boolean>; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||||||
|
||||||
// getNextStepsForContract: Next.GET; // - Jamie, is it this one? https://docs.marlowe.iohk.io/api/get-transaction-output-by-id? if so lets unify | ||||||
|
||||||
// postContractSource: ContractSources.POST; // - Jamie, is it this one? https://docs.marlowe.iohk.io/api/access-contract-import if so lets unify | ||||||
// getContractSource: ContractSource.GET; // - Jamie, is it this one? https://docs.marlowe.iohk.io/api/get-contract-import-by-id | ||||||
// getContractAdjacency: ContractSource.GET_ADJACENCY; // - Jamie, is it this one? https://docs.marlowe.iohk.io/api/get-adjacency-by-id if so lets unify | ||||||
// getContractClosure: ContractSource.GET_CLOSURE; // Jamie is it this one? - https://docs.marlowe.iohk.io/api/get-closure-by-id | ||||||
|
||||||
/** | ||||||
* Get payouts to parties from role-based contracts. | ||||||
* @see {@link https://docs.marlowe.iohk.io/api/get-role-payouts | The backend documentation} | ||||||
|
@@ -280,6 +312,18 @@ export function mkRestClient(baseURL: string): RestClient { | |||||
createContractSources(mainId, bundle) { | ||||||
return Sources.createContractSources(axiosInstance)(mainId, bundle); | ||||||
}, | ||||||
getContractSourceById(request) { | ||||||
return Sources.getContractSourceById(axiosInstance)(request); | ||||||
}, | ||||||
getContractSourceAdjacency(request) { | ||||||
return Sources.getContractSourceAdjacency(axiosInstance)(request); | ||||||
}, | ||||||
getContractSourceClosure(request) { | ||||||
return Sources.getContractSourceClosure(axiosInstance)(request); | ||||||
}, | ||||||
getNextStepsForContract(request) { | ||||||
return Next.getNextStepsForContract(axiosInstance)(request); | ||||||
}, | ||||||
submitContract(contractId, txEnvelope) { | ||||||
return submitContractViaAxios(axiosInstance)(contractId, txEnvelope); | ||||||
}, | ||||||
|
@@ -470,7 +514,7 @@ export interface ContractsAPI { | |||||
/** | ||||||
* @see {@link } | ||||||
*/ | ||||||
next: ContractNext.GET; | ||||||
next: Next.GET; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The + next: Next.getViaAxios(axiosInstance), Committable suggestion
Suggested change
|
||||||
transactions: { | ||||||
/** | ||||||
* @see {@link } | ||||||
|
@@ -550,7 +594,7 @@ export function mkFPTSRestClient(baseURL: string): FPTSRestAPI { | |||||
contract: { | ||||||
get: Contract.getViaAxios(axiosInstance), | ||||||
put: Contract.putViaAxios(axiosInstance), | ||||||
next: ContractNext.getViaAxios(axiosInstance), | ||||||
next: Next.getViaAxios(axiosInstance), | ||||||
transactions: { | ||||||
getHeadersByRange: | ||||||
Transactions.getHeadersByRangeViaAxios(axiosInstance), | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of
BuiltinByteString
directly as a type forcontractSourceId
is noted. Consider revisiting the previous discussion on using a type alias or branded type to clarify intent and ensure type safety.