@chainpayhq/sdk 0.0.0-stage → 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 +42 -2
- package/dist/accounts.d.ts +23 -0
- package/dist/accounts.js +148 -0
- package/dist/cards/accounts.d.ts +156 -0
- package/dist/cards/accounts.js +346 -0
- package/dist/cards/api.d.ts +379 -0
- package/dist/cards/api.js +241 -0
- package/dist/cards/commitment.d.ts +86 -0
- package/dist/cards/commitment.js +288 -0
- package/dist/cards/constants.d.ts +160 -0
- package/dist/cards/constants.js +163 -0
- package/dist/cards/draft.d.ts +57 -0
- package/dist/cards/draft.js +131 -0
- package/dist/cards/evidence.d.ts +69 -0
- package/dist/cards/evidence.js +41 -0
- package/dist/cards/hash.d.ts +9 -0
- package/dist/cards/hash.js +47 -0
- package/dist/cards/index.d.ts +14 -0
- package/dist/cards/index.js +14 -0
- package/dist/cards/instructions.d.ts +302 -0
- package/dist/cards/instructions.js +474 -0
- package/dist/cards/layout.d.ts +33 -0
- package/dist/cards/layout.js +137 -0
- package/dist/cards/math.d.ts +67 -0
- package/dist/cards/math.js +138 -0
- package/dist/cards/merchants.d.ts +23 -0
- package/dist/cards/merchants.js +38 -0
- package/dist/cards/pda.d.ts +42 -0
- package/dist/cards/pda.js +93 -0
- package/dist/cards/private-repayment.d.ts +198 -0
- package/dist/cards/private-repayment.js +485 -0
- package/dist/cards/redact.d.ts +18 -0
- package/dist/cards/redact.js +103 -0
- package/dist/cards/tee.d.ts +253 -0
- package/dist/cards/tee.js +605 -0
- package/dist/cli.d.ts +31 -0
- package/dist/cli.js +351 -0
- package/dist/client.d.ts +80 -0
- package/dist/client.js +493 -0
- package/dist/constants.d.ts +44 -0
- package/dist/constants.js +43 -0
- package/dist/crossmint-adapt.d.ts +43 -0
- package/dist/crossmint-adapt.js +68 -0
- package/dist/crossmint-order.d.ts +220 -0
- package/dist/crossmint-order.js +638 -0
- package/dist/delivery.d.ts +66 -0
- package/dist/delivery.js +232 -0
- package/dist/encoding.d.ts +51 -0
- package/dist/encoding.js +128 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +26 -0
- package/dist/known-assets.d.ts +30 -0
- package/dist/known-assets.js +49 -0
- package/dist/mandate-request.d.ts +123 -0
- package/dist/mandate-request.js +401 -0
- package/dist/mandate.d.ts +44 -0
- package/dist/mandate.js +157 -0
- package/dist/ops-snapshot.d.ts +157 -0
- package/dist/ops-snapshot.js +356 -0
- package/dist/payment-request.d.ts +37 -0
- package/dist/payment-request.js +218 -0
- package/dist/payment.d.ts +40 -0
- package/dist/payment.js +214 -0
- package/dist/pda.d.ts +13 -0
- package/dist/pda.js +36 -0
- package/dist/receipt-export.d.ts +55 -0
- package/dist/receipt-export.js +149 -0
- package/dist/receipt.d.ts +108 -0
- package/dist/receipt.js +213 -0
- package/dist/solana.d.ts +5 -0
- package/dist/solana.js +20 -0
- package/dist/token-capabilities.d.ts +9 -0
- package/dist/token-capabilities.js +139 -0
- package/dist/token.d.ts +18 -0
- package/dist/token.js +55 -0
- package/dist/transaction-reader.d.ts +10 -0
- package/dist/transaction-reader.js +18 -0
- package/dist/transaction-v1.d.ts +18 -0
- package/dist/transaction-v1.js +73 -0
- package/dist/types.d.ts +267 -0
- package/dist/types.js +1 -0
- package/dist/x402-adapt.d.ts +20 -0
- package/dist/x402-adapt.js +62 -0
- package/dist/x402-challenge.d.ts +116 -0
- package/dist/x402-challenge.js +385 -0
- package/dist/x402.d.ts +18 -0
- package/dist/x402.js +35 -0
- package/package.json +54 -4
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { hexToBytes } from "./receipt.js";
|
|
2
|
+
import { MEMO_PROGRAM_ID } from "./constants.js";
|
|
3
|
+
import { CROSSMINT_CONNECTOR, CROSSMINT_CONNECTOR_LABEL, MAX_CROSSMINT_MEMO_BYTES, crossmintPaymentTerms, deriveCrossmintPaymentReferences, parseCrossmintOrder, } from "./crossmint-order.js";
|
|
4
|
+
/** Terms plus the references the receipt PDA is derived from. */
|
|
5
|
+
export async function crossmintTermsToPrepareFields(terms) {
|
|
6
|
+
const references = await deriveCrossmintPaymentReferences(terms.orderId);
|
|
7
|
+
return {
|
|
8
|
+
connector: CROSSMINT_CONNECTOR,
|
|
9
|
+
connectorLabel: CROSSMINT_CONNECTOR_LABEL,
|
|
10
|
+
orderId: terms.orderId,
|
|
11
|
+
mint: terms.mint,
|
|
12
|
+
recipient: terms.recipient,
|
|
13
|
+
amount: terms.amount,
|
|
14
|
+
tokenProgram: terms.tokenProgram,
|
|
15
|
+
...references,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function crossmintFieldsToPreparePaymentInput(mandate, fields) {
|
|
19
|
+
return {
|
|
20
|
+
mandate,
|
|
21
|
+
invoiceHash: hexToBytes(fields.invoiceHash, "invoiceHash"),
|
|
22
|
+
paymentId: hexToBytes(fields.paymentId, "paymentId"),
|
|
23
|
+
signatureReference: hexToBytes(fields.signatureReference, "signatureReference"),
|
|
24
|
+
mint: fields.mint,
|
|
25
|
+
recipient: fields.recipient,
|
|
26
|
+
amount: BigInt(fields.amount),
|
|
27
|
+
tokenProgram: fields.tokenProgram,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** One call from a raw Crossmint order response to a ChainPay payment input. */
|
|
31
|
+
export async function crossmintOrderToPreparePaymentInput(mandate, order, expected = {}) {
|
|
32
|
+
const terms = crossmintPaymentTerms(parseCrossmintOrder(order), expected);
|
|
33
|
+
const fields = await crossmintTermsToPrepareFields(terms);
|
|
34
|
+
return { terms, fields, input: crossmintFieldsToPreparePaymentInput(mandate, fields) };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Crossmint's order memo as a top-level SPL Memo instruction with no accounts.
|
|
38
|
+
*
|
|
39
|
+
* Crossmint's own preparation has the payer sign the memo. In ChainPay the
|
|
40
|
+
* approved agent signs and pays fees, never the owner, so the memo names no
|
|
41
|
+
* signer; the memo program accepts an unsigned memo. The bytes are Crossmint's
|
|
42
|
+
* memo exactly, because Crossmint matches a payment to its order by this text.
|
|
43
|
+
*/
|
|
44
|
+
export function crossmintMemoInstruction(memo) {
|
|
45
|
+
const data = new TextEncoder().encode(memo);
|
|
46
|
+
if (data.length === 0 || data.length > MAX_CROSSMINT_MEMO_BYTES) {
|
|
47
|
+
throw new Error("Crossmint memo is empty or too long");
|
|
48
|
+
}
|
|
49
|
+
return { name: "crossmint_order_memo", programId: MEMO_PROGRAM_ID, keys: [], data };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The transaction a Crossmint checkout signs: the unchanged mandate payment,
|
|
53
|
+
* then Crossmint's memo. Nothing else is added and nothing is dropped; a
|
|
54
|
+
* prepared payment that is not exactly one `execute_payment` is refused.
|
|
55
|
+
* The receipt PDA and invoice hash are untouched: they come from the order id.
|
|
56
|
+
*/
|
|
57
|
+
export function crossmintPaymentTransaction(prepared, terms) {
|
|
58
|
+
if (!terms.memo)
|
|
59
|
+
throw new Error("Crossmint terms carry no checked order memo");
|
|
60
|
+
if (prepared.instructions.length !== 1 || prepared.instructions[0].name !== "execute_payment") {
|
|
61
|
+
throw new Error("A Crossmint payment must start from exactly one execute_payment instruction");
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
...prepared,
|
|
65
|
+
requiredSigners: [...prepared.requiredSigners],
|
|
66
|
+
instructions: [prepared.instructions[0], crossmintMemoInstruction(terms.memo)],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import type { Address, TokenProgram } from "./types.js";
|
|
2
|
+
export declare const CROSSMINT_CONNECTOR: "crossmint-checkout/1.0";
|
|
3
|
+
export declare const CROSSMINT_CONNECTOR_LABEL = "Crossmint checkout order settled through a ChainPay mandate. Proof is the settled signature and receipt PDA; Crossmint order state is read back from its Orders API.";
|
|
4
|
+
export declare const CROSSMINT_STAGING_BASE_URL = "https://staging.crossmint.com";
|
|
5
|
+
export declare const CROSSMINT_PRODUCTION_BASE_URL = "https://www.crossmint.com";
|
|
6
|
+
export declare const CROSSMINT_ORDERS_PATH = "/api/2022-06-09/orders";
|
|
7
|
+
/** Crossmint advances an order through these phases; only `payment` still owes money. */
|
|
8
|
+
export declare const CROSSMINT_PAYABLE_PHASE: "payment";
|
|
9
|
+
export declare const CROSSMINT_SETTLED_PHASES: readonly ["delivery", "completed"];
|
|
10
|
+
/**
|
|
11
|
+
* Crossmint's Solana memo is `------BEGIN MEMO------<JWT>------END MEMO------`,
|
|
12
|
+
* about 300 bytes. The bound keeps the memo plus `execute_payment` well inside
|
|
13
|
+
* one legacy transaction.
|
|
14
|
+
*/
|
|
15
|
+
export declare const MAX_CROSSMINT_MEMO_BYTES = 512;
|
|
16
|
+
export type CrossmintOrderErrorCode = "malformed" | "order_not_payable" | "terms_unavailable" | "terms_mismatch" | "unsupported_token_program";
|
|
17
|
+
export declare class CrossmintOrderError extends Error {
|
|
18
|
+
readonly code: CrossmintOrderErrorCode;
|
|
19
|
+
constructor(code: CrossmintOrderErrorCode, message: string);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The fields ChainPay reads from a Crossmint order. Everything except the order
|
|
23
|
+
* id, the phase, and the payment preparation is optional: a field Crossmint
|
|
24
|
+
* renames or drops must not stop a payment whose terms come from the
|
|
25
|
+
* transaction Crossmint itself prepared.
|
|
26
|
+
*/
|
|
27
|
+
export type CrossmintOrderSummary = {
|
|
28
|
+
orderId: string;
|
|
29
|
+
phase: string;
|
|
30
|
+
paymentStatus?: string;
|
|
31
|
+
paymentMethod?: string;
|
|
32
|
+
currency?: string;
|
|
33
|
+
quotedTotal?: {
|
|
34
|
+
amount: string;
|
|
35
|
+
currency?: string;
|
|
36
|
+
};
|
|
37
|
+
lineItemLocators: string[];
|
|
38
|
+
/**
|
|
39
|
+
* What each line item delivers and to whom. `lineItemCount` is the raw count
|
|
40
|
+
* Crossmint returned, so an item ChainPay could not read is never silently
|
|
41
|
+
* dropped from what the owner reviews.
|
|
42
|
+
*/
|
|
43
|
+
lineItems: CrossmintLineItem[];
|
|
44
|
+
lineItemCount: number;
|
|
45
|
+
serializedTransaction?: string;
|
|
46
|
+
/**
|
|
47
|
+
* `payment.preparation.transactionParameters.memo`, byte for byte (never
|
|
48
|
+
* trimmed). Crossmint pays every order into one shared treasury account, so
|
|
49
|
+
* this memo is the only thing that ties a payment to this order.
|
|
50
|
+
*/
|
|
51
|
+
transactionMemo?: string;
|
|
52
|
+
/** `transactionParameters.amount`, base units, when Crossmint states it. */
|
|
53
|
+
transactionAmount?: string;
|
|
54
|
+
payerAddress?: string;
|
|
55
|
+
preparationChain?: string;
|
|
56
|
+
quoteExpiresAt?: string;
|
|
57
|
+
quoteStatus?: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* One Crossmint line item as ChainPay reads it. A field that is absent stays
|
|
61
|
+
* undefined; a field Crossmint states twice with different values is flagged
|
|
62
|
+
* as a conflict instead of picking one, so checkout can fail closed.
|
|
63
|
+
*/
|
|
64
|
+
export type CrossmintLineItem = {
|
|
65
|
+
locator?: string;
|
|
66
|
+
/** `metadata.name`: what the owner is buying, in Crossmint's words. */
|
|
67
|
+
name?: string;
|
|
68
|
+
description?: string;
|
|
69
|
+
imageUrl?: string;
|
|
70
|
+
/** A metadata field Crossmint stated but ChainPay could not read within bounds. */
|
|
71
|
+
metadataUnreadable?: true;
|
|
72
|
+
chain?: string;
|
|
73
|
+
executionMode?: string;
|
|
74
|
+
quantity?: number;
|
|
75
|
+
quantityConflict?: true;
|
|
76
|
+
/** Wallet that receives the purchased item: Crossmint's `delivery.recipient`. */
|
|
77
|
+
deliveryRecipient?: string;
|
|
78
|
+
deliveryRecipientConflict?: true;
|
|
79
|
+
totalPrice?: {
|
|
80
|
+
amount: string;
|
|
81
|
+
currency?: string;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
/** The material terms of one item, bound into the reviewed approval. */
|
|
85
|
+
export type CrossmintBoundItem = {
|
|
86
|
+
/** Crossmint's live order responses carry no locator; kept when one is returned. */
|
|
87
|
+
locator: string | null;
|
|
88
|
+
name: string | null;
|
|
89
|
+
description: string | null;
|
|
90
|
+
imageUrl: string | null;
|
|
91
|
+
chain: string | null;
|
|
92
|
+
executionMode: string | null;
|
|
93
|
+
quantity: number | null;
|
|
94
|
+
deliveryRecipient: string | null;
|
|
95
|
+
totalPrice: {
|
|
96
|
+
amount: string;
|
|
97
|
+
currency: string | null;
|
|
98
|
+
} | null;
|
|
99
|
+
};
|
|
100
|
+
export type CrossmintQuoteCheck = "match" | "mismatch" | "unavailable";
|
|
101
|
+
export type CrossmintPaymentTerms = {
|
|
102
|
+
connector: typeof CROSSMINT_CONNECTOR;
|
|
103
|
+
connectorLabel: string;
|
|
104
|
+
orderId: string;
|
|
105
|
+
phase: string;
|
|
106
|
+
mint: Address;
|
|
107
|
+
recipient: Address;
|
|
108
|
+
amount: string;
|
|
109
|
+
decimals?: number;
|
|
110
|
+
tokenProgram: TokenProgram;
|
|
111
|
+
/**
|
|
112
|
+
* Crossmint's own prepared transfer is the only authority on what is owed.
|
|
113
|
+
* ChainPay reads it and never submits it: settlement goes through
|
|
114
|
+
* `execute_payment` so the mandate and the receipt still apply.
|
|
115
|
+
*/
|
|
116
|
+
termsSource: "serialized-transaction";
|
|
117
|
+
quoteCheck: CrossmintQuoteCheck;
|
|
118
|
+
quotedTotal?: {
|
|
119
|
+
amount: string;
|
|
120
|
+
currency?: string;
|
|
121
|
+
};
|
|
122
|
+
lineItemLocators: string[];
|
|
123
|
+
/**
|
|
124
|
+
* Who receives what, and how many. The payer and the token-transfer recipient
|
|
125
|
+
* say nothing about where the purchased item goes, so a changed delivery
|
|
126
|
+
* wallet or quantity must change the reviewed fingerprint too.
|
|
127
|
+
*/
|
|
128
|
+
items: CrossmintBoundItem[];
|
|
129
|
+
payerAddress?: string;
|
|
130
|
+
crossmintSourceTokenAccount?: Address;
|
|
131
|
+
/**
|
|
132
|
+
* Crossmint's exact order memo. Checkout carries it as a second top-level
|
|
133
|
+
* SPL Memo instruction beside `execute_payment`, because the shared treasury
|
|
134
|
+
* destination cannot tell orders apart. Set only by
|
|
135
|
+
* `validateCrossmintCheckoutOrder`, after the memo is checked against the
|
|
136
|
+
* prepared transaction and the order id.
|
|
137
|
+
*/
|
|
138
|
+
memo?: string;
|
|
139
|
+
};
|
|
140
|
+
export type CrossmintTransferTerms = {
|
|
141
|
+
mint: Address;
|
|
142
|
+
recipient: Address;
|
|
143
|
+
source: Address;
|
|
144
|
+
amount: string;
|
|
145
|
+
decimals?: number;
|
|
146
|
+
tokenProgram: TokenProgram;
|
|
147
|
+
/**
|
|
148
|
+
* Strict decoding only: the single SPL Memo instruction's text and the
|
|
149
|
+
* accounts it names. Every memo account must be a transaction signer.
|
|
150
|
+
*/
|
|
151
|
+
memo?: {
|
|
152
|
+
text: string;
|
|
153
|
+
signers: Address[];
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
export type CrossmintPaymentReferences = {
|
|
157
|
+
invoiceHash: string;
|
|
158
|
+
paymentId: string;
|
|
159
|
+
signatureReference: string;
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Scale a decimal display amount to base units without floating point.
|
|
163
|
+
* Returns undefined when the string is not a plain decimal number, because a
|
|
164
|
+
* quote ChainPay cannot read must be reported as unchecked, never as agreeing.
|
|
165
|
+
*/
|
|
166
|
+
export declare function scaleDecimalString(value: string, decimals: number): bigint | undefined;
|
|
167
|
+
/**
|
|
168
|
+
* Read a Crossmint create-order or get-order response. Accepts the documented
|
|
169
|
+
* `{ order }` envelope and a bare order object, because the same order shape is
|
|
170
|
+
* returned by both endpoints.
|
|
171
|
+
*/
|
|
172
|
+
export declare function parseCrossmintOrder(value: unknown): CrossmintOrderSummary;
|
|
173
|
+
/**
|
|
174
|
+
* Derive what a Crossmint order actually charges from the transaction Crossmint
|
|
175
|
+
* prepared for its own payer. Exactly one SPL Token or Token-2022 transfer must
|
|
176
|
+
* be present: an order that moves money in more than one transfer has no single
|
|
177
|
+
* set of terms a mandate can be checked against.
|
|
178
|
+
*/
|
|
179
|
+
export declare function decodeCrossmintTransferTerms(serializedTransaction: string, expected?: {
|
|
180
|
+
mint?: Address;
|
|
181
|
+
tokenProgram?: TokenProgram;
|
|
182
|
+
strict?: boolean;
|
|
183
|
+
}): CrossmintTransferTerms;
|
|
184
|
+
/**
|
|
185
|
+
* Check Crossmint's order memo and return it unchanged.
|
|
186
|
+
*
|
|
187
|
+
* The memo is `------BEGIN MEMO------<JWT>------END MEMO------`. Its JWT payload
|
|
188
|
+
* names the order (`orderIdentifier`). ChainPay cannot check the JWT signature,
|
|
189
|
+
* which is Crossmint's own; it only checks that the memo belongs to this order,
|
|
190
|
+
* so a memo copied from a different order is refused.
|
|
191
|
+
*/
|
|
192
|
+
export declare function crossmintOrderMemo(memo: string, orderId: string): string;
|
|
193
|
+
/** Narrow, fail-closed staging checkout contract; generic decoding is not checkout authorization. */
|
|
194
|
+
export declare function validateCrossmintCheckoutOrder(order: CrossmintOrderSummary, expected: {
|
|
195
|
+
orderId: string;
|
|
196
|
+
owner: Address;
|
|
197
|
+
source: Address;
|
|
198
|
+
mint: Address;
|
|
199
|
+
now?: number;
|
|
200
|
+
}): CrossmintPaymentTerms;
|
|
201
|
+
/**
|
|
202
|
+
* Turn a Crossmint order into the terms ChainPay will check against a mandate.
|
|
203
|
+
* A phase that no longer owes money is rejected here rather than at settlement,
|
|
204
|
+
* so an already-paid order cannot be charged a second time by mistake.
|
|
205
|
+
*/
|
|
206
|
+
export declare function crossmintPaymentTerms(order: CrossmintOrderSummary, expected?: {
|
|
207
|
+
mint?: Address;
|
|
208
|
+
tokenProgram?: TokenProgram;
|
|
209
|
+
}): CrossmintPaymentTerms;
|
|
210
|
+
/**
|
|
211
|
+
* Payment references for a Crossmint order.
|
|
212
|
+
*
|
|
213
|
+
* The invoice hash commits to the connector and the order id and nothing else.
|
|
214
|
+
* The receipt PDA is derived from it, so one Crossmint order can be settled at
|
|
215
|
+
* most once under a given mandate however its price or recipient later change —
|
|
216
|
+
* a repriced order cannot become a second charge.
|
|
217
|
+
*/
|
|
218
|
+
export declare function deriveCrossmintPaymentReferences(orderId: string): Promise<CrossmintPaymentReferences>;
|
|
219
|
+
/** Orders API URL for one order id, against the staging or production host. */
|
|
220
|
+
export declare function crossmintOrderUrl(baseUrl: string, orderId: string): string;
|