Skip to content
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-7691 flat version get transaction per contract #40

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/language/core/v1/src/inputs.ts
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
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
@@ -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
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
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
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),
});
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