Skip to content

Commit

Permalink
Merge pull request #40 from input-output-hk/hrajchert/PLT-7691-flat-v…
Browse files Browse the repository at this point in the history
…ersion-get-transaction-per-contract

PLT-7691 flat version get transaction per contract
  • Loading branch information
nhenin authored Oct 12, 2023
2 parents f069ff9 + cd4be9a commit 94fe4e6
Show file tree
Hide file tree
Showing 28 changed files with 304 additions and 138 deletions.
2 changes: 2 additions & 0 deletions packages/language/core/v1/src/inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ export const INotifyGuard: t.Type<INotify> = t.literal("input_notify");
* TODO: Comment
* @category Input
*/
// TODO: Try to make nominal as this gets replaced in the documentation and an interface
// cannot extend from builting type string.
export type BuiltinByteString = string;

/**
Expand Down
12 changes: 6 additions & 6 deletions packages/runtime/client/rest/src/contract/details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import * as t from "io-ts/lib/index.js";
import { Contract, MarloweState } from "@marlowe.io/language-core-v1";
import * as G from "@marlowe.io/language-core-v1/guards";
import { MarloweVersion } from "@marlowe.io/language-core-v1/version";
import { ContractId } from "@marlowe.io/runtime-core";
import { ContractIdGuard } from "@marlowe.io/runtime-core";

import { TxStatus } from "./transaction/status.js";

import { RoleName } from "./role.js";
import {
TxOutRef,
BlockHeader,
BlockHeaderGuard,
Metadata,
TextEnvelope,
TextEnvelopeGuard,
PolicyId,
} from "@marlowe.io/runtime-core";

Expand Down Expand Up @@ -51,16 +51,16 @@ export interface ContractDetails extends t.TypeOf<typeof ContractDetails> {}
* @category Validator
*/
export const ContractDetails = t.type({
contractId: ContractId,
contractId: ContractIdGuard,
roleTokenMintingPolicyId: PolicyId,
version: MarloweVersion,
status: TxStatus,
block: optionFromNullable(BlockHeader),
block: optionFromNullable(BlockHeaderGuard),
metadata: Metadata,
initialContract: G.Contract,
currentContract: optionFromNullable(G.Contract), // 3 actions
state: optionFromNullable(G.MarloweState),
txBody: optionFromNullable(TextEnvelope),
txBody: optionFromNullable(TextEnvelopeGuard),
utxo: optionFromNullable(TxOutRef),
unclaimedPayouts: t.array(Payout),
});
38 changes: 24 additions & 14 deletions packages/runtime/client/rest/src/contract/endpoints/collection.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AxiosInstance, ParamEncoder, ParamsSerializerOptions } from "axios";
import { AxiosInstance } from "axios";

import * as t from "io-ts/lib/index.js";
import * as TE from "fp-ts/lib/TaskEither.js";
Expand All @@ -21,8 +21,10 @@ import { DecodingError } from "@marlowe.io/adapter/codec";
import {
Tag,
Tags,
TagsGuard,
Metadata,
TextEnvelope,
TextEnvelopeGuard,
unAddressBech32,
unTxOutRef,
AddressesAndCollaterals,
Expand All @@ -33,7 +35,7 @@ import {
import { ContractHeader } from "../header.js";
import { RolesConfig } from "../role.js";

import { ContractId } from "@marlowe.io/runtime-core";
import { ContractId, ContractIdGuard } from "@marlowe.io/runtime-core";

/**
* @category GetContractsResponse
Expand All @@ -52,12 +54,11 @@ export const contractsRange = iso<ContractsRange>().wrap;
* Request options for the {@link index.RestAPI#getContracts | Get contracts } endpoint
* @category Endpoints
*/
export type GetContractsRequest = {
export interface GetContractsRequest {
/**
* Optional pagination request. Note that when you call {@link index.RestAPI#getContracts | Get contracts }
* the response includes the next and previous range headers.
*/
// QUESTION: @Jamie, is this supposed to be constructed by the user? or solely from other endpoints?
range?: ContractsRange;
/**
* Optional tags to filter the contracts by.
Expand All @@ -66,7 +67,7 @@ export type GetContractsRequest = {
// string supposed to be? I have some contracts with tag "{SurveyContract: CryptoPall2023}" that I don't know how to search for.
tags?: Tag[];
// FIXME: create ticket to Add RoleCurrency filter
};
}

export type GETHeadersByRange = (
rangeOption: O.Option<ContractsRange>
Expand Down Expand Up @@ -173,12 +174,12 @@ export const GetContractsResponse = t.type({
* Request options for the {@link index.RestAPI#createContract | Create contract } endpoint
* @category Endpoints
*/
export type CreateContractRequest = {
export interface CreateContractRequest {
// FIXME: create ticket to add stake address
// stakeAddress: void;
/**
* Address to send any remainders of the transaction.
* @see {@link @marlowe.io/wallet.WalletAPI#getChangeAddress}
* @see WalletAPI function {@link @marlowe.io/wallet!api.WalletAPI#getChangeAddress}
* @see {@link https://academy.glassnode.com/concepts/utxo#change-in-utxo-models}
*/
changeAddress: AddressBech32;
Expand Down Expand Up @@ -220,7 +221,7 @@ export type CreateContractRequest = {
* The validator version to use.
*/
version: MarloweVersion;
};
}

export type POST = (
postContractsRequest: PostContractsRequest,
Expand All @@ -238,7 +239,7 @@ export const PostContractsRequest = t.intersection([
t.type({
contract: G.Contract,
version: MarloweVersion,
tags: Tags,
tags: TagsGuard,
metadata: Metadata,
minUTxODeposit: t.number,
}),
Expand All @@ -249,16 +250,25 @@ export const PostContractsRequest = t.intersection([
// of creating a contract that later needs to be signed and submitted.
// Should we rename this to something like `UnsignedContractTx` or
// `UnsignedCreateContractTx`?
export type ContractTextEnvelope = t.TypeOf<typeof ContractTextEnvelope>;
export const ContractTextEnvelope = t.type({
contractId: ContractId,
tx: TextEnvelope,
export interface ContractTextEnvelope {
contractId: ContractId;
tx: TextEnvelope;
}

/**
* @hidden
*/
// TODO: Fix Type
// export const ContractTextEnvelopeGuard: t.Type<ContractTextEnvelope> = t.type({
export const ContractTextEnvelopeGuard = t.type({
contractId: ContractIdGuard,
tx: TextEnvelopeGuard,
});

export type PostResponse = t.TypeOf<typeof PostResponse>;
export const PostResponse = t.type({
links: t.type({ contract: t.string }),
resource: ContractTextEnvelope,
resource: ContractTextEnvelopeGuard,
});
/**
* @see {@link https://docs.marlowe.iohk.io/api/create-contracts}
Expand Down
16 changes: 8 additions & 8 deletions packages/runtime/client/rest/src/contract/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@ import { optionFromNullable } from "io-ts-types";
import { MarloweVersion } from "@marlowe.io/language-core-v1/version";

import {
BlockHeader,
BlockHeaderGuard,
Metadata,
PolicyId,
Tags,
TagsGuard,
} from "@marlowe.io/runtime-core";

import { TxStatus } from "./transaction/status.js";
import { ContractId } from "@marlowe.io/runtime-core";
import { ContractIdGuard } from "@marlowe.io/runtime-core";
/**
* A contract header contains minimal contract information that can be used to identify a contract.
* Use TODO to get full contract details
* Use {@link index.RestAPI#getContractById} to get full contract details
*
* @see The {@link ContractHeader:var | dynamic validator} for this type.
* @see The {@link https://github.com/input-output-hk/marlowe-cardano/blob/b39fe3c3ed67d41cdea6d45700093e7ffa4fad62/marlowe-runtime-web/src/Language/Marlowe/Runtime/Web/Types.hs#L502 | The backend definition } of this type
* @category GetContractsResponse
*/
Expand All @@ -25,14 +24,15 @@ export interface ContractHeader extends t.TypeOf<typeof ContractHeader> {}
* This is a {@link !io-ts-usage | Dynamic type validator} for a {@link ContractHeader:type}.
* @category Validator
* @category GetContractsResponse
* @hidden
*/
export const ContractHeader = t.type({
contractId: ContractId,
contractId: ContractIdGuard,
roleTokenMintingPolicyId: PolicyId,
version: MarloweVersion,
// TODO: Add continuations
tags: Tags,
tags: TagsGuard,
metadata: Metadata,
status: TxStatus,
block: optionFromNullable(BlockHeader),
block: optionFromNullable(BlockHeaderGuard),
});
6 changes: 6 additions & 0 deletions packages/runtime/client/rest/src/contract/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ export {
GetContractsRequest,
ContractsRange,
CreateContractRequest,
ContractTextEnvelope,
} from "./endpoints/collection.js";
export { TxHeader } from "./transaction/header.js";
export {
TransactionsRange,
GetTransactionsForContractResponse,
} from "./transaction/endpoints/collection.js";
22 changes: 8 additions & 14 deletions packages/runtime/client/rest/src/contract/transaction/details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,28 @@ import * as t from "io-ts/lib/index.js";

import { ISO8601 } from "@marlowe.io/adapter/time";

import {
BuiltinByteString,
Input,
MarloweState,
Contract,
} from "@marlowe.io/language-core-v1";
import * as G from "@marlowe.io/language-core-v1/guards";
import {
Tags,
TagsGuard,
Metadata,
BlockHeader,
BlockHeaderGuard,
TxOutRef,
TxId,
TextEnvelope,
TextEnvelopeGuard,
} from "@marlowe.io/runtime-core";

import { ContractId } from "@marlowe.io/runtime-core";
import { ContractIdGuard } from "@marlowe.io/runtime-core";
import { TxStatus } from "./status.js";

export type Details = t.TypeOf<typeof Details>;
export const Details = t.type({
contractId: ContractId,
contractId: ContractIdGuard,
transactionId: TxId,
continuations: optionFromNullable(G.BuiltinByteString),
tags: Tags,
tags: TagsGuard,
metadata: Metadata,
status: TxStatus,
block: optionFromNullable(BlockHeader),
block: optionFromNullable(BlockHeaderGuard),
inputUtxo: TxOutRef,
inputs: t.array(G.Input),
outputUtxo: optionFromNullable(TxOutRef),
Expand All @@ -39,5 +33,5 @@ export const Details = t.type({
consumingTx: optionFromNullable(TxId),
invalidBefore: ISO8601,
invalidHereafter: ISO8601,
txBody: optionFromNullable(TextEnvelope),
txBody: optionFromNullable(TextEnvelopeGuard),
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,33 @@ import { ISO8601 } from "@marlowe.io/adapter/time";
import {
AddressesAndCollaterals,
Metadata,
Tags,
TextEnvelope,
TagsGuard,
TextEnvelopeGuard,
TxId,
unAddressBech32,
unTxOutRef,
} from "@marlowe.io/runtime-core";

import { TxHeader } from "../header.js";
import { ContractId, unContractId } from "@marlowe.io/runtime-core";
import { TxHeader, TxHeaderGuard } from "../header.js";
import {
ContractId,
ContractIdGuard,
unContractId,
} from "@marlowe.io/runtime-core";

/**
* A transaction range provides pagination options for the {@link index.RestAPI#getTransactionsForContract | Get transactions for contract } endpoint
*/
export interface TransactionsRange
extends Newtype<{ readonly TransactionsRange: unique symbol }, string> {}
export const TransactionsRange = fromNewtype<TransactionsRange>(t.string);
export const TransactionsRangeGuard = fromNewtype<TransactionsRange>(t.string);
export const unTransactionsRange = iso<TransactionsRange>().unwrap;
export const transactionsRange = iso<TransactionsRange>().wrap;

export type GETHeadersByRange = (
contractId: ContractId,
rangeOption: O.Option<TransactionsRange>
) => TE.TaskEither<Error | DecodingError, GETByRangeResponse>;
) => TE.TaskEither<Error | DecodingError, GetTransactionsForContractResponse>;

export const getHeadersByRangeViaAxios: (
axiosInstance: AxiosInstance
Expand Down Expand Up @@ -77,24 +84,44 @@ export const getHeadersByRangeViaAxios: (
type GetContractsRawResponse = t.TypeOf<typeof GetContractsRawResponse>;
const GetContractsRawResponse = t.type({
data: t.type({
results: t.array(t.type({ links: t.type({}), resource: TxHeader })),
results: t.array(t.type({ links: t.type({}), resource: TxHeaderGuard })),
}),
previousRange: optionFromNullable(TransactionsRange),
nextRange: optionFromNullable(TransactionsRange),
previousRange: optionFromNullable(TransactionsRangeGuard),
nextRange: optionFromNullable(TransactionsRangeGuard),
});

export type GETByRangeResponse = t.TypeOf<typeof GETByRangeResponse>;
export const GETByRangeResponse = t.type({
headers: t.array(TxHeader),
previousRange: optionFromNullable(TransactionsRange),
nextRange: optionFromNullable(TransactionsRange),
/**
* Represents the response of the {@link index.RestAPI#getTransactionsForContract | Get transactions for contract } endpoint
* @category GetTransactionsForContractResponse
*/
export interface GetTransactionsForContractResponse {
/**
* The list of transactions heading information for the contract
*/
headers: TxHeader[];
/**
* The previous range header. This is used for pagination.
*/
previousRange: O.Option<TransactionsRange>;
/**
* The next range header. This is used for pagination.
*/
nextRange: O.Option<TransactionsRange>;
}

// TODO: Fix guard type
// export const GetTransactionsForContractResponseGuard: t.Type<GetTransactionsForContractResponse> = t.type({
export const GetTransactionsForContractResponseGuard = t.type({
headers: t.array(TxHeaderGuard),
previousRange: optionFromNullable(TransactionsRangeGuard),
nextRange: optionFromNullable(TransactionsRangeGuard),
});

export type TransactionTextEnvelope = t.TypeOf<typeof TransactionTextEnvelope>;
export const TransactionTextEnvelope = t.type({
contractId: ContractId,
contractId: ContractIdGuard,
transactionId: TxId,
tx: TextEnvelope,
tx: TextEnvelopeGuard,
});

export type POST = (
Expand Down Expand Up @@ -145,7 +172,7 @@ export const PostTransactionsRequest = t.intersection([
version: MarloweVersion,
inputs: t.array(G.Input),
metadata: Metadata,
tags: Tags,
tags: TagsGuard,
}),
t.partial({ invalidBefore: ISO8601 }),
t.partial({ invalidHereafter: ISO8601 }),
Expand Down
Loading

0 comments on commit 94fe4e6

Please sign in to comment.