@ghostgate/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +45 -0
- package/dist/fulfillment-eip712.d.ts +302 -0
- package/dist/fulfillment-eip712.d.ts.map +1 -0
- package/dist/fulfillment-eip712.js +267 -0
- package/dist/fulfillment-hash.d.ts +20 -0
- package/dist/fulfillment-hash.d.ts.map +1 -0
- package/dist/fulfillment-hash.js +124 -0
- package/dist/fulfillment-types.d.ts +64 -0
- package/dist/fulfillment-types.d.ts.map +1 -0
- package/dist/fulfillment-types.js +32 -0
- package/dist/fulfillment.d.ts +119 -0
- package/dist/fulfillment.d.ts.map +1 -0
- package/dist/fulfillment.js +422 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +277 -0
- package/package.json +60 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
export class FulfillmentCanonicalizationError extends Error {
|
|
3
|
+
constructor(code, message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.name = "FulfillmentCanonicalizationError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export const FULFILLMENT_ZERO_HASH_32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
10
|
+
const textEncoder = new TextEncoder();
|
|
11
|
+
const PERCENT_ESCAPE_INVALID = /%(?![0-9A-Fa-f]{2})/;
|
|
12
|
+
const isPlainObject = (value) => {
|
|
13
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
14
|
+
return false;
|
|
15
|
+
const proto = Object.getPrototypeOf(value);
|
|
16
|
+
return proto === Object.prototype || proto === null;
|
|
17
|
+
};
|
|
18
|
+
const jsonPrimitiveCanonical = (value) => {
|
|
19
|
+
if (typeof value === "number" && !Number.isFinite(value)) {
|
|
20
|
+
throw new FulfillmentCanonicalizationError("FULFILLMENT_JSON_NON_FINITE_NUMBER", "JSON canonicalization rejects non-finite numbers.");
|
|
21
|
+
}
|
|
22
|
+
const serialized = JSON.stringify(value);
|
|
23
|
+
if (serialized == null) {
|
|
24
|
+
throw new FulfillmentCanonicalizationError("FULFILLMENT_JSON_UNSUPPORTED_PRIMITIVE", "Unsupported primitive during JSON canonicalization.");
|
|
25
|
+
}
|
|
26
|
+
return serialized;
|
|
27
|
+
};
|
|
28
|
+
const canonicalizeJsonValue = (value) => {
|
|
29
|
+
if (value === null)
|
|
30
|
+
return "null";
|
|
31
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
32
|
+
return jsonPrimitiveCanonical(value);
|
|
33
|
+
}
|
|
34
|
+
if (typeof value === "bigint") {
|
|
35
|
+
throw new FulfillmentCanonicalizationError("FULFILLMENT_JSON_BIGINT_UNSUPPORTED", "JSON canonicalization does not support bigint values. Convert to string first.");
|
|
36
|
+
}
|
|
37
|
+
if (Array.isArray(value)) {
|
|
38
|
+
const items = value.map((item) => {
|
|
39
|
+
if (typeof item === "undefined" || typeof item === "function" || typeof item === "symbol") {
|
|
40
|
+
throw new FulfillmentCanonicalizationError("FULFILLMENT_JSON_ARRAY_UNSUPPORTED_VALUE", "Array contains unsupported value for canonical JSON hashing.");
|
|
41
|
+
}
|
|
42
|
+
return canonicalizeJsonValue(item);
|
|
43
|
+
});
|
|
44
|
+
return `[${items.join(",")}]`;
|
|
45
|
+
}
|
|
46
|
+
if (!isPlainObject(value)) {
|
|
47
|
+
throw new FulfillmentCanonicalizationError("FULFILLMENT_JSON_NON_PLAIN_OBJECT", "Canonical JSON hashing only supports plain objects and arrays.");
|
|
48
|
+
}
|
|
49
|
+
const entries = Object.entries(value).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
50
|
+
const serialized = entries.map(([key, entryValue]) => {
|
|
51
|
+
if (typeof entryValue === "undefined" || typeof entryValue === "function" || typeof entryValue === "symbol") {
|
|
52
|
+
throw new FulfillmentCanonicalizationError("FULFILLMENT_JSON_OBJECT_UNSUPPORTED_VALUE", `Object key '${key}' contains unsupported value for canonical JSON hashing.`);
|
|
53
|
+
}
|
|
54
|
+
return `${JSON.stringify(key)}:${canonicalizeJsonValue(entryValue)}`;
|
|
55
|
+
});
|
|
56
|
+
return `{${serialized.join(",")}}`;
|
|
57
|
+
};
|
|
58
|
+
export const canonicalizeJsonJcs = (value) => canonicalizeJsonValue(value);
|
|
59
|
+
const lowerHexSha256 = (bytes) => `0x${createHash("sha256").update(bytes).digest("hex")}`;
|
|
60
|
+
export const sha256HexUtf8 = (value) => lowerHexSha256(textEncoder.encode(value));
|
|
61
|
+
export const hashCanonicalJsonJcs = (value) => sha256HexUtf8(canonicalizeJsonJcs(value));
|
|
62
|
+
const validatePercentEscapes = (value) => {
|
|
63
|
+
if (PERCENT_ESCAPE_INVALID.test(value)) {
|
|
64
|
+
throw new FulfillmentCanonicalizationError("FULFILLMENT_QUERY_MALFORMED_PERCENT_ESCAPE", "Query string contains malformed percent escape.");
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const decodeFormComponent = (value) => {
|
|
68
|
+
validatePercentEscapes(value);
|
|
69
|
+
const plusAsSpace = value.replace(/\+/g, "%20");
|
|
70
|
+
try {
|
|
71
|
+
return decodeURIComponent(plusAsSpace);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
throw new FulfillmentCanonicalizationError("FULFILLMENT_QUERY_INVALID_UTF8", "Query string contains invalid UTF-8 percent encoding.");
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const encodeRfc3986Upper = (value) => encodeURIComponent(value)
|
|
78
|
+
.replace(/[!'()*]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`)
|
|
79
|
+
.replace(/%[0-9a-f]{2}/g, (match) => match.toUpperCase());
|
|
80
|
+
export const canonicalizeFulfillmentQuery = (rawQuery) => {
|
|
81
|
+
const raw = (rawQuery ?? "").trim();
|
|
82
|
+
const source = raw.startsWith("?") ? raw.slice(1) : raw;
|
|
83
|
+
if (!source) {
|
|
84
|
+
return { canonical: "", pairs: [] };
|
|
85
|
+
}
|
|
86
|
+
const parsedPairs = [];
|
|
87
|
+
const seenKeys = new Set();
|
|
88
|
+
const rawPairs = source.split("&").filter((segment) => segment.length > 0);
|
|
89
|
+
for (const rawPair of rawPairs) {
|
|
90
|
+
const eqIndex = rawPair.indexOf("=");
|
|
91
|
+
const rawKey = eqIndex === -1 ? rawPair : rawPair.slice(0, eqIndex);
|
|
92
|
+
const rawValue = eqIndex === -1 ? "" : rawPair.slice(eqIndex + 1);
|
|
93
|
+
const key = decodeFormComponent(rawKey);
|
|
94
|
+
const value = decodeFormComponent(rawValue);
|
|
95
|
+
if (!key) {
|
|
96
|
+
throw new FulfillmentCanonicalizationError("FULFILLMENT_QUERY_EMPTY_KEY", "Query string contains an empty key, which is not supported in Phase C MVP.");
|
|
97
|
+
}
|
|
98
|
+
if (seenKeys.has(key)) {
|
|
99
|
+
throw new FulfillmentCanonicalizationError("FULFILLMENT_QUERY_DUPLICATE_KEY", `Query string contains duplicate key '${key}', which is not supported in Phase C MVP.`);
|
|
100
|
+
}
|
|
101
|
+
seenKeys.add(key);
|
|
102
|
+
parsedPairs.push({ key, value });
|
|
103
|
+
}
|
|
104
|
+
parsedPairs.sort((a, b) => {
|
|
105
|
+
if (a.key < b.key)
|
|
106
|
+
return -1;
|
|
107
|
+
if (a.key > b.key)
|
|
108
|
+
return 1;
|
|
109
|
+
if (a.value < b.value)
|
|
110
|
+
return -1;
|
|
111
|
+
if (a.value > b.value)
|
|
112
|
+
return 1;
|
|
113
|
+
return 0;
|
|
114
|
+
});
|
|
115
|
+
const canonical = parsedPairs
|
|
116
|
+
.map(({ key, value }) => `${encodeRfc3986Upper(key)}=${encodeRfc3986Upper(value)}`)
|
|
117
|
+
.join("&");
|
|
118
|
+
return { canonical, pairs: parsedPairs };
|
|
119
|
+
};
|
|
120
|
+
export const hashCanonicalFulfillmentQuery = (rawQuery) => {
|
|
121
|
+
const { canonical } = canonicalizeFulfillmentQuery(rawQuery);
|
|
122
|
+
return canonical ? sha256HexUtf8(canonical) : FULFILLMENT_ZERO_HASH_32;
|
|
123
|
+
};
|
|
124
|
+
export const hashCanonicalFulfillmentBodyJson = (payload) => hashCanonicalJsonJcs(payload);
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export declare const FULFILLMENT_API_VERSION: 1;
|
|
2
|
+
export declare const FULFILLMENT_EIP712_DOMAIN_NAME: "GhostGateFulfillment";
|
|
3
|
+
export declare const FULFILLMENT_EIP712_DOMAIN_VERSION: "1";
|
|
4
|
+
export declare const FULFILLMENT_EIP712_VERIFIYING_CONTRACT_SENTINEL: "0x0000000000000000000000000000000000000000";
|
|
5
|
+
export declare const FULFILLMENT_DEFAULT_CHAIN_ID: 8453;
|
|
6
|
+
export declare const FULFILLMENT_TICKET_HEADER_VERSION: "x-ghost-fulfillment-ticket-version";
|
|
7
|
+
export declare const FULFILLMENT_TICKET_HEADER_PAYLOAD: "x-ghost-fulfillment-ticket";
|
|
8
|
+
export declare const FULFILLMENT_TICKET_HEADER_SIGNATURE: "x-ghost-fulfillment-ticket-sig";
|
|
9
|
+
export declare const FULFILLMENT_TICKET_HEADER_TICKET_ID: "x-ghost-fulfillment-ticket-id";
|
|
10
|
+
export declare const FULFILLMENT_TICKET_HEADER_CLIENT_REQUEST_ID: "x-ghost-fulfillment-client-request-id";
|
|
11
|
+
export declare const FULFILLMENT_TICKET_REQUEST_ACTION: "fulfillment_ticket";
|
|
12
|
+
export declare const FULFILLMENT_CAPTURE_DISPOSITIONS: readonly ["CAPTURED", "IDEMPOTENT_REPLAY"];
|
|
13
|
+
export type HexString = `0x${string}`;
|
|
14
|
+
export type Hex32 = `0x${string}`;
|
|
15
|
+
export type FulfillmentCaptureDisposition = (typeof FULFILLMENT_CAPTURE_DISPOSITIONS)[number];
|
|
16
|
+
export type FulfillmentTicketMessage = {
|
|
17
|
+
ticketId: Hex32;
|
|
18
|
+
consumer: HexString;
|
|
19
|
+
merchantOwner: HexString;
|
|
20
|
+
gatewayConfigIdHash: Hex32;
|
|
21
|
+
serviceSlug: string;
|
|
22
|
+
method: string;
|
|
23
|
+
path: string;
|
|
24
|
+
queryHash: Hex32;
|
|
25
|
+
bodyHash: Hex32;
|
|
26
|
+
cost: bigint;
|
|
27
|
+
issuedAt: bigint;
|
|
28
|
+
expiresAt: bigint;
|
|
29
|
+
};
|
|
30
|
+
export type FulfillmentDeliveryProofMessage = {
|
|
31
|
+
ticketId: Hex32;
|
|
32
|
+
deliveryProofId: Hex32;
|
|
33
|
+
merchantSigner: HexString;
|
|
34
|
+
serviceSlug: string;
|
|
35
|
+
completedAt: bigint;
|
|
36
|
+
statusCode: bigint;
|
|
37
|
+
latencyMs: bigint;
|
|
38
|
+
responseHash: Hex32;
|
|
39
|
+
};
|
|
40
|
+
export type FulfillmentTicketRequestAuthMessage = {
|
|
41
|
+
action: typeof FULFILLMENT_TICKET_REQUEST_ACTION;
|
|
42
|
+
serviceSlug: string;
|
|
43
|
+
method: string;
|
|
44
|
+
path: string;
|
|
45
|
+
queryHash: Hex32;
|
|
46
|
+
bodyHash: Hex32;
|
|
47
|
+
cost: bigint;
|
|
48
|
+
issuedAt: bigint;
|
|
49
|
+
nonce: string;
|
|
50
|
+
};
|
|
51
|
+
export type FulfillmentTicketEnvelope = {
|
|
52
|
+
version: typeof FULFILLMENT_API_VERSION;
|
|
53
|
+
payload: string;
|
|
54
|
+
signature: HexString;
|
|
55
|
+
};
|
|
56
|
+
export type FulfillmentDeliveryProofEnvelope = {
|
|
57
|
+
payload: string;
|
|
58
|
+
signature: HexString;
|
|
59
|
+
};
|
|
60
|
+
export type FulfillmentTicketHeaderRecord = Record<string, string>;
|
|
61
|
+
export declare const parseFulfillmentChainId: (rawValue: string | undefined, fallback?: number) => number;
|
|
62
|
+
export declare const normalizeFulfillmentMethod: (value: string) => string;
|
|
63
|
+
export declare const assertFulfillmentPath: (value: string) => string;
|
|
64
|
+
//# sourceMappingURL=fulfillment-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fulfillment-types.d.ts","sourceRoot":"","sources":["../src/fulfillment-types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,EAAG,CAAU,CAAC;AAElD,eAAO,MAAM,8BAA8B,EAAG,sBAA+B,CAAC;AAC9E,eAAO,MAAM,iCAAiC,EAAG,GAAY,CAAC;AAC9D,eAAO,MAAM,+CAA+C,EAC1D,4CAAqD,CAAC;AACxD,eAAO,MAAM,4BAA4B,EAAG,IAAa,CAAC;AAE1D,eAAO,MAAM,iCAAiC,EAAG,oCAA6C,CAAC;AAC/F,eAAO,MAAM,iCAAiC,EAAG,4BAAqC,CAAC;AACvF,eAAO,MAAM,mCAAmC,EAAG,gCAAyC,CAAC;AAC7F,eAAO,MAAM,mCAAmC,EAAG,+BAAwC,CAAC;AAC5F,eAAO,MAAM,2CAA2C,EAAG,uCAAgD,CAAC;AAE5G,eAAO,MAAM,iCAAiC,EAAG,oBAA6B,CAAC;AAC/E,eAAO,MAAM,gCAAgC,4CAA6C,CAAC;AAE3F,MAAM,MAAM,SAAS,GAAG,KAAK,MAAM,EAAE,CAAC;AACtC,MAAM,MAAM,KAAK,GAAG,KAAK,MAAM,EAAE,CAAC;AAClC,MAAM,MAAM,6BAA6B,GAAG,CAAC,OAAO,gCAAgC,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9F,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,KAAK,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;IACpB,aAAa,EAAE,SAAS,CAAC;IACzB,mBAAmB,EAAE,KAAK,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,KAAK,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC5C,QAAQ,EAAE,KAAK,CAAC;IAChB,eAAe,EAAE,KAAK,CAAC;IACvB,cAAc,EAAE,SAAS,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,KAAK,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,MAAM,EAAE,OAAO,iCAAiC,CAAC;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,KAAK,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,OAAO,uBAAuB,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEnE,eAAO,MAAM,uBAAuB,GAClC,UAAU,MAAM,GAAG,SAAS,EAC5B,WAAU,MAAqC,KAC9C,MAMF,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAI,OAAO,MAAM,KAAG,MAAoC,CAAC;AAEhG,eAAO,MAAM,qBAAqB,GAAI,OAAO,MAAM,KAAG,MASrD,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const FULFILLMENT_API_VERSION = 1;
|
|
2
|
+
export const FULFILLMENT_EIP712_DOMAIN_NAME = "GhostGateFulfillment";
|
|
3
|
+
export const FULFILLMENT_EIP712_DOMAIN_VERSION = "1";
|
|
4
|
+
export const FULFILLMENT_EIP712_VERIFIYING_CONTRACT_SENTINEL = "0x0000000000000000000000000000000000000000";
|
|
5
|
+
export const FULFILLMENT_DEFAULT_CHAIN_ID = 8453;
|
|
6
|
+
export const FULFILLMENT_TICKET_HEADER_VERSION = "x-ghost-fulfillment-ticket-version";
|
|
7
|
+
export const FULFILLMENT_TICKET_HEADER_PAYLOAD = "x-ghost-fulfillment-ticket";
|
|
8
|
+
export const FULFILLMENT_TICKET_HEADER_SIGNATURE = "x-ghost-fulfillment-ticket-sig";
|
|
9
|
+
export const FULFILLMENT_TICKET_HEADER_TICKET_ID = "x-ghost-fulfillment-ticket-id";
|
|
10
|
+
export const FULFILLMENT_TICKET_HEADER_CLIENT_REQUEST_ID = "x-ghost-fulfillment-client-request-id";
|
|
11
|
+
export const FULFILLMENT_TICKET_REQUEST_ACTION = "fulfillment_ticket";
|
|
12
|
+
export const FULFILLMENT_CAPTURE_DISPOSITIONS = ["CAPTURED", "IDEMPOTENT_REPLAY"];
|
|
13
|
+
export const parseFulfillmentChainId = (rawValue, fallback = FULFILLMENT_DEFAULT_CHAIN_ID) => {
|
|
14
|
+
const trimmed = rawValue?.trim();
|
|
15
|
+
if (!trimmed || !/^\d+$/.test(trimmed))
|
|
16
|
+
return fallback;
|
|
17
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
18
|
+
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
19
|
+
return fallback;
|
|
20
|
+
return parsed;
|
|
21
|
+
};
|
|
22
|
+
export const normalizeFulfillmentMethod = (value) => value.trim().toUpperCase();
|
|
23
|
+
export const assertFulfillmentPath = (value) => {
|
|
24
|
+
const trimmed = value.trim();
|
|
25
|
+
if (!trimmed.startsWith("/")) {
|
|
26
|
+
throw new Error(`Fulfillment path must start with '/'. Received: ${value}`);
|
|
27
|
+
}
|
|
28
|
+
if (trimmed.includes("?")) {
|
|
29
|
+
throw new Error(`Fulfillment path must not include query string. Received: ${value}`);
|
|
30
|
+
}
|
|
31
|
+
return trimmed;
|
|
32
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { parseWireFulfillmentTicketMessage } from "./fulfillment-eip712.js";
|
|
2
|
+
import { type FulfillmentDeliveryProofEnvelope, type FulfillmentTicketEnvelope, type FulfillmentTicketHeaderRecord, type Hex32 } from "./fulfillment-types.js";
|
|
3
|
+
type QueryInput = string | URLSearchParams | Record<string, string | number | boolean | null | undefined>;
|
|
4
|
+
export type GhostFulfillmentConsumerConfig = {
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
privateKey?: `0x${string}`;
|
|
7
|
+
chainId?: number;
|
|
8
|
+
defaultServiceSlug?: string;
|
|
9
|
+
};
|
|
10
|
+
export type GhostFulfillmentMerchantConfig = {
|
|
11
|
+
baseUrl?: string;
|
|
12
|
+
delegatedPrivateKey?: `0x${string}`;
|
|
13
|
+
protocolSignerAddresses: Array<`0x${string}` | string>;
|
|
14
|
+
chainId?: number;
|
|
15
|
+
};
|
|
16
|
+
export type FulfillmentExecuteInput = {
|
|
17
|
+
serviceSlug?: string;
|
|
18
|
+
method?: string;
|
|
19
|
+
path: string;
|
|
20
|
+
query?: QueryInput | null;
|
|
21
|
+
body?: unknown;
|
|
22
|
+
cost?: number;
|
|
23
|
+
clientRequestId?: string | null;
|
|
24
|
+
headers?: Record<string, string>;
|
|
25
|
+
};
|
|
26
|
+
export type FulfillmentTicketRequestResult = {
|
|
27
|
+
status: number;
|
|
28
|
+
endpoint: string;
|
|
29
|
+
payload: unknown;
|
|
30
|
+
ok: boolean;
|
|
31
|
+
ticketId: Hex32 | null;
|
|
32
|
+
ticket: FulfillmentTicketEnvelope | null;
|
|
33
|
+
merchantTargetUrl: string | null;
|
|
34
|
+
clientRequestId: string | null;
|
|
35
|
+
};
|
|
36
|
+
export type FulfillmentExecuteResult = {
|
|
37
|
+
ticket: FulfillmentTicketRequestResult;
|
|
38
|
+
merchant: {
|
|
39
|
+
attempted: boolean;
|
|
40
|
+
status: number | null;
|
|
41
|
+
url: string | null;
|
|
42
|
+
bodyText: string | null;
|
|
43
|
+
bodyJson: unknown;
|
|
44
|
+
headers: Record<string, string> | null;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export type FulfillmentTicketBindingInput = {
|
|
48
|
+
method?: string;
|
|
49
|
+
path?: string;
|
|
50
|
+
query?: QueryInput | null;
|
|
51
|
+
body?: unknown;
|
|
52
|
+
serviceSlug?: string;
|
|
53
|
+
};
|
|
54
|
+
export type VerifiedFulfillmentTicket = {
|
|
55
|
+
ticketId: Hex32;
|
|
56
|
+
ticket: FulfillmentTicketEnvelope;
|
|
57
|
+
payload: ReturnType<typeof parseWireFulfillmentTicketMessage>;
|
|
58
|
+
signer: `0x${string}`;
|
|
59
|
+
clientRequestId: string | null;
|
|
60
|
+
};
|
|
61
|
+
export type CaptureCompletionInput = {
|
|
62
|
+
ticketId: Hex32 | string;
|
|
63
|
+
serviceSlug: string;
|
|
64
|
+
statusCode: number;
|
|
65
|
+
latencyMs: number;
|
|
66
|
+
responseBodyJson?: unknown;
|
|
67
|
+
responseBodyText?: string | null;
|
|
68
|
+
completedAtMs?: number;
|
|
69
|
+
deliveryProofId?: Hex32 | string;
|
|
70
|
+
};
|
|
71
|
+
export type CaptureCompletionResult = {
|
|
72
|
+
status: number;
|
|
73
|
+
endpoint: string;
|
|
74
|
+
payload: unknown;
|
|
75
|
+
ok: boolean;
|
|
76
|
+
deliveryProof: FulfillmentDeliveryProofEnvelope;
|
|
77
|
+
debug: Record<string, unknown>;
|
|
78
|
+
};
|
|
79
|
+
export declare class GhostFulfillmentConsumer {
|
|
80
|
+
private readonly baseUrl;
|
|
81
|
+
private readonly privateKey;
|
|
82
|
+
private readonly chainId;
|
|
83
|
+
private readonly defaultServiceSlug;
|
|
84
|
+
constructor(config?: GhostFulfillmentConsumerConfig);
|
|
85
|
+
requestTicket(input: FulfillmentExecuteInput): Promise<FulfillmentTicketRequestResult>;
|
|
86
|
+
execute(input: FulfillmentExecuteInput): Promise<FulfillmentExecuteResult>;
|
|
87
|
+
}
|
|
88
|
+
export declare class GhostFulfillmentMerchant {
|
|
89
|
+
private readonly baseUrl;
|
|
90
|
+
private readonly delegatedPrivateKey;
|
|
91
|
+
private readonly protocolSignerAddresses;
|
|
92
|
+
private readonly chainId;
|
|
93
|
+
constructor(config: GhostFulfillmentMerchantConfig);
|
|
94
|
+
parseTicketHeaders(headers: Headers | Record<string, string | undefined | null>): {
|
|
95
|
+
ticketId: Hex32;
|
|
96
|
+
ticket: FulfillmentTicketEnvelope;
|
|
97
|
+
clientRequestId: string | null;
|
|
98
|
+
} | null;
|
|
99
|
+
requireFulfillmentTicket(input: {
|
|
100
|
+
headers: Headers | Record<string, string | undefined | null>;
|
|
101
|
+
expected?: FulfillmentTicketBindingInput;
|
|
102
|
+
nowMs?: number;
|
|
103
|
+
}): Promise<VerifiedFulfillmentTicket>;
|
|
104
|
+
captureCompletion(input: CaptureCompletionInput): Promise<CaptureCompletionResult>;
|
|
105
|
+
}
|
|
106
|
+
export declare const fulfillmentTicketHeadersToRecord: (input: {
|
|
107
|
+
ticketId: string;
|
|
108
|
+
ticket: FulfillmentTicketEnvelope;
|
|
109
|
+
clientRequestId?: string | null;
|
|
110
|
+
}) => FulfillmentTicketHeaderRecord;
|
|
111
|
+
export declare const parseFulfillmentTicketHeadersFromRecord: (headers: Pick<Headers, "get"> | Record<string, string | null | undefined>) => {
|
|
112
|
+
ticketId: Hex32;
|
|
113
|
+
ticket: FulfillmentTicketEnvelope;
|
|
114
|
+
clientRequestId: string | null;
|
|
115
|
+
} | null;
|
|
116
|
+
export declare const debugFulfillmentTicketEnvelope: (envelope: FulfillmentTicketEnvelope) => Record<string, unknown>;
|
|
117
|
+
export declare const debugFulfillmentDeliveryProofEnvelope: (envelope: FulfillmentDeliveryProofEnvelope) => Record<string, unknown>;
|
|
118
|
+
export default GhostFulfillmentConsumer;
|
|
119
|
+
//# sourceMappingURL=fulfillment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fulfillment.d.ts","sourceRoot":"","sources":["../src/fulfillment.ts"],"names":[],"mappings":"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"}
|