@t402/tezos 2.3.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.
Files changed (42) hide show
  1. package/README.md +161 -0
  2. package/dist/exact-direct/client/index.d.cts +92 -0
  3. package/dist/exact-direct/client/index.d.ts +92 -0
  4. package/dist/exact-direct/client/index.js +204 -0
  5. package/dist/exact-direct/client/index.js.map +1 -0
  6. package/dist/exact-direct/client/index.mjs +176 -0
  7. package/dist/exact-direct/client/index.mjs.map +1 -0
  8. package/dist/exact-direct/facilitator/index.d.cts +110 -0
  9. package/dist/exact-direct/facilitator/index.d.ts +110 -0
  10. package/dist/exact-direct/facilitator/index.js +331 -0
  11. package/dist/exact-direct/facilitator/index.js.map +1 -0
  12. package/dist/exact-direct/facilitator/index.mjs +303 -0
  13. package/dist/exact-direct/facilitator/index.mjs.map +1 -0
  14. package/dist/exact-direct/server/index.d.cts +109 -0
  15. package/dist/exact-direct/server/index.d.ts +109 -0
  16. package/dist/exact-direct/server/index.js +226 -0
  17. package/dist/exact-direct/server/index.js.map +1 -0
  18. package/dist/exact-direct/server/index.mjs +198 -0
  19. package/dist/exact-direct/server/index.mjs.map +1 -0
  20. package/dist/index.d.cts +124 -0
  21. package/dist/index.d.ts +124 -0
  22. package/dist/index.js +228 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/index.mjs +170 -0
  25. package/dist/index.mjs.map +1 -0
  26. package/dist/types-DQMtUOa_.d.cts +125 -0
  27. package/dist/types-DQMtUOa_.d.ts +125 -0
  28. package/package.json +100 -0
  29. package/src/constants.ts +53 -0
  30. package/src/exact-direct/client/index.ts +13 -0
  31. package/src/exact-direct/client/register.ts +71 -0
  32. package/src/exact-direct/client/scheme.ts +177 -0
  33. package/src/exact-direct/facilitator/index.ts +13 -0
  34. package/src/exact-direct/facilitator/register.ts +74 -0
  35. package/src/exact-direct/facilitator/scheme.ts +311 -0
  36. package/src/exact-direct/server/index.ts +13 -0
  37. package/src/exact-direct/server/register.ts +64 -0
  38. package/src/exact-direct/server/scheme.ts +205 -0
  39. package/src/index.ts +32 -0
  40. package/src/tokens.ts +86 -0
  41. package/src/types.ts +160 -0
  42. package/src/utils.ts +128 -0
package/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # @t402/tezos
2
+
3
+ Tezos implementation of the t402 payment protocol using the **exact-direct** payment scheme with FA2 token transfers (TZIP-12).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @t402/tezos
9
+ # or
10
+ pnpm add @t402/tezos
11
+ ```
12
+
13
+ ## Overview
14
+
15
+ This package provides support for USDT payments on Tezos using the exact-direct scheme. The client executes an FA2 `transfer` operation directly on-chain, then provides the operation hash as proof of payment.
16
+
17
+ Three main components:
18
+
19
+ - **Client** - For applications that make payments (have Tezos wallets)
20
+ - **Facilitator** - For payment processors that verify operations via TzKT
21
+ - **Server** - For resource servers that accept payments and build payment requirements
22
+
23
+ ## Supported Networks
24
+
25
+ | Network | CAIP-2 Identifier | USDT Contract | Status |
26
+ |---------|-------------------|---------------|--------|
27
+ | Tezos Mainnet | `tezos:NetXdQprcVkpaWU` | `KT1XnTn74bUtxHfDtBmm2bGZAQfhPbvKWR8o` | Production |
28
+ | Tezos Ghostnet | `tezos:NetXnHfVqm9iesp` | - | Testnet |
29
+
30
+ ## Package Exports
31
+
32
+ ### Main Package (`@t402/tezos`)
33
+
34
+ **Constants:**
35
+ - `TEZOS_MAINNET_CAIP2` - CAIP-2 identifier for mainnet
36
+ - `TEZOS_GHOSTNET_CAIP2` - CAIP-2 identifier for ghostnet
37
+ - `DEFAULT_MAINNET_RPC` - Default RPC endpoint
38
+ - `DEFAULT_MAINNET_INDEXER` - TzKT API endpoint
39
+ - `getNetworkConfig(network)` - Get network configuration
40
+
41
+ **Tokens:**
42
+ - `USDT_MAINNET` - USDT token config on mainnet
43
+ - `TOKEN_REGISTRY` - Token configurations by network
44
+ - `getTokenBySymbol(network, symbol)` - Get token by symbol
45
+ - `getTokenByContract(network, address, tokenId)` - Get token by contract
46
+ - `getDefaultToken(network)` - Get default token
47
+
48
+ **Utilities:**
49
+ - `isValidTezosAddress(address)` - Validate tz1/tz2/tz3/KT1 address
50
+ - `isValidOperationHash(hash)` - Validate operation hash
51
+ - `isTezosNetwork(network)` - Check if network is Tezos
52
+ - `compareAddresses(addr1, addr2)` - Compare addresses
53
+ - `formatAmount(amount, decimals)` - Format for display
54
+ - `parseAmount(amount, decimals)` - Parse to smallest units
55
+ - `extractFA2TransferDetails(operation)` - Extract transfer from operation
56
+
57
+ ### Client (`@t402/tezos/exact-direct/client`)
58
+
59
+ ```typescript
60
+ import { createExactDirectTezosClient } from '@t402/tezos/exact-direct/client';
61
+
62
+ const client = createExactDirectTezosClient({
63
+ signer: myTezosSigner,
64
+ });
65
+ ```
66
+
67
+ ### Server (`@t402/tezos/exact-direct/server`)
68
+
69
+ ```typescript
70
+ import { registerExactDirectTezosServer } from '@t402/tezos/exact-direct/server';
71
+
72
+ registerExactDirectTezosServer(server);
73
+ ```
74
+
75
+ ### Facilitator (`@t402/tezos/exact-direct/facilitator`)
76
+
77
+ ```typescript
78
+ import { createExactDirectTezosFacilitator } from '@t402/tezos/exact-direct/facilitator';
79
+
80
+ const facilitator = createExactDirectTezosFacilitator(signer);
81
+ ```
82
+
83
+ ## Payment Flow
84
+
85
+ 1. **Client** requests protected resource
86
+ 2. **Server** responds with 402 + payment requirements (network, amount, payTo)
87
+ 3. **Client** calls FA2 `transfer` entrypoint on USDT contract
88
+ 4. **Client** submits operation hash as payment proof
89
+ 5. **Facilitator** queries TzKT API to verify the operation
90
+ 6. **Facilitator** confirms payment matches requirements
91
+
92
+ ## Payload Structure
93
+
94
+ ```typescript
95
+ interface ExactDirectTezosPayload {
96
+ opHash: string; // Operation hash (starts with 'o')
97
+ from: string; // Sender address (tz1/tz2/tz3)
98
+ to: string; // Recipient address
99
+ amount: string; // Amount in smallest units
100
+ contractAddress: string; // FA2 contract (KT1...)
101
+ tokenId: number; // Token ID (0 for USDT)
102
+ }
103
+ ```
104
+
105
+ ## Address Formats
106
+
107
+ Tezos uses different address prefixes:
108
+ - `tz1` - Ed25519 public key hash
109
+ - `tz2` - Secp256k1 public key hash
110
+ - `tz3` - P256 public key hash
111
+ - `KT1` - Smart contract address
112
+
113
+ All addresses are 36 characters, Base58Check encoded.
114
+
115
+ Examples:
116
+ ```
117
+ tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb (implicit account)
118
+ KT1XnTn74bUtxHfDtBmm2bGZAQfhPbvKWR8o (USDT contract)
119
+ ```
120
+
121
+ ## FA2 Token Standard
122
+
123
+ This package uses the FA2 (TZIP-12) token standard:
124
+ - Multi-asset contract support
125
+ - Token ID identifies specific token within contract
126
+ - Standard `transfer` entrypoint
127
+
128
+ ```typescript
129
+ // FA2 transfer parameter structure
130
+ [{
131
+ from_: "tz1...",
132
+ txs: [{
133
+ to_: "tz2...",
134
+ token_id: 0,
135
+ amount: "1000000"
136
+ }]
137
+ }]
138
+ ```
139
+
140
+ ## Development
141
+
142
+ ```bash
143
+ # Build
144
+ pnpm build
145
+
146
+ # Test
147
+ pnpm test
148
+
149
+ # Test with coverage
150
+ pnpm test:coverage
151
+
152
+ # Lint
153
+ pnpm lint
154
+ ```
155
+
156
+ ## Related Packages
157
+
158
+ - `@t402/core` - Core protocol types and client
159
+ - `@t402/fetch` - HTTP wrapper with automatic payment handling
160
+ - `@t402/evm` - EVM chains implementation
161
+ - `@t402/polkadot` - Polkadot Asset Hub implementation
@@ -0,0 +1,92 @@
1
+ import { SchemeNetworkClient, PaymentRequirements, PaymentPayload, Network } from '@t402/core/types';
2
+ import { T as TezosSigner } from '../../types-DQMtUOa_.cjs';
3
+ import { t402Client } from '@t402/core/client';
4
+
5
+ /**
6
+ * Tezos Exact-Direct Client Scheme
7
+ *
8
+ * The client executes the FA2 transfer directly and provides
9
+ * the operation hash as proof of payment.
10
+ */
11
+
12
+ /**
13
+ * Configuration for ExactDirectTezosClient
14
+ */
15
+ interface ExactDirectTezosClientConfig {
16
+ /**
17
+ * Whether to verify the operation was successful before returning
18
+ * @default true
19
+ */
20
+ verifyOperation?: boolean;
21
+ }
22
+ /**
23
+ * Tezos Exact-Direct Client
24
+ *
25
+ * Implements the client-side payment flow where the client:
26
+ * 1. Receives payment requirements
27
+ * 2. Executes the FA2 transfer operation
28
+ * 3. Returns operation hash as proof
29
+ */
30
+ declare class ExactDirectTezosClient implements SchemeNetworkClient {
31
+ private readonly signer;
32
+ readonly scheme = "exact-direct";
33
+ constructor(signer: TezosSigner, config?: ExactDirectTezosClientConfig);
34
+ /**
35
+ * Create a payment payload by executing the transfer
36
+ */
37
+ createPaymentPayload(t402Version: number, paymentRequirements: PaymentRequirements): Promise<Pick<PaymentPayload, "t402Version" | "payload">>;
38
+ /**
39
+ * Parse CAIP-19 asset identifier for Tezos FA2
40
+ * Format: tezos:{chainRef}/fa2:{contractAddress}/{tokenId}
41
+ */
42
+ private parseAssetIdentifier;
43
+ /**
44
+ * Validate payment requirements
45
+ */
46
+ private validateRequirements;
47
+ }
48
+
49
+ /**
50
+ * Registration function for Tezos Exact-Direct client
51
+ */
52
+
53
+ /**
54
+ * Configuration options for registering Tezos schemes to a t402Client
55
+ */
56
+ interface TezosClientConfig {
57
+ /**
58
+ * The Tezos signer for payment operations
59
+ */
60
+ signer: TezosSigner;
61
+ /**
62
+ * Optional specific networks to register
63
+ * If not provided, registers wildcard support (tezos:*)
64
+ */
65
+ networks?: Network[];
66
+ /**
67
+ * Optional scheme configuration
68
+ */
69
+ schemeConfig?: ExactDirectTezosClientConfig;
70
+ }
71
+ /**
72
+ * Registers Tezos exact-direct payment scheme to a t402Client instance.
73
+ *
74
+ * @param client - The t402Client instance to register schemes to
75
+ * @param config - Configuration for Tezos client registration
76
+ * @returns The client instance for chaining
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * import { registerExactDirectTezosClient } from "@t402/tezos/exact-direct/client";
81
+ * import { t402Client } from "@t402/core/client";
82
+ *
83
+ * const client = new t402Client();
84
+ * registerExactDirectTezosClient(client, {
85
+ * signer: myTezosSigner,
86
+ * networks: ["tezos:NetXdQprcVkpaWU"]
87
+ * });
88
+ * ```
89
+ */
90
+ declare function registerExactDirectTezosClient(client: t402Client, config: TezosClientConfig): t402Client;
91
+
92
+ export { ExactDirectTezosClient, type ExactDirectTezosClientConfig, type TezosClientConfig, registerExactDirectTezosClient };
@@ -0,0 +1,92 @@
1
+ import { SchemeNetworkClient, PaymentRequirements, PaymentPayload, Network } from '@t402/core/types';
2
+ import { T as TezosSigner } from '../../types-DQMtUOa_.js';
3
+ import { t402Client } from '@t402/core/client';
4
+
5
+ /**
6
+ * Tezos Exact-Direct Client Scheme
7
+ *
8
+ * The client executes the FA2 transfer directly and provides
9
+ * the operation hash as proof of payment.
10
+ */
11
+
12
+ /**
13
+ * Configuration for ExactDirectTezosClient
14
+ */
15
+ interface ExactDirectTezosClientConfig {
16
+ /**
17
+ * Whether to verify the operation was successful before returning
18
+ * @default true
19
+ */
20
+ verifyOperation?: boolean;
21
+ }
22
+ /**
23
+ * Tezos Exact-Direct Client
24
+ *
25
+ * Implements the client-side payment flow where the client:
26
+ * 1. Receives payment requirements
27
+ * 2. Executes the FA2 transfer operation
28
+ * 3. Returns operation hash as proof
29
+ */
30
+ declare class ExactDirectTezosClient implements SchemeNetworkClient {
31
+ private readonly signer;
32
+ readonly scheme = "exact-direct";
33
+ constructor(signer: TezosSigner, config?: ExactDirectTezosClientConfig);
34
+ /**
35
+ * Create a payment payload by executing the transfer
36
+ */
37
+ createPaymentPayload(t402Version: number, paymentRequirements: PaymentRequirements): Promise<Pick<PaymentPayload, "t402Version" | "payload">>;
38
+ /**
39
+ * Parse CAIP-19 asset identifier for Tezos FA2
40
+ * Format: tezos:{chainRef}/fa2:{contractAddress}/{tokenId}
41
+ */
42
+ private parseAssetIdentifier;
43
+ /**
44
+ * Validate payment requirements
45
+ */
46
+ private validateRequirements;
47
+ }
48
+
49
+ /**
50
+ * Registration function for Tezos Exact-Direct client
51
+ */
52
+
53
+ /**
54
+ * Configuration options for registering Tezos schemes to a t402Client
55
+ */
56
+ interface TezosClientConfig {
57
+ /**
58
+ * The Tezos signer for payment operations
59
+ */
60
+ signer: TezosSigner;
61
+ /**
62
+ * Optional specific networks to register
63
+ * If not provided, registers wildcard support (tezos:*)
64
+ */
65
+ networks?: Network[];
66
+ /**
67
+ * Optional scheme configuration
68
+ */
69
+ schemeConfig?: ExactDirectTezosClientConfig;
70
+ }
71
+ /**
72
+ * Registers Tezos exact-direct payment scheme to a t402Client instance.
73
+ *
74
+ * @param client - The t402Client instance to register schemes to
75
+ * @param config - Configuration for Tezos client registration
76
+ * @returns The client instance for chaining
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * import { registerExactDirectTezosClient } from "@t402/tezos/exact-direct/client";
81
+ * import { t402Client } from "@t402/core/client";
82
+ *
83
+ * const client = new t402Client();
84
+ * registerExactDirectTezosClient(client, {
85
+ * signer: myTezosSigner,
86
+ * networks: ["tezos:NetXdQprcVkpaWU"]
87
+ * });
88
+ * ```
89
+ */
90
+ declare function registerExactDirectTezosClient(client: t402Client, config: TezosClientConfig): t402Client;
91
+
92
+ export { ExactDirectTezosClient, type ExactDirectTezosClientConfig, type TezosClientConfig, registerExactDirectTezosClient };
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/exact-direct/client/index.ts
21
+ var client_exports = {};
22
+ __export(client_exports, {
23
+ ExactDirectTezosClient: () => ExactDirectTezosClient,
24
+ registerExactDirectTezosClient: () => registerExactDirectTezosClient
25
+ });
26
+ module.exports = __toCommonJS(client_exports);
27
+
28
+ // src/constants.ts
29
+ var SCHEME_EXACT_DIRECT = "exact-direct";
30
+ var TEZOS_CAIP2_NAMESPACE = "tezos";
31
+ var TEZOS_MAINNET_CAIP2 = "tezos:NetXdQprcVkpaWU";
32
+ var TEZOS_GHOSTNET_CAIP2 = "tezos:NetXnHfVqm9iesp";
33
+ var DEFAULT_MAINNET_RPC = "https://mainnet.api.tez.ie";
34
+ var DEFAULT_GHOSTNET_RPC = "https://ghostnet.tezos.marigold.dev";
35
+ var DEFAULT_MAINNET_INDEXER = "https://api.tzkt.io";
36
+ var DEFAULT_GHOSTNET_INDEXER = "https://api.ghostnet.tzkt.io";
37
+ var NETWORK_CONFIGS = {
38
+ [TEZOS_MAINNET_CAIP2]: {
39
+ name: "Tezos Mainnet",
40
+ rpcUrl: DEFAULT_MAINNET_RPC,
41
+ indexerUrl: DEFAULT_MAINNET_INDEXER
42
+ },
43
+ [TEZOS_GHOSTNET_CAIP2]: {
44
+ name: "Tezos Ghostnet",
45
+ rpcUrl: DEFAULT_GHOSTNET_RPC,
46
+ indexerUrl: DEFAULT_GHOSTNET_INDEXER
47
+ }
48
+ };
49
+
50
+ // src/types.ts
51
+ function isValidTezosAddress(address) {
52
+ if (!address) return false;
53
+ const prefixPattern = /^(tz1|tz2|tz3|KT1)/;
54
+ if (!prefixPattern.test(address)) return false;
55
+ return address.length === 36;
56
+ }
57
+
58
+ // src/tokens.ts
59
+ var USDT_MAINNET = {
60
+ contractAddress: "KT1XnTn74bUtxHfDtBmm2bGZAQfhPbvKWR8o",
61
+ tokenId: 0,
62
+ symbol: "USDt",
63
+ name: "Tether USD",
64
+ decimals: 6
65
+ };
66
+ var TOKEN_REGISTRY = {
67
+ [TEZOS_MAINNET_CAIP2]: [USDT_MAINNET],
68
+ [TEZOS_GHOSTNET_CAIP2]: []
69
+ };
70
+ var DEFAULT_TOKENS = {
71
+ [TEZOS_MAINNET_CAIP2]: USDT_MAINNET,
72
+ [TEZOS_GHOSTNET_CAIP2]: void 0
73
+ };
74
+ function getTokenBySymbol(network, symbol) {
75
+ const tokens = TOKEN_REGISTRY[network];
76
+ if (!tokens) return void 0;
77
+ return tokens.find(
78
+ (t) => t.symbol.toLowerCase() === symbol.toLowerCase()
79
+ );
80
+ }
81
+
82
+ // src/utils.ts
83
+ function compareAddresses(addr1, addr2) {
84
+ if (!addr1 || !addr2) return false;
85
+ return addr1 === addr2;
86
+ }
87
+
88
+ // src/exact-direct/client/scheme.ts
89
+ var ExactDirectTezosClient = class {
90
+ constructor(signer, config = {}) {
91
+ this.signer = signer;
92
+ void config;
93
+ }
94
+ scheme = SCHEME_EXACT_DIRECT;
95
+ /**
96
+ * Create a payment payload by executing the transfer
97
+ */
98
+ async createPaymentPayload(t402Version, paymentRequirements) {
99
+ this.validateRequirements(paymentRequirements);
100
+ const from = await this.signer.getAddress();
101
+ const assetInfo = this.parseAssetIdentifier(paymentRequirements.asset);
102
+ if (!assetInfo) {
103
+ throw new Error(`Invalid asset identifier: ${paymentRequirements.asset}`);
104
+ }
105
+ const amount = BigInt(paymentRequirements.amount);
106
+ const balance = await this.signer.getBalance(
107
+ assetInfo.contractAddress,
108
+ assetInfo.tokenId
109
+ );
110
+ if (balance < amount) {
111
+ throw new Error(
112
+ `Insufficient balance: have ${balance}, need ${amount}`
113
+ );
114
+ }
115
+ const opHash = await this.signer.transfer(
116
+ assetInfo.contractAddress,
117
+ assetInfo.tokenId,
118
+ paymentRequirements.payTo,
119
+ amount
120
+ );
121
+ const payload = {
122
+ opHash,
123
+ from,
124
+ to: paymentRequirements.payTo,
125
+ amount: paymentRequirements.amount,
126
+ contractAddress: assetInfo.contractAddress,
127
+ tokenId: assetInfo.tokenId
128
+ };
129
+ return {
130
+ t402Version,
131
+ payload
132
+ };
133
+ }
134
+ /**
135
+ * Parse CAIP-19 asset identifier for Tezos FA2
136
+ * Format: tezos:{chainRef}/fa2:{contractAddress}/{tokenId}
137
+ */
138
+ parseAssetIdentifier(asset) {
139
+ const caipMatch = asset.match(/^tezos:[^/]+\/fa2:([^/]+)\/(\d+)$/);
140
+ if (caipMatch) {
141
+ return {
142
+ contractAddress: caipMatch[1],
143
+ tokenId: parseInt(caipMatch[2], 10)
144
+ };
145
+ }
146
+ const simpleMatch = asset.match(/^(KT1[a-zA-Z0-9]+)(?:\/(\d+))?$/);
147
+ if (simpleMatch) {
148
+ return {
149
+ contractAddress: simpleMatch[1],
150
+ tokenId: simpleMatch[2] ? parseInt(simpleMatch[2], 10) : 0
151
+ };
152
+ }
153
+ return null;
154
+ }
155
+ /**
156
+ * Validate payment requirements
157
+ */
158
+ validateRequirements(requirements) {
159
+ if (requirements.scheme !== SCHEME_EXACT_DIRECT) {
160
+ throw new Error(
161
+ `Invalid scheme: expected ${SCHEME_EXACT_DIRECT}, got ${requirements.scheme}`
162
+ );
163
+ }
164
+ if (!requirements.network.startsWith(`${TEZOS_CAIP2_NAMESPACE}:`)) {
165
+ throw new Error(`Invalid network: ${requirements.network}`);
166
+ }
167
+ if (!isValidTezosAddress(requirements.payTo)) {
168
+ throw new Error(`Invalid payTo address: ${requirements.payTo}`);
169
+ }
170
+ const amount = BigInt(requirements.amount);
171
+ if (amount <= 0n) {
172
+ throw new Error(`Invalid amount: ${requirements.amount}`);
173
+ }
174
+ const assetInfo = this.parseAssetIdentifier(requirements.asset);
175
+ if (!assetInfo) {
176
+ throw new Error(`Invalid asset: ${requirements.asset}`);
177
+ }
178
+ const tokenConfig = getTokenBySymbol(requirements.network, "USDt");
179
+ if (tokenConfig && !compareAddresses(tokenConfig.contractAddress, assetInfo.contractAddress)) {
180
+ console.warn(
181
+ `Using non-standard token: ${assetInfo.contractAddress}`
182
+ );
183
+ }
184
+ }
185
+ };
186
+
187
+ // src/exact-direct/client/register.ts
188
+ function registerExactDirectTezosClient(client, config) {
189
+ const scheme = new ExactDirectTezosClient(config.signer, config.schemeConfig);
190
+ if (config.networks && config.networks.length > 0) {
191
+ config.networks.forEach((network) => {
192
+ client.register(network, scheme);
193
+ });
194
+ } else {
195
+ client.register("tezos:*", scheme);
196
+ }
197
+ return client;
198
+ }
199
+ // Annotate the CommonJS export names for ESM import in node:
200
+ 0 && (module.exports = {
201
+ ExactDirectTezosClient,
202
+ registerExactDirectTezosClient
203
+ });
204
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/exact-direct/client/index.ts","../../../src/constants.ts","../../../src/types.ts","../../../src/tokens.ts","../../../src/utils.ts","../../../src/exact-direct/client/scheme.ts","../../../src/exact-direct/client/register.ts"],"sourcesContent":["/**\n * Tezos Exact-Direct Client\n */\n\nexport {\n ExactDirectTezosClient,\n type ExactDirectTezosClientConfig,\n} from \"./scheme.js\";\n\nexport {\n registerExactDirectTezosClient,\n type TezosClientConfig,\n} from \"./register.js\";\n","/**\n * Tezos mechanism constants\n */\n\n// Scheme identifiers\nexport const SCHEME_EXACT_DIRECT = \"exact-direct\";\n\n// CAIP-2 namespace\nexport const TEZOS_CAIP2_NAMESPACE = \"tezos\";\n\n// CAIP-2 network identifiers (derived from genesis block hash)\nexport const TEZOS_MAINNET_CAIP2 = \"tezos:NetXdQprcVkpaWU\";\nexport const TEZOS_GHOSTNET_CAIP2 = \"tezos:NetXnHfVqm9iesp\";\n\n// Default RPC endpoints\nexport const DEFAULT_MAINNET_RPC = \"https://mainnet.api.tez.ie\";\nexport const DEFAULT_GHOSTNET_RPC = \"https://ghostnet.tezos.marigold.dev\";\n\n// Default indexer API endpoints (TzKT)\nexport const DEFAULT_MAINNET_INDEXER = \"https://api.tzkt.io\";\nexport const DEFAULT_GHOSTNET_INDEXER = \"https://api.ghostnet.tzkt.io\";\n\n// FA2 token standard (TZIP-12)\nexport const FA2_TRANSFER_ENTRYPOINT = \"transfer\";\nexport const FA2_BALANCE_OF_ENTRYPOINT = \"balance_of\";\nexport const FA2_UPDATE_OPERATORS_ENTRYPOINT = \"update_operators\";\n\n// Supported networks\nexport const SUPPORTED_NETWORKS = [\n TEZOS_MAINNET_CAIP2,\n TEZOS_GHOSTNET_CAIP2,\n] as const;\n\n// Network configurations\nexport const NETWORK_CONFIGS: Record<\n string,\n {\n name: string;\n rpcUrl: string;\n indexerUrl: string;\n }\n> = {\n [TEZOS_MAINNET_CAIP2]: {\n name: \"Tezos Mainnet\",\n rpcUrl: DEFAULT_MAINNET_RPC,\n indexerUrl: DEFAULT_MAINNET_INDEXER,\n },\n [TEZOS_GHOSTNET_CAIP2]: {\n name: \"Tezos Ghostnet\",\n rpcUrl: DEFAULT_GHOSTNET_RPC,\n indexerUrl: DEFAULT_GHOSTNET_INDEXER,\n },\n};\n","/**\n * Tezos mechanism types\n */\n\nimport type { Network } from \"@t402/core/types\";\n\n/**\n * Exact-direct payment payload for Tezos\n */\nexport type ExactDirectTezosPayload = {\n /** Operation hash (o...) */\n opHash: string;\n /** Sender address (tz1/tz2/tz3...) */\n from: string;\n /** Recipient address */\n to: string;\n /** Amount in smallest units */\n amount: string;\n /** FA2 contract address (KT1...) */\n contractAddress: string;\n /** Token ID within the FA2 contract */\n tokenId: number;\n};\n\n/**\n * Tezos signer interface for client-side operations\n */\nexport interface TezosSigner {\n /** Get the signer's address */\n getAddress(): Promise<string>;\n\n /**\n * Execute an FA2 transfer\n * @param contractAddress FA2 contract address\n * @param tokenId Token ID\n * @param to Recipient address\n * @param amount Amount to transfer\n * @returns Operation hash\n */\n transfer(\n contractAddress: string,\n tokenId: number,\n to: string,\n amount: bigint,\n ): Promise<string>;\n\n /**\n * Get token balance\n * @param contractAddress FA2 contract address\n * @param tokenId Token ID\n * @param address Address to check (optional, defaults to signer address)\n * @returns Balance in smallest units\n */\n getBalance(\n contractAddress: string,\n tokenId: number,\n address?: string,\n ): Promise<bigint>;\n}\n\n/**\n * Tezos signer interface for facilitator operations\n */\nexport interface FacilitatorTezosSigner {\n /** Get facilitator addresses for a network */\n getAddresses(network: Network): string[];\n\n /**\n * Query an operation by hash\n * @param opHash Operation hash\n * @returns Operation result or null if not found\n */\n queryOperation(opHash: string): Promise<TezosOperationResult | null>;\n\n /**\n * Get token balance for an address\n * @param contractAddress FA2 contract address\n * @param tokenId Token ID\n * @param address Address to check\n * @returns Balance as string\n */\n getBalance(\n contractAddress: string,\n tokenId: number,\n address: string,\n ): Promise<string>;\n}\n\n/**\n * Tezos operation result from indexer\n */\nexport interface TezosOperationResult {\n /** Operation hash */\n hash: string;\n /** Block level */\n level: number;\n /** Timestamp */\n timestamp: string;\n /** Status: applied, failed, backtracked, skipped */\n status: \"applied\" | \"failed\" | \"backtracked\" | \"skipped\";\n /** Sender address */\n sender: {\n address: string;\n };\n /** Target contract (for contract calls) */\n target?: {\n address: string;\n };\n /** Entrypoint called */\n entrypoint?: string;\n /** Parameter value */\n parameter?: unknown;\n /** Amount transferred (in mutez for XTZ) */\n amount?: number;\n /** Errors if failed */\n errors?: Array<{\n type: string;\n message?: string;\n }>;\n}\n\n/**\n * FA2 transfer parameter structure\n */\nexport interface FA2TransferParam {\n from_: string;\n txs: Array<{\n to_: string;\n token_id: number;\n amount: string;\n }>;\n}\n\n/**\n * Check if a string is a valid Tezos address\n */\nexport function isValidTezosAddress(address: string): boolean {\n if (!address) return false;\n // tz1, tz2, tz3 for implicit accounts, KT1 for contracts\n const prefixPattern = /^(tz1|tz2|tz3|KT1)/;\n if (!prefixPattern.test(address)) return false;\n // Base58 check - length should be 36 characters\n return address.length === 36;\n}\n\n/**\n * Check if a string is a valid Tezos operation hash\n */\nexport function isValidOperationHash(opHash: string): boolean {\n if (!opHash) return false;\n // Operation hashes start with 'o' and are 51 characters\n return opHash.startsWith(\"o\") && opHash.length === 51;\n}\n\n/**\n * Check if a network is a Tezos network\n */\nexport function isTezosNetwork(network: string): boolean {\n return network.startsWith(\"tezos:\");\n}\n","/**\n * Tezos token registry\n */\n\nimport { TEZOS_MAINNET_CAIP2, TEZOS_GHOSTNET_CAIP2 } from \"./constants.js\";\n\n/**\n * Token configuration for Tezos FA2 tokens\n */\nexport interface TokenConfig {\n /** FA2 contract address (KT1...) */\n contractAddress: string;\n /** Token ID within the FA2 contract */\n tokenId: number;\n /** Token symbol */\n symbol: string;\n /** Token name */\n name: string;\n /** Token decimals */\n decimals: number;\n}\n\n/**\n * USDT on Tezos Mainnet\n */\nexport const USDT_MAINNET: TokenConfig = {\n contractAddress: \"KT1XnTn74bUtxHfDtBmm2bGZAQfhPbvKWR8o\",\n tokenId: 0,\n symbol: \"USDt\",\n name: \"Tether USD\",\n decimals: 6,\n};\n\n/**\n * Token registry by network\n */\nexport const TOKEN_REGISTRY: Record<string, TokenConfig[]> = {\n [TEZOS_MAINNET_CAIP2]: [USDT_MAINNET],\n [TEZOS_GHOSTNET_CAIP2]: [],\n};\n\n/**\n * Default token for each network\n */\nexport const DEFAULT_TOKENS: Record<string, TokenConfig | undefined> = {\n [TEZOS_MAINNET_CAIP2]: USDT_MAINNET,\n [TEZOS_GHOSTNET_CAIP2]: undefined,\n};\n\n/**\n * Get token by symbol for a network\n */\nexport function getTokenBySymbol(\n network: string,\n symbol: string,\n): TokenConfig | undefined {\n const tokens = TOKEN_REGISTRY[network];\n if (!tokens) return undefined;\n return tokens.find(\n (t) => t.symbol.toLowerCase() === symbol.toLowerCase(),\n );\n}\n\n/**\n * Get token by contract address and token ID\n */\nexport function getTokenByContract(\n network: string,\n contractAddress: string,\n tokenId: number,\n): TokenConfig | undefined {\n const tokens = TOKEN_REGISTRY[network];\n if (!tokens) return undefined;\n return tokens.find(\n (t) =>\n t.contractAddress.toLowerCase() === contractAddress.toLowerCase() &&\n t.tokenId === tokenId,\n );\n}\n\n/**\n * Get default token for a network\n */\nexport function getDefaultToken(network: string): TokenConfig | undefined {\n return DEFAULT_TOKENS[network];\n}\n","/**\n * Tezos utility functions\n */\n\nimport {\n NETWORK_CONFIGS,\n TEZOS_CAIP2_NAMESPACE,\n SUPPORTED_NETWORKS,\n} from \"./constants.js\";\n\n/**\n * Get network configuration\n */\nexport function getNetworkConfig(network: string) {\n return NETWORK_CONFIGS[network];\n}\n\n/**\n * Check if a network is supported\n */\nexport function isSupportedNetwork(network: string): boolean {\n return (SUPPORTED_NETWORKS as readonly string[]).includes(network);\n}\n\n/**\n * Parse a CAIP-2 network identifier to extract the chain reference\n */\nexport function parseNetworkId(network: string): {\n namespace: string;\n reference: string;\n} | null {\n const parts = network.split(\":\");\n if (parts.length !== 2) return null;\n return {\n namespace: parts[0],\n reference: parts[1],\n };\n}\n\n/**\n * Build a CAIP-2 network identifier\n */\nexport function buildNetworkId(reference: string): string {\n return `${TEZOS_CAIP2_NAMESPACE}:${reference}`;\n}\n\n/**\n * Get indexer URL for a network\n */\nexport function getIndexerUrl(network: string): string | undefined {\n return NETWORK_CONFIGS[network]?.indexerUrl;\n}\n\n/**\n * Get RPC URL for a network\n */\nexport function getRpcUrl(network: string): string | undefined {\n return NETWORK_CONFIGS[network]?.rpcUrl;\n}\n\n/**\n * Compare two Tezos addresses (case-insensitive for base58)\n */\nexport function compareAddresses(addr1: string, addr2: string): boolean {\n if (!addr1 || !addr2) return false;\n return addr1 === addr2;\n}\n\n/**\n * Format amount with decimals\n */\nexport function formatAmount(amount: bigint, decimals: number): string {\n const divisor = BigInt(10 ** decimals);\n const wholePart = amount / divisor;\n const fractionalPart = amount % divisor;\n const fractionalStr = fractionalPart.toString().padStart(decimals, \"0\");\n return `${wholePart}.${fractionalStr}`;\n}\n\n/**\n * Parse amount string to bigint\n */\nexport function parseAmount(amount: string, decimals: number): bigint {\n const [whole, fractional = \"\"] = amount.split(\".\");\n const paddedFractional = fractional.padEnd(decimals, \"0\").slice(0, decimals);\n return BigInt(whole + paddedFractional);\n}\n\n/**\n * Extract FA2 transfer details from operation parameter\n */\nexport function extractFA2TransferDetails(\n parameter: unknown,\n): {\n from: string;\n to: string;\n tokenId: number;\n amount: string;\n} | null {\n if (!parameter || !Array.isArray(parameter)) return null;\n\n // FA2 transfer parameter is an array of { from_: string, txs: [...] }\n const firstTransfer = parameter[0];\n if (!firstTransfer || typeof firstTransfer !== \"object\") return null;\n\n const transfer = firstTransfer as Record<string, unknown>;\n const from = transfer.from_ as string;\n const txs = transfer.txs as Array<{\n to_: string;\n token_id: number | string;\n amount: number | string;\n }>;\n\n if (!from || !Array.isArray(txs) || txs.length === 0) return null;\n\n const firstTx = txs[0];\n if (!firstTx) return null;\n\n return {\n from,\n to: firstTx.to_,\n tokenId:\n typeof firstTx.token_id === \"string\"\n ? parseInt(firstTx.token_id, 10)\n : firstTx.token_id,\n amount: String(firstTx.amount),\n };\n}\n","/**\n * Tezos Exact-Direct Client Scheme\n *\n * The client executes the FA2 transfer directly and provides\n * the operation hash as proof of payment.\n */\n\nimport type {\n SchemeNetworkClient,\n PaymentPayload,\n PaymentRequirements,\n} from \"@t402/core/types\";\nimport { SCHEME_EXACT_DIRECT, TEZOS_CAIP2_NAMESPACE } from \"../../constants.js\";\nimport type { TezosSigner, ExactDirectTezosPayload } from \"../../types.js\";\nimport { isValidTezosAddress } from \"../../types.js\";\nimport { getTokenBySymbol } from \"../../tokens.js\";\nimport { compareAddresses } from \"../../utils.js\";\n\n/**\n * Configuration for ExactDirectTezosClient\n */\nexport interface ExactDirectTezosClientConfig {\n /**\n * Whether to verify the operation was successful before returning\n * @default true\n */\n verifyOperation?: boolean;\n}\n\n/**\n * Tezos Exact-Direct Client\n *\n * Implements the client-side payment flow where the client:\n * 1. Receives payment requirements\n * 2. Executes the FA2 transfer operation\n * 3. Returns operation hash as proof\n */\nexport class ExactDirectTezosClient implements SchemeNetworkClient {\n readonly scheme = SCHEME_EXACT_DIRECT;\n\n constructor(\n private readonly signer: TezosSigner,\n config: ExactDirectTezosClientConfig = {},\n ) {\n // Config reserved for future use\n void config;\n }\n\n /**\n * Create a payment payload by executing the transfer\n */\n async createPaymentPayload(\n t402Version: number,\n paymentRequirements: PaymentRequirements,\n ): Promise<Pick<PaymentPayload, \"t402Version\" | \"payload\">> {\n // Validate requirements\n this.validateRequirements(paymentRequirements);\n\n // Get sender address\n const from = await this.signer.getAddress();\n\n // Parse asset to get contract address and token ID\n const assetInfo = this.parseAssetIdentifier(paymentRequirements.asset);\n if (!assetInfo) {\n throw new Error(`Invalid asset identifier: ${paymentRequirements.asset}`);\n }\n\n // Get amount\n const amount = BigInt(paymentRequirements.amount);\n\n // Check balance\n const balance = await this.signer.getBalance(\n assetInfo.contractAddress,\n assetInfo.tokenId,\n );\n if (balance < amount) {\n throw new Error(\n `Insufficient balance: have ${balance}, need ${amount}`,\n );\n }\n\n // Execute transfer\n const opHash = await this.signer.transfer(\n assetInfo.contractAddress,\n assetInfo.tokenId,\n paymentRequirements.payTo,\n amount,\n );\n\n // Create payload\n const payload: ExactDirectTezosPayload = {\n opHash,\n from,\n to: paymentRequirements.payTo,\n amount: paymentRequirements.amount,\n contractAddress: assetInfo.contractAddress,\n tokenId: assetInfo.tokenId,\n };\n\n return {\n t402Version,\n payload,\n };\n }\n\n /**\n * Parse CAIP-19 asset identifier for Tezos FA2\n * Format: tezos:{chainRef}/fa2:{contractAddress}/{tokenId}\n */\n private parseAssetIdentifier(\n asset: string,\n ): { contractAddress: string; tokenId: number } | null {\n // Try parsing CAIP-19 format\n const caipMatch = asset.match(/^tezos:[^/]+\\/fa2:([^/]+)\\/(\\d+)$/);\n if (caipMatch) {\n return {\n contractAddress: caipMatch[1],\n tokenId: parseInt(caipMatch[2], 10),\n };\n }\n\n // Try simple format: contractAddress/tokenId or just contractAddress (default tokenId 0)\n const simpleMatch = asset.match(/^(KT1[a-zA-Z0-9]+)(?:\\/(\\d+))?$/);\n if (simpleMatch) {\n return {\n contractAddress: simpleMatch[1],\n tokenId: simpleMatch[2] ? parseInt(simpleMatch[2], 10) : 0,\n };\n }\n\n return null;\n }\n\n /**\n * Validate payment requirements\n */\n private validateRequirements(requirements: PaymentRequirements): void {\n // Check scheme\n if (requirements.scheme !== SCHEME_EXACT_DIRECT) {\n throw new Error(\n `Invalid scheme: expected ${SCHEME_EXACT_DIRECT}, got ${requirements.scheme}`,\n );\n }\n\n // Check network\n if (!requirements.network.startsWith(`${TEZOS_CAIP2_NAMESPACE}:`)) {\n throw new Error(`Invalid network: ${requirements.network}`);\n }\n\n // Check payTo address\n if (!isValidTezosAddress(requirements.payTo)) {\n throw new Error(`Invalid payTo address: ${requirements.payTo}`);\n }\n\n // Check amount\n const amount = BigInt(requirements.amount);\n if (amount <= 0n) {\n throw new Error(`Invalid amount: ${requirements.amount}`);\n }\n\n // Check asset\n const assetInfo = this.parseAssetIdentifier(requirements.asset);\n if (!assetInfo) {\n throw new Error(`Invalid asset: ${requirements.asset}`);\n }\n\n // Verify token is supported (warn for unknown tokens)\n const tokenConfig = getTokenBySymbol(requirements.network, \"USDt\");\n if (tokenConfig && !compareAddresses(tokenConfig.contractAddress, assetInfo.contractAddress)) {\n console.warn(\n `Using non-standard token: ${assetInfo.contractAddress}`,\n );\n }\n }\n}\n\nexport default ExactDirectTezosClient;\n","/**\n * Registration function for Tezos Exact-Direct client\n */\n\nimport { t402Client } from \"@t402/core/client\";\nimport type { Network } from \"@t402/core/types\";\nimport type { TezosSigner } from \"../../types.js\";\nimport {\n ExactDirectTezosClient,\n type ExactDirectTezosClientConfig,\n} from \"./scheme.js\";\n\n/**\n * Configuration options for registering Tezos schemes to a t402Client\n */\nexport interface TezosClientConfig {\n /**\n * The Tezos signer for payment operations\n */\n signer: TezosSigner;\n\n /**\n * Optional specific networks to register\n * If not provided, registers wildcard support (tezos:*)\n */\n networks?: Network[];\n\n /**\n * Optional scheme configuration\n */\n schemeConfig?: ExactDirectTezosClientConfig;\n}\n\n/**\n * Registers Tezos exact-direct payment scheme to a t402Client instance.\n *\n * @param client - The t402Client instance to register schemes to\n * @param config - Configuration for Tezos client registration\n * @returns The client instance for chaining\n *\n * @example\n * ```typescript\n * import { registerExactDirectTezosClient } from \"@t402/tezos/exact-direct/client\";\n * import { t402Client } from \"@t402/core/client\";\n *\n * const client = new t402Client();\n * registerExactDirectTezosClient(client, {\n * signer: myTezosSigner,\n * networks: [\"tezos:NetXdQprcVkpaWU\"]\n * });\n * ```\n */\nexport function registerExactDirectTezosClient(\n client: t402Client,\n config: TezosClientConfig,\n): t402Client {\n const scheme = new ExactDirectTezosClient(config.signer, config.schemeConfig);\n\n // Register scheme\n if (config.networks && config.networks.length > 0) {\n // Register specific networks\n config.networks.forEach((network) => {\n client.register(network, scheme);\n });\n } else {\n // Register wildcard for all Tezos networks\n client.register(\"tezos:*\", scheme);\n }\n\n return client;\n}\n"],"mappings":"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","names":[]}